Compare commits

..

No commits in common. "main" and "0.19.4-beta.1" have entirely different histories.

169 changed files with 14495 additions and 32117 deletions

View file

@ -13,12 +13,7 @@
["@babel/typescript", { "isTSX": true, "allExtensions": true }] ["@babel/typescript", { "isTSX": true, "allExtensions": true }]
], ],
"plugins": [ "plugins": [
["@babel/plugin-proposal-decorators", { "version": "legacy" }], "@babel/plugin-transform-runtime",
[
"@babel/plugin-transform-runtime",
// version defaults to 7.0.0 for which non-legacy decorators produce duplicate code
{ "version": "^7.24.3" }
],
["babel-plugin-inferno", { "imports": true }], ["babel-plugin-inferno", { "imports": true }],
["@babel/plugin-transform-class-properties", { "loose": true }] ["@babel/plugin-transform-class-properties", { "loose": true }]
] ]

9
.eslintignore Normal file
View file

@ -0,0 +1,9 @@
generate_translations.js
webpack.config.js
src/shared/build-config.js
src/api_tests
**/*.png
**/*.css
**/*.scss
**/*.svg
src/shared/translations/**

50
.eslintrc.json Normal file
View file

@ -0,0 +1,50 @@
{
"root": true,
"env": {
"browser": true
},
"plugins": ["@typescript-eslint", "jsx-a11y", "prettier"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:inferno/recommended",
"plugin:jsx-a11y/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"warnOnUnsupportedTypeScriptVersion": false
},
"rules": {
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"arrow-body-style": 0,
"curly": 0,
"eol-last": 0,
"eqeqeq": "error",
"func-style": 0,
"import/no-duplicates": 0,
"max-statements": 0,
"max-params": 0,
"new-cap": 0,
"no-console": 0,
"no-duplicate-imports": 0,
"no-extra-parens": 0,
"no-return-assign": 0,
"no-throw-literal": 0,
"no-trailing-spaces": 0,
"no-unused-expressions": 0,
"no-useless-constructor": 0,
"no-useless-escape": 0,
"no-var": 0,
"prefer-const": "error",
"prefer-rest-params": 0,
"prettier/prettier": "error",
"quote-props": 0,
"unicorn/filename-case": 0,
"jsx-a11y/media-has-caption": 0
}
}

2
.github/CODEOWNERS vendored
View file

@ -1 +1 @@
* @dessalines @SleeplessOne1917 @matc-pub * @dessalines @SleeplessOne1917

View file

@ -4,4 +4,3 @@ src/assets/css/themes/*.css
src/assets/css/code-themes/*.css src/assets/css/code-themes/*.css
stats.json stats.json
dist dist
pnpm-lock.yaml

View file

@ -9,7 +9,7 @@ steps:
- git submodule init - git submodule init
- git submodule update --recursive --remote - git submodule update --recursive --remote
when: when:
- event: [pull_request, tag] - event: pull_request
install: install:
image: node:20-alpine image: node:20-alpine
@ -38,13 +38,10 @@ steps:
publish_release_docker: publish_release_docker:
image: woodpeckerci/plugin-docker-buildx image: woodpeckerci/plugin-docker-buildx
secrets: [docker_username, docker_password]
settings: settings:
repo: dessalines/lemmy-ui repo: dessalines/lemmy-ui
dockerfile: Dockerfile dockerfile: Dockerfile
username:
from_secret: docker_username
password:
from_secret: docker_password
platforms: linux/amd64, linux/arm64 platforms: linux/amd64, linux/arm64
tag: ${CI_COMMIT_TAG} tag: ${CI_COMMIT_TAG}
when: when:
@ -52,13 +49,10 @@ steps:
nightly_build: nightly_build:
image: woodpeckerci/plugin-docker-buildx image: woodpeckerci/plugin-docker-buildx
secrets: [docker_username, docker_password]
settings: settings:
repo: dessalines/lemmy-ui repo: dessalines/lemmy-ui
dockerfile: Dockerfile dockerfile: Dockerfile
username:
from_secret: docker_username
password:
from_secret: docker_password
platforms: linux/amd64, linux/arm64 platforms: linux/amd64, linux/arm64
tag: dev tag: dev
when: when:
@ -70,7 +64,7 @@ steps:
- apk add curl - apk add curl
- "curl -d'Lemmy-UI CI build failed: ${CI_PIPELINE_URL}' ntfy.sh/lemmy_drone_ci" - "curl -d'Lemmy-UI CI build failed: ${CI_PIPELINE_URL}' ntfy.sh/lemmy_drone_ci"
when: when:
- event: [pull_request, tag] - event: pull_request
status: failure status: failure
notify_on_tag_deploy: notify_on_tag_deploy:

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
FROM node:alpine as builder FROM node:21-alpine as builder
# Added vips-dev and pkgconfig so that local vips is used instead of prebuilt # Added vips-dev and pkgconfig so that local vips is used instead of prebuilt
# Done for two reasons: # Done for two reasons:
@ -6,11 +6,8 @@ FROM node:alpine as builder
# - It can break depending on the CPU (https://github.com/LemmyNet/lemmy-ui/issues/1566) # - It can break depending on the CPU (https://github.com/LemmyNet/lemmy-ui/issues/1566)
RUN apk update && apk upgrade && apk add --no-cache curl python3 build-base gcc wget git vips-dev pkgconfig RUN apk update && apk upgrade && apk add --no-cache curl python3 build-base gcc wget git vips-dev pkgconfig
# Enable corepack to use pnpm # Install node-gyp and pnpm
RUN corepack enable RUN npm install -g pnpm node-gyp
# Install node-gyp
RUN npm install -g node-gyp
WORKDIR /usr/src/app WORKDIR /usr/src/app
@ -43,7 +40,7 @@ RUN rm -rf ./node_modules/import-sort-parser-typescript
RUN rm -rf ./node_modules/typescript RUN rm -rf ./node_modules/typescript
RUN rm -rf ./node_modules/npm RUN rm -rf ./node_modules/npm
FROM node:alpine as runner FROM node:21-alpine as runner
ENV NODE_ENV=production ENV NODE_ENV=production
RUN apk update && apk add --no-cache curl vips-cpp && rm -rf /var/cache/apk/* RUN apk update && apk add --no-cache curl vips-cpp && rm -rf /var/cache/apk/*

View file

@ -14,19 +14,18 @@ body = """
{%- if version %} in {{ version }}{%- endif -%} {%- if version %} in {{ version }}{%- endif -%}
{% for commit in commits %} {% for commit in commits %}
{% if commit.remote.pr_title -%} {% if commit.github.pr_title -%}
{%- set commit_message = commit.remote.pr_title -%} {%- set commit_message = commit.github.pr_title -%}
{%- else -%} {%- else -%}
{%- set commit_message = commit.message -%} {%- set commit_message = commit.message -%}
{%- endif -%} {%- endif -%}
* {{ commit_message | split(pat="\n") | first | trim }}\ * {{ commit_message | split(pat="\n") | first | trim }}\
{% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%} {% if commit.github.username %} by @{{ commit.github.username }}{%- endif -%}
{% if commit.remote.pr_number %} in \ {% if commit.github.pr_number %} in \
[#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \ [#{{ commit.github.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.github.pr_number }}) \
{%- endif %} {%- endif %}
{%- endfor -%} {%- endfor -%}
{%- if github -%}
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} {% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
{% raw %}\n{% endraw -%} {% raw %}\n{% endraw -%}
## New Contributors ## New Contributors
@ -37,7 +36,6 @@ body = """
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \ [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
{%- endif %} {%- endif %}
{%- endfor -%} {%- endfor -%}
{%- endif -%}
{% if version %} {% if version %}
{% if previous.version %} {% if previous.version %}
@ -53,7 +51,7 @@ body = """
""" """
# remove the leading and trailing whitespace from the template # remove the leading and trailing whitespace from the template
trim = true trim = true
# template for the changelog footer # changelog footer
footer = """ footer = """
<!-- generated by git-cliff --> <!-- generated by git-cliff -->
""" """
@ -72,12 +70,16 @@ commit_preprocessors = [
# remove issue numbers from commits # remove issue numbers from commits
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" }, { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
] ]
commit_parsers = [ # protect breaking changes from being skipped due to matching a skipping commit_parser
{ field = "author.name", pattern = "renovate", skip = true }, protect_breaking_commits = false
{ field = "message", pattern = "Upping version", skip = true },
]
# filter out the commits that are not matched by commit parsers # filter out the commits that are not matched by commit parsers
filter_commits = false filter_commits = false
# regex for matching git tags
tag_pattern = "v[0-9].*"
# regex for skipping tags
skip_tags = "beta|alpha"
# regex for ignoring tags
ignore_tags = "rc"
# sort the tags topologically # sort the tags topologically
topo_order = false topo_order = false
# sort the commits inside sections by oldest/newest order # sort the commits inside sections by oldest/newest order

View file

@ -1,6 +1,6 @@
FROM node:20-alpine as builder FROM node:20-alpine as builder
RUN apk update && apk add curl python3 build-base gcc wget git --no-cache RUN apk update && apk add curl python3 build-base gcc wget git --no-cache
RUN corepack enable pnpm RUN npm install -g pnpm
WORKDIR /usr/src/app WORKDIR /usr/src/app

View file

@ -1,95 +0,0 @@
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import prettier from "eslint-plugin-prettier/recommended";
import jsxa11y from "eslint-plugin-jsx-a11y";
import inferno from "eslint-plugin-inferno";
export default [
pluginJs.configs.recommended,
...tseslint.configs.recommended,
prettier,
{
plugins: {
inferno: inferno,
rules: inferno.configs.recommended,
},
},
{
plugins: {
"jsx-a11y": jsxa11y,
},
rules: jsxa11y.configs.recommended.rules,
},
{
languageOptions: {
parser: tseslint.parser,
},
},
// For some reason this has to be in its own block
{
ignores: [
"generate_translations.js",
"webpack.config.js",
"src/shared/build-config.js",
"src/api_tests",
"**/*.png",
"**/*.css",
"**/*.scss",
"**/*.svg",
"src/shared/translations/**",
"dist/*",
".yalc/*",
],
},
{
files: ["src/**/*.js", "src/**/*.mjs", "src/**/*.ts", "src/**/*.tsx"],
rules: {
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_" },
],
"explicit-module-boundary-types": 0,
"no-empty-function": 0,
"no-non-null-assertion": 0,
"arrow-body-style": 0,
curly: 0,
"eol-last": 0,
eqeqeq: "error",
"func-style": 0,
"import/no-duplicates": 0,
"max-statements": 0,
"max-params": 0,
"new-cap": 0,
"no-console": 0,
"no-duplicate-imports": 0,
"no-extra-parens": 0,
"no-return-assign": 0,
"no-throw-literal": 0,
"no-trailing-spaces": 0,
"no-unused-expressions": 0,
"no-useless-constructor": 0,
"no-useless-escape": 0,
"no-var": 0,
"prefer-const": "error",
"prefer-rest-params": 0,
"prettier/prettier": "error",
"quote-props": 0,
"unicorn/filename-case": 0,
"jsx-a11y/media-has-caption": 0,
"jsx-a11y/label-has-associated-control": 0,
"no-restricted-imports": [
"error",
{
patterns: [
{
group: ["assets/*", "client/*", "server/*", "shared/*"],
message: "Use relative import instead.",
},
],
},
],
},
},
];

View file

@ -1,6 +0,0 @@
#!/bin/sh
set -e
# Adding to CHANGELOG.md
git cliff --output CHANGELOG.md
prettier -w CHANGELOG.md

@ -1 +1 @@
Subproject commit 2bde7acef9807d28cb13b6584fc63d7b8a457005 Subproject commit b3131d6881adb639dc0e298cc7c213c5245091f6

View file

@ -1,7 +1,7 @@
{ {
"name": "lemmy-ui", "name": "lemmy-ui",
"description": "An isomorphic UI for lemmy", "description": "An isomorphic UI for lemmy",
"version": "0.19.6-beta.7", "version": "0.19.4-beta.1",
"author": "Dessalines <tyhou13@gmx.com>", "author": "Dessalines <tyhou13@gmx.com>",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"scripts": { "scripts": {
@ -9,8 +9,8 @@
"build:dev": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=development", "build:dev": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=development",
"build:prod": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=production", "build:prod": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=production",
"clean": "pnpm rimraf dist", "clean": "pnpm rimraf dist",
"dev": "node generate_translations.js && pnpm build:dev --watch", "dev": "pnpm build:dev --watch",
"lint": "pnpm translations:generate && tsc --noEmit && pnpm eslint --report-unused-disable-directives && pnpm prettier --check \"src/**/*.{ts,tsx,js,mjs,css,scss}\"", "lint": "pnpm translations:generate && tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx \"src/**\" && prettier --check \"src/**/*.{ts,tsx,js,css,scss}\"",
"prebuild:dev": "pnpm clean && node generate_translations.js", "prebuild:dev": "pnpm clean && node generate_translations.js",
"prebuild:prod": "pnpm clean && node generate_translations.js", "prebuild:prod": "pnpm clean && node generate_translations.js",
"prepare": "husky", "prepare": "husky",
@ -25,14 +25,15 @@
"node": ">=8.9.0" "node": ">=8.9.0"
}, },
"dependencies": { "dependencies": {
"@babel/plugin-proposal-decorators": "^7.24.7", "@babel/plugin-proposal-decorators": "^7.24.1",
"@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-class-properties": "^7.24.1",
"@babel/plugin-transform-runtime": "^7.25.4", "@babel/plugin-transform-runtime": "^7.24.3",
"@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-typescript": "^7.24.1",
"@babel/preset-env": "^7.25.4", "@babel/preset-env": "^7.24.3",
"@babel/preset-typescript": "^7.24.7", "@babel/preset-typescript": "^7.24.1",
"@babel/runtime": "^7.25.4", "@babel/runtime": "^7.24.1",
"@emoji-mart/data": "^1.2.1", "@emoji-mart/data": "^1.1.2",
"@shortcm/qr-image": "^9.0.4",
"autosize": "^6.0.1", "autosize": "^6.0.1",
"babel-loader": "^9.1.3", "babel-loader": "^9.1.3",
"babel-plugin-inferno": "^6.7.1", "babel-plugin-inferno": "^6.7.1",
@ -40,18 +41,17 @@
"check-password-strength": "^2.0.10", "check-password-strength": "^2.0.10",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"clean-webpack-plugin": "^4.0.0", "clean-webpack-plugin": "^4.0.0",
"cookie": "^1.0.0", "cookie": "^0.6.0",
"cookie-parser": "^1.4.6",
"copy-webpack-plugin": "^12.0.2", "copy-webpack-plugin": "^12.0.2",
"css-loader": "^7.1.2", "css-loader": "^6.10.0",
"date-fns": "^4.0.0", "date-fns": "^3.6.0",
"emoji-mart": "^5.6.0", "emoji-mart": "^5.5.2",
"emoji-short-name": "^2.0.0", "emoji-short-name": "^2.0.0",
"express": "~4.21.0", "express": "~4.19.2",
"highlight.js": "^11.10.0", "highlight.js": "^11.9.0",
"history": "^5.3.0", "history": "^5.3.0",
"html-to-text": "^9.0.5", "html-to-text": "^9.0.5",
"i18next": "^23.14.0", "i18next": "^23.10.1",
"inferno": "^8.2.3", "inferno": "^8.2.3",
"inferno-create-element": "^8.2.3", "inferno-create-element": "^8.2.3",
"inferno-helmet": "^5.2.1", "inferno-helmet": "^5.2.1",
@ -60,78 +60,72 @@
"inferno-router": "^8.2.3", "inferno-router": "^8.2.3",
"inferno-server": "^8.2.3", "inferno-server": "^8.2.3",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"lemmy-js-client": "0.20.0-alpha.17", "lemmy-js-client": "0.19.4-alpha.14",
"lodash.isequal": "^4.5.0", "lodash.isequal": "^4.5.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"markdown-it-bidi": "^0.2.0", "markdown-it-bidi": "^0.1.0",
"markdown-it-container": "^4.0.0", "markdown-it-container": "^4.0.0",
"markdown-it-emoji": "^3.0.0", "markdown-it-emoji": "^3.0.0",
"markdown-it-footnote": "^4.0.0", "markdown-it-footnote": "^4.0.0",
"markdown-it-highlightjs": "^4.1.0", "markdown-it-highlightjs": "^4.0.1",
"markdown-it-html5-embed": "^1.0.0", "markdown-it-html5-embed": "^1.0.0",
"markdown-it-ruby": "^1.0.0", "markdown-it-ruby": "^0.1.1",
"markdown-it-sub": "^2.0.0", "markdown-it-sub": "^2.0.0",
"markdown-it-sup": "^2.0.0", "markdown-it-sup": "^2.0.0",
"mini-css-extract-plugin": "^2.9.1", "mini-css-extract-plugin": "^2.8.1",
"qreator": "^9.3.0",
"register-service-worker": "^1.7.2", "register-service-worker": "^1.7.2",
"run-node-webpack-plugin": "^1.3.0", "run-node-webpack-plugin": "^1.3.0",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"sanitize-html": "^2.13.0", "sanitize-html": "^2.13.0",
"sass": "^1.77.8", "sass": "^1.72.0",
"sass-loader": "^16.0.1", "sass-loader": "^14.1.1",
"serialize-javascript": "^6.0.2", "serialize-javascript": "^6.0.2",
"service-worker-webpack": "^1.0.0", "service-worker-webpack": "^1.0.0",
"sharp": "0.33.5", "sharp": "0.33.3",
"tippy.js": "^6.3.7", "tippy.js": "^6.3.7",
"toastify-js": "^1.12.0", "toastify-js": "^1.12.0",
"tributejs": "^5.1.3", "tributejs": "^5.1.3",
"webpack": "^5.94.0", "webpack": "^5.91.0",
"webpack-cli": "^5.1.4", "webpack-cli": "^5.1.4",
"webpack-node-externals": "^3.0.0" "webpack-node-externals": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.25.2", "@babel/core": "^7.24.3",
"@eslint/js": "^9.9.1",
"@types/autosize": "^4.0.3", "@types/autosize": "^4.0.3",
"@types/bootstrap": "^5.2.10", "@types/bootstrap": "^5.2.10",
"@types/cookie": "^0.6.0", "@types/cookie": "^0.6.0",
"@types/cookie-parser": "^1.4.7",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"@types/html-to-text": "^9.0.4", "@types/html-to-text": "^9.0.4",
"@types/lodash.isequal": "^4.5.8", "@types/lodash.isequal": "^4.5.8",
"@types/markdown-it": "^14.1.2", "@types/markdown-it": "^13.0.7",
"@types/markdown-it-container": "^2.0.10", "@types/markdown-it-container": "^2.0.9",
"@types/node": "^22.5.0", "@types/node": "^20.11.30",
"@types/path-browserify": "^1.0.3", "@types/path-browserify": "^1.0.2",
"@types/sanitize-html": "^2.13.0", "@types/sanitize-html": "^2.11.0",
"@types/serialize-javascript": "^5.0.4", "@types/serialize-javascript": "^5.0.4",
"@types/toastify-js": "^1.12.3", "@types/toastify-js": "^1.12.3",
"@typescript-eslint/eslint-plugin": "^8.3.0", "@typescript-eslint/eslint-plugin": "^7.4.0",
"@typescript-eslint/parser": "^8.3.0", "@typescript-eslint/parser": "^7.4.0",
"eslint": "^9.9.1", "eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0", "eslint-plugin-inferno": "^7.33.3",
"eslint-plugin-inferno": "^7.34.0", "eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-prettier": "^5.2.1", "husky": "^9.0.11",
"globals": "^15.9.0",
"husky": "^9.1.5",
"import-sort-style-module": "^6.0.0", "import-sort-style-module": "^6.0.0",
"lint-staged": "^15.2.9", "lint-staged": "^15.2.2",
"prettier": "^3.3.3", "prettier": "^3.2.5",
"prettier-plugin-import-sort": "^0.0.7", "prettier-plugin-import-sort": "^0.0.7",
"prettier-plugin-organize-imports": "^4.0.0", "prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-packagejson": "^2.5.2", "prettier-plugin-packagejson": "^2.4.12",
"qs": "^6.13.0", "qs": "^6.12.0",
"rimraf": "^6.0.1", "rimraf": "^5.0.5",
"sortpack": "^2.4.0", "sortpack": "^2.4.0",
"style-loader": "^4.0.0", "style-loader": "^3.3.4",
"terser": "^5.31.6", "terser": "^5.29.2",
"typescript": "^5.5.4", "typescript": "^5.4.3",
"typescript-eslint": "^8.3.0",
"typescript-language-server": "^4.3.3", "typescript-language-server": "^4.3.3",
"webpack-bundle-analyzer": "^4.10.2", "webpack-bundle-analyzer": "^4.10.1",
"webpack-dev-server": "5.1.0" "webpack-dev-server": "5.0.4"
}, },
"lint-staged": { "lint-staged": {
"*.{css, scss}": [ "*.{css, scss}": [
@ -145,7 +139,7 @@
"sortpack" "sortpack"
] ]
}, },
"packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee", "packageManager": "pnpm@8.14.3",
"engineStrict": true, "engineStrict": true,
"importSort": { "importSort": {
".js, .jsx, .ts, .tsx": { ".js, .jsx, .ts, .tsx": {

File diff suppressed because it is too large Load diff

View file

@ -1,7 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"schedule": ["every weekend"],
"automerge": true,
"ignoreDeps": ["lemmy-js-client"]
}

View file

@ -189,18 +189,12 @@ blockquote {
margin-top: -4px; margin-top: -4px;
} }
/* comments */
.new-comments { .new-comments {
max-height: 50vh; max-height: 50vh;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
} }
.comment-content ul,
.comment-content ol {
margin-bottom: 1rem;
}
.comments { .comments {
list-style: none; list-style: none;
padding: 0; padding: 0;
@ -461,15 +455,3 @@ br.big {
.totp-link { .totp-link {
width: fit-content; width: fit-content;
} }
.oauth-item details[open] .oauth-item-caret {
transform: rotate(90deg);
}
.default-oauth-providers-section > ul {
list-style: none;
}
em-emoji-picker {
width: 100%;
}

View file

@ -40,8 +40,8 @@ hr.my-3 {
} }
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -85,28 +85,28 @@ hr.my-3 {
--bs-danger-rgb: 231, 76, 60; --bs-danger-rgb: 231, 76, 60;
--bs-light-rgb: 48, 48, 48; --bs-light-rgb: 48, 48, 48;
--bs-dark-rgb: 222, 226, 230; --bs-dark-rgb: 222, 226, 230;
--bs-primary-text-emphasis: rgb(0, 75.2, 56); --bs-primary-text-emphasis: #004b38;
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6); --bs-secondary-text-emphasis: #45484c;
--bs-success-text-emphasis: rgb(0, 75.2, 56); --bs-success-text-emphasis: #004b38;
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6); --bs-info-text-emphasis: #153d58;
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2); --bs-warning-text-emphasis: #613e07;
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24); --bs-danger-text-emphasis: #5c1e18;
--bs-light-text-emphasis: #444; --bs-light-text-emphasis: #444;
--bs-dark-text-emphasis: #444; --bs-dark-text-emphasis: #444;
--bs-primary-bg-subtle: rgb(204, 241.6, 232); --bs-primary-bg-subtle: #ccf2e8;
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8); --bs-secondary-bg-subtle: #eff0f2;
--bs-success-bg-subtle: rgb(204, 241.6, 232); --bs-success-bg-subtle: #ccf2e8;
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8); --bs-info-bg-subtle: #d6eaf8;
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6); --bs-warning-bg-subtle: #fdebd0;
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216); --bs-danger-bg-subtle: #fadbd8;
--bs-light-bg-subtle: rgb(251.5, 252, 252.5); --bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(153, 228.2, 209); --bs-primary-border-subtle: #99e4d1;
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6); --bs-secondary-border-subtle: #dee1e5;
--bs-success-border-subtle: rgb(153, 228.2, 209); --bs-success-border-subtle: #99e4d1;
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6); --bs-info-border-subtle: #aed6f1;
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2); --bs-warning-border-subtle: #fad7a0;
--bs-danger-border-subtle: rgb(245.4, 183.4, 177); --bs-danger-border-subtle: #f5b7b1;
--bs-light-border-subtle: #ebebeb; --bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255; --bs-white-rgb: 255, 255, 255;
@ -137,7 +137,7 @@ hr.my-3 {
--bs-link-color: #00bc8c; --bs-link-color: #00bc8c;
--bs-link-color-rgb: 0, 188, 140; --bs-link-color-rgb: 0, 188, 140;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(0, 150.4, 112); --bs-link-hover-color: #009670;
--bs-link-hover-color-rgb: 0, 150, 112; --bs-link-hover-color-rgb: 0, 150, 112;
--bs-code-color: #d63384; --bs-code-color: #d63384;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
@ -182,44 +182,44 @@ hr.my-3 {
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #292929; --bs-tertiary-bg: #292929;
--bs-tertiary-bg-rgb: 41, 41, 41; --bs-tertiary-bg-rgb: 41, 41, 41;
--bs-primary-text-emphasis: rgb(102, 214.8, 186); --bs-primary-text-emphasis: #66d7ba;
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4); --bs-secondary-text-emphasis: #ced3d7;
--bs-success-text-emphasis: rgb(102, 214.8, 186); --bs-success-text-emphasis: #66d7ba;
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4); --bs-info-text-emphasis: #85c1e9;
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8); --bs-warning-text-emphasis: #f8c471;
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138); --bs-danger-text-emphasis: #f1948a;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(0, 37.6, 28); --bs-primary-bg-subtle: #00261c;
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8); --bs-secondary-bg-subtle: #232426;
--bs-success-bg-subtle: rgb(0, 37.6, 28); --bs-success-bg-subtle: #00261c;
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8); --bs-info-bg-subtle: #0a1e2c;
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6); --bs-warning-bg-subtle: #311f04;
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12); --bs-danger-bg-subtle: #2e0f0c;
--bs-light-bg-subtle: #303030; --bs-light-bg-subtle: #303030;
--bs-dark-bg-subtle: #181818; --bs-dark-bg-subtle: #181818;
--bs-primary-border-subtle: rgb(0, 112.8, 84); --bs-primary-border-subtle: #007154;
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4); --bs-secondary-border-subtle: #686d71;
--bs-success-border-subtle: rgb(0, 112.8, 84); --bs-success-border-subtle: #007154;
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4); --bs-info-border-subtle: #1f5b83;
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8); --bs-warning-border-subtle: #925e0b;
--bs-danger-border-subtle: rgb(138.6, 45.6, 36); --bs-danger-border-subtle: #8b2e24;
--bs-light-border-subtle: #444; --bs-light-border-subtle: #444;
--bs-dark-border-subtle: #303030; --bs-dark-border-subtle: #303030;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(102, 214.8, 186); --bs-link-color: #66d7ba;
--bs-link-hover-color: rgb(132.6, 222.84, 199.8); --bs-link-hover-color: #85dfc8;
--bs-link-color-rgb: 102, 215, 186; --bs-link-color-rgb: 102, 215, 186;
--bs-link-hover-color-rgb: 133, 223, 200; --bs-link-hover-color-rgb: 133, 223, 200;
--bs-code-color: rgb(230.4, 132.6, 181.2); --bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: #333; --bs-highlight-bg: #333;
--bs-border-color: #444; --bs-border-color: #444;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15); --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: rgb(102, 214.8, 186); --bs-form-valid-color: #66d7ba;
--bs-form-valid-border-color: rgb(102, 214.8, 186); --bs-form-valid-border-color: #66d7ba;
--bs-form-invalid-color: rgb(240.6, 147.6, 138); --bs-form-invalid-color: #f1948a;
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138); --bs-form-invalid-border-color: #f1948a;
} }
*, *,
@ -1951,13 +1951,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204, 241.6, 232); --bs-table-bg: #ccf2e8;
--bs-table-border-color: rgb(163.2, 193.28, 185.6); --bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4); --bs-table-striped-bg: #c2e6dc;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.6, 217.44, 208.8); --bs-table-active-bg: #b8dad1;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6); --bs-table-hover-bg: #bde0d7;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1965,13 +1965,13 @@ progress {
.table-secondary { .table-secondary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(238.6, 240.2, 241.8); --bs-table-bg: #eff0f2;
--bs-table-border-color: rgb(190.88, 192.16, 193.44); --bs-table-border-color: #bfc0c2;
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71); --bs-table-striped-bg: #e3e4e6;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(214.74, 216.18, 217.62); --bs-table-active-bg: #d7d8da;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665); --bs-table-hover-bg: #dddee0;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1979,13 +1979,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204, 241.6, 232); --bs-table-bg: #ccf2e8;
--bs-table-border-color: rgb(163.2, 193.28, 185.6); --bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4); --bs-table-striped-bg: #c2e6dc;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.6, 217.44, 208.8); --bs-table-active-bg: #b8dad1;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6); --bs-table-hover-bg: #bde0d7;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1993,13 +1993,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(214.4, 234.4, 247.8); --bs-table-bg: #d6eaf8;
--bs-table-border-color: rgb(171.52, 187.52, 198.24); --bs-table-border-color: #abbbc6;
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41); --bs-table-striped-bg: #cbdeec;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(192.96, 210.96, 223.02); --bs-table-active-bg: #c1d3df;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215); --bs-table-hover-bg: #c6d8e5;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2007,13 +2007,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(252.6, 235.2, 207.6); --bs-table-bg: #fdebd0;
--bs-table-border-color: rgb(202.08, 188.16, 166.08); --bs-table-border-color: #cabca6;
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22); --bs-table-striped-bg: #f0dfc6;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(227.34, 211.68, 186.84); --bs-table-active-bg: #e4d4bb;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03); --bs-table-hover-bg: #ead9c0;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2021,13 +2021,13 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(250.2, 219.2, 216); --bs-table-bg: #fadbd8;
--bs-table-border-color: rgb(200.16, 175.36, 172.8); --bs-table-border-color: #c8afad;
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2); --bs-table-striped-bg: #eed0cd;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(225.18, 197.28, 194.4); --bs-table-active-bg: #e1c5c2;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8); --bs-table-hover-bg: #e7cbc8;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2036,12 +2036,12 @@ progress {
.table-light { .table-light {
--bs-table-color: #fff; --bs-table-color: #fff;
--bs-table-bg: #303030; --bs-table-bg: #303030;
--bs-table-border-color: rgb(89.4, 89.4, 89.4); --bs-table-border-color: #595959;
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35); --bs-table-striped-bg: #3a3a3a;
--bs-table-striped-color: #fff; --bs-table-striped-color: #fff;
--bs-table-active-bg: rgb(68.7, 68.7, 68.7); --bs-table-active-bg: #454545;
--bs-table-active-color: #fff; --bs-table-active-color: #fff;
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525); --bs-table-hover-bg: #404040;
--bs-table-hover-color: #fff; --bs-table-hover-color: #fff;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2050,12 +2050,12 @@ progress {
.table-dark { .table-dark {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: #dee2e6; --bs-table-bg: #dee2e6;
--bs-table-border-color: rgb(177.6, 180.8, 184); --bs-table-border-color: #b2b5b8;
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5); --bs-table-striped-bg: #d3d7db;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(199.8, 203.4, 207); --bs-table-active-bg: #c8cbcf;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75); --bs-table-hover-bg: #cdd1d5;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2155,7 +2155,7 @@ progress {
.form-control:focus { .form-control:focus {
color: #fff; color: #fff;
background-color: #444; background-color: #444;
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2173,7 +2173,7 @@ progress {
opacity: 1; opacity: 1;
} }
.form-control:disabled { .form-control:disabled {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
opacity: 1; opacity: 1;
} }
.form-control::file-selector-button { .form-control::file-selector-button {
@ -2300,7 +2300,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2309,7 +2309,7 @@ textarea.form-control-lg {
background-image: none; background-image: none;
} }
.form-select:disabled { .form-select:disabled {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
} }
.form-select:-moz-focusring { .form-select:-moz-focusring {
color: transparent; color: transparent;
@ -2384,7 +2384,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2431,7 +2431,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28127.5, 221.5, 197.5%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2380dec6'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2501,7 +2501,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(178.5, 234.9, 220.5); background-color: #b3ebdd;
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
width: 100%; width: 100%;
@ -2527,7 +2527,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(178.5, 234.9, 220.5); background-color: #b3ebdd;
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
width: 100%; width: 100%;
@ -2634,7 +2634,7 @@ textarea.form-control-lg {
} }
.form-floating > :disabled ~ label::after, .form-floating > :disabled ~ label::after,
.form-floating > .form-control:disabled ~ label::after { .form-floating > .form-control:disabled ~ label::after {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
} }
.input-group { .input-group {
@ -2975,9 +2975,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2991,12 +2988,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c; --bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c; --bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25); --bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-hover-border-color: #1ac398;
--bs-btn-focus-shadow-rgb: 0, 160, 119; --bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51, 201.4, 163); --bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-active-border-color: #1ac398;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c; --bs-btn-disabled-bg: #00bc8c;
@ -3008,12 +3005,12 @@ textarea.form-control-lg {
--bs-btn-bg: #adb5bd; --bs-btn-bg: #adb5bd;
--bs-btn-border-color: #adb5bd; --bs-btn-border-color: #adb5bd;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9); --bs-btn-hover-bg: #b9c0c7;
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6); --bs-btn-hover-border-color: #b5bcc4;
--bs-btn-focus-shadow-rgb: 147, 154, 161; --bs-btn-focus-shadow-rgb: 147, 154, 161;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2); --bs-btn-active-bg: #bdc4ca;
--bs-btn-active-border-color: rgb(181.2, 188.4, 195.6); --bs-btn-active-border-color: #b5bcc4;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #adb5bd; --bs-btn-disabled-bg: #adb5bd;
@ -3025,12 +3022,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c; --bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c; --bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25); --bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-hover-border-color: #1ac398;
--bs-btn-focus-shadow-rgb: 0, 160, 119; --bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51, 201.4, 163); --bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-active-border-color: #1ac398;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c; --bs-btn-disabled-bg: #00bc8c;
@ -3042,12 +3039,12 @@ textarea.form-control-lg {
--bs-btn-bg: #3498db; --bs-btn-bg: #3498db;
--bs-btn-border-color: #3498db; --bs-btn-border-color: #3498db;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15); --bs-btn-hover-bg: #2c81ba;
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2); --bs-btn-hover-border-color: #2a7aaf;
--bs-btn-focus-shadow-rgb: 82, 167, 224; --bs-btn-focus-shadow-rgb: 82, 167, 224;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2); --bs-btn-active-bg: #2a7aaf;
--bs-btn-active-border-color: rgb(39, 114, 164.25); --bs-btn-active-border-color: #2772a4;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #3498db; --bs-btn-disabled-bg: #3498db;
@ -3059,12 +3056,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f39c12; --bs-btn-bg: #f39c12;
--bs-btn-border-color: #f39c12; --bs-btn-border-color: #f39c12;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55); --bs-btn-hover-bg: #f5ab36;
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7); --bs-btn-hover-border-color: #f4a62a;
--bs-btn-focus-shadow-rgb: 207, 133, 15; --bs-btn-focus-shadow-rgb: 207, 133, 15;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4); --bs-btn-active-bg: #f5b041;
--bs-btn-active-border-color: rgb(244.2, 165.9, 41.7); --bs-btn-active-border-color: #f4a62a;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #f39c12; --bs-btn-disabled-bg: #f39c12;
@ -3076,12 +3073,12 @@ textarea.form-control-lg {
--bs-btn-bg: #e74c3c; --bs-btn-bg: #e74c3c;
--bs-btn-border-color: #e74c3c; --bs-btn-border-color: #e74c3c;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(196.35, 64.6, 51); --bs-btn-hover-bg: #c44133;
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48); --bs-btn-hover-border-color: #b93d30;
--bs-btn-focus-shadow-rgb: 235, 103, 89; --bs-btn-focus-shadow-rgb: 235, 103, 89;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(184.8, 60.8, 48); --bs-btn-active-bg: #b93d30;
--bs-btn-active-border-color: rgb(173.25, 57, 45); --bs-btn-active-border-color: #ad392d;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #e74c3c; --bs-btn-disabled-bg: #e74c3c;
@ -3093,11 +3090,11 @@ textarea.form-control-lg {
--bs-btn-bg: #303030; --bs-btn-bg: #303030;
--bs-btn-border-color: #303030; --bs-btn-border-color: #303030;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8); --bs-btn-hover-bg: #292929;
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4); --bs-btn-hover-border-color: #262626;
--bs-btn-focus-shadow-rgb: 79, 79, 79; --bs-btn-focus-shadow-rgb: 79, 79, 79;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(38.4, 38.4, 38.4); --bs-btn-active-bg: #262626;
--bs-btn-active-border-color: #242424; --bs-btn-active-border-color: #242424;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
@ -3110,12 +3107,12 @@ textarea.form-control-lg {
--bs-btn-bg: #dee2e6; --bs-btn-bg: #dee2e6;
--bs-btn-border-color: #dee2e6; --bs-btn-border-color: #dee2e6;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75); --bs-btn-hover-bg: #e3e6ea;
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5); --bs-btn-hover-border-color: #e1e5e9;
--bs-btn-focus-shadow-rgb: 189, 192, 196; --bs-btn-focus-shadow-rgb: 189, 192, 196;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(228.6, 231.8, 235); --bs-btn-active-bg: #e5e8eb;
--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5); --bs-btn-active-border-color: #e1e5e9;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #dee2e6; --bs-btn-disabled-bg: #dee2e6;
@ -4502,11 +4499,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23dee2e6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%280, 75.2, 56%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23004b38'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #80dec6;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4564,6 +4562,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4581,7 +4580,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4592,11 +4591,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4605,27 +4604,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -4670,16 +4669,16 @@ textarea.form-control-lg {
--bs-pagination-border-color: transparent; --bs-pagination-border-color: transparent;
--bs-pagination-border-radius: var(--bs-border-radius); --bs-pagination-border-radius: var(--bs-border-radius);
--bs-pagination-hover-color: #fff; --bs-pagination-hover-color: #fff;
--bs-pagination-hover-bg: rgb(0, 239, 177.9787234043); --bs-pagination-hover-bg: #00efb2;
--bs-pagination-hover-border-color: transparent; --bs-pagination-hover-border-color: transparent;
--bs-pagination-focus-color: var(--bs-link-hover-color); --bs-pagination-focus-color: var(--bs-link-hover-color);
--bs-pagination-focus-bg: var(--bs-secondary-bg); --bs-pagination-focus-bg: var(--bs-secondary-bg);
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-pagination-active-color: #fff; --bs-pagination-active-color: #fff;
--bs-pagination-active-bg: rgb(0, 239, 177.9787234043); --bs-pagination-active-bg: #00efb2;
--bs-pagination-active-border-color: transparent; --bs-pagination-active-border-color: transparent;
--bs-pagination-disabled-color: #fff; --bs-pagination-disabled-color: #fff;
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936); --bs-pagination-disabled-bg: #007053;
--bs-pagination-disabled-border-color: transparent; --bs-pagination-disabled-border-color: transparent;
display: flex; display: flex;
padding-left: 0; padding-left: 0;
@ -5499,6 +5498,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6063,12 +6063,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6688,11 +6696,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {

View file

@ -1,7 +1,7 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -45,28 +45,28 @@
--bs-danger-rgb: 231, 76, 60; --bs-danger-rgb: 231, 76, 60;
--bs-light-rgb: 17, 17, 17; --bs-light-rgb: 17, 17, 17;
--bs-dark-rgb: 222, 226, 230; --bs-dark-rgb: 222, 226, 230;
--bs-primary-text-emphasis: rgb(0, 75.2, 56); --bs-primary-text-emphasis: #004b38;
--bs-secondary-text-emphasis: rgb(40.8, 40.8, 40.8); --bs-secondary-text-emphasis: #292929;
--bs-success-text-emphasis: rgb(0, 75.2, 56); --bs-success-text-emphasis: #004b38;
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6); --bs-info-text-emphasis: #153d58;
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2); --bs-warning-text-emphasis: #613e07;
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24); --bs-danger-text-emphasis: #5c1e18;
--bs-light-text-emphasis: #333; --bs-light-text-emphasis: #333;
--bs-dark-text-emphasis: #333; --bs-dark-text-emphasis: #333;
--bs-primary-bg-subtle: rgb(204, 241.6, 232); --bs-primary-bg-subtle: #ccf2e8;
--bs-secondary-bg-subtle: rgb(224.4, 224.4, 224.4); --bs-secondary-bg-subtle: #e0e0e0;
--bs-success-bg-subtle: rgb(204, 241.6, 232); --bs-success-bg-subtle: #ccf2e8;
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8); --bs-info-bg-subtle: #d6eaf8;
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6); --bs-warning-bg-subtle: #fdebd0;
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216); --bs-danger-bg-subtle: #fadbd8;
--bs-light-bg-subtle: rgb(245.5, 246, 246.5); --bs-light-bg-subtle: #f6f6f7;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(153, 228.2, 209); --bs-primary-border-subtle: #99e4d1;
--bs-secondary-border-subtle: rgb(193.8, 193.8, 193.8); --bs-secondary-border-subtle: #c2c2c2;
--bs-success-border-subtle: rgb(153, 228.2, 209); --bs-success-border-subtle: #99e4d1;
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6); --bs-info-border-subtle: #aed6f1;
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2); --bs-warning-border-subtle: #fad7a0;
--bs-danger-border-subtle: rgb(245.4, 183.4, 177); --bs-danger-border-subtle: #f5b7b1;
--bs-light-border-subtle: #ebebeb; --bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 243, 243, 243; --bs-white-rgb: 243, 243, 243;
@ -97,7 +97,7 @@
--bs-link-color: #00bc8c; --bs-link-color: #00bc8c;
--bs-link-color-rgb: 0, 188, 140; --bs-link-color-rgb: 0, 188, 140;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(0, 150.4, 112); --bs-link-hover-color: #009670;
--bs-link-hover-color-rgb: 0, 150, 112; --bs-link-hover-color-rgb: 0, 150, 112;
--bs-code-color: #d63384; --bs-code-color: #d63384;
--bs-highlight-color: #ebebeb; --bs-highlight-color: #ebebeb;
@ -140,46 +140,46 @@
--bs-secondary-bg-rgb: 32, 32, 32; --bs-secondary-bg-rgb: 32, 32, 32;
--bs-tertiary-color: rgba(222, 226, 230, 0.5); --bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: rgb(24.5, 24.5, 24.5); --bs-tertiary-bg: #191919;
--bs-tertiary-bg-rgb: 25, 25, 25; --bs-tertiary-bg-rgb: 25, 25, 25;
--bs-primary-text-emphasis: rgb(102, 214.8, 186); --bs-primary-text-emphasis: #66d7ba;
--bs-secondary-text-emphasis: rgb(163.2, 163.2, 163.2); --bs-secondary-text-emphasis: #a3a3a3;
--bs-success-text-emphasis: rgb(102, 214.8, 186); --bs-success-text-emphasis: #66d7ba;
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4); --bs-info-text-emphasis: #85c1e9;
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8); --bs-warning-text-emphasis: #f8c471;
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138); --bs-danger-text-emphasis: #f1948a;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(0, 37.6, 28); --bs-primary-bg-subtle: #00261c;
--bs-secondary-bg-subtle: rgb(20.4, 20.4, 20.4); --bs-secondary-bg-subtle: #141414;
--bs-success-bg-subtle: rgb(0, 37.6, 28); --bs-success-bg-subtle: #00261c;
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8); --bs-info-bg-subtle: #0a1e2c;
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6); --bs-warning-bg-subtle: #311f04;
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12); --bs-danger-bg-subtle: #2e0f0c;
--bs-light-bg-subtle: #202020; --bs-light-bg-subtle: #202020;
--bs-dark-bg-subtle: #101010; --bs-dark-bg-subtle: #101010;
--bs-primary-border-subtle: rgb(0, 112.8, 84); --bs-primary-border-subtle: #007154;
--bs-secondary-border-subtle: rgb(61.2, 61.2, 61.2); --bs-secondary-border-subtle: #3d3d3d;
--bs-success-border-subtle: rgb(0, 112.8, 84); --bs-success-border-subtle: #007154;
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4); --bs-info-border-subtle: #1f5b83;
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8); --bs-warning-border-subtle: #925e0b;
--bs-danger-border-subtle: rgb(138.6, 45.6, 36); --bs-danger-border-subtle: #8b2e24;
--bs-light-border-subtle: #333; --bs-light-border-subtle: #333;
--bs-dark-border-subtle: #202020; --bs-dark-border-subtle: #202020;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(102, 214.8, 186); --bs-link-color: #66d7ba;
--bs-link-hover-color: rgb(132.6, 222.84, 199.8); --bs-link-hover-color: #85dfc8;
--bs-link-color-rgb: 102, 215, 186; --bs-link-color-rgb: 102, 215, 186;
--bs-link-hover-color-rgb: 133, 223, 200; --bs-link-hover-color-rgb: 133, 223, 200;
--bs-code-color: rgb(230.4, 132.6, 181.2); --bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: #111; --bs-highlight-bg: #111;
--bs-border-color: #333; --bs-border-color: #333;
--bs-border-color-translucent: rgba(243, 243, 243, 0.15); --bs-border-color-translucent: rgba(243, 243, 243, 0.15);
--bs-form-valid-color: rgb(102, 214.8, 186); --bs-form-valid-color: #66d7ba;
--bs-form-valid-border-color: rgb(102, 214.8, 186); --bs-form-valid-border-color: #66d7ba;
--bs-form-invalid-color: rgb(240.6, 147.6, 138); --bs-form-invalid-color: #f1948a;
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138); --bs-form-invalid-border-color: #f1948a;
} }
*, *,
@ -1935,13 +1935,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204, 241.6, 232); --bs-table-bg: #ccf2e8;
--bs-table-border-color: rgb(163.2, 193.28, 185.6); --bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4); --bs-table-striped-bg: #c2e6dc;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.6, 217.44, 208.8); --bs-table-active-bg: #b8dad1;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6); --bs-table-hover-bg: #bde0d7;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1949,13 +1949,13 @@ progress {
.table-secondary { .table-secondary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(224.4, 224.4, 224.4); --bs-table-bg: #e0e0e0;
--bs-table-border-color: rgb(179.52, 179.52, 179.52); --bs-table-border-color: #b3b3b3;
--bs-table-striped-bg: rgb(213.18, 213.18, 213.18); --bs-table-striped-bg: #d5d5d5;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(201.96, 201.96, 201.96); --bs-table-active-bg: #cacaca;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(207.57, 207.57, 207.57); --bs-table-hover-bg: #cfcfcf;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1963,13 +1963,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204, 241.6, 232); --bs-table-bg: #ccf2e8;
--bs-table-border-color: rgb(163.2, 193.28, 185.6); --bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4); --bs-table-striped-bg: #c2e6dc;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.6, 217.44, 208.8); --bs-table-active-bg: #b8dad1;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6); --bs-table-hover-bg: #bde0d7;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1977,13 +1977,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(214.4, 234.4, 247.8); --bs-table-bg: #d6eaf8;
--bs-table-border-color: rgb(171.52, 187.52, 198.24); --bs-table-border-color: #abbbc6;
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41); --bs-table-striped-bg: #cbdeec;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(192.96, 210.96, 223.02); --bs-table-active-bg: #c1d3df;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215); --bs-table-hover-bg: #c6d8e5;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1991,13 +1991,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(252.6, 235.2, 207.6); --bs-table-bg: #fdebd0;
--bs-table-border-color: rgb(202.08, 188.16, 166.08); --bs-table-border-color: #cabca6;
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22); --bs-table-striped-bg: #f0dfc6;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(227.34, 211.68, 186.84); --bs-table-active-bg: #e4d4bb;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03); --bs-table-hover-bg: #ead9c0;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2005,13 +2005,13 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(250.2, 219.2, 216); --bs-table-bg: #fadbd8;
--bs-table-border-color: rgb(200.16, 175.36, 172.8); --bs-table-border-color: #c8afad;
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2); --bs-table-striped-bg: #eed0cd;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(225.18, 197.28, 194.4); --bs-table-active-bg: #e1c5c2;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8); --bs-table-hover-bg: #e7cbc8;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2020,12 +2020,12 @@ progress {
.table-light { .table-light {
--bs-table-color: #f3f3f3; --bs-table-color: #f3f3f3;
--bs-table-bg: #111; --bs-table-bg: #111;
--bs-table-border-color: rgb(62.2, 62.2, 62.2); --bs-table-border-color: #3e3e3e;
--bs-table-striped-bg: rgb(28.3, 28.3, 28.3); --bs-table-striped-bg: #1c1c1c;
--bs-table-striped-color: #f3f3f3; --bs-table-striped-color: #f3f3f3;
--bs-table-active-bg: rgb(39.6, 39.6, 39.6); --bs-table-active-bg: #282828;
--bs-table-active-color: #f3f3f3; --bs-table-active-color: #f3f3f3;
--bs-table-hover-bg: rgb(33.95, 33.95, 33.95); --bs-table-hover-bg: #222222;
--bs-table-hover-color: #f3f3f3; --bs-table-hover-color: #f3f3f3;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2034,12 +2034,12 @@ progress {
.table-dark { .table-dark {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: #dee2e6; --bs-table-bg: #dee2e6;
--bs-table-border-color: rgb(177.6, 180.8, 184); --bs-table-border-color: #b2b5b8;
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5); --bs-table-striped-bg: #d3d7db;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(199.8, 203.4, 207); --bs-table-active-bg: #c8cbcf;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75); --bs-table-hover-bg: #cdd1d5;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2139,7 +2139,7 @@ progress {
.form-control:focus { .form-control:focus {
color: #f3f3f3; color: #f3f3f3;
background-color: #111; background-color: #111;
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2415,7 +2415,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28127.5, 221.5, 197.5%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2380dec6'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(178.5, 234.9, 220.5); background-color: #b3ebdd;
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
width: 100%; width: 100%;
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(178.5, 234.9, 220.5); background-color: #b3ebdd;
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
width: 100%; width: 100%;
@ -2959,9 +2959,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2975,12 +2972,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c; --bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c; --bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25); --bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-hover-border-color: #1ac398;
--bs-btn-focus-shadow-rgb: 0, 160, 119; --bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51, 201.4, 163); --bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-active-border-color: #1ac398;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c; --bs-btn-disabled-bg: #00bc8c;
@ -2992,12 +2989,12 @@ textarea.form-control-lg {
--bs-btn-bg: #666; --bs-btn-bg: #666;
--bs-btn-border-color: #666; --bs-btn-border-color: #666;
--bs-btn-hover-color: #f3f3f3; --bs-btn-hover-color: #f3f3f3;
--bs-btn-hover-bg: rgb(86.7, 86.7, 86.7); --bs-btn-hover-bg: #575757;
--bs-btn-hover-border-color: rgb(81.6, 81.6, 81.6); --bs-btn-hover-border-color: #525252;
--bs-btn-focus-shadow-rgb: 123, 123, 123; --bs-btn-focus-shadow-rgb: 123, 123, 123;
--bs-btn-active-color: #f3f3f3; --bs-btn-active-color: #f3f3f3;
--bs-btn-active-bg: rgb(81.6, 81.6, 81.6); --bs-btn-active-bg: #525252;
--bs-btn-active-border-color: rgb(76.5, 76.5, 76.5); --bs-btn-active-border-color: #4d4d4d;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #f3f3f3; --bs-btn-disabled-color: #f3f3f3;
--bs-btn-disabled-bg: #666; --bs-btn-disabled-bg: #666;
@ -3009,12 +3006,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c; --bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c; --bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25); --bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-hover-border-color: #1ac398;
--bs-btn-focus-shadow-rgb: 0, 160, 119; --bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51, 201.4, 163); --bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-active-border-color: #1ac398;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c; --bs-btn-disabled-bg: #00bc8c;
@ -3026,12 +3023,12 @@ textarea.form-control-lg {
--bs-btn-bg: #3498db; --bs-btn-bg: #3498db;
--bs-btn-border-color: #3498db; --bs-btn-border-color: #3498db;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(82.45, 167.45, 224.4); --bs-btn-hover-bg: #52a7e0;
--bs-btn-hover-border-color: rgb(72.3, 162.3, 222.6); --bs-btn-hover-border-color: #48a2df;
--bs-btn-focus-shadow-rgb: 44, 129, 186; --bs-btn-focus-shadow-rgb: 44, 129, 186;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(92.6, 172.6, 226.2); --bs-btn-active-bg: #5dade2;
--bs-btn-active-border-color: rgb(72.3, 162.3, 222.6); --bs-btn-active-border-color: #48a2df;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #3498db; --bs-btn-disabled-bg: #3498db;
@ -3043,12 +3040,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f39c12; --bs-btn-bg: #f39c12;
--bs-btn-border-color: #f39c12; --bs-btn-border-color: #f39c12;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55); --bs-btn-hover-bg: #f5ab36;
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7); --bs-btn-hover-border-color: #f4a62a;
--bs-btn-focus-shadow-rgb: 207, 133, 15; --bs-btn-focus-shadow-rgb: 207, 133, 15;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4); --bs-btn-active-bg: #f5b041;
--bs-btn-active-border-color: rgb(244.2, 165.9, 41.7); --bs-btn-active-border-color: #f4a62a;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #f39c12; --bs-btn-disabled-bg: #f39c12;
@ -3060,12 +3057,12 @@ textarea.form-control-lg {
--bs-btn-bg: #e74c3c; --bs-btn-bg: #e74c3c;
--bs-btn-border-color: #e74c3c; --bs-btn-border-color: #e74c3c;
--bs-btn-hover-color: #f3f3f3; --bs-btn-hover-color: #f3f3f3;
--bs-btn-hover-bg: rgb(196.35, 64.6, 51); --bs-btn-hover-bg: #c44133;
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48); --bs-btn-hover-border-color: #b93d30;
--bs-btn-focus-shadow-rgb: 233, 101, 87; --bs-btn-focus-shadow-rgb: 233, 101, 87;
--bs-btn-active-color: #f3f3f3; --bs-btn-active-color: #f3f3f3;
--bs-btn-active-bg: rgb(184.8, 60.8, 48); --bs-btn-active-bg: #b93d30;
--bs-btn-active-border-color: rgb(173.25, 57, 45); --bs-btn-active-border-color: #ad392d;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #f3f3f3; --bs-btn-disabled-color: #f3f3f3;
--bs-btn-disabled-bg: #e74c3c; --bs-btn-disabled-bg: #e74c3c;
@ -3077,12 +3074,12 @@ textarea.form-control-lg {
--bs-btn-bg: #111; --bs-btn-bg: #111;
--bs-btn-border-color: #111; --bs-btn-border-color: #111;
--bs-btn-hover-color: #f3f3f3; --bs-btn-hover-color: #f3f3f3;
--bs-btn-hover-bg: rgb(14.45, 14.45, 14.45); --bs-btn-hover-bg: #0e0e0e;
--bs-btn-hover-border-color: rgb(13.6, 13.6, 13.6); --bs-btn-hover-border-color: #0e0e0e;
--bs-btn-focus-shadow-rgb: 51, 51, 51; --bs-btn-focus-shadow-rgb: 51, 51, 51;
--bs-btn-active-color: #f3f3f3; --bs-btn-active-color: #f3f3f3;
--bs-btn-active-bg: rgb(13.6, 13.6, 13.6); --bs-btn-active-bg: #0e0e0e;
--bs-btn-active-border-color: rgb(12.75, 12.75, 12.75); --bs-btn-active-border-color: #0d0d0d;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #f3f3f3; --bs-btn-disabled-color: #f3f3f3;
--bs-btn-disabled-bg: #111; --bs-btn-disabled-bg: #111;
@ -3094,12 +3091,12 @@ textarea.form-control-lg {
--bs-btn-bg: #dee2e6; --bs-btn-bg: #dee2e6;
--bs-btn-border-color: #dee2e6; --bs-btn-border-color: #dee2e6;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75); --bs-btn-hover-bg: #e3e6ea;
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5); --bs-btn-hover-border-color: #e1e5e9;
--bs-btn-focus-shadow-rgb: 189, 192, 196; --bs-btn-focus-shadow-rgb: 189, 192, 196;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(228.6, 231.8, 235); --bs-btn-active-bg: #e5e8eb;
--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5); --bs-btn-active-border-color: #e1e5e9;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #dee2e6; --bs-btn-disabled-bg: #dee2e6;
@ -4490,11 +4487,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ebebeb' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ebebeb'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%280, 75.2, 56%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23004b38'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #80dec6;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4552,6 +4550,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4569,7 +4568,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4580,11 +4579,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4593,27 +4592,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -4658,16 +4657,16 @@ textarea.form-control-lg {
--bs-pagination-border-color: transparent; --bs-pagination-border-color: transparent;
--bs-pagination-border-radius: var(--bs-border-radius); --bs-pagination-border-radius: var(--bs-border-radius);
--bs-pagination-hover-color: #f3f3f3; --bs-pagination-hover-color: #f3f3f3;
--bs-pagination-hover-bg: rgb(0, 239, 177.9787234043); --bs-pagination-hover-bg: #00efb2;
--bs-pagination-hover-border-color: transparent; --bs-pagination-hover-border-color: transparent;
--bs-pagination-focus-color: var(--bs-link-hover-color); --bs-pagination-focus-color: var(--bs-link-hover-color);
--bs-pagination-focus-bg: var(--bs-secondary-bg); --bs-pagination-focus-bg: var(--bs-secondary-bg);
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-pagination-active-color: #f3f3f3; --bs-pagination-active-color: #f3f3f3;
--bs-pagination-active-bg: rgb(0, 239, 177.9787234043); --bs-pagination-active-bg: #00efb2;
--bs-pagination-active-border-color: transparent; --bs-pagination-active-border-color: transparent;
--bs-pagination-disabled-color: #f3f3f3; --bs-pagination-disabled-color: #f3f3f3;
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936); --bs-pagination-disabled-bg: #007053;
--bs-pagination-disabled-border-color: transparent; --bs-pagination-disabled-border-color: transparent;
display: flex; display: flex;
padding-left: 0; padding-left: 0;
@ -5487,6 +5486,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6051,12 +6051,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f3f3f3'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6676,11 +6684,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {

View file

@ -1,7 +1,7 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -45,28 +45,28 @@
--bs-danger-rgb: 231, 76, 60; --bs-danger-rgb: 231, 76, 60;
--bs-light-rgb: 48, 48, 48; --bs-light-rgb: 48, 48, 48;
--bs-dark-rgb: 222, 226, 230; --bs-dark-rgb: 222, 226, 230;
--bs-primary-text-emphasis: rgb(22, 36, 50.8); --bs-primary-text-emphasis: #162433;
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6); --bs-secondary-text-emphasis: #45484c;
--bs-success-text-emphasis: rgb(0, 75.2, 56); --bs-success-text-emphasis: #004b38;
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6); --bs-info-text-emphasis: #153d58;
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2); --bs-warning-text-emphasis: #613e07;
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24); --bs-danger-text-emphasis: #5c1e18;
--bs-light-text-emphasis: #444; --bs-light-text-emphasis: #444;
--bs-dark-text-emphasis: #444; --bs-dark-text-emphasis: #444;
--bs-primary-bg-subtle: rgb(215, 222, 229.4); --bs-primary-bg-subtle: #d7dee5;
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8); --bs-secondary-bg-subtle: #eff0f2;
--bs-success-bg-subtle: rgb(204, 241.6, 232); --bs-success-bg-subtle: #ccf2e8;
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8); --bs-info-bg-subtle: #d6eaf8;
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6); --bs-warning-bg-subtle: #fdebd0;
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216); --bs-danger-bg-subtle: #fadbd8;
--bs-light-bg-subtle: rgb(251.5, 252, 252.5); --bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(175, 189, 203.8); --bs-primary-border-subtle: #afbdcc;
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6); --bs-secondary-border-subtle: #dee1e5;
--bs-success-border-subtle: rgb(153, 228.2, 209); --bs-success-border-subtle: #99e4d1;
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6); --bs-info-border-subtle: #aed6f1;
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2); --bs-warning-border-subtle: #fad7a0;
--bs-danger-border-subtle: rgb(245.4, 183.4, 177); --bs-danger-border-subtle: #f5b7b1;
--bs-light-border-subtle: #ebebeb; --bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255; --bs-white-rgb: 255, 255, 255;
@ -97,7 +97,7 @@
--bs-link-color: #e74c3c; --bs-link-color: #e74c3c;
--bs-link-color-rgb: 231, 76, 60; --bs-link-color-rgb: 231, 76, 60;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(184.8, 60.8, 48); --bs-link-hover-color: #b93d30;
--bs-link-hover-color-rgb: 185, 61, 48; --bs-link-hover-color-rgb: 185, 61, 48;
--bs-code-color: #d63384; --bs-code-color: #d63384;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
@ -142,44 +142,44 @@
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #292929; --bs-tertiary-bg: #292929;
--bs-tertiary-bg-rgb: 41, 41, 41; --bs-tertiary-bg-rgb: 41, 41, 41;
--bs-primary-text-emphasis: rgb(135, 156, 178.2); --bs-primary-text-emphasis: #879cb2;
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4); --bs-secondary-text-emphasis: #ced3d7;
--bs-success-text-emphasis: rgb(102, 214.8, 186); --bs-success-text-emphasis: #66d7ba;
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4); --bs-info-text-emphasis: #85c1e9;
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8); --bs-warning-text-emphasis: #f8c471;
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138); --bs-danger-text-emphasis: #f1948a;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(11, 18, 25.4); --bs-primary-bg-subtle: #0b1219;
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8); --bs-secondary-bg-subtle: #232426;
--bs-success-bg-subtle: rgb(0, 37.6, 28); --bs-success-bg-subtle: #00261c;
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8); --bs-info-bg-subtle: #0a1e2c;
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6); --bs-warning-bg-subtle: #311f04;
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12); --bs-danger-bg-subtle: #2e0f0c;
--bs-light-bg-subtle: #303030; --bs-light-bg-subtle: #303030;
--bs-dark-bg-subtle: #181818; --bs-dark-bg-subtle: #181818;
--bs-primary-border-subtle: rgb(33, 54, 76.2); --bs-primary-border-subtle: #21364c;
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4); --bs-secondary-border-subtle: #686d71;
--bs-success-border-subtle: rgb(0, 112.8, 84); --bs-success-border-subtle: #007154;
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4); --bs-info-border-subtle: #1f5b83;
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8); --bs-warning-border-subtle: #925e0b;
--bs-danger-border-subtle: rgb(138.6, 45.6, 36); --bs-danger-border-subtle: #8b2e24;
--bs-light-border-subtle: #444; --bs-light-border-subtle: #444;
--bs-dark-border-subtle: #303030; --bs-dark-border-subtle: #303030;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(135, 156, 178.2); --bs-link-color: #879cb2;
--bs-link-hover-color: rgb(159, 175.8, 193.56); --bs-link-hover-color: #9fb0c1;
--bs-link-color-rgb: 135, 156, 178; --bs-link-color-rgb: 135, 156, 178;
--bs-link-hover-color-rgb: 159, 176, 194; --bs-link-hover-color-rgb: 159, 176, 193;
--bs-code-color: rgb(230.4, 132.6, 181.2); --bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: #333; --bs-highlight-bg: #333;
--bs-border-color: #444; --bs-border-color: #444;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15); --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: rgb(102, 214.8, 186); --bs-form-valid-color: #66d7ba;
--bs-form-valid-border-color: rgb(102, 214.8, 186); --bs-form-valid-border-color: #66d7ba;
--bs-form-invalid-color: rgb(240.6, 147.6, 138); --bs-form-invalid-color: #f1948a;
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138); --bs-form-invalid-border-color: #f1948a;
} }
*, *,
@ -1935,13 +1935,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(215, 222, 229.4); --bs-table-bg: #d7dee5;
--bs-table-border-color: rgb(172, 177.6, 183.52); --bs-table-border-color: #acb2b7;
--bs-table-striped-bg: rgb(204.25, 210.9, 217.93); --bs-table-striped-bg: #ccd3da;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(193.5, 199.8, 206.46); --bs-table-active-bg: #c2c8ce;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(198.875, 205.35, 212.195); --bs-table-hover-bg: #c7cdd4;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1949,13 +1949,13 @@ progress {
.table-secondary { .table-secondary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(238.6, 240.2, 241.8); --bs-table-bg: #eff0f2;
--bs-table-border-color: rgb(190.88, 192.16, 193.44); --bs-table-border-color: #bfc0c2;
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71); --bs-table-striped-bg: #e3e4e6;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(214.74, 216.18, 217.62); --bs-table-active-bg: #d7d8da;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665); --bs-table-hover-bg: #dddee0;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1963,13 +1963,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204, 241.6, 232); --bs-table-bg: #ccf2e8;
--bs-table-border-color: rgb(163.2, 193.28, 185.6); --bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4); --bs-table-striped-bg: #c2e6dc;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.6, 217.44, 208.8); --bs-table-active-bg: #b8dad1;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6); --bs-table-hover-bg: #bde0d7;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1977,13 +1977,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(214.4, 234.4, 247.8); --bs-table-bg: #d6eaf8;
--bs-table-border-color: rgb(171.52, 187.52, 198.24); --bs-table-border-color: #abbbc6;
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41); --bs-table-striped-bg: #cbdeec;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(192.96, 210.96, 223.02); --bs-table-active-bg: #c1d3df;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215); --bs-table-hover-bg: #c6d8e5;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1991,13 +1991,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(252.6, 235.2, 207.6); --bs-table-bg: #fdebd0;
--bs-table-border-color: rgb(202.08, 188.16, 166.08); --bs-table-border-color: #cabca6;
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22); --bs-table-striped-bg: #f0dfc6;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(227.34, 211.68, 186.84); --bs-table-active-bg: #e4d4bb;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03); --bs-table-hover-bg: #ead9c0;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2005,13 +2005,13 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(250.2, 219.2, 216); --bs-table-bg: #fadbd8;
--bs-table-border-color: rgb(200.16, 175.36, 172.8); --bs-table-border-color: #c8afad;
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2); --bs-table-striped-bg: #eed0cd;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(225.18, 197.28, 194.4); --bs-table-active-bg: #e1c5c2;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8); --bs-table-hover-bg: #e7cbc8;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2020,12 +2020,12 @@ progress {
.table-light { .table-light {
--bs-table-color: #fff; --bs-table-color: #fff;
--bs-table-bg: #303030; --bs-table-bg: #303030;
--bs-table-border-color: rgb(89.4, 89.4, 89.4); --bs-table-border-color: #595959;
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35); --bs-table-striped-bg: #3a3a3a;
--bs-table-striped-color: #fff; --bs-table-striped-color: #fff;
--bs-table-active-bg: rgb(68.7, 68.7, 68.7); --bs-table-active-bg: #454545;
--bs-table-active-color: #fff; --bs-table-active-color: #fff;
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525); --bs-table-hover-bg: #404040;
--bs-table-hover-color: #fff; --bs-table-hover-color: #fff;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2034,12 +2034,12 @@ progress {
.table-dark { .table-dark {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: #dee2e6; --bs-table-bg: #dee2e6;
--bs-table-border-color: rgb(177.6, 180.8, 184); --bs-table-border-color: #b2b5b8;
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5); --bs-table-striped-bg: #d3d7db;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(199.8, 203.4, 207); --bs-table-active-bg: #c8cbcf;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75); --bs-table-hover-bg: #cdd1d5;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2139,7 +2139,7 @@ progress {
.form-control:focus { .form-control:focus {
color: #fff; color: #fff;
background-color: #444; background-color: #444;
border-color: rgb(155, 172.5, 191); border-color: #9badbf;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25); box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
} }
@ -2157,7 +2157,7 @@ progress {
opacity: 1; opacity: 1;
} }
.form-control:disabled { .form-control:disabled {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
opacity: 1; opacity: 1;
} }
.form-control::file-selector-button { .form-control::file-selector-button {
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(155, 172.5, 191); border-color: #9badbf;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25); box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
} }
@ -2293,7 +2293,7 @@ textarea.form-control-lg {
background-image: none; background-image: none;
} }
.form-select:disabled { .form-select:disabled {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
} }
.form-select:-moz-focusring { .form-select:-moz-focusring {
color: transparent; color: transparent;
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(155, 172.5, 191); border-color: #9badbf;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25); box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
} }
@ -2415,7 +2415,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28155, 172.5, 191%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%239badbf'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(195, 205.5, 216.6); background-color: #c3ced9;
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
width: 100%; width: 100%;
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(195, 205.5, 216.6); background-color: #c3ced9;
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
width: 100%; width: 100%;
@ -2618,7 +2618,7 @@ textarea.form-control-lg {
} }
.form-floating > :disabled ~ label::after, .form-floating > :disabled ~ label::after,
.form-floating > .form-control:disabled ~ label::after { .form-floating > .form-control:disabled ~ label::after {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
} }
.input-group { .input-group {
@ -2959,9 +2959,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2975,12 +2972,12 @@ textarea.form-control-lg {
--bs-btn-bg: #375a7f; --bs-btn-bg: #375a7f;
--bs-btn-border-color: #375a7f; --bs-btn-border-color: #375a7f;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(46.75, 76.5, 107.95); --bs-btn-hover-bg: #2f4d6c;
--bs-btn-hover-border-color: rgb(44, 72, 101.6); --bs-btn-hover-border-color: #2c4866;
--bs-btn-focus-shadow-rgb: 85, 115, 146; --bs-btn-focus-shadow-rgb: 85, 115, 146;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(44, 72, 101.6); --bs-btn-active-bg: #2c4866;
--bs-btn-active-border-color: rgb(41.25, 67.5, 95.25); --bs-btn-active-border-color: #29445f;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #375a7f; --bs-btn-disabled-bg: #375a7f;
@ -2992,12 +2989,12 @@ textarea.form-control-lg {
--bs-btn-bg: #adb5bd; --bs-btn-bg: #adb5bd;
--bs-btn-border-color: #adb5bd; --bs-btn-border-color: #adb5bd;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9); --bs-btn-hover-bg: #b9c0c7;
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6); --bs-btn-hover-border-color: #b5bcc4;
--bs-btn-focus-shadow-rgb: 147, 154, 161; --bs-btn-focus-shadow-rgb: 147, 154, 161;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2); --bs-btn-active-bg: #bdc4ca;
--bs-btn-active-border-color: rgb(181.2, 188.4, 195.6); --bs-btn-active-border-color: #b5bcc4;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #adb5bd; --bs-btn-disabled-bg: #adb5bd;
@ -3009,12 +3006,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c; --bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c; --bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25); --bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-hover-border-color: #1ac398;
--bs-btn-focus-shadow-rgb: 0, 160, 119; --bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51, 201.4, 163); --bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-active-border-color: #1ac398;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c; --bs-btn-disabled-bg: #00bc8c;
@ -3026,12 +3023,12 @@ textarea.form-control-lg {
--bs-btn-bg: #3498db; --bs-btn-bg: #3498db;
--bs-btn-border-color: #3498db; --bs-btn-border-color: #3498db;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15); --bs-btn-hover-bg: #2c81ba;
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2); --bs-btn-hover-border-color: #2a7aaf;
--bs-btn-focus-shadow-rgb: 82, 167, 224; --bs-btn-focus-shadow-rgb: 82, 167, 224;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2); --bs-btn-active-bg: #2a7aaf;
--bs-btn-active-border-color: rgb(39, 114, 164.25); --bs-btn-active-border-color: #2772a4;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #3498db; --bs-btn-disabled-bg: #3498db;
@ -3043,12 +3040,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f39c12; --bs-btn-bg: #f39c12;
--bs-btn-border-color: #f39c12; --bs-btn-border-color: #f39c12;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55); --bs-btn-hover-bg: #f5ab36;
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7); --bs-btn-hover-border-color: #f4a62a;
--bs-btn-focus-shadow-rgb: 207, 133, 15; --bs-btn-focus-shadow-rgb: 207, 133, 15;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4); --bs-btn-active-bg: #f5b041;
--bs-btn-active-border-color: rgb(244.2, 165.9, 41.7); --bs-btn-active-border-color: #f4a62a;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #f39c12; --bs-btn-disabled-bg: #f39c12;
@ -3060,12 +3057,12 @@ textarea.form-control-lg {
--bs-btn-bg: #e74c3c; --bs-btn-bg: #e74c3c;
--bs-btn-border-color: #e74c3c; --bs-btn-border-color: #e74c3c;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(196.35, 64.6, 51); --bs-btn-hover-bg: #c44133;
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48); --bs-btn-hover-border-color: #b93d30;
--bs-btn-focus-shadow-rgb: 235, 103, 89; --bs-btn-focus-shadow-rgb: 235, 103, 89;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(184.8, 60.8, 48); --bs-btn-active-bg: #b93d30;
--bs-btn-active-border-color: rgb(173.25, 57, 45); --bs-btn-active-border-color: #ad392d;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #e74c3c; --bs-btn-disabled-bg: #e74c3c;
@ -3077,11 +3074,11 @@ textarea.form-control-lg {
--bs-btn-bg: #303030; --bs-btn-bg: #303030;
--bs-btn-border-color: #303030; --bs-btn-border-color: #303030;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8); --bs-btn-hover-bg: #292929;
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4); --bs-btn-hover-border-color: #262626;
--bs-btn-focus-shadow-rgb: 79, 79, 79; --bs-btn-focus-shadow-rgb: 79, 79, 79;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(38.4, 38.4, 38.4); --bs-btn-active-bg: #262626;
--bs-btn-active-border-color: #242424; --bs-btn-active-border-color: #242424;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
@ -3094,12 +3091,12 @@ textarea.form-control-lg {
--bs-btn-bg: #dee2e6; --bs-btn-bg: #dee2e6;
--bs-btn-border-color: #dee2e6; --bs-btn-border-color: #dee2e6;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75); --bs-btn-hover-bg: #e3e6ea;
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5); --bs-btn-hover-border-color: #e1e5e9;
--bs-btn-focus-shadow-rgb: 189, 192, 196; --bs-btn-focus-shadow-rgb: 189, 192, 196;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(228.6, 231.8, 235); --bs-btn-active-bg: #e5e8eb;
--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5); --bs-btn-active-border-color: #e1e5e9;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #dee2e6; --bs-btn-disabled-bg: #dee2e6;
@ -4490,11 +4487,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23dee2e6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%2822, 36, 50.8%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23162433'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #9badbf;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4552,6 +4550,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4569,7 +4568,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4580,11 +4579,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4593,27 +4592,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28135, 156, 178.2%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23879cb2'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28135, 156, 178.2%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23879cb2'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -4658,16 +4657,16 @@ textarea.form-control-lg {
--bs-pagination-border-color: transparent; --bs-pagination-border-color: transparent;
--bs-pagination-border-radius: var(--bs-border-radius); --bs-pagination-border-radius: var(--bs-border-radius);
--bs-pagination-hover-color: #fff; --bs-pagination-hover-color: #fff;
--bs-pagination-hover-bg: rgb(0, 239, 177.9787234043); --bs-pagination-hover-bg: #00efb2;
--bs-pagination-hover-border-color: transparent; --bs-pagination-hover-border-color: transparent;
--bs-pagination-focus-color: var(--bs-link-hover-color); --bs-pagination-focus-color: var(--bs-link-hover-color);
--bs-pagination-focus-bg: var(--bs-secondary-bg); --bs-pagination-focus-bg: var(--bs-secondary-bg);
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25); --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(55, 90, 127, 0.25);
--bs-pagination-active-color: #fff; --bs-pagination-active-color: #fff;
--bs-pagination-active-bg: rgb(0, 239, 177.9787234043); --bs-pagination-active-bg: #00efb2;
--bs-pagination-active-border-color: transparent; --bs-pagination-active-border-color: transparent;
--bs-pagination-disabled-color: #fff; --bs-pagination-disabled-color: #fff;
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936); --bs-pagination-disabled-bg: #007053;
--bs-pagination-disabled-border-color: transparent; --bs-pagination-disabled-border-color: transparent;
display: flex; display: flex;
padding-left: 0; padding-left: 0;
@ -5487,6 +5486,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6051,12 +6051,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6676,11 +6684,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {

View file

@ -1,7 +1,7 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -45,28 +45,28 @@
--bs-danger-rgb: 231, 76, 60; --bs-danger-rgb: 231, 76, 60;
--bs-light-rgb: 48, 48, 48; --bs-light-rgb: 48, 48, 48;
--bs-dark-rgb: 222, 226, 230; --bs-dark-rgb: 222, 226, 230;
--bs-primary-text-emphasis: rgb(0, 75.2, 56); --bs-primary-text-emphasis: #004b38;
--bs-secondary-text-emphasis: rgb(69.2, 72.4, 75.6); --bs-secondary-text-emphasis: #45484c;
--bs-success-text-emphasis: rgb(0, 75.2, 56); --bs-success-text-emphasis: #004b38;
--bs-info-text-emphasis: rgb(20.8, 60.8, 87.6); --bs-info-text-emphasis: #153d58;
--bs-warning-text-emphasis: rgb(97.2, 62.4, 7.2); --bs-warning-text-emphasis: #613e07;
--bs-danger-text-emphasis: rgb(92.4, 30.4, 24); --bs-danger-text-emphasis: #5c1e18;
--bs-light-text-emphasis: #444; --bs-light-text-emphasis: #444;
--bs-dark-text-emphasis: #444; --bs-dark-text-emphasis: #444;
--bs-primary-bg-subtle: rgb(204, 241.6, 232); --bs-primary-bg-subtle: #ccf2e8;
--bs-secondary-bg-subtle: rgb(238.6, 240.2, 241.8); --bs-secondary-bg-subtle: #eff0f2;
--bs-success-bg-subtle: rgb(204, 241.6, 232); --bs-success-bg-subtle: #ccf2e8;
--bs-info-bg-subtle: rgb(214.4, 234.4, 247.8); --bs-info-bg-subtle: #d6eaf8;
--bs-warning-bg-subtle: rgb(252.6, 235.2, 207.6); --bs-warning-bg-subtle: #fdebd0;
--bs-danger-bg-subtle: rgb(250.2, 219.2, 216); --bs-danger-bg-subtle: #fadbd8;
--bs-light-bg-subtle: rgb(251.5, 252, 252.5); --bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(153, 228.2, 209); --bs-primary-border-subtle: #99e4d1;
--bs-secondary-border-subtle: rgb(222.2, 225.4, 228.6); --bs-secondary-border-subtle: #dee1e5;
--bs-success-border-subtle: rgb(153, 228.2, 209); --bs-success-border-subtle: #99e4d1;
--bs-info-border-subtle: rgb(173.8, 213.8, 240.6); --bs-info-border-subtle: #aed6f1;
--bs-warning-border-subtle: rgb(250.2, 215.4, 160.2); --bs-warning-border-subtle: #fad7a0;
--bs-danger-border-subtle: rgb(245.4, 183.4, 177); --bs-danger-border-subtle: #f5b7b1;
--bs-light-border-subtle: #ebebeb; --bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255; --bs-white-rgb: 255, 255, 255;
@ -97,7 +97,7 @@
--bs-link-color: #00bc8c; --bs-link-color: #00bc8c;
--bs-link-color-rgb: 0, 188, 140; --bs-link-color-rgb: 0, 188, 140;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(0, 150.4, 112); --bs-link-hover-color: #009670;
--bs-link-hover-color-rgb: 0, 150, 112; --bs-link-hover-color-rgb: 0, 150, 112;
--bs-code-color: #d63384; --bs-code-color: #d63384;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
@ -142,44 +142,44 @@
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #292929; --bs-tertiary-bg: #292929;
--bs-tertiary-bg-rgb: 41, 41, 41; --bs-tertiary-bg-rgb: 41, 41, 41;
--bs-primary-text-emphasis: rgb(102, 214.8, 186); --bs-primary-text-emphasis: #66d7ba;
--bs-secondary-text-emphasis: rgb(205.8, 210.6, 215.4); --bs-secondary-text-emphasis: #ced3d7;
--bs-success-text-emphasis: rgb(102, 214.8, 186); --bs-success-text-emphasis: #66d7ba;
--bs-info-text-emphasis: rgb(133.2, 193.2, 233.4); --bs-info-text-emphasis: #85c1e9;
--bs-warning-text-emphasis: rgb(247.8, 195.6, 112.8); --bs-warning-text-emphasis: #f8c471;
--bs-danger-text-emphasis: rgb(240.6, 147.6, 138); --bs-danger-text-emphasis: #f1948a;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(0, 37.6, 28); --bs-primary-bg-subtle: #00261c;
--bs-secondary-bg-subtle: rgb(34.6, 36.2, 37.8); --bs-secondary-bg-subtle: #232426;
--bs-success-bg-subtle: rgb(0, 37.6, 28); --bs-success-bg-subtle: #00261c;
--bs-info-bg-subtle: rgb(10.4, 30.4, 43.8); --bs-info-bg-subtle: #0a1e2c;
--bs-warning-bg-subtle: rgb(48.6, 31.2, 3.6); --bs-warning-bg-subtle: #311f04;
--bs-danger-bg-subtle: rgb(46.2, 15.2, 12); --bs-danger-bg-subtle: #2e0f0c;
--bs-light-bg-subtle: #303030; --bs-light-bg-subtle: #303030;
--bs-dark-bg-subtle: #181818; --bs-dark-bg-subtle: #181818;
--bs-primary-border-subtle: rgb(0, 112.8, 84); --bs-primary-border-subtle: #007154;
--bs-secondary-border-subtle: rgb(103.8, 108.6, 113.4); --bs-secondary-border-subtle: #686d71;
--bs-success-border-subtle: rgb(0, 112.8, 84); --bs-success-border-subtle: #007154;
--bs-info-border-subtle: rgb(31.2, 91.2, 131.4); --bs-info-border-subtle: #1f5b83;
--bs-warning-border-subtle: rgb(145.8, 93.6, 10.8); --bs-warning-border-subtle: #925e0b;
--bs-danger-border-subtle: rgb(138.6, 45.6, 36); --bs-danger-border-subtle: #8b2e24;
--bs-light-border-subtle: #444; --bs-light-border-subtle: #444;
--bs-dark-border-subtle: #303030; --bs-dark-border-subtle: #303030;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(102, 214.8, 186); --bs-link-color: #66d7ba;
--bs-link-hover-color: rgb(132.6, 222.84, 199.8); --bs-link-hover-color: #85dfc8;
--bs-link-color-rgb: 102, 215, 186; --bs-link-color-rgb: 102, 215, 186;
--bs-link-hover-color-rgb: 133, 223, 200; --bs-link-hover-color-rgb: 133, 223, 200;
--bs-code-color: rgb(230.4, 132.6, 181.2); --bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: #333; --bs-highlight-bg: #333;
--bs-border-color: #444; --bs-border-color: #444;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15); --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: rgb(102, 214.8, 186); --bs-form-valid-color: #66d7ba;
--bs-form-valid-border-color: rgb(102, 214.8, 186); --bs-form-valid-border-color: #66d7ba;
--bs-form-invalid-color: rgb(240.6, 147.6, 138); --bs-form-invalid-color: #f1948a;
--bs-form-invalid-border-color: rgb(240.6, 147.6, 138); --bs-form-invalid-border-color: #f1948a;
} }
*, *,
@ -1935,13 +1935,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204, 241.6, 232); --bs-table-bg: #ccf2e8;
--bs-table-border-color: rgb(163.2, 193.28, 185.6); --bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4); --bs-table-striped-bg: #c2e6dc;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.6, 217.44, 208.8); --bs-table-active-bg: #b8dad1;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6); --bs-table-hover-bg: #bde0d7;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1949,13 +1949,13 @@ progress {
.table-secondary { .table-secondary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(238.6, 240.2, 241.8); --bs-table-bg: #eff0f2;
--bs-table-border-color: rgb(190.88, 192.16, 193.44); --bs-table-border-color: #bfc0c2;
--bs-table-striped-bg: rgb(226.67, 228.19, 229.71); --bs-table-striped-bg: #e3e4e6;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(214.74, 216.18, 217.62); --bs-table-active-bg: #d7d8da;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(220.705, 222.185, 223.665); --bs-table-hover-bg: #dddee0;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1963,13 +1963,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204, 241.6, 232); --bs-table-bg: #ccf2e8;
--bs-table-border-color: rgb(163.2, 193.28, 185.6); --bs-table-border-color: #a3c2ba;
--bs-table-striped-bg: rgb(193.8, 229.52, 220.4); --bs-table-striped-bg: #c2e6dc;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.6, 217.44, 208.8); --bs-table-active-bg: #b8dad1;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.7, 223.48, 214.6); --bs-table-hover-bg: #bde0d7;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1977,13 +1977,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(214.4, 234.4, 247.8); --bs-table-bg: #d6eaf8;
--bs-table-border-color: rgb(171.52, 187.52, 198.24); --bs-table-border-color: #abbbc6;
--bs-table-striped-bg: rgb(203.68, 222.68, 235.41); --bs-table-striped-bg: #cbdeec;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(192.96, 210.96, 223.02); --bs-table-active-bg: #c1d3df;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(198.32, 216.82, 229.215); --bs-table-hover-bg: #c6d8e5;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1991,13 +1991,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(252.6, 235.2, 207.6); --bs-table-bg: #fdebd0;
--bs-table-border-color: rgb(202.08, 188.16, 166.08); --bs-table-border-color: #cabca6;
--bs-table-striped-bg: rgb(239.97, 223.44, 197.22); --bs-table-striped-bg: #f0dfc6;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(227.34, 211.68, 186.84); --bs-table-active-bg: #e4d4bb;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(233.655, 217.56, 192.03); --bs-table-hover-bg: #ead9c0;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2005,13 +2005,13 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(250.2, 219.2, 216); --bs-table-bg: #fadbd8;
--bs-table-border-color: rgb(200.16, 175.36, 172.8); --bs-table-border-color: #c8afad;
--bs-table-striped-bg: rgb(237.69, 208.24, 205.2); --bs-table-striped-bg: #eed0cd;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(225.18, 197.28, 194.4); --bs-table-active-bg: #e1c5c2;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(231.435, 202.76, 199.8); --bs-table-hover-bg: #e7cbc8;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2020,12 +2020,12 @@ progress {
.table-light { .table-light {
--bs-table-color: #fff; --bs-table-color: #fff;
--bs-table-bg: #303030; --bs-table-bg: #303030;
--bs-table-border-color: rgb(89.4, 89.4, 89.4); --bs-table-border-color: #595959;
--bs-table-striped-bg: rgb(58.35, 58.35, 58.35); --bs-table-striped-bg: #3a3a3a;
--bs-table-striped-color: #fff; --bs-table-striped-color: #fff;
--bs-table-active-bg: rgb(68.7, 68.7, 68.7); --bs-table-active-bg: #454545;
--bs-table-active-color: #fff; --bs-table-active-color: #fff;
--bs-table-hover-bg: rgb(63.525, 63.525, 63.525); --bs-table-hover-bg: #404040;
--bs-table-hover-color: #fff; --bs-table-hover-color: #fff;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2034,12 +2034,12 @@ progress {
.table-dark { .table-dark {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: #dee2e6; --bs-table-bg: #dee2e6;
--bs-table-border-color: rgb(177.6, 180.8, 184); --bs-table-border-color: #b2b5b8;
--bs-table-striped-bg: rgb(210.9, 214.7, 218.5); --bs-table-striped-bg: #d3d7db;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(199.8, 203.4, 207); --bs-table-active-bg: #c8cbcf;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(205.35, 209.05, 212.75); --bs-table-hover-bg: #cdd1d5;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2139,7 +2139,7 @@ progress {
.form-control:focus { .form-control:focus {
color: #fff; color: #fff;
background-color: #444; background-color: #444;
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2157,7 +2157,7 @@ progress {
opacity: 1; opacity: 1;
} }
.form-control:disabled { .form-control:disabled {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
opacity: 1; opacity: 1;
} }
.form-control::file-selector-button { .form-control::file-selector-button {
@ -2284,7 +2284,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2293,7 +2293,7 @@ textarea.form-control-lg {
background-image: none; background-image: none;
} }
.form-select:disabled { .form-select:disabled {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
} }
.form-select:-moz-focusring { .form-select:-moz-focusring {
color: transparent; color: transparent;
@ -2368,7 +2368,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(127.5, 221.5, 197.5); border-color: #80dec6;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
} }
@ -2415,7 +2415,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28127.5, 221.5, 197.5%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2380dec6'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2485,7 +2485,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(178.5, 234.9, 220.5); background-color: #b3ebdd;
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
width: 100%; width: 100%;
@ -2511,7 +2511,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(178.5, 234.9, 220.5); background-color: #b3ebdd;
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
width: 100%; width: 100%;
@ -2618,7 +2618,7 @@ textarea.form-control-lg {
} }
.form-floating > :disabled ~ label::after, .form-floating > :disabled ~ label::after,
.form-floating > .form-control:disabled ~ label::after { .form-floating > .form-control:disabled ~ label::after {
background-color: rgb(42.5, 42.5, 42.5); background-color: #2b2b2b;
} }
.input-group { .input-group {
@ -2959,9 +2959,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2975,12 +2972,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c; --bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c; --bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25); --bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-hover-border-color: #1ac398;
--bs-btn-focus-shadow-rgb: 0, 160, 119; --bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51, 201.4, 163); --bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-active-border-color: #1ac398;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c; --bs-btn-disabled-bg: #00bc8c;
@ -2992,12 +2989,12 @@ textarea.form-control-lg {
--bs-btn-bg: #adb5bd; --bs-btn-bg: #adb5bd;
--bs-btn-border-color: #adb5bd; --bs-btn-border-color: #adb5bd;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(185.3, 192.1, 198.9); --bs-btn-hover-bg: #b9c0c7;
--bs-btn-hover-border-color: rgb(181.2, 188.4, 195.6); --bs-btn-hover-border-color: #b5bcc4;
--bs-btn-focus-shadow-rgb: 147, 154, 161; --bs-btn-focus-shadow-rgb: 147, 154, 161;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(189.4, 195.8, 202.2); --bs-btn-active-bg: #bdc4ca;
--bs-btn-active-border-color: rgb(181.2, 188.4, 195.6); --bs-btn-active-border-color: #b5bcc4;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #adb5bd; --bs-btn-disabled-bg: #adb5bd;
@ -3009,12 +3006,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00bc8c; --bs-btn-bg: #00bc8c;
--bs-btn-border-color: #00bc8c; --bs-btn-border-color: #00bc8c;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(38.25, 198.05, 157.25); --bs-btn-hover-bg: #26c69d;
--bs-btn-hover-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-hover-border-color: #1ac398;
--bs-btn-focus-shadow-rgb: 0, 160, 119; --bs-btn-focus-shadow-rgb: 0, 160, 119;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51, 201.4, 163); --bs-btn-active-bg: #33c9a3;
--bs-btn-active-border-color: rgb(25.5, 194.7, 151.5); --bs-btn-active-border-color: #1ac398;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #00bc8c; --bs-btn-disabled-bg: #00bc8c;
@ -3026,12 +3023,12 @@ textarea.form-control-lg {
--bs-btn-bg: #3498db; --bs-btn-bg: #3498db;
--bs-btn-border-color: #3498db; --bs-btn-border-color: #3498db;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(44.2, 129.2, 186.15); --bs-btn-hover-bg: #2c81ba;
--bs-btn-hover-border-color: rgb(41.6, 121.6, 175.2); --bs-btn-hover-border-color: #2a7aaf;
--bs-btn-focus-shadow-rgb: 82, 167, 224; --bs-btn-focus-shadow-rgb: 82, 167, 224;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(41.6, 121.6, 175.2); --bs-btn-active-bg: #2a7aaf;
--bs-btn-active-border-color: rgb(39, 114, 164.25); --bs-btn-active-border-color: #2772a4;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #3498db; --bs-btn-disabled-bg: #3498db;
@ -3043,12 +3040,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f39c12; --bs-btn-bg: #f39c12;
--bs-btn-border-color: #f39c12; --bs-btn-border-color: #f39c12;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(244.8, 170.85, 53.55); --bs-btn-hover-bg: #f5ab36;
--bs-btn-hover-border-color: rgb(244.2, 165.9, 41.7); --bs-btn-hover-border-color: #f4a62a;
--bs-btn-focus-shadow-rgb: 207, 133, 15; --bs-btn-focus-shadow-rgb: 207, 133, 15;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(245.4, 175.8, 65.4); --bs-btn-active-bg: #f5b041;
--bs-btn-active-border-color: rgb(244.2, 165.9, 41.7); --bs-btn-active-border-color: #f4a62a;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #f39c12; --bs-btn-disabled-bg: #f39c12;
@ -3060,12 +3057,12 @@ textarea.form-control-lg {
--bs-btn-bg: #e74c3c; --bs-btn-bg: #e74c3c;
--bs-btn-border-color: #e74c3c; --bs-btn-border-color: #e74c3c;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(196.35, 64.6, 51); --bs-btn-hover-bg: #c44133;
--bs-btn-hover-border-color: rgb(184.8, 60.8, 48); --bs-btn-hover-border-color: #b93d30;
--bs-btn-focus-shadow-rgb: 235, 103, 89; --bs-btn-focus-shadow-rgb: 235, 103, 89;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(184.8, 60.8, 48); --bs-btn-active-bg: #b93d30;
--bs-btn-active-border-color: rgb(173.25, 57, 45); --bs-btn-active-border-color: #ad392d;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #e74c3c; --bs-btn-disabled-bg: #e74c3c;
@ -3077,11 +3074,11 @@ textarea.form-control-lg {
--bs-btn-bg: #303030; --bs-btn-bg: #303030;
--bs-btn-border-color: #303030; --bs-btn-border-color: #303030;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(40.8, 40.8, 40.8); --bs-btn-hover-bg: #292929;
--bs-btn-hover-border-color: rgb(38.4, 38.4, 38.4); --bs-btn-hover-border-color: #262626;
--bs-btn-focus-shadow-rgb: 79, 79, 79; --bs-btn-focus-shadow-rgb: 79, 79, 79;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(38.4, 38.4, 38.4); --bs-btn-active-bg: #262626;
--bs-btn-active-border-color: #242424; --bs-btn-active-border-color: #242424;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
@ -3094,12 +3091,12 @@ textarea.form-control-lg {
--bs-btn-bg: #dee2e6; --bs-btn-bg: #dee2e6;
--bs-btn-border-color: #dee2e6; --bs-btn-border-color: #dee2e6;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75); --bs-btn-hover-bg: #e3e6ea;
--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5); --bs-btn-hover-border-color: #e1e5e9;
--bs-btn-focus-shadow-rgb: 189, 192, 196; --bs-btn-focus-shadow-rgb: 189, 192, 196;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(228.6, 231.8, 235); --bs-btn-active-bg: #e5e8eb;
--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5); --bs-btn-active-border-color: #e1e5e9;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #dee2e6; --bs-btn-disabled-bg: #dee2e6;
@ -4490,11 +4487,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23dee2e6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%280, 75.2, 56%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23004b38'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #80dec6;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4552,6 +4550,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4569,7 +4568,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4580,11 +4579,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4593,27 +4592,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28102, 214.8, 186%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2366d7ba'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -4658,16 +4657,16 @@ textarea.form-control-lg {
--bs-pagination-border-color: transparent; --bs-pagination-border-color: transparent;
--bs-pagination-border-radius: var(--bs-border-radius); --bs-pagination-border-radius: var(--bs-border-radius);
--bs-pagination-hover-color: #fff; --bs-pagination-hover-color: #fff;
--bs-pagination-hover-bg: rgb(0, 239, 177.9787234043); --bs-pagination-hover-bg: #00efb2;
--bs-pagination-hover-border-color: transparent; --bs-pagination-hover-border-color: transparent;
--bs-pagination-focus-color: var(--bs-link-hover-color); --bs-pagination-focus-color: var(--bs-link-hover-color);
--bs-pagination-focus-bg: var(--bs-secondary-bg); --bs-pagination-focus-bg: var(--bs-secondary-bg);
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25); --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(0, 188, 140, 0.25);
--bs-pagination-active-color: #fff; --bs-pagination-active-color: #fff;
--bs-pagination-active-bg: rgb(0, 239, 177.9787234043); --bs-pagination-active-bg: #00efb2;
--bs-pagination-active-border-color: transparent; --bs-pagination-active-border-color: transparent;
--bs-pagination-disabled-color: #fff; --bs-pagination-disabled-color: #fff;
--bs-pagination-disabled-bg: rgb(0, 111.5, 83.0319148936); --bs-pagination-disabled-bg: #007053;
--bs-pagination-disabled-border-color: transparent; --bs-pagination-disabled-border-color: transparent;
display: flex; display: flex;
padding-left: 0; padding-left: 0;
@ -5487,6 +5486,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6051,12 +6051,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6676,11 +6684,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
@import "variables.i386-dark"; @import "variables.i386";
@import "../../../../node_modules/bootstrap/scss/bootstrap"; @import "../../../../node_modules/bootstrap/scss/bootstrap";
.btn-outline-secondary { .btn-outline-secondary {

View file

@ -40,8 +40,8 @@ hr.my-3 {
} }
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -74,7 +74,7 @@ hr.my-3 {
--bs-success: #6610f2; --bs-success: #6610f2;
--bs-info: #007bff; --bs-info: #007bff;
--bs-warning: #ffc107; --bs-warning: #ffc107;
--bs-danger: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-danger: #873208;
--bs-light: #f8f9fa; --bs-light: #f8f9fa;
--bs-dark: #212529; --bs-dark: #212529;
--bs-primary-rgb: 241, 100, 30; --bs-primary-rgb: 241, 100, 30;
@ -85,28 +85,28 @@ hr.my-3 {
--bs-danger-rgb: 135, 50, 8; --bs-danger-rgb: 135, 50, 8;
--bs-light-rgb: 248, 249, 250; --bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41; --bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: rgb(96.4, 40, 12); --bs-primary-text-emphasis: #60280c;
--bs-secondary-text-emphasis: rgb(0, 67.2, 28); --bs-secondary-text-emphasis: #00431c;
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8); --bs-success-text-emphasis: #290661;
--bs-info-text-emphasis: rgb(0, 49.2, 102); --bs-info-text-emphasis: #003166;
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8); --bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: rgb(54.0376569038, 20.1740585774, 3.3623430962); --bs-danger-text-emphasis: #361403;
--bs-light-text-emphasis: #495057; --bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057; --bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: rgb(252.2, 224, 210); --bs-primary-bg-subtle: #fce0d2;
--bs-secondary-bg-subtle: rgb(204, 237.6, 218); --bs-secondary-bg-subtle: #cceeda;
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4); --bs-success-bg-subtle: #e0cffc;
--bs-info-bg-subtle: rgb(204, 228.6, 255); --bs-info-bg-subtle: #cce5ff;
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4); --bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: rgb(231.0188284519, 214.0870292887, 205.6811715481); --bs-danger-bg-subtle: #e7d6ce;
--bs-light-bg-subtle: rgb(251.5, 252, 252.5); --bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(249.4, 193, 165); --bs-primary-border-subtle: #f9c1a5;
--bs-secondary-border-subtle: rgb(153, 220.2, 181); --bs-secondary-border-subtle: #99dcb5;
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8); --bs-success-border-subtle: #c29ffa;
--bs-info-border-subtle: rgb(153, 202.2, 255); --bs-info-border-subtle: #99caff;
--bs-warning-border-subtle: rgb(255, 230.2, 155.8); --bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: rgb(207.0376569038, 173.1740585774, 156.3623430962); --bs-danger-border-subtle: #cfad9c;
--bs-light-border-subtle: #e9ecef; --bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255; --bs-white-rgb: 255, 255, 255;
@ -137,7 +137,7 @@ hr.my-3 {
--bs-link-color: #f1641e; --bs-link-color: #f1641e;
--bs-link-color-rgb: 241, 100, 30; --bs-link-color-rgb: 241, 100, 30;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(192.8, 80, 24); --bs-link-hover-color: #c15018;
--bs-link-hover-color-rgb: 193, 80, 24; --bs-link-hover-color-rgb: 193, 80, 24;
--bs-code-color: #d63384; --bs-code-color: #d63384;
--bs-highlight-color: #495057; --bs-highlight-color: #495057;
@ -162,8 +162,8 @@ hr.my-3 {
--bs-focus-ring-color: rgba(241, 100, 30, 0.25); --bs-focus-ring-color: rgba(241, 100, 30, 0.25);
--bs-form-valid-color: #007bff; --bs-form-valid-color: #007bff;
--bs-form-valid-border-color: #007bff; --bs-form-valid-border-color: #007bff;
--bs-form-invalid-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-form-invalid-color: #873208;
--bs-form-invalid-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-form-invalid-border-color: #873208;
} }
[data-bs-theme=dark] { [data-bs-theme=dark] {
@ -180,46 +180,46 @@ hr.my-3 {
--bs-secondary-bg-rgb: 52, 58, 64; --bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5); --bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: rgb(42.5, 47.5, 52.5); --bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53; --bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: rgb(246.6, 162, 120); --bs-primary-text-emphasis: #f7a278;
--bs-secondary-text-emphasis: rgb(102, 202.8, 144); --bs-secondary-text-emphasis: #66cb90;
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2); --bs-success-text-emphasis: #a370f7;
--bs-info-text-emphasis: rgb(102, 175.8, 255); --bs-info-text-emphasis: #66b0ff;
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2); --bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: rgb(183.0564853556, 132.2610878661, 107.0435146444); --bs-danger-text-emphasis: #b7846b;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(48.2, 20, 6); --bs-primary-bg-subtle: #301406;
--bs-secondary-bg-subtle: rgb(0, 33.6, 14); --bs-secondary-bg-subtle: #00220e;
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4); --bs-success-bg-subtle: #140330;
--bs-info-bg-subtle: rgb(0, 24.6, 51); --bs-info-bg-subtle: #001933;
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4); --bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: rgb(27.0188284519, 10.0870292887, 1.6811715481); --bs-danger-bg-subtle: #1b0a02;
--bs-light-bg-subtle: #343a40; --bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #2b2e31; --bs-dark-bg-subtle: #2b2e31;
--bs-primary-border-subtle: rgb(144.6, 60, 18); --bs-primary-border-subtle: #913c12;
--bs-secondary-border-subtle: rgb(0, 100.8, 42); --bs-secondary-border-subtle: #00652a;
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2); --bs-success-border-subtle: #3d0a91;
--bs-info-border-subtle: rgb(0, 73.8, 153); --bs-info-border-subtle: #004a99;
--bs-warning-border-subtle: rgb(153, 115.8, 4.2); --bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: rgb(81.0564853556, 30.2610878661, 5.0435146444); --bs-danger-border-subtle: #511e05;
--bs-light-border-subtle: #495057; --bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40; --bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(246.6, 162, 120); --bs-link-color: #f7a278;
--bs-link-hover-color: rgb(248.28, 180.6, 147); --bs-link-hover-color: #f9b593;
--bs-link-color-rgb: 247, 162, 120; --bs-link-color-rgb: 247, 162, 120;
--bs-link-hover-color-rgb: 248, 181, 147; --bs-link-hover-color-rgb: 249, 181, 147;
--bs-code-color: rgb(230.4, 132.6, 181.2); --bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: rgb(102, 77.2, 2.8); --bs-highlight-bg: #664d03;
--bs-border-color: #495057; --bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15); --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: rgb(102, 202.8, 144); --bs-form-valid-color: #66cb90;
--bs-form-valid-border-color: rgb(102, 202.8, 144); --bs-form-valid-border-color: #66cb90;
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6); --bs-form-invalid-color: #e891a6;
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6); --bs-form-invalid-border-color: #e891a6;
} }
*, *,
@ -1950,13 +1950,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(252.2, 224, 210); --bs-table-bg: #fce0d2;
--bs-table-border-color: rgb(208.56, 186, 174.8); --bs-table-border-color: #d0baaf;
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2); --bs-table-striped-bg: #f1d7c9;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(230.38, 205, 192.4); --bs-table-active-bg: #e6cdc0;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8); --bs-table-hover-bg: #ecd2c5;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1964,13 +1964,13 @@ progress {
.table-secondary { .table-secondary {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(204, 237.6, 218); --bs-table-bg: #cceeda;
--bs-table-border-color: rgb(170, 196.88, 181.2); --bs-table-border-color: #aac5b5;
--bs-table-striped-bg: rgb(195.5, 227.42, 208.8); --bs-table-striped-bg: #c4e4d1;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(187, 217.24, 199.6); --bs-table-active-bg: #bbdac8;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(191.25, 222.33, 204.2); --bs-table-hover-bg: #bfdfcc;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1978,13 +1978,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(224.4, 207.2, 252.4); --bs-table-bg: #e0cffc;
--bs-table-border-color: rgb(186.32, 172.56, 208.72); --bs-table-border-color: #baacd0;
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48); --bs-table-striped-bg: #d7c6f1;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(205.36, 189.88, 230.56); --bs-table-active-bg: #cdbee6;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02); --bs-table-hover-bg: #d2c2ec;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1992,13 +1992,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(204, 228.6, 255); --bs-table-bg: #cce5ff;
--bs-table-border-color: rgb(170, 189.68, 210.8); --bs-table-border-color: #aabed3;
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95); --bs-table-striped-bg: #c4dbf4;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(187, 209.14, 232.9); --bs-table-active-bg: #bbd2e9;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425); --bs-table-hover-bg: #bfd6ee;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2006,13 +2006,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(255, 242.6, 205.4); --bs-table-bg: #fff3cd;
--bs-table-border-color: rgb(210.8, 200.88, 171.12); --bs-table-border-color: #d3c9ab;
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83); --bs-table-striped-bg: #f4e9c4;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(232.9, 221.74, 188.26); --bs-table-active-bg: #e9debc;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545); --bs-table-hover-bg: #eee3c0;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2020,13 +2020,13 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(231.0188284519, 214.0870292887, 205.6811715481); --bs-table-bg: #e7d6ce;
--bs-table-border-color: rgb(191.6150627615, 178.069623431, 171.3449372385); --bs-table-border-color: #c0b2ac;
--bs-table-striped-bg: rgb(221.1678870293, 205.0826778243, 197.0971129707); --bs-table-striped-bg: #ddcdc5;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(211.3169456067, 196.0783263598, 188.5130543933); --bs-table-active-bg: #d3c4bd;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(216.242416318, 200.5805020921, 192.805083682); --bs-table-hover-bg: #d8c9c1;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2035,12 +2035,12 @@ progress {
.table-light { .table-light {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: #f8f9fa; --bs-table-bg: #f8f9fa;
--bs-table-border-color: rgb(205.2, 206, 206.8); --bs-table-border-color: #cdcecf;
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2); --bs-table-striped-bg: #edeeef;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(226.6, 227.5, 228.4); --bs-table-active-bg: #e3e4e4;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8); --bs-table-hover-bg: #e8e9ea;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2049,12 +2049,12 @@ progress {
.table-dark { .table-dark {
--bs-table-color: #fff; --bs-table-color: #fff;
--bs-table-bg: #212529; --bs-table-bg: #212529;
--bs-table-border-color: rgb(77.4, 80.6, 83.8); --bs-table-border-color: #4d5154;
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7); --bs-table-striped-bg: #2c3034;
--bs-table-striped-color: #fff; --bs-table-striped-color: #fff;
--bs-table-active-bg: rgb(55.2, 58.8, 62.4); --bs-table-active-bg: #373b3e;
--bs-table-active-color: #fff; --bs-table-active-color: #fff;
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05); --bs-table-hover-bg: #323539;
--bs-table-hover-color: #fff; --bs-table-hover-color: #fff;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2154,7 +2154,7 @@ progress {
.form-control:focus { .form-control:focus {
color: var(--bs-body-color); color: var(--bs-body-color);
background-color: var(--bs-body-bg); background-color: var(--bs-body-bg);
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
} }
@ -2299,7 +2299,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
} }
@ -2383,7 +2383,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
} }
@ -2430,7 +2430,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28248, 177.5, 142.5%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f8b28f'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2500,7 +2500,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(250.8, 208.5, 187.5); background-color: #fbd1bc;
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
width: 100%; width: 100%;
@ -2526,7 +2526,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(250.8, 208.5, 187.5); background-color: #fbd1bc;
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
width: 100%; width: 100%;
@ -2849,7 +2849,7 @@ textarea.form-control-lg {
.was-validated .form-control:invalid, .form-control.is-invalid { .was-validated .form-control:invalid, .form-control.is-invalid {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
padding-right: calc(1.5em + 0.75rem); padding-right: calc(1.5em + 0.75rem);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29' stroke='none'/%3e%3c/svg%3e"); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23873208'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23873208' stroke='none'/%3e%3c/svg%3e");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: right calc(0.375em + 0.1875rem) center; background-position: right calc(0.375em + 0.1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2868,7 +2868,7 @@ textarea.form-control-lg {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
} }
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29' stroke='none'/%3e%3c/svg%3e"); --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23873208'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23873208' stroke='none'/%3e%3c/svg%3e");
padding-right: 4.125rem; padding-right: 4.125rem;
background-position: right 0.75rem center, center right 2.25rem; background-position: right 0.75rem center, center right 2.25rem;
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2974,9 +2974,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2990,12 +2987,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f1641e; --bs-btn-bg: #f1641e;
--bs-btn-border-color: #f1641e; --bs-btn-border-color: #f1641e;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(204.85, 85, 25.5); --bs-btn-hover-bg: #cd551a;
--bs-btn-hover-border-color: rgb(192.8, 80, 24); --bs-btn-hover-border-color: #c15018;
--bs-btn-focus-shadow-rgb: 243, 123, 64; --bs-btn-focus-shadow-rgb: 243, 123, 64;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(192.8, 80, 24); --bs-btn-active-bg: #c15018;
--bs-btn-active-border-color: rgb(180.75, 75, 22.5); --bs-btn-active-border-color: #b54b17;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #f1641e; --bs-btn-disabled-bg: #f1641e;
@ -3007,12 +3004,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00a846; --bs-btn-bg: #00a846;
--bs-btn-border-color: #00a846; --bs-btn-border-color: #00a846;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(0, 142.8, 59.5); --bs-btn-hover-bg: #008f3c;
--bs-btn-hover-border-color: rgb(0, 134.4, 56); --bs-btn-hover-border-color: #008638;
--bs-btn-focus-shadow-rgb: 38, 181, 98; --bs-btn-focus-shadow-rgb: 38, 181, 98;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(0, 134.4, 56); --bs-btn-active-bg: #008638;
--bs-btn-active-border-color: rgb(0, 126, 52.5); --bs-btn-active-border-color: #007e35;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #00a846; --bs-btn-disabled-bg: #00a846;
@ -3024,12 +3021,12 @@ textarea.form-control-lg {
--bs-btn-bg: #6610f2; --bs-btn-bg: #6610f2;
--bs-btn-border-color: #6610f2; --bs-btn-border-color: #6610f2;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7); --bs-btn-hover-bg: #570ece;
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6); --bs-btn-hover-border-color: #520dc2;
--bs-btn-focus-shadow-rgb: 125, 52, 244; --bs-btn-focus-shadow-rgb: 125, 52, 244;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6); --bs-btn-active-bg: #520dc2;
--bs-btn-active-border-color: rgb(76.5, 12, 181.5); --bs-btn-active-border-color: #4d0cb6;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #6610f2; --bs-btn-disabled-bg: #6610f2;
@ -3041,12 +3038,12 @@ textarea.form-control-lg {
--bs-btn-bg: #007bff; --bs-btn-bg: #007bff;
--bs-btn-border-color: #007bff; --bs-btn-border-color: #007bff;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(0, 104.55, 216.75); --bs-btn-hover-bg: #0069d9;
--bs-btn-hover-border-color: rgb(0, 98.4, 204); --bs-btn-hover-border-color: #0062cc;
--bs-btn-focus-shadow-rgb: 38, 143, 255; --bs-btn-focus-shadow-rgb: 38, 143, 255;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(0, 98.4, 204); --bs-btn-active-bg: #0062cc;
--bs-btn-active-border-color: rgb(0, 92.25, 191.25); --bs-btn-active-border-color: #005cbf;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #007bff; --bs-btn-disabled-bg: #007bff;
@ -3058,12 +3055,12 @@ textarea.form-control-lg {
--bs-btn-bg: #ffc107; --bs-btn-bg: #ffc107;
--bs-btn-border-color: #ffc107; --bs-btn-border-color: #ffc107;
--bs-btn-hover-color: #222; --bs-btn-hover-color: #222;
--bs-btn-hover-bg: rgb(255, 202.3, 44.2); --bs-btn-hover-bg: #ffca2c;
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8); --bs-btn-hover-border-color: #ffc720;
--bs-btn-focus-shadow-rgb: 222, 169, 11; --bs-btn-focus-shadow-rgb: 222, 169, 11;
--bs-btn-active-color: #222; --bs-btn-active-color: #222;
--bs-btn-active-bg: rgb(255, 205.4, 56.6); --bs-btn-active-bg: #ffcd39;
--bs-btn-active-border-color: rgb(255, 199.2, 31.8); --bs-btn-active-border-color: #ffc720;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #222; --bs-btn-disabled-color: #222;
--bs-btn-disabled-bg: #ffc107; --bs-btn-disabled-bg: #ffc107;
@ -3072,19 +3069,19 @@ textarea.form-control-lg {
.btn-danger { .btn-danger {
--bs-btn-color: #fff; --bs-btn-color: #fff;
--bs-btn-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-bg: #873208;
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-border-color: #873208;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(114.8300209205, 42.869874477, 7.1449790795); --bs-btn-hover-bg: #732b07;
--bs-btn-hover-border-color: rgb(108.0753138075, 40.3481171548, 6.7246861925); --bs-btn-hover-border-color: #6c2806;
--bs-btn-focus-shadow-rgb: 153, 81, 45; --bs-btn-focus-shadow-rgb: 153, 81, 45;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(108.0753138075, 40.3481171548, 6.7246861925); --bs-btn-active-bg: #6c2806;
--bs-btn-active-border-color: rgb(101.3206066946, 37.8263598326, 6.3043933054); --bs-btn-active-border-color: #652606;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-disabled-bg: #873208;
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-disabled-border-color: #873208;
} }
.btn-light { .btn-light {
@ -3092,12 +3089,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f8f9fa; --bs-btn-bg: #f8f9fa;
--bs-btn-border-color: #f8f9fa; --bs-btn-border-color: #f8f9fa;
--bs-btn-hover-color: #222; --bs-btn-hover-color: #222;
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5); --bs-btn-hover-bg: #d3d4d5;
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200); --bs-btn-hover-border-color: #c6c7c8;
--bs-btn-focus-shadow-rgb: 216, 217, 218; --bs-btn-focus-shadow-rgb: 216, 217, 218;
--bs-btn-active-color: #222; --bs-btn-active-color: #222;
--bs-btn-active-bg: rgb(198.4, 199.2, 200); --bs-btn-active-bg: #c6c7c8;
--bs-btn-active-border-color: rgb(186, 186.75, 187.5); --bs-btn-active-border-color: #babbbc;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #222; --bs-btn-disabled-color: #222;
--bs-btn-disabled-bg: #f8f9fa; --bs-btn-disabled-bg: #f8f9fa;
@ -3109,12 +3106,12 @@ textarea.form-control-lg {
--bs-btn-bg: #212529; --bs-btn-bg: #212529;
--bs-btn-border-color: #212529; --bs-btn-border-color: #212529;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1); --bs-btn-hover-bg: #424649;
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4); --bs-btn-hover-border-color: #373b3e;
--bs-btn-focus-shadow-rgb: 66, 70, 73; --bs-btn-focus-shadow-rgb: 66, 70, 73;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8); --bs-btn-active-bg: #4d5154;
--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4); --bs-btn-active-border-color: #373b3e;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #212529; --bs-btn-disabled-bg: #212529;
@ -3207,19 +3204,19 @@ textarea.form-control-lg {
} }
.btn-outline-danger { .btn-outline-danger {
--bs-btn-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-color: #873208;
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-border-color: #873208;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-hover-bg: #873208;
--bs-btn-hover-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-hover-border-color: #873208;
--bs-btn-focus-shadow-rgb: 135, 50, 8; --bs-btn-focus-shadow-rgb: 135, 50, 8;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-active-bg: #873208;
--bs-btn-active-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-active-border-color: #873208;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-disabled-color: #873208;
--bs-btn-disabled-bg: transparent; --bs-btn-disabled-bg: transparent;
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-disabled-border-color: #873208;
--bs-gradient: none; --bs-gradient: none;
} }
@ -4501,11 +4498,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23495057' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%2896.4, 40, 12%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2360280c'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #f8b28f;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4563,6 +4561,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4580,7 +4579,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4591,11 +4590,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4604,27 +4603,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -5498,6 +5497,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6062,12 +6062,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6687,11 +6695,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {
@ -6846,8 +6857,8 @@ textarea.form-control-lg {
text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important; text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important;
} }
.link-danger:hover, .link-danger:focus { .link-danger:hover, .link-danger:focus {
color: RGBA(108, 40, 7, var(--bs-link-opacity, 1)) !important; color: RGBA(108, 40, 6, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(108, 40, 7, var(--bs-link-underline-opacity, 1)) !important; text-decoration-color: RGBA(108, 40, 6, var(--bs-link-underline-opacity, 1)) !important;
} }
.link-light { .link-light {

View file

@ -1,7 +1,7 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -34,7 +34,7 @@
--bs-success: #6610f2; --bs-success: #6610f2;
--bs-info: #007bff; --bs-info: #007bff;
--bs-warning: #ffc107; --bs-warning: #ffc107;
--bs-danger: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-danger: #8c3409;
--bs-light: #f8f9fa; --bs-light: #f8f9fa;
--bs-dark: #212529; --bs-dark: #212529;
--bs-primary-rgb: 241, 100, 30; --bs-primary-rgb: 241, 100, 30;
@ -45,28 +45,28 @@
--bs-danger-rgb: 140, 52, 9; --bs-danger-rgb: 140, 52, 9;
--bs-light-rgb: 248, 249, 250; --bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41; --bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: rgb(96.4, 40, 12); --bs-primary-text-emphasis: #60280c;
--bs-secondary-text-emphasis: #500000; --bs-secondary-text-emphasis: #500000;
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8); --bs-success-text-emphasis: #290661;
--bs-info-text-emphasis: rgb(0, 49.2, 102); --bs-info-text-emphasis: #003166;
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8); --bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: rgb(55.9581589958, 20.8910460251, 3.4818410042); --bs-danger-text-emphasis: #381504;
--bs-light-text-emphasis: #495057; --bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057; --bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: rgb(252.2, 224, 210); --bs-primary-bg-subtle: #fce0d2;
--bs-secondary-bg-subtle: #f4cccc; --bs-secondary-bg-subtle: #f4cccc;
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4); --bs-success-bg-subtle: #e0cffc;
--bs-info-bg-subtle: rgb(204, 228.6, 255); --bs-info-bg-subtle: #cce5ff;
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4); --bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: rgb(231.9790794979, 214.4455230126, 205.7409205021); --bs-danger-bg-subtle: #e8d6ce;
--bs-light-bg-subtle: rgb(251.5, 252, 252.5); --bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(249.4, 193, 165); --bs-primary-border-subtle: #f9c1a5;
--bs-secondary-border-subtle: #e99999; --bs-secondary-border-subtle: #e99999;
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8); --bs-success-border-subtle: #c29ffa;
--bs-info-border-subtle: rgb(153, 202.2, 255); --bs-info-border-subtle: #99caff;
--bs-warning-border-subtle: rgb(255, 230.2, 155.8); --bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: rgb(208.9581589958, 173.8910460251, 156.4818410042); --bs-danger-border-subtle: #d1ae9d;
--bs-light-border-subtle: #e9ecef; --bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255; --bs-white-rgb: 255, 255, 255;
@ -97,7 +97,7 @@
--bs-link-color: #f1641e; --bs-link-color: #f1641e;
--bs-link-color-rgb: 241, 100, 30; --bs-link-color-rgb: 241, 100, 30;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(192.8, 80, 24); --bs-link-hover-color: #c15018;
--bs-link-hover-color-rgb: 193, 80, 24; --bs-link-hover-color-rgb: 193, 80, 24;
--bs-code-color: #d63384; --bs-code-color: #d63384;
--bs-highlight-color: #495057; --bs-highlight-color: #495057;
@ -122,8 +122,8 @@
--bs-focus-ring-color: rgba(241, 100, 30, 0.25); --bs-focus-ring-color: rgba(241, 100, 30, 0.25);
--bs-form-valid-color: #007bff; --bs-form-valid-color: #007bff;
--bs-form-valid-border-color: #007bff; --bs-form-valid-border-color: #007bff;
--bs-form-invalid-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-form-invalid-color: #8c3409;
--bs-form-invalid-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-form-invalid-border-color: #8c3409;
} }
[data-bs-theme=dark] { [data-bs-theme=dark] {
@ -140,46 +140,46 @@
--bs-secondary-bg-rgb: 52, 58, 64; --bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5); --bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: rgb(42.5, 47.5, 52.5); --bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53; --bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: rgb(246.6, 162, 120); --bs-primary-text-emphasis: #f7a278;
--bs-secondary-text-emphasis: #de6666; --bs-secondary-text-emphasis: #de6666;
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2); --bs-success-text-emphasis: #a370f7;
--bs-info-text-emphasis: rgb(102, 175.8, 255); --bs-info-text-emphasis: #66b0ff;
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2); --bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: rgb(185.9372384937, 133.3365690377, 107.2227615063); --bs-danger-text-emphasis: #ba856b;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(48.2, 20, 6); --bs-primary-bg-subtle: #301406;
--bs-secondary-bg-subtle: #280000; --bs-secondary-bg-subtle: #280000;
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4); --bs-success-bg-subtle: #140330;
--bs-info-bg-subtle: rgb(0, 24.6, 51); --bs-info-bg-subtle: #001933;
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4); --bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: rgb(27.9790794979, 10.4455230126, 1.7409205021); --bs-danger-bg-subtle: #1c0a02;
--bs-light-bg-subtle: #343a40; --bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #2b2e31; --bs-dark-bg-subtle: #2b2e31;
--bs-primary-border-subtle: rgb(144.6, 60, 18); --bs-primary-border-subtle: #913c12;
--bs-secondary-border-subtle: #780000; --bs-secondary-border-subtle: #780000;
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2); --bs-success-border-subtle: #3d0a91;
--bs-info-border-subtle: rgb(0, 73.8, 153); --bs-info-border-subtle: #004a99;
--bs-warning-border-subtle: rgb(153, 115.8, 4.2); --bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: rgb(83.9372384937, 31.3365690377, 5.2227615063); --bs-danger-border-subtle: #541f05;
--bs-light-border-subtle: #495057; --bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40; --bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(246.6, 162, 120); --bs-link-color: #f7a278;
--bs-link-hover-color: rgb(248.28, 180.6, 147); --bs-link-hover-color: #f9b593;
--bs-link-color-rgb: 247, 162, 120; --bs-link-color-rgb: 247, 162, 120;
--bs-link-hover-color-rgb: 248, 181, 147; --bs-link-hover-color-rgb: 249, 181, 147;
--bs-code-color: rgb(230.4, 132.6, 181.2); --bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: rgb(102, 77.2, 2.8); --bs-highlight-bg: #664d03;
--bs-border-color: #495057; --bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15); --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: rgb(102, 202.8, 144); --bs-form-valid-color: #66cb90;
--bs-form-valid-border-color: rgb(102, 202.8, 144); --bs-form-valid-border-color: #66cb90;
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6); --bs-form-invalid-color: #e891a6;
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6); --bs-form-invalid-border-color: #e891a6;
} }
*, *,
@ -1934,13 +1934,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(252.2, 224, 210); --bs-table-bg: #fce0d2;
--bs-table-border-color: rgb(208.56, 186, 174.8); --bs-table-border-color: #d0baaf;
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2); --bs-table-striped-bg: #f1d7c9;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(230.38, 205, 192.4); --bs-table-active-bg: #e6cdc0;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8); --bs-table-hover-bg: #ecd2c5;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1950,11 +1950,11 @@ progress {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: #f4cccc; --bs-table-bg: #f4cccc;
--bs-table-border-color: #caaaaa; --bs-table-border-color: #caaaaa;
--bs-table-striped-bg: rgb(233.5, 195.5, 195.5); --bs-table-striped-bg: #eac4c4;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: #dfbbbb; --bs-table-active-bg: #dfbbbb;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(228.25, 191.25, 191.25); --bs-table-hover-bg: #e4bfbf;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1962,13 +1962,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(224.4, 207.2, 252.4); --bs-table-bg: #e0cffc;
--bs-table-border-color: rgb(186.32, 172.56, 208.72); --bs-table-border-color: #baacd0;
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48); --bs-table-striped-bg: #d7c6f1;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(205.36, 189.88, 230.56); --bs-table-active-bg: #cdbee6;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02); --bs-table-hover-bg: #d2c2ec;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1976,13 +1976,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(204, 228.6, 255); --bs-table-bg: #cce5ff;
--bs-table-border-color: rgb(170, 189.68, 210.8); --bs-table-border-color: #aabed3;
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95); --bs-table-striped-bg: #c4dbf4;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(187, 209.14, 232.9); --bs-table-active-bg: #bbd2e9;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425); --bs-table-hover-bg: #bfd6ee;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1990,13 +1990,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(255, 242.6, 205.4); --bs-table-bg: #fff3cd;
--bs-table-border-color: rgb(210.8, 200.88, 171.12); --bs-table-border-color: #d3c9ab;
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83); --bs-table-striped-bg: #f4e9c4;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(232.9, 221.74, 188.26); --bs-table-active-bg: #e9debc;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545); --bs-table-hover-bg: #eee3c0;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2004,13 +2004,13 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(231.9790794979, 214.4455230126, 205.7409205021); --bs-table-bg: #e8d6ce;
--bs-table-border-color: rgb(192.3832635983, 178.35641841, 171.3927364017); --bs-table-border-color: #c0b2ac;
--bs-table-striped-bg: rgb(222.080125523, 205.4232468619, 197.153874477); --bs-table-striped-bg: #decdc5;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(212.1811715481, 196.4009707113, 188.5668284519); --bs-table-active-bg: #d4c4bd;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(217.1306485356, 200.9121087866, 192.8603514644); --bs-table-hover-bg: #d9c9c1;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2019,12 +2019,12 @@ progress {
.table-light { .table-light {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: #f8f9fa; --bs-table-bg: #f8f9fa;
--bs-table-border-color: rgb(205.2, 206, 206.8); --bs-table-border-color: #cdcecf;
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2); --bs-table-striped-bg: #edeeef;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(226.6, 227.5, 228.4); --bs-table-active-bg: #e3e4e4;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8); --bs-table-hover-bg: #e8e9ea;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2033,12 +2033,12 @@ progress {
.table-dark { .table-dark {
--bs-table-color: #fff; --bs-table-color: #fff;
--bs-table-bg: #212529; --bs-table-bg: #212529;
--bs-table-border-color: rgb(77.4, 80.6, 83.8); --bs-table-border-color: #4d5154;
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7); --bs-table-striped-bg: #2c3034;
--bs-table-striped-color: #fff; --bs-table-striped-color: #fff;
--bs-table-active-bg: rgb(55.2, 58.8, 62.4); --bs-table-active-bg: #373b3e;
--bs-table-active-color: #fff; --bs-table-active-color: #fff;
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05); --bs-table-hover-bg: #323539;
--bs-table-hover-color: #fff; --bs-table-hover-color: #fff;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2138,7 +2138,7 @@ progress {
.form-control:focus { .form-control:focus {
color: var(--bs-body-color); color: var(--bs-body-color);
background-color: var(--bs-body-bg); background-color: var(--bs-body-bg);
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
} }
@ -2283,7 +2283,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
} }
@ -2367,7 +2367,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
} }
@ -2414,7 +2414,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28248, 177.5, 142.5%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f8b28f'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2484,7 +2484,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(250.8, 208.5, 187.5); background-color: #fbd1bc;
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
width: 100%; width: 100%;
@ -2510,7 +2510,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(250.8, 208.5, 187.5); background-color: #fbd1bc;
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
width: 100%; width: 100%;
@ -2833,7 +2833,7 @@ textarea.form-control-lg {
.was-validated .form-control:invalid, .form-control.is-invalid { .was-validated .form-control:invalid, .form-control.is-invalid {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
padding-right: calc(1.5em + 0.75rem); padding-right: calc(1.5em + 0.75rem);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28139.8953974895, 52.2276150628, 8.7046025105%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28139.8953974895, 52.2276150628, 8.7046025105%29' stroke='none'/%3e%3c/svg%3e"); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%238c3409'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%238c3409' stroke='none'/%3e%3c/svg%3e");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: right calc(0.375em + 0.1875rem) center; background-position: right calc(0.375em + 0.1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2852,7 +2852,7 @@ textarea.form-control-lg {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
} }
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28139.8953974895, 52.2276150628, 8.7046025105%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28139.8953974895, 52.2276150628, 8.7046025105%29' stroke='none'/%3e%3c/svg%3e"); --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%238c3409'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%238c3409' stroke='none'/%3e%3c/svg%3e");
padding-right: 4.125rem; padding-right: 4.125rem;
background-position: right 0.75rem center, center right 2.25rem; background-position: right 0.75rem center, center right 2.25rem;
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2958,9 +2958,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2974,12 +2971,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f1641e; --bs-btn-bg: #f1641e;
--bs-btn-border-color: #f1641e; --bs-btn-border-color: #f1641e;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(204.85, 85, 25.5); --bs-btn-hover-bg: #cd551a;
--bs-btn-hover-border-color: rgb(192.8, 80, 24); --bs-btn-hover-border-color: #c15018;
--bs-btn-focus-shadow-rgb: 243, 123, 64; --bs-btn-focus-shadow-rgb: 243, 123, 64;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(192.8, 80, 24); --bs-btn-active-bg: #c15018;
--bs-btn-active-border-color: rgb(180.75, 75, 22.5); --bs-btn-active-border-color: #b54b17;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #f1641e; --bs-btn-disabled-bg: #f1641e;
@ -3008,12 +3005,12 @@ textarea.form-control-lg {
--bs-btn-bg: #6610f2; --bs-btn-bg: #6610f2;
--bs-btn-border-color: #6610f2; --bs-btn-border-color: #6610f2;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7); --bs-btn-hover-bg: #570ece;
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6); --bs-btn-hover-border-color: #520dc2;
--bs-btn-focus-shadow-rgb: 125, 52, 244; --bs-btn-focus-shadow-rgb: 125, 52, 244;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6); --bs-btn-active-bg: #520dc2;
--bs-btn-active-border-color: rgb(76.5, 12, 181.5); --bs-btn-active-border-color: #4d0cb6;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #6610f2; --bs-btn-disabled-bg: #6610f2;
@ -3025,12 +3022,12 @@ textarea.form-control-lg {
--bs-btn-bg: #007bff; --bs-btn-bg: #007bff;
--bs-btn-border-color: #007bff; --bs-btn-border-color: #007bff;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(0, 104.55, 216.75); --bs-btn-hover-bg: #0069d9;
--bs-btn-hover-border-color: rgb(0, 98.4, 204); --bs-btn-hover-border-color: #0062cc;
--bs-btn-focus-shadow-rgb: 38, 143, 255; --bs-btn-focus-shadow-rgb: 38, 143, 255;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(0, 98.4, 204); --bs-btn-active-bg: #0062cc;
--bs-btn-active-border-color: rgb(0, 92.25, 191.25); --bs-btn-active-border-color: #005cbf;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #007bff; --bs-btn-disabled-bg: #007bff;
@ -3042,12 +3039,12 @@ textarea.form-control-lg {
--bs-btn-bg: #ffc107; --bs-btn-bg: #ffc107;
--bs-btn-border-color: #ffc107; --bs-btn-border-color: #ffc107;
--bs-btn-hover-color: #222; --bs-btn-hover-color: #222;
--bs-btn-hover-bg: rgb(255, 202.3, 44.2); --bs-btn-hover-bg: #ffca2c;
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8); --bs-btn-hover-border-color: #ffc720;
--bs-btn-focus-shadow-rgb: 222, 169, 11; --bs-btn-focus-shadow-rgb: 222, 169, 11;
--bs-btn-active-color: #222; --bs-btn-active-color: #222;
--bs-btn-active-bg: rgb(255, 205.4, 56.6); --bs-btn-active-bg: #ffcd39;
--bs-btn-active-border-color: rgb(255, 199.2, 31.8); --bs-btn-active-border-color: #ffc720;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #222; --bs-btn-disabled-color: #222;
--bs-btn-disabled-bg: #ffc107; --bs-btn-disabled-bg: #ffc107;
@ -3056,19 +3053,19 @@ textarea.form-control-lg {
.btn-danger { .btn-danger {
--bs-btn-color: #fff; --bs-btn-color: #fff;
--bs-btn-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-bg: #8c3409;
--bs-btn-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-border-color: #8c3409;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(118.9110878661, 44.3934728033, 7.3989121339); --bs-btn-hover-bg: #772c08;
--bs-btn-hover-border-color: rgb(111.9163179916, 41.7820920502, 6.9636820084); --bs-btn-hover-border-color: #702a07;
--bs-btn-focus-shadow-rgb: 157, 83, 46; --bs-btn-focus-shadow-rgb: 157, 82, 46;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(111.9163179916, 41.7820920502, 6.9636820084); --bs-btn-active-bg: #702a07;
--bs-btn-active-border-color: rgb(104.9215481172, 39.1707112971, 6.5284518828); --bs-btn-active-border-color: #692707;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-disabled-bg: #8c3409;
--bs-btn-disabled-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-disabled-border-color: #8c3409;
} }
.btn-light { .btn-light {
@ -3076,12 +3073,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f8f9fa; --bs-btn-bg: #f8f9fa;
--bs-btn-border-color: #f8f9fa; --bs-btn-border-color: #f8f9fa;
--bs-btn-hover-color: #222; --bs-btn-hover-color: #222;
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5); --bs-btn-hover-bg: #d3d4d5;
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200); --bs-btn-hover-border-color: #c6c7c8;
--bs-btn-focus-shadow-rgb: 216, 217, 218; --bs-btn-focus-shadow-rgb: 216, 217, 218;
--bs-btn-active-color: #222; --bs-btn-active-color: #222;
--bs-btn-active-bg: rgb(198.4, 199.2, 200); --bs-btn-active-bg: #c6c7c8;
--bs-btn-active-border-color: rgb(186, 186.75, 187.5); --bs-btn-active-border-color: #babbbc;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #222; --bs-btn-disabled-color: #222;
--bs-btn-disabled-bg: #f8f9fa; --bs-btn-disabled-bg: #f8f9fa;
@ -3093,12 +3090,12 @@ textarea.form-control-lg {
--bs-btn-bg: #212529; --bs-btn-bg: #212529;
--bs-btn-border-color: #212529; --bs-btn-border-color: #212529;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1); --bs-btn-hover-bg: #424649;
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4); --bs-btn-hover-border-color: #373b3e;
--bs-btn-focus-shadow-rgb: 66, 70, 73; --bs-btn-focus-shadow-rgb: 66, 70, 73;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8); --bs-btn-active-bg: #4d5154;
--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4); --bs-btn-active-border-color: #373b3e;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #212529; --bs-btn-disabled-bg: #212529;
@ -3191,19 +3188,19 @@ textarea.form-control-lg {
} }
.btn-outline-danger { .btn-outline-danger {
--bs-btn-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-color: #8c3409;
--bs-btn-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-border-color: #8c3409;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-hover-bg: #8c3409;
--bs-btn-hover-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-hover-border-color: #8c3409;
--bs-btn-focus-shadow-rgb: 140, 52, 9; --bs-btn-focus-shadow-rgb: 140, 52, 9;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-active-bg: #8c3409;
--bs-btn-active-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-active-border-color: #8c3409;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-disabled-color: #8c3409;
--bs-btn-disabled-bg: transparent; --bs-btn-disabled-bg: transparent;
--bs-btn-disabled-border-color: rgb(139.8953974895, 52.2276150628, 8.7046025105); --bs-btn-disabled-border-color: #8c3409;
--bs-gradient: none; --bs-gradient: none;
} }
@ -4489,11 +4486,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23495057' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%2896.4, 40, 12%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2360280c'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #f8b28f;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4551,6 +4549,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4568,7 +4567,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4579,11 +4578,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4592,27 +4591,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -5486,6 +5485,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6050,12 +6050,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6675,11 +6683,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {

View file

@ -1,7 +1,7 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -34,7 +34,7 @@
--bs-success: #6610f2; --bs-success: #6610f2;
--bs-info: #007bff; --bs-info: #007bff;
--bs-warning: #ffc107; --bs-warning: #ffc107;
--bs-danger: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-danger: #873208;
--bs-light: #f8f9fa; --bs-light: #f8f9fa;
--bs-dark: #212529; --bs-dark: #212529;
--bs-primary-rgb: 241, 100, 30; --bs-primary-rgb: 241, 100, 30;
@ -45,28 +45,28 @@
--bs-danger-rgb: 135, 50, 8; --bs-danger-rgb: 135, 50, 8;
--bs-light-rgb: 248, 249, 250; --bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41; --bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: rgb(96.4, 40, 12); --bs-primary-text-emphasis: #60280c;
--bs-secondary-text-emphasis: rgb(0, 67.2, 28); --bs-secondary-text-emphasis: #00431c;
--bs-success-text-emphasis: rgb(40.8, 6.4, 96.8); --bs-success-text-emphasis: #290661;
--bs-info-text-emphasis: rgb(0, 49.2, 102); --bs-info-text-emphasis: #003166;
--bs-warning-text-emphasis: rgb(102, 77.2, 2.8); --bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: rgb(54.0376569038, 20.1740585774, 3.3623430962); --bs-danger-text-emphasis: #361403;
--bs-light-text-emphasis: #495057; --bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057; --bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: rgb(252.2, 224, 210); --bs-primary-bg-subtle: #fce0d2;
--bs-secondary-bg-subtle: rgb(204, 237.6, 218); --bs-secondary-bg-subtle: #cceeda;
--bs-success-bg-subtle: rgb(224.4, 207.2, 252.4); --bs-success-bg-subtle: #e0cffc;
--bs-info-bg-subtle: rgb(204, 228.6, 255); --bs-info-bg-subtle: #cce5ff;
--bs-warning-bg-subtle: rgb(255, 242.6, 205.4); --bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: rgb(231.0188284519, 214.0870292887, 205.6811715481); --bs-danger-bg-subtle: #e7d6ce;
--bs-light-bg-subtle: rgb(251.5, 252, 252.5); --bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(249.4, 193, 165); --bs-primary-border-subtle: #f9c1a5;
--bs-secondary-border-subtle: rgb(153, 220.2, 181); --bs-secondary-border-subtle: #99dcb5;
--bs-success-border-subtle: rgb(193.8, 159.4, 249.8); --bs-success-border-subtle: #c29ffa;
--bs-info-border-subtle: rgb(153, 202.2, 255); --bs-info-border-subtle: #99caff;
--bs-warning-border-subtle: rgb(255, 230.2, 155.8); --bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: rgb(207.0376569038, 173.1740585774, 156.3623430962); --bs-danger-border-subtle: #cfad9c;
--bs-light-border-subtle: #e9ecef; --bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255; --bs-white-rgb: 255, 255, 255;
@ -97,7 +97,7 @@
--bs-link-color: #f1641e; --bs-link-color: #f1641e;
--bs-link-color-rgb: 241, 100, 30; --bs-link-color-rgb: 241, 100, 30;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(192.8, 80, 24); --bs-link-hover-color: #c15018;
--bs-link-hover-color-rgb: 193, 80, 24; --bs-link-hover-color-rgb: 193, 80, 24;
--bs-code-color: #d63384; --bs-code-color: #d63384;
--bs-highlight-color: #495057; --bs-highlight-color: #495057;
@ -122,8 +122,8 @@
--bs-focus-ring-color: rgba(241, 100, 30, 0.25); --bs-focus-ring-color: rgba(241, 100, 30, 0.25);
--bs-form-valid-color: #007bff; --bs-form-valid-color: #007bff;
--bs-form-valid-border-color: #007bff; --bs-form-valid-border-color: #007bff;
--bs-form-invalid-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-form-invalid-color: #873208;
--bs-form-invalid-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-form-invalid-border-color: #873208;
} }
[data-bs-theme=dark] { [data-bs-theme=dark] {
@ -140,46 +140,46 @@
--bs-secondary-bg-rgb: 52, 58, 64; --bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5); --bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: rgb(42.5, 47.5, 52.5); --bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53; --bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: rgb(246.6, 162, 120); --bs-primary-text-emphasis: #f7a278;
--bs-secondary-text-emphasis: rgb(102, 202.8, 144); --bs-secondary-text-emphasis: #66cb90;
--bs-success-text-emphasis: rgb(163.2, 111.6, 247.2); --bs-success-text-emphasis: #a370f7;
--bs-info-text-emphasis: rgb(102, 175.8, 255); --bs-info-text-emphasis: #66b0ff;
--bs-warning-text-emphasis: rgb(255, 217.8, 106.2); --bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: rgb(183.0564853556, 132.2610878661, 107.0435146444); --bs-danger-text-emphasis: #b7846b;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(48.2, 20, 6); --bs-primary-bg-subtle: #301406;
--bs-secondary-bg-subtle: rgb(0, 33.6, 14); --bs-secondary-bg-subtle: #00220e;
--bs-success-bg-subtle: rgb(20.4, 3.2, 48.4); --bs-success-bg-subtle: #140330;
--bs-info-bg-subtle: rgb(0, 24.6, 51); --bs-info-bg-subtle: #001933;
--bs-warning-bg-subtle: rgb(51, 38.6, 1.4); --bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: rgb(27.0188284519, 10.0870292887, 1.6811715481); --bs-danger-bg-subtle: #1b0a02;
--bs-light-bg-subtle: #343a40; --bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #2b2e31; --bs-dark-bg-subtle: #2b2e31;
--bs-primary-border-subtle: rgb(144.6, 60, 18); --bs-primary-border-subtle: #913c12;
--bs-secondary-border-subtle: rgb(0, 100.8, 42); --bs-secondary-border-subtle: #00652a;
--bs-success-border-subtle: rgb(61.2, 9.6, 145.2); --bs-success-border-subtle: #3d0a91;
--bs-info-border-subtle: rgb(0, 73.8, 153); --bs-info-border-subtle: #004a99;
--bs-warning-border-subtle: rgb(153, 115.8, 4.2); --bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: rgb(81.0564853556, 30.2610878661, 5.0435146444); --bs-danger-border-subtle: #511e05;
--bs-light-border-subtle: #495057; --bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40; --bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(246.6, 162, 120); --bs-link-color: #f7a278;
--bs-link-hover-color: rgb(248.28, 180.6, 147); --bs-link-hover-color: #f9b593;
--bs-link-color-rgb: 247, 162, 120; --bs-link-color-rgb: 247, 162, 120;
--bs-link-hover-color-rgb: 248, 181, 147; --bs-link-hover-color-rgb: 249, 181, 147;
--bs-code-color: rgb(230.4, 132.6, 181.2); --bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: rgb(102, 77.2, 2.8); --bs-highlight-bg: #664d03;
--bs-border-color: #495057; --bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15); --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: rgb(102, 202.8, 144); --bs-form-valid-color: #66cb90;
--bs-form-valid-border-color: rgb(102, 202.8, 144); --bs-form-valid-border-color: #66cb90;
--bs-form-invalid-color: rgb(231.6, 145.2, 165.6); --bs-form-invalid-color: #e891a6;
--bs-form-invalid-border-color: rgb(231.6, 145.2, 165.6); --bs-form-invalid-border-color: #e891a6;
} }
*, *,
@ -1934,13 +1934,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(252.2, 224, 210); --bs-table-bg: #fce0d2;
--bs-table-border-color: rgb(208.56, 186, 174.8); --bs-table-border-color: #d0baaf;
--bs-table-striped-bg: rgb(241.29, 214.5, 201.2); --bs-table-striped-bg: #f1d7c9;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(230.38, 205, 192.4); --bs-table-active-bg: #e6cdc0;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(235.835, 209.75, 196.8); --bs-table-hover-bg: #ecd2c5;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1948,13 +1948,13 @@ progress {
.table-secondary { .table-secondary {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(204, 237.6, 218); --bs-table-bg: #cceeda;
--bs-table-border-color: rgb(170, 196.88, 181.2); --bs-table-border-color: #aac5b5;
--bs-table-striped-bg: rgb(195.5, 227.42, 208.8); --bs-table-striped-bg: #c4e4d1;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(187, 217.24, 199.6); --bs-table-active-bg: #bbdac8;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(191.25, 222.33, 204.2); --bs-table-hover-bg: #bfdfcc;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1962,13 +1962,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(224.4, 207.2, 252.4); --bs-table-bg: #e0cffc;
--bs-table-border-color: rgb(186.32, 172.56, 208.72); --bs-table-border-color: #baacd0;
--bs-table-striped-bg: rgb(214.88, 198.54, 241.48); --bs-table-striped-bg: #d7c6f1;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(205.36, 189.88, 230.56); --bs-table-active-bg: #cdbee6;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(210.12, 194.21, 236.02); --bs-table-hover-bg: #d2c2ec;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1976,13 +1976,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(204, 228.6, 255); --bs-table-bg: #cce5ff;
--bs-table-border-color: rgb(170, 189.68, 210.8); --bs-table-border-color: #aabed3;
--bs-table-striped-bg: rgb(195.5, 218.87, 243.95); --bs-table-striped-bg: #c4dbf4;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(187, 209.14, 232.9); --bs-table-active-bg: #bbd2e9;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(191.25, 214.005, 238.425); --bs-table-hover-bg: #bfd6ee;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1990,13 +1990,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(255, 242.6, 205.4); --bs-table-bg: #fff3cd;
--bs-table-border-color: rgb(210.8, 200.88, 171.12); --bs-table-border-color: #d3c9ab;
--bs-table-striped-bg: rgb(243.95, 232.17, 196.83); --bs-table-striped-bg: #f4e9c4;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(232.9, 221.74, 188.26); --bs-table-active-bg: #e9debc;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(238.425, 226.955, 192.545); --bs-table-hover-bg: #eee3c0;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2004,13 +2004,13 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: rgb(231.0188284519, 214.0870292887, 205.6811715481); --bs-table-bg: #e7d6ce;
--bs-table-border-color: rgb(191.6150627615, 178.069623431, 171.3449372385); --bs-table-border-color: #c0b2ac;
--bs-table-striped-bg: rgb(221.1678870293, 205.0826778243, 197.0971129707); --bs-table-striped-bg: #ddcdc5;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(211.3169456067, 196.0783263598, 188.5130543933); --bs-table-active-bg: #d3c4bd;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(216.242416318, 200.5805020921, 192.805083682); --bs-table-hover-bg: #d8c9c1;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2019,12 +2019,12 @@ progress {
.table-light { .table-light {
--bs-table-color: #222; --bs-table-color: #222;
--bs-table-bg: #f8f9fa; --bs-table-bg: #f8f9fa;
--bs-table-border-color: rgb(205.2, 206, 206.8); --bs-table-border-color: #cdcecf;
--bs-table-striped-bg: rgb(237.3, 238.25, 239.2); --bs-table-striped-bg: #edeeef;
--bs-table-striped-color: #222; --bs-table-striped-color: #222;
--bs-table-active-bg: rgb(226.6, 227.5, 228.4); --bs-table-active-bg: #e3e4e4;
--bs-table-active-color: #222; --bs-table-active-color: #222;
--bs-table-hover-bg: rgb(231.95, 232.875, 233.8); --bs-table-hover-bg: #e8e9ea;
--bs-table-hover-color: #222; --bs-table-hover-color: #222;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2033,12 +2033,12 @@ progress {
.table-dark { .table-dark {
--bs-table-color: #fff; --bs-table-color: #fff;
--bs-table-bg: #212529; --bs-table-bg: #212529;
--bs-table-border-color: rgb(77.4, 80.6, 83.8); --bs-table-border-color: #4d5154;
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7); --bs-table-striped-bg: #2c3034;
--bs-table-striped-color: #fff; --bs-table-striped-color: #fff;
--bs-table-active-bg: rgb(55.2, 58.8, 62.4); --bs-table-active-bg: #373b3e;
--bs-table-active-color: #fff; --bs-table-active-color: #fff;
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05); --bs-table-hover-bg: #323539;
--bs-table-hover-color: #fff; --bs-table-hover-color: #fff;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2138,7 +2138,7 @@ progress {
.form-control:focus { .form-control:focus {
color: var(--bs-body-color); color: var(--bs-body-color);
background-color: var(--bs-body-bg); background-color: var(--bs-body-bg);
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
} }
@ -2283,7 +2283,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.75);
} }
@ -2367,7 +2367,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(248, 177.5, 142.5); border-color: #f8b28f;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
} }
@ -2414,7 +2414,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28248, 177.5, 142.5%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f8b28f'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2484,7 +2484,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(250.8, 208.5, 187.5); background-color: #fbd1bc;
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
width: 100%; width: 100%;
@ -2510,7 +2510,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(250.8, 208.5, 187.5); background-color: #fbd1bc;
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
width: 100%; width: 100%;
@ -2833,7 +2833,7 @@ textarea.form-control-lg {
.was-validated .form-control:invalid, .form-control.is-invalid { .was-validated .form-control:invalid, .form-control.is-invalid {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
padding-right: calc(1.5em + 0.75rem); padding-right: calc(1.5em + 0.75rem);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29' stroke='none'/%3e%3c/svg%3e"); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23873208'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23873208' stroke='none'/%3e%3c/svg%3e");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: right calc(0.375em + 0.1875rem) center; background-position: right calc(0.375em + 0.1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2852,7 +2852,7 @@ textarea.form-control-lg {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
} }
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] {
--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='rgb%28135.0941422594, 50.4351464435, 8.4058577406%29' stroke='none'/%3e%3c/svg%3e"); --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23873208'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23873208' stroke='none'/%3e%3c/svg%3e");
padding-right: 4.125rem; padding-right: 4.125rem;
background-position: right 0.75rem center, center right 2.25rem; background-position: right 0.75rem center, center right 2.25rem;
background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
@ -2958,9 +2958,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2974,12 +2971,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f1641e; --bs-btn-bg: #f1641e;
--bs-btn-border-color: #f1641e; --bs-btn-border-color: #f1641e;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(204.85, 85, 25.5); --bs-btn-hover-bg: #cd551a;
--bs-btn-hover-border-color: rgb(192.8, 80, 24); --bs-btn-hover-border-color: #c15018;
--bs-btn-focus-shadow-rgb: 243, 123, 64; --bs-btn-focus-shadow-rgb: 243, 123, 64;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(192.8, 80, 24); --bs-btn-active-bg: #c15018;
--bs-btn-active-border-color: rgb(180.75, 75, 22.5); --bs-btn-active-border-color: #b54b17;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #f1641e; --bs-btn-disabled-bg: #f1641e;
@ -2991,12 +2988,12 @@ textarea.form-control-lg {
--bs-btn-bg: #00a846; --bs-btn-bg: #00a846;
--bs-btn-border-color: #00a846; --bs-btn-border-color: #00a846;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(0, 142.8, 59.5); --bs-btn-hover-bg: #008f3c;
--bs-btn-hover-border-color: rgb(0, 134.4, 56); --bs-btn-hover-border-color: #008638;
--bs-btn-focus-shadow-rgb: 38, 181, 98; --bs-btn-focus-shadow-rgb: 38, 181, 98;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(0, 134.4, 56); --bs-btn-active-bg: #008638;
--bs-btn-active-border-color: rgb(0, 126, 52.5); --bs-btn-active-border-color: #007e35;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #00a846; --bs-btn-disabled-bg: #00a846;
@ -3008,12 +3005,12 @@ textarea.form-control-lg {
--bs-btn-bg: #6610f2; --bs-btn-bg: #6610f2;
--bs-btn-border-color: #6610f2; --bs-btn-border-color: #6610f2;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(86.7, 13.6, 205.7); --bs-btn-hover-bg: #570ece;
--bs-btn-hover-border-color: rgb(81.6, 12.8, 193.6); --bs-btn-hover-border-color: #520dc2;
--bs-btn-focus-shadow-rgb: 125, 52, 244; --bs-btn-focus-shadow-rgb: 125, 52, 244;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(81.6, 12.8, 193.6); --bs-btn-active-bg: #520dc2;
--bs-btn-active-border-color: rgb(76.5, 12, 181.5); --bs-btn-active-border-color: #4d0cb6;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #6610f2; --bs-btn-disabled-bg: #6610f2;
@ -3025,12 +3022,12 @@ textarea.form-control-lg {
--bs-btn-bg: #007bff; --bs-btn-bg: #007bff;
--bs-btn-border-color: #007bff; --bs-btn-border-color: #007bff;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(0, 104.55, 216.75); --bs-btn-hover-bg: #0069d9;
--bs-btn-hover-border-color: rgb(0, 98.4, 204); --bs-btn-hover-border-color: #0062cc;
--bs-btn-focus-shadow-rgb: 38, 143, 255; --bs-btn-focus-shadow-rgb: 38, 143, 255;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(0, 98.4, 204); --bs-btn-active-bg: #0062cc;
--bs-btn-active-border-color: rgb(0, 92.25, 191.25); --bs-btn-active-border-color: #005cbf;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #007bff; --bs-btn-disabled-bg: #007bff;
@ -3042,12 +3039,12 @@ textarea.form-control-lg {
--bs-btn-bg: #ffc107; --bs-btn-bg: #ffc107;
--bs-btn-border-color: #ffc107; --bs-btn-border-color: #ffc107;
--bs-btn-hover-color: #222; --bs-btn-hover-color: #222;
--bs-btn-hover-bg: rgb(255, 202.3, 44.2); --bs-btn-hover-bg: #ffca2c;
--bs-btn-hover-border-color: rgb(255, 199.2, 31.8); --bs-btn-hover-border-color: #ffc720;
--bs-btn-focus-shadow-rgb: 222, 169, 11; --bs-btn-focus-shadow-rgb: 222, 169, 11;
--bs-btn-active-color: #222; --bs-btn-active-color: #222;
--bs-btn-active-bg: rgb(255, 205.4, 56.6); --bs-btn-active-bg: #ffcd39;
--bs-btn-active-border-color: rgb(255, 199.2, 31.8); --bs-btn-active-border-color: #ffc720;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #222; --bs-btn-disabled-color: #222;
--bs-btn-disabled-bg: #ffc107; --bs-btn-disabled-bg: #ffc107;
@ -3056,19 +3053,19 @@ textarea.form-control-lg {
.btn-danger { .btn-danger {
--bs-btn-color: #fff; --bs-btn-color: #fff;
--bs-btn-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-bg: #873208;
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-border-color: #873208;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(114.8300209205, 42.869874477, 7.1449790795); --bs-btn-hover-bg: #732b07;
--bs-btn-hover-border-color: rgb(108.0753138075, 40.3481171548, 6.7246861925); --bs-btn-hover-border-color: #6c2806;
--bs-btn-focus-shadow-rgb: 153, 81, 45; --bs-btn-focus-shadow-rgb: 153, 81, 45;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(108.0753138075, 40.3481171548, 6.7246861925); --bs-btn-active-bg: #6c2806;
--bs-btn-active-border-color: rgb(101.3206066946, 37.8263598326, 6.3043933054); --bs-btn-active-border-color: #652606;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-disabled-bg: #873208;
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-disabled-border-color: #873208;
} }
.btn-light { .btn-light {
@ -3076,12 +3073,12 @@ textarea.form-control-lg {
--bs-btn-bg: #f8f9fa; --bs-btn-bg: #f8f9fa;
--bs-btn-border-color: #f8f9fa; --bs-btn-border-color: #f8f9fa;
--bs-btn-hover-color: #222; --bs-btn-hover-color: #222;
--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5); --bs-btn-hover-bg: #d3d4d5;
--bs-btn-hover-border-color: rgb(198.4, 199.2, 200); --bs-btn-hover-border-color: #c6c7c8;
--bs-btn-focus-shadow-rgb: 216, 217, 218; --bs-btn-focus-shadow-rgb: 216, 217, 218;
--bs-btn-active-color: #222; --bs-btn-active-color: #222;
--bs-btn-active-bg: rgb(198.4, 199.2, 200); --bs-btn-active-bg: #c6c7c8;
--bs-btn-active-border-color: rgb(186, 186.75, 187.5); --bs-btn-active-border-color: #babbbc;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #222; --bs-btn-disabled-color: #222;
--bs-btn-disabled-bg: #f8f9fa; --bs-btn-disabled-bg: #f8f9fa;
@ -3093,12 +3090,12 @@ textarea.form-control-lg {
--bs-btn-bg: #212529; --bs-btn-bg: #212529;
--bs-btn-border-color: #212529; --bs-btn-border-color: #212529;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1); --bs-btn-hover-bg: #424649;
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4); --bs-btn-hover-border-color: #373b3e;
--bs-btn-focus-shadow-rgb: 66, 70, 73; --bs-btn-focus-shadow-rgb: 66, 70, 73;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8); --bs-btn-active-bg: #4d5154;
--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4); --bs-btn-active-border-color: #373b3e;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #212529; --bs-btn-disabled-bg: #212529;
@ -3191,19 +3188,19 @@ textarea.form-control-lg {
} }
.btn-outline-danger { .btn-outline-danger {
--bs-btn-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-color: #873208;
--bs-btn-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-border-color: #873208;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-hover-bg: #873208;
--bs-btn-hover-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-hover-border-color: #873208;
--bs-btn-focus-shadow-rgb: 135, 50, 8; --bs-btn-focus-shadow-rgb: 135, 50, 8;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-active-bg: #873208;
--bs-btn-active-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-active-border-color: #873208;
--bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(34, 34, 34, 0.125);
--bs-btn-disabled-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-disabled-color: #873208;
--bs-btn-disabled-bg: transparent; --bs-btn-disabled-bg: transparent;
--bs-btn-disabled-border-color: rgb(135.0941422594, 50.4351464435, 8.4058577406); --bs-btn-disabled-border-color: #873208;
--bs-gradient: none; --bs-gradient: none;
} }
@ -4489,11 +4486,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23495057' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%2896.4, 40, 12%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2360280c'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #f8b28f;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(241, 100, 30, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4551,6 +4549,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4568,7 +4567,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4579,11 +4578,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4592,27 +4591,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28246.6, 162, 120%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23f7a278'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -5486,6 +5485,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6050,12 +6050,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6675,11 +6683,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {
@ -6834,8 +6845,8 @@ textarea.form-control-lg {
text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important; text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important;
} }
.link-danger:hover, .link-danger:focus { .link-danger:hover, .link-danger:focus {
color: RGBA(108, 40, 7, var(--bs-link-opacity, 1)) !important; color: RGBA(108, 40, 6, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(108, 40, 7, var(--bs-link-underline-opacity, 1)) !important; text-decoration-color: RGBA(108, 40, 6, var(--bs-link-underline-opacity, 1)) !important;
} }
.link-light { .link-light {

View file

@ -1,7 +1,7 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -45,27 +45,27 @@
--bs-danger-rgb: 255, 95, 110; --bs-danger-rgb: 255, 95, 110;
--bs-light-rgb: 68, 68, 68; --bs-light-rgb: 68, 68, 68;
--bs-dark-rgb: 235, 235, 235; --bs-dark-rgb: 235, 235, 235;
--bs-primary-text-emphasis: rgb(102, 25.6, 74.4); --bs-primary-text-emphasis: #661a4a;
--bs-secondary-text-emphasis: rgb(0.4, 82, 101.6); --bs-secondary-text-emphasis: #005266;
--bs-success-text-emphasis: rgb(2, 102, 64.4); --bs-success-text-emphasis: #026640;
--bs-info-text-emphasis: rgb(0.4, 82, 101.6); --bs-info-text-emphasis: #005266;
--bs-warning-text-emphasis: rgb(102, 100.4, 60); --bs-warning-text-emphasis: #66643c;
--bs-danger-text-emphasis: #66262c; --bs-danger-text-emphasis: #66262c;
--bs-light-text-emphasis: #444; --bs-light-text-emphasis: #444;
--bs-dark-text-emphasis: #444; --bs-dark-text-emphasis: #444;
--bs-primary-bg-subtle: rgb(255, 216.8, 241.2); --bs-primary-bg-subtle: #ffd9f1;
--bs-secondary-bg-subtle: rgb(204.2, 245, 254.8); --bs-secondary-bg-subtle: #ccf5ff;
--bs-success-bg-subtle: rgb(205, 255, 236.2); --bs-success-bg-subtle: #cdffec;
--bs-info-bg-subtle: rgb(204.2, 245, 254.8); --bs-info-bg-subtle: #ccf5ff;
--bs-warning-bg-subtle: rgb(255, 254.2, 234); --bs-warning-bg-subtle: #fffeea;
--bs-danger-bg-subtle: #ffdfe2; --bs-danger-bg-subtle: #ffdfe2;
--bs-light-bg-subtle: rgb(251.5, 252, 252.5); --bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(255, 178.6, 227.4); --bs-primary-border-subtle: #ffb3e3;
--bs-secondary-border-subtle: rgb(153.4, 235, 254.6); --bs-secondary-border-subtle: #99ebff;
--bs-success-border-subtle: rgb(155, 255, 217.4); --bs-success-border-subtle: #9bffd9;
--bs-info-border-subtle: rgb(153.4, 235, 254.6); --bs-info-border-subtle: #99ebff;
--bs-warning-border-subtle: rgb(255, 253.4, 213); --bs-warning-border-subtle: #fffdd5;
--bs-danger-border-subtle: #ffbfc5; --bs-danger-border-subtle: #ffbfc5;
--bs-light-border-subtle: #ebebeb; --bs-light-border-subtle: #ebebeb;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
@ -97,7 +97,7 @@
--bs-link-color: rgb(255, 64, 186); --bs-link-color: rgb(255, 64, 186);
--bs-link-color-rgb: 255, 64, 186; --bs-link-color-rgb: 255, 64, 186;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(204, 51.2, 148.8); --bs-link-hover-color: #cc3395;
--bs-link-hover-color-rgb: 204, 51, 149; --bs-link-hover-color-rgb: 204, 51, 149;
--bs-code-color: rgb(255, 64, 186); --bs-code-color: rgb(255, 64, 186);
--bs-highlight-color: #ebebeb; --bs-highlight-color: #ebebeb;
@ -142,42 +142,42 @@
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #292929; --bs-tertiary-bg: #292929;
--bs-tertiary-bg-rgb: 41, 41, 41; --bs-tertiary-bg-rgb: 41, 41, 41;
--bs-primary-text-emphasis: rgb(255, 140.4, 213.6); --bs-primary-text-emphasis: #ff8cd6;
--bs-secondary-text-emphasis: rgb(102.6, 225, 254.4); --bs-secondary-text-emphasis: #67e1fe;
--bs-success-text-emphasis: rgb(105, 255, 198.6); --bs-success-text-emphasis: #69ffc7;
--bs-info-text-emphasis: rgb(102.6, 225, 254.4); --bs-info-text-emphasis: #67e1fe;
--bs-warning-text-emphasis: rgb(255, 252.6, 192); --bs-warning-text-emphasis: #fffdc0;
--bs-danger-text-emphasis: #ff9fa8; --bs-danger-text-emphasis: #ff9fa8;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(51, 12.8, 37.2); --bs-primary-bg-subtle: #330d25;
--bs-secondary-bg-subtle: rgb(0.2, 41, 50.8); --bs-secondary-bg-subtle: #002933;
--bs-success-bg-subtle: rgb(1, 51, 32.2); --bs-success-bg-subtle: #013320;
--bs-info-bg-subtle: rgb(0.2, 41, 50.8); --bs-info-bg-subtle: #002933;
--bs-warning-bg-subtle: rgb(51, 50.2, 30); --bs-warning-bg-subtle: #33321e;
--bs-danger-bg-subtle: #331316; --bs-danger-bg-subtle: #331316;
--bs-light-bg-subtle: #303030; --bs-light-bg-subtle: #303030;
--bs-dark-bg-subtle: #181818; --bs-dark-bg-subtle: #181818;
--bs-primary-border-subtle: rgb(153, 38.4, 111.6); --bs-primary-border-subtle: #992670;
--bs-secondary-border-subtle: rgb(0.6, 123, 152.4); --bs-secondary-border-subtle: #017b98;
--bs-success-border-subtle: rgb(3, 153, 96.6); --bs-success-border-subtle: #039961;
--bs-info-border-subtle: rgb(0.6, 123, 152.4); --bs-info-border-subtle: #017b98;
--bs-warning-border-subtle: rgb(153, 150.6, 90); --bs-warning-border-subtle: #99975a;
--bs-danger-border-subtle: #993942; --bs-danger-border-subtle: #993942;
--bs-light-border-subtle: #444; --bs-light-border-subtle: #444;
--bs-dark-border-subtle: #303030; --bs-dark-border-subtle: #303030;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(255, 140.4, 213.6); --bs-link-color: #ff8cd6;
--bs-link-hover-color: rgb(255, 163.32, 221.88); --bs-link-hover-color: #ffa3de;
--bs-link-color-rgb: 255, 140, 214; --bs-link-color-rgb: 255, 140, 214;
--bs-link-hover-color-rgb: 255, 163, 222; --bs-link-hover-color-rgb: 255, 163, 222;
--bs-code-color: rgb(255, 140.4, 213.6); --bs-code-color: #ff8cd6;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: #888; --bs-highlight-bg: #888;
--bs-border-color: #444; --bs-border-color: #444;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15); --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: rgb(105, 255, 198.6); --bs-form-valid-color: #69ffc7;
--bs-form-valid-border-color: rgb(105, 255, 198.6); --bs-form-valid-border-color: #69ffc7;
--bs-form-invalid-color: #ff9fa8; --bs-form-invalid-color: #ff9fa8;
--bs-form-invalid-border-color: #ff9fa8; --bs-form-invalid-border-color: #ff9fa8;
} }
@ -1936,13 +1936,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(255, 216.8, 241.2); --bs-table-bg: #ffd9f1;
--bs-table-border-color: rgb(204, 173.44, 192.96); --bs-table-border-color: #ccaec1;
--bs-table-striped-bg: rgb(242.25, 205.96, 229.14); --bs-table-striped-bg: #f2cee5;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(229.5, 195.12, 217.08); --bs-table-active-bg: #e6c3d9;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(235.875, 200.54, 223.11); --bs-table-hover-bg: #ecc9df;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1950,13 +1950,13 @@ progress {
.table-secondary { .table-secondary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204.2, 245, 254.8); --bs-table-bg: #ccf5ff;
--bs-table-border-color: rgb(163.36, 196, 203.84); --bs-table-border-color: #a3c4cc;
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06); --bs-table-striped-bg: #c2e9f2;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.78, 220.5, 229.32); --bs-table-active-bg: #b8dde6;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69); --bs-table-hover-bg: #bde3ec;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1964,13 +1964,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(205, 255, 236.2); --bs-table-bg: #cdffec;
--bs-table-border-color: rgb(164, 204, 188.96); --bs-table-border-color: #a4ccbd;
--bs-table-striped-bg: rgb(194.75, 242.25, 224.39); --bs-table-striped-bg: #c3f2e0;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(184.5, 229.5, 212.58); --bs-table-active-bg: #b9e6d4;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(189.625, 235.875, 218.485); --bs-table-hover-bg: #beecda;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1978,13 +1978,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204.2, 245, 254.8); --bs-table-bg: #ccf5ff;
--bs-table-border-color: rgb(163.36, 196, 203.84); --bs-table-border-color: #a3c4cc;
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06); --bs-table-striped-bg: #c2e9f2;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.78, 220.5, 229.32); --bs-table-active-bg: #b8dde6;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69); --bs-table-hover-bg: #bde3ec;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1992,13 +1992,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(255, 254.2, 234); --bs-table-bg: #fffeea;
--bs-table-border-color: rgb(204, 203.36, 187.2); --bs-table-border-color: #cccbbb;
--bs-table-striped-bg: rgb(242.25, 241.49, 222.3); --bs-table-striped-bg: #f2f1de;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(229.5, 228.78, 210.6); --bs-table-active-bg: #e6e5d3;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(235.875, 235.135, 216.45); --bs-table-hover-bg: #ecebd8;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2007,12 +2007,12 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: #ffdfe2; --bs-table-bg: #ffdfe2;
--bs-table-border-color: rgb(204, 178.4, 180.8); --bs-table-border-color: #ccb2b5;
--bs-table-striped-bg: rgb(242.25, 211.85, 214.7); --bs-table-striped-bg: #f2d4d7;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(229.5, 200.7, 203.4); --bs-table-active-bg: #e6c9cb;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(235.875, 206.275, 209.05); --bs-table-hover-bg: #ecced1;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2021,12 +2021,12 @@ progress {
.table-light { .table-light {
--bs-table-color: #fff; --bs-table-color: #fff;
--bs-table-bg: #444; --bs-table-bg: #444;
--bs-table-border-color: rgb(105.4, 105.4, 105.4); --bs-table-border-color: dimgray;
--bs-table-striped-bg: rgb(77.35, 77.35, 77.35); --bs-table-striped-bg: #4d4d4d;
--bs-table-striped-color: #fff; --bs-table-striped-color: #fff;
--bs-table-active-bg: rgb(86.7, 86.7, 86.7); --bs-table-active-bg: #575757;
--bs-table-active-color: #fff; --bs-table-active-color: #fff;
--bs-table-hover-bg: rgb(82.025, 82.025, 82.025); --bs-table-hover-bg: #525252;
--bs-table-hover-color: #fff; --bs-table-hover-color: #fff;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2036,11 +2036,11 @@ progress {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: #ebebeb; --bs-table-bg: #ebebeb;
--bs-table-border-color: #bcbcbc; --bs-table-border-color: #bcbcbc;
--bs-table-striped-bg: rgb(223.25, 223.25, 223.25); --bs-table-striped-bg: #dfdfdf;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(211.5, 211.5, 211.5); --bs-table-active-bg: #d4d4d4;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(217.375, 217.375, 217.375); --bs-table-hover-bg: #d9d9d9;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2141,7 +2141,7 @@ progress {
.form-control:focus { .form-control:focus {
color: #fff; color: #fff;
background-color: #888; background-color: #888;
border-color: rgb(255, 159.5, 220.5); border-color: #ffa0dd;
outline: 0; outline: 0;
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25); box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
} }
@ -2288,7 +2288,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(255, 159.5, 220.5); border-color: #ffa0dd;
outline: 0; outline: 0;
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25); box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
} }
@ -2372,7 +2372,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(255, 159.5, 220.5); border-color: #ffa0dd;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25); box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
} }
@ -2419,7 +2419,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28255, 159.5, 220.5%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffa0dd'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2491,7 +2491,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(255, 197.7, 234.3); background-color: #ffc6ea;
background-image: var(--bs-gradient); background-image: var(--bs-gradient);
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
@ -2521,7 +2521,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(255, 197.7, 234.3); background-color: #ffc6ea;
background-image: var(--bs-gradient); background-image: var(--bs-gradient);
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
@ -2763,7 +2763,7 @@ textarea.form-control-lg {
} }
.was-validated .form-control:valid:focus, .form-control.is-valid:focus { .was-validated .form-control:valid:focus, .form-control.is-valid:focus {
border-color: var(--bs-form-valid-border-color); border-color: var(--bs-form-valid-border-color);
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
} }
.was-validated textarea.form-control:valid, textarea.form-control.is-valid { .was-validated textarea.form-control:valid, textarea.form-control.is-valid {
@ -2782,7 +2782,7 @@ textarea.form-control-lg {
} }
.was-validated .form-select:valid:focus, .form-select.is-valid:focus { .was-validated .form-select:valid:focus, .form-select.is-valid:focus {
border-color: var(--bs-form-valid-border-color); border-color: var(--bs-form-valid-border-color);
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
} }
.was-validated .form-control-color:valid, .form-control-color.is-valid { .was-validated .form-control-color:valid, .form-control-color.is-valid {
@ -2853,7 +2853,7 @@ textarea.form-control-lg {
} }
.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
} }
.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { .was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {
@ -2872,7 +2872,7 @@ textarea.form-control-lg {
} }
.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { .was-validated .form-select:invalid:focus, .form-select.is-invalid:focus {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
} }
.was-validated .form-control-color:invalid, .form-control-color.is-invalid { .was-validated .form-control-color:invalid, .form-control-color.is-invalid {
@ -2976,9 +2976,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2994,12 +2991,12 @@ textarea.form-control-lg {
--bs-btn-bg: rgb(255, 64, 186); --bs-btn-bg: rgb(255, 64, 186);
--bs-btn-border-color: rgb(255, 64, 186); --bs-btn-border-color: rgb(255, 64, 186);
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(216.75, 54.4, 158.1); --bs-btn-hover-bg: #d9369e;
--bs-btn-hover-border-color: rgb(204, 51.2, 148.8); --bs-btn-hover-border-color: #cc3395;
--bs-btn-focus-shadow-rgb: 255, 93, 196; --bs-btn-focus-shadow-rgb: 255, 93, 196;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(204, 51.2, 148.8); --bs-btn-active-bg: #cc3395;
--bs-btn-active-border-color: rgb(191.25, 48, 139.5); --bs-btn-active-border-color: #bf308c;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: rgb(255, 64, 186); --bs-btn-disabled-bg: rgb(255, 64, 186);
@ -3011,12 +3008,12 @@ textarea.form-control-lg {
--bs-btn-bg: #01cdfe; --bs-btn-bg: #01cdfe;
--bs-btn-border-color: #01cdfe; --bs-btn-border-color: #01cdfe;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15); --bs-btn-hover-bg: #27d5fe;
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1); --bs-btn-hover-border-color: #1ad2fe;
--bs-btn-focus-shadow-rgb: 1, 174, 216; --bs-btn-focus-shadow-rgb: 1, 174, 216;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51.8, 215, 254.2); --bs-btn-active-bg: #34d7fe;
--bs-btn-active-border-color: rgb(26.4, 210, 254.1); --bs-btn-active-border-color: #1ad2fe;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #01cdfe; --bs-btn-disabled-bg: #01cdfe;
@ -3028,12 +3025,12 @@ textarea.form-control-lg {
--bs-btn-bg: #05ffa1; --bs-btn-bg: #05ffa1;
--bs-btn-border-color: #05ffa1; --bs-btn-border-color: #05ffa1;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(42.5, 255, 175.1); --bs-btn-hover-bg: #2bffaf;
--bs-btn-hover-border-color: rgb(30, 255, 170.4); --bs-btn-hover-border-color: #1effaa;
--bs-btn-focus-shadow-rgb: 4, 217, 137; --bs-btn-focus-shadow-rgb: 4, 217, 137;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(55, 255, 179.8); --bs-btn-active-bg: #37ffb4;
--bs-btn-active-border-color: rgb(30, 255, 170.4); --bs-btn-active-border-color: #1effaa;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #05ffa1; --bs-btn-disabled-bg: #05ffa1;
@ -3045,12 +3042,12 @@ textarea.form-control-lg {
--bs-btn-bg: #01cdfe; --bs-btn-bg: #01cdfe;
--bs-btn-border-color: #01cdfe; --bs-btn-border-color: #01cdfe;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15); --bs-btn-hover-bg: #27d5fe;
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1); --bs-btn-hover-border-color: #1ad2fe;
--bs-btn-focus-shadow-rgb: 1, 174, 216; --bs-btn-focus-shadow-rgb: 1, 174, 216;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51.8, 215, 254.2); --bs-btn-active-bg: #34d7fe;
--bs-btn-active-border-color: rgb(26.4, 210, 254.1); --bs-btn-active-border-color: #1ad2fe;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #01cdfe; --bs-btn-disabled-bg: #01cdfe;
@ -3062,12 +3059,12 @@ textarea.form-control-lg {
--bs-btn-bg: #fffb96; --bs-btn-bg: #fffb96;
--bs-btn-border-color: #fffb96; --bs-btn-border-color: #fffb96;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(255, 251.6, 165.75); --bs-btn-hover-bg: #fffca6;
--bs-btn-hover-border-color: rgb(255, 251.4, 160.5); --bs-btn-hover-border-color: #fffba1;
--bs-btn-focus-shadow-rgb: 217, 213, 128; --bs-btn-focus-shadow-rgb: 217, 213, 128;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(255, 251.8, 171); --bs-btn-active-bg: #fffcab;
--bs-btn-active-border-color: rgb(255, 251.4, 160.5); --bs-btn-active-border-color: #fffba1;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #fffb96; --bs-btn-disabled-bg: #fffb96;
@ -3079,12 +3076,12 @@ textarea.form-control-lg {
--bs-btn-bg: rgb(255, 95, 110); --bs-btn-bg: rgb(255, 95, 110);
--bs-btn-border-color: rgb(255, 95, 110); --bs-btn-border-color: rgb(255, 95, 110);
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(255, 119, 131.75); --bs-btn-hover-bg: #ff7784;
--bs-btn-hover-border-color: rgb(255, 111, 124.5); --bs-btn-hover-border-color: #ff6f7d;
--bs-btn-focus-shadow-rgb: 217, 81, 94; --bs-btn-focus-shadow-rgb: 217, 81, 94;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: #ff7f8b; --bs-btn-active-bg: #ff7f8b;
--bs-btn-active-border-color: rgb(255, 111, 124.5); --bs-btn-active-border-color: #ff6f7d;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: rgb(255, 95, 110); --bs-btn-disabled-bg: rgb(255, 95, 110);
@ -3096,11 +3093,11 @@ textarea.form-control-lg {
--bs-btn-bg: #444; --bs-btn-bg: #444;
--bs-btn-border-color: #444; --bs-btn-border-color: #444;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(57.8, 57.8, 57.8); --bs-btn-hover-bg: #3a3a3a;
--bs-btn-hover-border-color: rgb(54.4, 54.4, 54.4); --bs-btn-hover-border-color: #363636;
--bs-btn-focus-shadow-rgb: 96, 96, 96; --bs-btn-focus-shadow-rgb: 96, 96, 96;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(54.4, 54.4, 54.4); --bs-btn-active-bg: #363636;
--bs-btn-active-border-color: #333333; --bs-btn-active-border-color: #333333;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
@ -4530,11 +4527,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ebebeb' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ebebeb'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%28102, 25.6, 74.4%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23661a4a'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #ffa0dd;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4592,6 +4590,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4609,7 +4608,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4620,11 +4619,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4633,27 +4632,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28255, 140.4, 213.6%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ff8cd6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28255, 140.4, 213.6%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ff8cd6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -5531,6 +5530,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6098,12 +6098,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6729,11 +6737,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {

View file

@ -1,7 +1,7 @@
@charset "UTF-8"; @charset "UTF-8";
/*! /*!
* Bootstrap v5.3.3 (https://getbootstrap.com/) * Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors * Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
:root, :root,
@ -35,7 +35,7 @@
--bs-info: #01cdfe; --bs-info: #01cdfe;
--bs-warning: #fffb96; --bs-warning: #fffb96;
--bs-danger: rgb(255, 95, 110); --bs-danger: rgb(255, 95, 110);
--bs-light: rgb(217.6474137931, 222.175, 226.7025862069); --bs-light: #dadee3;
--bs-dark: #212529; --bs-dark: #212529;
--bs-primary-rgb: 255, 64, 186; --bs-primary-rgb: 255, 64, 186;
--bs-secondary-rgb: 1, 205, 254; --bs-secondary-rgb: 1, 205, 254;
@ -45,27 +45,27 @@
--bs-danger-rgb: 255, 95, 110; --bs-danger-rgb: 255, 95, 110;
--bs-light-rgb: 218, 222, 227; --bs-light-rgb: 218, 222, 227;
--bs-dark-rgb: 33, 37, 41; --bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: rgb(102, 25.6, 74.4); --bs-primary-text-emphasis: #661a4a;
--bs-secondary-text-emphasis: rgb(0.4, 82, 101.6); --bs-secondary-text-emphasis: #005266;
--bs-success-text-emphasis: rgb(2, 102, 64.4); --bs-success-text-emphasis: #026640;
--bs-info-text-emphasis: rgb(0.4, 82, 101.6); --bs-info-text-emphasis: #005266;
--bs-warning-text-emphasis: rgb(102, 100.4, 60); --bs-warning-text-emphasis: #66643c;
--bs-danger-text-emphasis: #66262c; --bs-danger-text-emphasis: #66262c;
--bs-light-text-emphasis: #495057; --bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057; --bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: rgb(255, 216.8, 241.2); --bs-primary-bg-subtle: #ffd9f1;
--bs-secondary-bg-subtle: rgb(204.2, 245, 254.8); --bs-secondary-bg-subtle: #ccf5ff;
--bs-success-bg-subtle: rgb(205, 255, 236.2); --bs-success-bg-subtle: #cdffec;
--bs-info-bg-subtle: rgb(204.2, 245, 254.8); --bs-info-bg-subtle: #ccf5ff;
--bs-warning-bg-subtle: rgb(255, 254.2, 234); --bs-warning-bg-subtle: #fffeea;
--bs-danger-bg-subtle: #ffdfe2; --bs-danger-bg-subtle: #ffdfe2;
--bs-light-bg-subtle: rgb(251.5, 252, 252.5); --bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da; --bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: rgb(255, 178.6, 227.4); --bs-primary-border-subtle: #ffb3e3;
--bs-secondary-border-subtle: rgb(153.4, 235, 254.6); --bs-secondary-border-subtle: #99ebff;
--bs-success-border-subtle: rgb(155, 255, 217.4); --bs-success-border-subtle: #9bffd9;
--bs-info-border-subtle: rgb(153.4, 235, 254.6); --bs-info-border-subtle: #99ebff;
--bs-warning-border-subtle: rgb(255, 253.4, 213); --bs-warning-border-subtle: #fffdd5;
--bs-danger-border-subtle: #ffbfc5; --bs-danger-border-subtle: #ffbfc5;
--bs-light-border-subtle: #e9ecef; --bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd; --bs-dark-border-subtle: #adb5bd;
@ -97,11 +97,11 @@
--bs-link-color: rgb(255, 64, 186); --bs-link-color: rgb(255, 64, 186);
--bs-link-color-rgb: 255, 64, 186; --bs-link-color-rgb: 255, 64, 186;
--bs-link-decoration: none; --bs-link-decoration: none;
--bs-link-hover-color: rgb(204, 51.2, 148.8); --bs-link-hover-color: #cc3395;
--bs-link-hover-color-rgb: 204, 51, 149; --bs-link-hover-color-rgb: 204, 51, 149;
--bs-code-color: rgb(255, 64, 186); --bs-code-color: rgb(255, 64, 186);
--bs-highlight-color: #495057; --bs-highlight-color: #495057;
--bs-highlight-bg: rgb(255, 254.2, 234); --bs-highlight-bg: #fffeea;
--bs-border-width: 1px; --bs-border-width: 1px;
--bs-border-style: solid; --bs-border-style: solid;
--bs-border-color: #dee2e6; --bs-border-color: #dee2e6;
@ -140,44 +140,44 @@
--bs-secondary-bg-rgb: 52, 58, 64; --bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5); --bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230; --bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: rgb(42.5, 47.5, 52.5); --bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53; --bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: rgb(255, 140.4, 213.6); --bs-primary-text-emphasis: #ff8cd6;
--bs-secondary-text-emphasis: rgb(102.6, 225, 254.4); --bs-secondary-text-emphasis: #67e1fe;
--bs-success-text-emphasis: rgb(105, 255, 198.6); --bs-success-text-emphasis: #69ffc7;
--bs-info-text-emphasis: rgb(102.6, 225, 254.4); --bs-info-text-emphasis: #67e1fe;
--bs-warning-text-emphasis: rgb(255, 252.6, 192); --bs-warning-text-emphasis: #fffdc0;
--bs-danger-text-emphasis: #ff9fa8; --bs-danger-text-emphasis: #ff9fa8;
--bs-light-text-emphasis: #f8f9fa; --bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6; --bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: rgb(51, 12.8, 37.2); --bs-primary-bg-subtle: #330d25;
--bs-secondary-bg-subtle: rgb(0.2, 41, 50.8); --bs-secondary-bg-subtle: #002933;
--bs-success-bg-subtle: rgb(1, 51, 32.2); --bs-success-bg-subtle: #013320;
--bs-info-bg-subtle: rgb(0.2, 41, 50.8); --bs-info-bg-subtle: #002933;
--bs-warning-bg-subtle: rgb(51, 50.2, 30); --bs-warning-bg-subtle: #33321e;
--bs-danger-bg-subtle: #331316; --bs-danger-bg-subtle: #331316;
--bs-light-bg-subtle: #343a40; --bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20; --bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: rgb(153, 38.4, 111.6); --bs-primary-border-subtle: #992670;
--bs-secondary-border-subtle: rgb(0.6, 123, 152.4); --bs-secondary-border-subtle: #017b98;
--bs-success-border-subtle: rgb(3, 153, 96.6); --bs-success-border-subtle: #039961;
--bs-info-border-subtle: rgb(0.6, 123, 152.4); --bs-info-border-subtle: #017b98;
--bs-warning-border-subtle: rgb(153, 150.6, 90); --bs-warning-border-subtle: #99975a;
--bs-danger-border-subtle: #993942; --bs-danger-border-subtle: #993942;
--bs-light-border-subtle: #495057; --bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40; --bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit; --bs-heading-color: inherit;
--bs-link-color: rgb(255, 140.4, 213.6); --bs-link-color: #ff8cd6;
--bs-link-hover-color: rgb(255, 163.32, 221.88); --bs-link-hover-color: #ffa3de;
--bs-link-color-rgb: 255, 140, 214; --bs-link-color-rgb: 255, 140, 214;
--bs-link-hover-color-rgb: 255, 163, 222; --bs-link-hover-color-rgb: 255, 163, 222;
--bs-code-color: rgb(255, 140.4, 213.6); --bs-code-color: #ff8cd6;
--bs-highlight-color: #dee2e6; --bs-highlight-color: #dee2e6;
--bs-highlight-bg: rgb(102, 100.4, 60); --bs-highlight-bg: #66643c;
--bs-border-color: #495057; --bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15); --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: rgb(105, 255, 198.6); --bs-form-valid-color: #69ffc7;
--bs-form-valid-border-color: rgb(105, 255, 198.6); --bs-form-valid-border-color: #69ffc7;
--bs-form-invalid-color: #ff9fa8; --bs-form-invalid-color: #ff9fa8;
--bs-form-invalid-border-color: #ff9fa8; --bs-form-invalid-border-color: #ff9fa8;
} }
@ -1935,13 +1935,13 @@ progress {
.table-primary { .table-primary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(255, 216.8, 241.2); --bs-table-bg: #ffd9f1;
--bs-table-border-color: rgb(204, 173.44, 192.96); --bs-table-border-color: #ccaec1;
--bs-table-striped-bg: rgb(242.25, 205.96, 229.14); --bs-table-striped-bg: #f2cee5;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(229.5, 195.12, 217.08); --bs-table-active-bg: #e6c3d9;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(235.875, 200.54, 223.11); --bs-table-hover-bg: #ecc9df;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1949,13 +1949,13 @@ progress {
.table-secondary { .table-secondary {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204.2, 245, 254.8); --bs-table-bg: #ccf5ff;
--bs-table-border-color: rgb(163.36, 196, 203.84); --bs-table-border-color: #a3c4cc;
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06); --bs-table-striped-bg: #c2e9f2;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.78, 220.5, 229.32); --bs-table-active-bg: #b8dde6;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69); --bs-table-hover-bg: #bde3ec;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1963,13 +1963,13 @@ progress {
.table-success { .table-success {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(205, 255, 236.2); --bs-table-bg: #cdffec;
--bs-table-border-color: rgb(164, 204, 188.96); --bs-table-border-color: #a4ccbd;
--bs-table-striped-bg: rgb(194.75, 242.25, 224.39); --bs-table-striped-bg: #c3f2e0;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(184.5, 229.5, 212.58); --bs-table-active-bg: #b9e6d4;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(189.625, 235.875, 218.485); --bs-table-hover-bg: #beecda;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1977,13 +1977,13 @@ progress {
.table-info { .table-info {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(204.2, 245, 254.8); --bs-table-bg: #ccf5ff;
--bs-table-border-color: rgb(163.36, 196, 203.84); --bs-table-border-color: #a3c4cc;
--bs-table-striped-bg: rgb(193.99, 232.75, 242.06); --bs-table-striped-bg: #c2e9f2;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(183.78, 220.5, 229.32); --bs-table-active-bg: #b8dde6;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(188.885, 226.625, 235.69); --bs-table-hover-bg: #bde3ec;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -1991,13 +1991,13 @@ progress {
.table-warning { .table-warning {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(255, 254.2, 234); --bs-table-bg: #fffeea;
--bs-table-border-color: rgb(204, 203.36, 187.2); --bs-table-border-color: #cccbbb;
--bs-table-striped-bg: rgb(242.25, 241.49, 222.3); --bs-table-striped-bg: #f2f1de;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(229.5, 228.78, 210.6); --bs-table-active-bg: #e6e5d3;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(235.875, 235.135, 216.45); --bs-table-hover-bg: #ecebd8;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2006,12 +2006,12 @@ progress {
.table-danger { .table-danger {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: #ffdfe2; --bs-table-bg: #ffdfe2;
--bs-table-border-color: rgb(204, 178.4, 180.8); --bs-table-border-color: #ccb2b5;
--bs-table-striped-bg: rgb(242.25, 211.85, 214.7); --bs-table-striped-bg: #f2d4d7;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(229.5, 200.7, 203.4); --bs-table-active-bg: #e6c9cb;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(235.875, 206.275, 209.05); --bs-table-hover-bg: #ecced1;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2019,13 +2019,13 @@ progress {
.table-light { .table-light {
--bs-table-color: #000; --bs-table-color: #000;
--bs-table-bg: rgb(217.6474137931, 222.175, 226.7025862069); --bs-table-bg: #dadee3;
--bs-table-border-color: rgb(174.1179310345, 177.74, 181.3620689655); --bs-table-border-color: #aeb2b6;
--bs-table-striped-bg: rgb(206.7650431034, 211.06625, 215.3674568966); --bs-table-striped-bg: #cfd3d8;
--bs-table-striped-color: #000; --bs-table-striped-color: #000;
--bs-table-active-bg: rgb(195.8826724138, 199.9575, 204.0323275862); --bs-table-active-bg: #c4c8cc;
--bs-table-active-color: #000; --bs-table-active-color: #000;
--bs-table-hover-bg: rgb(201.3238577586, 205.511875, 209.6998922414); --bs-table-hover-bg: #cacdd2;
--bs-table-hover-color: #000; --bs-table-hover-color: #000;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2034,12 +2034,12 @@ progress {
.table-dark { .table-dark {
--bs-table-color: #fff; --bs-table-color: #fff;
--bs-table-bg: #212529; --bs-table-bg: #212529;
--bs-table-border-color: rgb(77.4, 80.6, 83.8); --bs-table-border-color: #4d5154;
--bs-table-striped-bg: rgb(44.1, 47.9, 51.7); --bs-table-striped-bg: #2c3034;
--bs-table-striped-color: #fff; --bs-table-striped-color: #fff;
--bs-table-active-bg: rgb(55.2, 58.8, 62.4); --bs-table-active-bg: #373b3e;
--bs-table-active-color: #fff; --bs-table-active-color: #fff;
--bs-table-hover-bg: rgb(49.65, 53.35, 57.05); --bs-table-hover-bg: #323539;
--bs-table-hover-color: #fff; --bs-table-hover-color: #fff;
color: var(--bs-table-color); color: var(--bs-table-color);
border-color: var(--bs-table-border-color); border-color: var(--bs-table-border-color);
@ -2140,7 +2140,7 @@ progress {
.form-control:focus { .form-control:focus {
color: var(--bs-body-color); color: var(--bs-body-color);
background-color: var(--bs-body-bg); background-color: var(--bs-body-bg);
border-color: rgb(255, 159.5, 220.5); border-color: #ffa0dd;
outline: 0; outline: 0;
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25); box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
} }
@ -2287,7 +2287,7 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
border-color: rgb(255, 159.5, 220.5); border-color: #ffa0dd;
outline: 0; outline: 0;
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25); box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
} }
@ -2371,7 +2371,7 @@ textarea.form-control-lg {
filter: brightness(90%); filter: brightness(90%);
} }
.form-check-input:focus { .form-check-input:focus {
border-color: rgb(255, 159.5, 220.5); border-color: #ffa0dd;
outline: 0; outline: 0;
box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25); box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
} }
@ -2418,7 +2418,7 @@ textarea.form-control-lg {
} }
} }
.form-switch .form-check-input:focus { .form-switch .form-check-input:focus {
--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28255, 159.5, 220.5%29'/%3e%3c/svg%3e"); --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffa0dd'/%3e%3c/svg%3e");
} }
.form-switch .form-check-input:checked { .form-switch .form-check-input:checked {
background-position: right center; background-position: right center;
@ -2490,7 +2490,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-webkit-slider-thumb:active { .form-range::-webkit-slider-thumb:active {
background-color: rgb(255, 197.7, 234.3); background-color: #ffc6ea;
background-image: var(--bs-gradient); background-image: var(--bs-gradient);
} }
.form-range::-webkit-slider-runnable-track { .form-range::-webkit-slider-runnable-track {
@ -2520,7 +2520,7 @@ textarea.form-control-lg {
} }
} }
.form-range::-moz-range-thumb:active { .form-range::-moz-range-thumb:active {
background-color: rgb(255, 197.7, 234.3); background-color: #ffc6ea;
background-image: var(--bs-gradient); background-image: var(--bs-gradient);
} }
.form-range::-moz-range-track { .form-range::-moz-range-track {
@ -2762,7 +2762,7 @@ textarea.form-control-lg {
} }
.was-validated .form-control:valid:focus, .form-control.is-valid:focus { .was-validated .form-control:valid:focus, .form-control.is-valid:focus {
border-color: var(--bs-form-valid-border-color); border-color: var(--bs-form-valid-border-color);
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
} }
.was-validated textarea.form-control:valid, textarea.form-control.is-valid { .was-validated textarea.form-control:valid, textarea.form-control.is-valid {
@ -2781,7 +2781,7 @@ textarea.form-control-lg {
} }
.was-validated .form-select:valid:focus, .form-select.is-valid:focus { .was-validated .form-select:valid:focus, .form-select.is-valid:focus {
border-color: var(--bs-form-valid-border-color); border-color: var(--bs-form-valid-border-color);
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25);
} }
.was-validated .form-control-color:valid, .form-control-color.is-valid { .was-validated .form-control-color:valid, .form-control-color.is-valid {
@ -2852,7 +2852,7 @@ textarea.form-control-lg {
} }
.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
} }
.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { .was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {
@ -2871,7 +2871,7 @@ textarea.form-control-lg {
} }
.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { .was-validated .form-select:invalid:focus, .form-select.is-invalid:focus {
border-color: var(--bs-form-invalid-border-color); border-color: var(--bs-form-invalid-border-color);
box-shadow: var(--bs-box-shadow-inset), 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
} }
.was-validated .form-control-color:invalid, .form-control-color.is-invalid { .was-validated .form-control-color:invalid, .form-control-color.is-invalid {
@ -2975,9 +2975,6 @@ textarea.form-control-lg {
.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible {
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow); box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
} }
.btn-check:checked:focus-visible + .btn {
box-shadow: var(--bs-btn-active-shadow), var(--bs-btn-focus-box-shadow);
}
.btn:disabled, .btn.disabled, fieldset:disabled .btn { .btn:disabled, .btn.disabled, fieldset:disabled .btn {
color: var(--bs-btn-disabled-color); color: var(--bs-btn-disabled-color);
pointer-events: none; pointer-events: none;
@ -2993,12 +2990,12 @@ textarea.form-control-lg {
--bs-btn-bg: rgb(255, 64, 186); --bs-btn-bg: rgb(255, 64, 186);
--bs-btn-border-color: rgb(255, 64, 186); --bs-btn-border-color: rgb(255, 64, 186);
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(216.75, 54.4, 158.1); --bs-btn-hover-bg: #d9369e;
--bs-btn-hover-border-color: rgb(204, 51.2, 148.8); --bs-btn-hover-border-color: #cc3395;
--bs-btn-focus-shadow-rgb: 255, 93, 196; --bs-btn-focus-shadow-rgb: 255, 93, 196;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(204, 51.2, 148.8); --bs-btn-active-bg: #cc3395;
--bs-btn-active-border-color: rgb(191.25, 48, 139.5); --bs-btn-active-border-color: #bf308c;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: rgb(255, 64, 186); --bs-btn-disabled-bg: rgb(255, 64, 186);
@ -3010,12 +3007,12 @@ textarea.form-control-lg {
--bs-btn-bg: #01cdfe; --bs-btn-bg: #01cdfe;
--bs-btn-border-color: #01cdfe; --bs-btn-border-color: #01cdfe;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15); --bs-btn-hover-bg: #27d5fe;
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1); --bs-btn-hover-border-color: #1ad2fe;
--bs-btn-focus-shadow-rgb: 1, 174, 216; --bs-btn-focus-shadow-rgb: 1, 174, 216;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51.8, 215, 254.2); --bs-btn-active-bg: #34d7fe;
--bs-btn-active-border-color: rgb(26.4, 210, 254.1); --bs-btn-active-border-color: #1ad2fe;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #01cdfe; --bs-btn-disabled-bg: #01cdfe;
@ -3027,12 +3024,12 @@ textarea.form-control-lg {
--bs-btn-bg: #05ffa1; --bs-btn-bg: #05ffa1;
--bs-btn-border-color: #05ffa1; --bs-btn-border-color: #05ffa1;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(42.5, 255, 175.1); --bs-btn-hover-bg: #2bffaf;
--bs-btn-hover-border-color: rgb(30, 255, 170.4); --bs-btn-hover-border-color: #1effaa;
--bs-btn-focus-shadow-rgb: 4, 217, 137; --bs-btn-focus-shadow-rgb: 4, 217, 137;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(55, 255, 179.8); --bs-btn-active-bg: #37ffb4;
--bs-btn-active-border-color: rgb(30, 255, 170.4); --bs-btn-active-border-color: #1effaa;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #05ffa1; --bs-btn-disabled-bg: #05ffa1;
@ -3044,12 +3041,12 @@ textarea.form-control-lg {
--bs-btn-bg: #01cdfe; --bs-btn-bg: #01cdfe;
--bs-btn-border-color: #01cdfe; --bs-btn-border-color: #01cdfe;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(39.1, 212.5, 254.15); --bs-btn-hover-bg: #27d5fe;
--bs-btn-hover-border-color: rgb(26.4, 210, 254.1); --bs-btn-hover-border-color: #1ad2fe;
--bs-btn-focus-shadow-rgb: 1, 174, 216; --bs-btn-focus-shadow-rgb: 1, 174, 216;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(51.8, 215, 254.2); --bs-btn-active-bg: #34d7fe;
--bs-btn-active-border-color: rgb(26.4, 210, 254.1); --bs-btn-active-border-color: #1ad2fe;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #01cdfe; --bs-btn-disabled-bg: #01cdfe;
@ -3061,12 +3058,12 @@ textarea.form-control-lg {
--bs-btn-bg: #fffb96; --bs-btn-bg: #fffb96;
--bs-btn-border-color: #fffb96; --bs-btn-border-color: #fffb96;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(255, 251.6, 165.75); --bs-btn-hover-bg: #fffca6;
--bs-btn-hover-border-color: rgb(255, 251.4, 160.5); --bs-btn-hover-border-color: #fffba1;
--bs-btn-focus-shadow-rgb: 217, 213, 128; --bs-btn-focus-shadow-rgb: 217, 213, 128;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(255, 251.8, 171); --bs-btn-active-bg: #fffcab;
--bs-btn-active-border-color: rgb(255, 251.4, 160.5); --bs-btn-active-border-color: #fffba1;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: #fffb96; --bs-btn-disabled-bg: #fffb96;
@ -3078,12 +3075,12 @@ textarea.form-control-lg {
--bs-btn-bg: rgb(255, 95, 110); --bs-btn-bg: rgb(255, 95, 110);
--bs-btn-border-color: rgb(255, 95, 110); --bs-btn-border-color: rgb(255, 95, 110);
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(255, 119, 131.75); --bs-btn-hover-bg: #ff7784;
--bs-btn-hover-border-color: rgb(255, 111, 124.5); --bs-btn-hover-border-color: #ff6f7d;
--bs-btn-focus-shadow-rgb: 217, 81, 94; --bs-btn-focus-shadow-rgb: 217, 81, 94;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: #ff7f8b; --bs-btn-active-bg: #ff7f8b;
--bs-btn-active-border-color: rgb(255, 111, 124.5); --bs-btn-active-border-color: #ff6f7d;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: rgb(255, 95, 110); --bs-btn-disabled-bg: rgb(255, 95, 110);
@ -3092,19 +3089,19 @@ textarea.form-control-lg {
.btn-light { .btn-light {
--bs-btn-color: #000; --bs-btn-color: #000;
--bs-btn-bg: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-bg: #dadee3;
--bs-btn-border-color: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-border-color: #dadee3;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(185.0003017241, 188.84875, 192.6971982759); --bs-btn-hover-bg: #b9bdc1;
--bs-btn-hover-border-color: rgb(174.1179310345, 177.74, 181.3620689655); --bs-btn-hover-border-color: #aeb2b6;
--bs-btn-focus-shadow-rgb: 185, 189, 193; --bs-btn-focus-shadow-rgb: 185, 189, 193;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(174.1179310345, 177.74, 181.3620689655); --bs-btn-active-bg: #aeb2b6;
--bs-btn-active-border-color: rgb(163.2355603448, 166.63125, 170.0269396552); --bs-btn-active-border-color: #a4a7aa;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #000; --bs-btn-disabled-color: #000;
--bs-btn-disabled-bg: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-disabled-bg: #dadee3;
--bs-btn-disabled-border-color: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-disabled-border-color: #dadee3;
} }
.btn-dark { .btn-dark {
@ -3112,12 +3109,12 @@ textarea.form-control-lg {
--bs-btn-bg: #212529; --bs-btn-bg: #212529;
--bs-btn-border-color: #212529; --bs-btn-border-color: #212529;
--bs-btn-hover-color: #fff; --bs-btn-hover-color: #fff;
--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1); --bs-btn-hover-bg: #424649;
--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4); --bs-btn-hover-border-color: #373b3e;
--bs-btn-focus-shadow-rgb: 66, 70, 73; --bs-btn-focus-shadow-rgb: 66, 70, 73;
--bs-btn-active-color: #fff; --bs-btn-active-color: #fff;
--bs-btn-active-bg: rgb(77.4, 80.6, 83.8); --bs-btn-active-bg: #4d5154;
--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4); --bs-btn-active-border-color: #373b3e;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: #fff; --bs-btn-disabled-color: #fff;
--bs-btn-disabled-bg: #212529; --bs-btn-disabled-bg: #212529;
@ -3227,19 +3224,19 @@ textarea.form-control-lg {
} }
.btn-outline-light { .btn-outline-light {
--bs-btn-color: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-color: #dadee3;
--bs-btn-border-color: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-border-color: #dadee3;
--bs-btn-hover-color: #000; --bs-btn-hover-color: #000;
--bs-btn-hover-bg: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-hover-bg: #dadee3;
--bs-btn-hover-border-color: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-hover-border-color: #dadee3;
--bs-btn-focus-shadow-rgb: 218, 222, 227; --bs-btn-focus-shadow-rgb: 218, 222, 227;
--bs-btn-active-color: #000; --bs-btn-active-color: #000;
--bs-btn-active-bg: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-active-bg: #dadee3;
--bs-btn-active-border-color: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-active-border-color: #dadee3;
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
--bs-btn-disabled-color: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-disabled-color: #dadee3;
--bs-btn-disabled-bg: transparent; --bs-btn-disabled-bg: transparent;
--bs-btn-disabled-border-color: rgb(217.6474137931, 222.175, 226.7025862069); --bs-btn-disabled-border-color: #dadee3;
--bs-gradient: none; --bs-gradient: none;
} }
@ -4529,11 +4526,12 @@ textarea.form-control-lg {
--bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-padding-y: 1rem;
--bs-accordion-btn-color: var(--bs-body-color); --bs-accordion-btn-color: var(--bs-body-color);
--bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-bg: var(--bs-accordion-bg);
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23495057' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23495057'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-width: 1.25rem;
--bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transform: rotate(-180deg);
--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%28102, 25.6, 74.4%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23661a4a'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-focus-border-color: #ffa0dd;
--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25); --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(255, 64, 186, 0.25);
--bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-x: 1.25rem;
--bs-accordion-body-padding-y: 1rem; --bs-accordion-body-padding-y: 1rem;
@ -4591,6 +4589,7 @@ textarea.form-control-lg {
} }
.accordion-button:focus { .accordion-button:focus {
z-index: 3; z-index: 3;
border-color: var(--bs-accordion-btn-focus-border-color);
outline: 0; outline: 0;
box-shadow: var(--bs-accordion-btn-focus-box-shadow); box-shadow: var(--bs-accordion-btn-focus-box-shadow);
} }
@ -4608,7 +4607,7 @@ textarea.form-control-lg {
border-top-left-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius);
border-top-right-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:first-of-type > .accordion-header .accordion-button { .accordion-item:first-of-type .accordion-button {
border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius);
border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius);
} }
@ -4619,11 +4618,11 @@ textarea.form-control-lg {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
.accordion-item:last-of-type > .accordion-header .accordion-button.collapsed { .accordion-item:last-of-type .accordion-button.collapsed {
border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius);
border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius);
} }
.accordion-item:last-of-type > .accordion-collapse { .accordion-item:last-of-type .accordion-collapse {
border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius);
} }
@ -4632,27 +4631,27 @@ textarea.form-control-lg {
padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x);
} }
.accordion-flush > .accordion-item { .accordion-flush .accordion-collapse {
border-width: 0;
}
.accordion-flush .accordion-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
border-radius: 0; border-radius: 0;
} }
.accordion-flush > .accordion-item:first-child { .accordion-flush .accordion-item:first-child {
border-top: 0; border-top: 0;
} }
.accordion-flush > .accordion-item:last-child { .accordion-flush .accordion-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
.accordion-flush > .accordion-item > .accordion-header .accordion-button, .accordion-flush > .accordion-item > .accordion-header .accordion-button.collapsed { .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed {
border-radius: 0;
}
.accordion-flush > .accordion-item > .accordion-collapse {
border-radius: 0; border-radius: 0;
} }
[data-bs-theme=dark] .accordion-button::after { [data-bs-theme=dark] .accordion-button::after {
--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28255, 140.4, 213.6%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ff8cd6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28255, 140.4, 213.6%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ff8cd6'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.breadcrumb { .breadcrumb {
@ -5530,6 +5529,7 @@ textarea.form-control-lg {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-modal-header-padding); padding: var(--bs-modal-header-padding);
border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);
border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius);
@ -6097,12 +6097,20 @@ textarea.form-control-lg {
background-size: 100% 100%; background-size: 100% 100%;
} }
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e");
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") /*rtl:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")*/; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
} }
.carousel-indicators { .carousel-indicators {
@ -6728,11 +6736,14 @@ textarea.form-control-lg {
.offcanvas-header { .offcanvas-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
} }
.offcanvas-header .btn-close { .offcanvas-header .btn-close {
padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5);
margin: calc(-0.5 * var(--bs-offcanvas-padding-y)) calc(-0.5 * var(--bs-offcanvas-padding-x)) calc(-0.5 * var(--bs-offcanvas-padding-y)) auto; margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y));
margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x));
margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y));
} }
.offcanvas-title { .offcanvas-title {
@ -6896,8 +6907,8 @@ textarea.form-control-lg {
text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important; text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important;
} }
.link-light:hover, .link-light:focus { .link-light:hover, .link-light:focus {
color: RGBA(225, 229, 232, var(--bs-link-opacity, 1)) !important; color: RGBA(225, 229, 233, var(--bs-link-opacity, 1)) !important;
text-decoration-color: RGBA(225, 229, 232, var(--bs-link-underline-opacity, 1)) !important; text-decoration-color: RGBA(225, 229, 233, var(--bs-link-underline-opacity, 1)) !important;
} }
.link-dark { .link-dark {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

View file

@ -60,10 +60,6 @@
<symbol id="icon-add" viewBox="0 0 32 32" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <symbol id="icon-add" viewBox="0 0 32 32" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<path d="M14.5,14.501l-10.502,0c-0.828,0 -1.5,0.673 -1.5,1.5c0,0.828 0.672,1.5 1.5,1.5l10.502,0l-0.001,10.502c0,0.828 0.672,1.5 1.5,1.501c0.828,-0 1.5,-0.673 1.5,-1.5l0.001,-10.503l10.502,0c0.828,0 1.5,-0.672 1.5,-1.5c0,-0.827 -0.672,-1.5 -1.5,-1.5l-10.502,0l0.001,-10.501c-0,-0.828 -0.672,-1.501 -1.5,-1.501c-0.828,0 -1.5,0.672 -1.5,1.5l-0.001,10.502Z"/> <path d="M14.5,14.501l-10.502,0c-0.828,0 -1.5,0.673 -1.5,1.5c0,0.828 0.672,1.5 1.5,1.5l10.502,0l-0.001,10.502c0,0.828 0.672,1.5 1.5,1.501c0.828,-0 1.5,-0.673 1.5,-1.5l0.001,-10.503l10.502,0c0.828,0 1.5,-0.672 1.5,-1.5c0,-0.827 -0.672,-1.5 -1.5,-1.5l-10.502,0l0.001,-10.501c-0,-0.828 -0.672,-1.501 -1.5,-1.501c-0.828,0 -1.5,0.672 -1.5,1.5l-0.001,10.502Z"/>
</symbol> </symbol>
<symbol id="icon-video" viewBox="0 0 256 256">
<rect width="256" height="256" fill="none"/>
<polygon points="160 112 112 80 112 144 160 112" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><rect x="32" y="48" width="192" height="128" rx="8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="32" y1="208" x2="224" y2="208" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
</symbol>
<symbol id="icon-play" viewBox="0 0 24 24"> <symbol id="icon-play" viewBox="0 0 24 24">
<path d="M5.541 2.159c-0.153-0.1-0.34-0.159-0.541-0.159-0.552 0-1 0.448-1 1v18c-0.001 0.182 0.050 0.372 0.159 0.541 0.299 0.465 0.917 0.599 1.382 0.3l14-9c0.114-0.072 0.219-0.174 0.3-0.3 0.299-0.465 0.164-1.083-0.3-1.382zM6 4.832l11.151 7.168-11.151 7.168z"/> <path d="M5.541 2.159c-0.153-0.1-0.34-0.159-0.541-0.159-0.552 0-1 0.448-1 1v18c-0.001 0.182 0.050 0.372 0.159 0.541 0.299 0.465 0.917 0.599 1.382 0.3l14-9c0.114-0.072 0.219-0.174 0.3-0.3 0.299-0.465 0.164-1.083-0.3-1.382zM6 4.832l11.151 7.168-11.151 7.168z"/>
</symbol> </symbol>
@ -174,11 +170,8 @@
<symbol id="icon-message-square" viewBox="0 0 24 24"> <symbol id="icon-message-square" viewBox="0 0 24 24">
<path d="M22 15v-10c0-0.828-0.337-1.58-0.879-2.121s-1.293-0.879-2.121-0.879h-14c-0.828 0-1.58 0.337-2.121 0.879s-0.879 1.293-0.879 2.121v16c0 0.256 0.098 0.512 0.293 0.707 0.391 0.391 1.024 0.391 1.414 0l3.707-3.707h11.586c0.828 0 1.58-0.337 2.121-0.879s0.879-1.293 0.879-2.121zM20 15c0 0.276-0.111 0.525-0.293 0.707s-0.431 0.293-0.707 0.293h-12c-0.276 0-0.526 0.112-0.707 0.293l-2.293 2.293v-13.586c0-0.276 0.111-0.525 0.293-0.707s0.431-0.293 0.707-0.293h14c0.276 0 0.525 0.111 0.707 0.293s0.293 0.431 0.293 0.707z"/> <path d="M22 15v-10c0-0.828-0.337-1.58-0.879-2.121s-1.293-0.879-2.121-0.879h-14c-0.828 0-1.58 0.337-2.121 0.879s-0.879 1.293-0.879 2.121v16c0 0.256 0.098 0.512 0.293 0.707 0.391 0.391 1.024 0.391 1.414 0l3.707-3.707h11.586c0.828 0 1.58-0.337 2.121-0.879s0.879-1.293 0.879-2.121zM20 15c0 0.276-0.111 0.525-0.293 0.707s-0.431 0.293-0.707 0.293h-12c-0.276 0-0.526 0.112-0.707 0.293l-2.293 2.293v-13.586c0-0.276 0.111-0.525 0.293-0.707s0.431-0.293 0.707-0.293h14c0.276 0 0.525 0.111 0.707 0.293s0.293 0.431 0.293 0.707z"/>
</symbol> </symbol>
<symbol id="icon-image" viewBox="0 0 256 256"> <symbol id="icon-image" viewBox="0 0 24 24">
<path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,16V158.75l-26.07-26.06a16,16,0,0,0-22.63,0l-20,20-44-44a16,16,0,0,0-22.62,0L40,149.37V56ZM40,172l52-52,80,80H40Zm176,28H194.63l-36-36,20-20L216,181.38V200ZM144,100a12,12,0,1,1,12,12A12,12,0,0,1,144,100Z" /> <path d="M5 2c-0.828 0-1.58 0.337-2.121 0.879s-0.879 1.293-0.879 2.121v14c0 0.828 0.337 1.58 0.879 2.121s1.293 0.879 2.121 0.879h14c0.828 0 1.58-0.337 2.121-0.879s0.879-1.293 0.879-2.121v-14c0-0.828-0.337-1.58-0.879-2.121s-1.293-0.879-2.121-0.879zM11 8.5c0-0.69-0.281-1.316-0.732-1.768s-1.078-0.732-1.768-0.732-1.316 0.281-1.768 0.732-0.732 1.078-0.732 1.768 0.281 1.316 0.732 1.768 1.078 0.732 1.768 0.732 1.316-0.281 1.768-0.732 0.732-1.078 0.732-1.768zM9 8.5c0 0.138-0.055 0.262-0.146 0.354s-0.216 0.146-0.354 0.146-0.262-0.055-0.354-0.146-0.146-0.216-0.146-0.354 0.055-0.262 0.146-0.354 0.216-0.146 0.354-0.146 0.262 0.055 0.354 0.146 0.146 0.216 0.146 0.354zM7.414 20l8.586-8.586 4 4v3.586c0 0.276-0.111 0.525-0.293 0.707s-0.431 0.293-0.707 0.293zM20 12.586l-3.293-3.293c-0.391-0.391-1.024-0.391-1.414 0l-10.644 10.644c-0.135-0.050-0.255-0.129-0.356-0.23-0.182-0.182-0.293-0.431-0.293-0.707v-14c0-0.276 0.111-0.525 0.293-0.707s0.431-0.293 0.707-0.293h14c0.276 0 0.525 0.111 0.707 0.293s0.293 0.431 0.293 0.707z"/>
</symbol>
<symbol id="icon-image-broken" viewBox="0 0 256 256">
<path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16h64a8,8,0,0,0,7.59-5.47l14.83-44.48L163,151.43a8.07,8.07,0,0,0,4.46-4.46l14.62-36.55,44.48-14.83A8,8,0,0,0,232,88V56A16,16,0,0,0,216,40ZM112.41,157.47,98.23,200H40V172l52-52,30.42,30.42L117,152.57A8,8,0,0,0,112.41,157.47ZM216,82.23,173.47,96.41a8,8,0,0,0-4.9,4.62l-14.72,36.82L138.58,144l-35.27-35.27a16,16,0,0,0-22.62,0L40,149.37V56H216Zm12.68,33a8,8,0,0,0-7.21-1.1l-23.8,7.94a8,8,0,0,0-4.9,4.61l-14.31,35.77-35.77,14.31a8,8,0,0,0-4.61,4.9l-7.94,23.8A8,8,0,0,0,137.73,216H216a16,16,0,0,0,16-16V121.73A8,8,0,0,0,228.68,115.24ZM216,200H148.83l3.25-9.75,35.51-14.2a8.07,8.07,0,0,0,4.46-4.46l14.2-35.51,9.75-3.25Z" />
</symbol> </symbol>
<symbol id="icon-external-link" viewBox="0 0 24 24"> <symbol id="icon-external-link" viewBox="0 0 24 24">
<path d="M17 13v6c0 0.276-0.111 0.525-0.293 0.707s-0.431 0.293-0.707 0.293h-11c-0.276 0-0.525-0.111-0.707-0.293s-0.293-0.431-0.293-0.707v-11c0-0.276 0.111-0.525 0.293-0.707s0.431-0.293 0.707-0.293h6c0.552 0 1-0.448 1-1s-0.448-1-1-1h-6c-0.828 0-1.58 0.337-2.121 0.879s-0.879 1.293-0.879 2.121v11c0 0.828 0.337 1.58 0.879 2.121s1.293 0.879 2.121 0.879h11c0.828 0 1.58-0.337 2.121-0.879s0.879-1.293 0.879-2.121v-6c0-0.552-0.448-1-1-1s-1 0.448-1 1zM10.707 14.707l9.293-9.293v3.586c0 0.552 0.448 1 1 1s1-0.448 1-1v-6c0-0.136-0.027-0.265-0.076-0.383s-0.121-0.228-0.216-0.323c-0.001-0.001-0.001-0.001-0.002-0.002-0.092-0.092-0.202-0.166-0.323-0.216-0.118-0.049-0.247-0.076-0.383-0.076h-6c-0.552 0-1 0.448-1 1s0.448 1 1 1h3.586l-9.293 9.293c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0z"/> <path d="M17 13v6c0 0.276-0.111 0.525-0.293 0.707s-0.431 0.293-0.707 0.293h-11c-0.276 0-0.525-0.111-0.707-0.293s-0.293-0.431-0.293-0.707v-11c0-0.276 0.111-0.525 0.293-0.707s0.431-0.293 0.707-0.293h6c0.552 0 1-0.448 1-1s-0.448-1-1-1h-6c-0.828 0-1.58 0.337-2.121 0.879s-0.879 1.293-0.879 2.121v11c0 0.828 0.337 1.58 0.879 2.121s1.293 0.879 2.121 0.879h11c0.828 0 1.58-0.337 2.121-0.879s0.879-1.293 0.879-2.121v-6c0-0.552-0.448-1-1-1s-1 0.448-1 1zM10.707 14.707l9.293-9.293v3.586c0 0.552 0.448 1 1 1s1-0.448 1-1v-6c0-0.136-0.027-0.265-0.076-0.383s-0.121-0.228-0.216-0.323c-0.001-0.001-0.001-0.001-0.002-0.002-0.092-0.092-0.202-0.166-0.323-0.216-0.118-0.049-0.247-0.076-0.383-0.076h-6c-0.552 0-1 0.448-1 1s0.448 1 1 1h3.586l-9.293 9.293c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0z"/>
@ -299,14 +292,5 @@
<line x1="16" y1="216" x2="240" y2="216" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/> <line x1="16" y1="216" x2="240" y2="216" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
<path d="M152,216V160a8,8,0,0,0-8-8H112a8,8,0,0,0-8,8v56" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/> <path d="M152,216V160a8,8,0,0,0-8-8H112a8,8,0,0,0-8,8v56" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
</symbol> </symbol>
<symbol id="icon-info" fill="currentColor" viewBox="0 0 256 256">
<path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z" />
</symbol>
<symbol id="icon-history" viewBox="0 0 256 256">
<path d="M136,80v43.47l36.12,21.67a8,8,0,0,1-8.24,13.72l-40-24A8,8,0,0,1,120,128V80a8,8,0,0,1,16,0Zm-8-48A95.44,95.44,0,0,0,60.08,60.15C52.81,67.51,46.35,74.59,40,82V64a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H72a8,8,0,0,0,0-16H49c7.15-8.42,14.27-16.35,22.39-24.57a80,80,0,1,1,1.66,114.75,8,8,0,1,0-11,11.64A96,96,0,1,0,128,32Z" />
</symbol>
<symbol id="icon-caret-right" fill="currentColor" viewBox="0 0 256 256">
<path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z" />
</symbol>
</defs> </defs>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View file

@ -1,11 +1,10 @@
import { initializeSite } from "@utils/app"; import { initializeSite } from "@utils/app";
import { hydrate } from "inferno-hydrate"; import { hydrate } from "inferno-hydrate";
import { BrowserRouter } from "inferno-router"; import { BrowserRouter } from "inferno-router";
import App from "../shared/components/app/app"; import { App } from "../shared/components/app/app";
import { lazyHighlightjs } from "../shared/lazy-highlightjs"; import { lazyHighlightjs } from "../shared/lazy-highlightjs";
import { loadUserLanguage } from "../shared/services/I18NextService"; import { loadUserLanguage } from "../shared/services/I18NextService";
import { verifyDynamicImports } from "../shared/dynamic-imports"; import { verifyDynamicImports } from "../shared/dynamic-imports";
import { setupEmojiDataModel } from "../shared/markdown";
import "bootstrap/js/dist/collapse"; import "bootstrap/js/dist/collapse";
import "bootstrap/js/dist/dropdown"; import "bootstrap/js/dist/dropdown";
@ -17,13 +16,11 @@ async function startClient() {
verifyDynamicImports(true).then(x => console.log(x)); verifyDynamicImports(true).then(x => console.log(x));
}; };
window.history.scrollRestoration = "manual";
initializeSite(window.isoData.site_res); initializeSite(window.isoData.site_res);
lazyHighlightjs.enableLazyLoading(); lazyHighlightjs.enableLazyLoading();
await Promise.all([loadUserLanguage(), setupEmojiDataModel()]); await loadUserLanguage();
const wrapper = ( const wrapper = (
<BrowserRouter> <BrowserRouter>

View file

@ -6,7 +6,7 @@ import { StaticRouter, matchPath } from "inferno-router";
import { Match } from "inferno-router/dist/Route"; import { Match } from "inferno-router/dist/Route";
import { renderToString } from "inferno-server"; import { renderToString } from "inferno-server";
import { GetSiteResponse, LemmyHttp } from "lemmy-js-client"; import { GetSiteResponse, LemmyHttp } from "lemmy-js-client";
import App from "../../shared/components/app/app"; import { App } from "../../shared/components/app/app";
import { import {
InitialFetchRequest, InitialFetchRequest,
IsoDataOptionalSite, IsoDataOptionalSite,
@ -28,7 +28,6 @@ import {
} from "../../shared/services/"; } from "../../shared/services/";
import { parsePath } from "history"; import { parsePath } from "history";
import { getQueryString } from "@utils/helpers"; import { getQueryString } from "@utils/helpers";
import { adultConsentCookieKey } from "../../shared/config";
export default async (req: Request, res: Response) => { export default async (req: Request, res: Response) => {
try { try {
@ -143,9 +142,6 @@ export default async (req: Request, res: Response) => {
site_res: site, site_res: site,
routeData, routeData,
errorPageData, errorPageData,
showAdultConsentModal:
!!site?.site_view.site.content_warning &&
!(site.my_user || req.cookies[adultConsentCookieKey]),
}; };
const wrapper = ( const wrapper = (

View file

@ -14,10 +14,8 @@ import ThemesListHandler from "./handlers/themes-list-handler";
import { setCacheControl, setDefaultCsp } from "./middleware"; import { setCacheControl, setDefaultCsp } from "./middleware";
import CodeThemeHandler from "./handlers/code-theme-handler"; import CodeThemeHandler from "./handlers/code-theme-handler";
import { verifyDynamicImports } from "../shared/dynamic-imports"; import { verifyDynamicImports } from "../shared/dynamic-imports";
import cookieParser from "cookie-parser";
const server = express(); const server = express();
server.use(cookieParser());
const [hostname, port] = process.env["LEMMY_UI_HOST"] const [hostname, port] = process.env["LEMMY_UI_HOST"]
? process.env["LEMMY_UI_HOST"].split(":") ? process.env["LEMMY_UI_HOST"].split(":")

View file

@ -14,7 +14,7 @@ const themes: ReadonlyArray<string> = [
"litely-compact", "litely-compact",
"vaporwave-dark", "vaporwave-dark",
"vaporwave-light", "vaporwave-light",
"i386-dark", "i386",
]; ];
export async function buildThemeList(): Promise<ReadonlyArray<string>> { export async function buildThemeList(): Promise<ReadonlyArray<string>> {

View file

@ -33,29 +33,22 @@ export async function createSsrHtml(
); );
if (!appleTouchIcon) { if (!appleTouchIcon) {
try { appleTouchIcon = site?.site_view.site.icon
appleTouchIcon = site?.site_view.site.icon ? `data:image/png;base64,${await sharp(
? `data:image/png;base64,${await sharp( await fetchIconPng(site.site_view.site.icon),
await fetchIconPng(site.site_view.site.icon), )
) .resize(180, 180)
.resize(180, 180) .extend({
.extend({ bottom: 20,
bottom: 20, top: 20,
top: 20, left: 20,
left: 20, right: 20,
right: 20, background: "#222222",
background: "#222222", })
}) .png()
.png() .toBuffer()
.toBuffer() .then(buf => buf.toString("base64"))}`
.then(buf => buf.toString("base64"))}` : favIconPngUrl;
: favIconPngUrl;
} catch {
console.log(
"Could not fetch site logo for apple touch icon. Using default icon.",
);
appleTouchIcon = favIconPngUrl;
}
} }
const erudaStr = const erudaStr =
@ -87,14 +80,13 @@ export async function createSsrHtml(
<html ${helmet.htmlAttributes.toString()}> <html ${helmet.htmlAttributes.toString()}>
<head> <head>
<script nonce="${cspNonce}"> <script nonce="${cspNonce}">
window.isoData = ${serialize(isoData)};
if (!document.documentElement.hasAttribute("data-bs-theme")) { if (!document.documentElement.hasAttribute("data-bs-theme")) {
const light = window.matchMedia("(prefers-color-scheme: light)").matches; const light = window.matchMedia("(prefers-color-scheme: light)").matches;
document.documentElement.setAttribute("data-bs-theme", light ? "light" : "dark"); document.documentElement.setAttribute("data-bs-theme", light ? "light" : "dark");
} }
</script> </script>
${lazyScripts} ${lazyScripts}
<script nonce="${cspNonce}">window.isoData = ${serialize(isoData)}</script>
<!-- A remote debugging utility for mobile --> <!-- A remote debugging utility for mobile -->
${erudaStr} ${erudaStr}
@ -105,17 +97,6 @@ export async function createSsrHtml(
${helmet.title.toString()} ${helmet.title.toString()}
${helmet.meta.toString()} ${helmet.meta.toString()}
<style>
#app[data-adult-consent] {
filter: blur(10px);
-webkit-filter: blur(10px);
-moz-filter: blur(10px);
-o-filter: blur(10px);
-ms-filter: blur(10px);
pointer-events: none;
}
</style>
<!-- Required meta tags --> <!-- Required meta tags -->
<meta name="Description" content="Lemmy"> <meta name="Description" content="Lemmy">
<meta charset="utf-8"> <meta charset="utf-8">

View file

@ -1,54 +1,19 @@
import { readFile } from "fs/promises";
import { Site } from "lemmy-js-client"; import { Site } from "lemmy-js-client";
import path from "path";
import { fetchIconPng } from "./fetch-icon-png"; import { fetchIconPng } from "./fetch-icon-png";
import { getStaticDir } from "@utils/env";
type Icon = { sizes: string; src: string; type: string; purpose: string };
const iconSizes = [72, 96, 128, 144, 152, 192, 384, 512]; const iconSizes = [72, 96, 128, 144, 152, 192, 384, 512];
let icons: Icon[] | null = null;
function mapIcon(src: string, size: number): Icon { const defaultLogoPathDirectory = path.join(
return { process.cwd(),
sizes: `${size}x${size}`, "dist",
type: "image/png", "assets",
src, "icons",
purpose: "any maskable", );
};
}
function generateDefaultIcons() {
return iconSizes.map(size =>
mapIcon(`${getStaticDir()}/assets/icons/icon-${size}x${size}.png`, size),
);
}
export default async function (site: Site) { export default async function (site: Site) {
if (!icons) { const icon = site.icon ? await fetchIconPng(site.icon) : null;
try {
const icon = site.icon ? await fetchIconPng(site.icon) : null;
if (icon) {
icons = await Promise.all(
iconSizes.map(async size => {
const sharp = (await import("sharp")).default;
const src = `data:image/png:base64,${await sharp(icon)
.resize(size, size)
.png()
.toBuffer()
.then(buf => buf.toString("base64"))}`;
return mapIcon(src, size);
}),
);
} else {
icons = generateDefaultIcons();
}
} catch {
console.log(
`Failed to fetch site logo for manifest icon. Using default icon`,
);
icons = generateDefaultIcons();
}
}
return { return {
name: site.name, name: site.name,
@ -59,7 +24,29 @@ export default async function (site: Site) {
id: "/", id: "/",
background_color: "#222222", background_color: "#222222",
theme_color: "#222222", theme_color: "#222222",
icons, icons: await Promise.all(
iconSizes.map(async size => {
let src = await readFile(
path.join(defaultLogoPathDirectory, `icon-${size}x${size}.png`),
).then(buf => buf.toString("base64"));
if (icon) {
const sharp = (await import("sharp")).default;
src = await sharp(icon)
.resize(size, size)
.png()
.toBuffer()
.then(buf => buf.toString("base64"));
}
return {
sizes: `${size}x${size}`,
type: "image/png",
src: `data:image/png;base64,${src}`,
purpose: "any maskable",
};
}),
),
shortcuts: [ shortcuts: [
{ {
name: "Search", name: "Search",

View file

@ -1,5 +1,5 @@
import { isAnonymousPath, isAuthPath, setIsoData } from "@utils/app"; import { isAnonymousPath, isAuthPath, setIsoData } from "@utils/app";
import { Component, createRef, linkEvent } from "inferno"; import { Component, RefObject, createRef, linkEvent } from "inferno";
import { Provider } from "inferno-i18next-dess"; import { Provider } from "inferno-i18next-dess";
import { Route, Switch } from "inferno-router"; import { Route, Switch } from "inferno-router";
import { IsoDataOptionalSite } from "../../interfaces"; import { IsoDataOptionalSite } from "../../interfaces";
@ -13,108 +13,32 @@ import { Navbar } from "./navbar";
import "./styles.scss"; import "./styles.scss";
import { Theme } from "./theme"; import { Theme } from "./theme";
import AnonymousGuard from "../common/anonymous-guard"; import AnonymousGuard from "../common/anonymous-guard";
import AdultConsentModal from "../common/modal/adult-consent-modal";
import { destroyTippy, setupTippy } from "../../tippy";
function handleJumpToContent(app: App, event: any) { export class App extends Component<any, any> {
event.preventDefault();
app.contentRef.current?.focus();
}
export default class App extends Component<any, any> {
private isoData: IsoDataOptionalSite = setIsoData(this.context); private isoData: IsoDataOptionalSite = setIsoData(this.context);
private readonly rootRef = createRef<HTMLDivElement>(); private readonly mainContentRef: RefObject<HTMLElement>;
readonly contentRef = createRef<HTMLDivElement>(); constructor(props: any, context: any) {
super(props, context);
componentDidMount() { this.mainContentRef = createRef();
setupTippy(this.rootRef);
} }
componentWillUnmount() { handleJumpToContent(event) {
destroyTippy(); event.preventDefault();
this.mainContentRef.current?.focus();
} }
routes = routes.map(
({
path,
component: RouteComponent,
fetchInitialData,
getQueryParams,
mountedSameRouteNavKey,
}) => (
<Route
key={path}
path={path}
exact
component={routeProps => {
if (!fetchInitialData) {
FirstLoadService.falsify();
}
let queryProps = routeProps;
if (getQueryParams && this.isoData.site_res) {
// ErrorGuard will not render its children when
// site_res is missing, this guarantees that props
// will always contain the query params.
queryProps = {
...routeProps,
...getQueryParams(
routeProps.location.search,
this.isoData.site_res,
),
};
}
// When key is location.key the component will be recreated when
// navigating to itself. This is usesful to e.g. reset forms.
const key = mountedSameRouteNavKey ?? routeProps.location.key;
return (
<ErrorGuard>
<div tabIndex={-1} ref={this.contentRef}>
{RouteComponent &&
(isAuthPath(path ?? "") ? (
<AuthGuard {...routeProps}>
<RouteComponent key={key} {...queryProps} />
</AuthGuard>
) : isAnonymousPath(path ?? "") ? (
<AnonymousGuard>
<RouteComponent key={key} {...queryProps} />
</AnonymousGuard>
) : (
<RouteComponent key={key} {...queryProps} />
))}
</div>
</ErrorGuard>
);
}}
/>
),
);
render() { render() {
const siteRes = this.isoData.site_res; const siteRes = this.isoData.site_res;
const siteView = siteRes?.site_view; const siteView = siteRes?.site_view;
return ( return (
<Provider i18next={I18NextService.i18n}> <>
{/* This fragment is required to avoid an SSR error*/} <Provider i18next={I18NextService.i18n}>
<> <div id="app" className="lemmy-site">
{this.isoData.showAdultConsentModal && (
<AdultConsentModal
contentWarning={siteView!.site.content_warning!}
/>
)}
<div
id="app"
className="lemmy-site"
ref={this.rootRef}
data-adult-consent={this.isoData.showAdultConsentModal || null}
>
<button <button
type="button" type="button"
className="btn skip-link bg-light position-absolute start-0 z-3" className="btn skip-link bg-light position-absolute start-0 z-3"
onClick={linkEvent(this, handleJumpToContent)} onClick={linkEvent(this, this.handleJumpToContent)}
> >
{I18NextService.i18n.t("jump_to_content", "Jump to content")} {I18NextService.i18n.t("jump_to_content", "Jump to content")}
</button> </button>
@ -124,14 +48,65 @@ export default class App extends Component<any, any> {
<Navbar siteRes={siteRes} /> <Navbar siteRes={siteRes} />
<div className="mt-4 p-0 fl-1"> <div className="mt-4 p-0 fl-1">
<Switch> <Switch>
{this.routes} {routes.map(
({
path,
component: RouteComponent,
fetchInitialData,
getQueryParams,
}) => (
<Route
key={path}
path={path}
exact
component={routeProps => {
if (!fetchInitialData) {
FirstLoadService.falsify();
}
let queryProps = routeProps;
if (getQueryParams && this.isoData.site_res) {
// ErrorGuard will not render its children when
// site_res is missing, this guarantees that props
// will always contain the query params.
queryProps = {
...routeProps,
...getQueryParams(
routeProps.location.search,
this.isoData.site_res,
),
};
}
return (
<ErrorGuard>
<div tabIndex={-1}>
{RouteComponent &&
(isAuthPath(path ?? "") ? (
<AuthGuard {...routeProps}>
<RouteComponent {...queryProps} />
</AuthGuard>
) : isAnonymousPath(path ?? "") ? (
<AnonymousGuard>
<RouteComponent {...queryProps} />
</AnonymousGuard>
) : (
<RouteComponent {...queryProps} />
))}
</div>
</ErrorGuard>
);
}}
/>
),
)}
<Route component={ErrorPage} /> <Route component={ErrorPage} />
</Switch> </Switch>
</div> </div>
<Footer site={siteRes} /> <Footer site={siteRes} />
</div> </div>
</> </Provider>
</Provider> </>
); );
} }
} }

View file

@ -15,7 +15,6 @@ import { toast } from "../../toast";
import { Icon } from "../common/icon"; import { Icon } from "../common/icon";
import { PictrsImage } from "../common/pictrs-image"; import { PictrsImage } from "../common/pictrs-image";
import { Subscription } from "rxjs"; import { Subscription } from "rxjs";
import { tippyMixin } from "../mixins/tippy-mixin";
interface NavbarProps { interface NavbarProps {
siteRes?: GetSiteResponse; siteRes?: GetSiteResponse;
@ -43,7 +42,6 @@ function handleLogOut(i: Navbar) {
handleCollapseClick(i); handleCollapseClick(i);
} }
@tippyMixin
export class Navbar extends Component<NavbarProps, NavbarState> { export class Navbar extends Component<NavbarProps, NavbarState> {
collapseButtonRef = createRef<HTMLButtonElement>(); collapseButtonRef = createRef<HTMLButtonElement>();
mobileMenuRef = createRef<HTMLDivElement>(); mobileMenuRef = createRef<HTMLDivElement>();
@ -63,7 +61,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
this.handleOutsideMenuClick = this.handleOutsideMenuClick.bind(this); this.handleOutsideMenuClick = this.handleOutsideMenuClick.bind(this);
} }
async componentWillMount() { async componentDidMount() {
// Subscribe to jwt changes // Subscribe to jwt changes
if (isBrowser()) { if (isBrowser()) {
// On the first load, check the unreads // On the first load, check the unreads

View file

@ -2,23 +2,18 @@ import { capitalizeFirstLetter } from "@utils/helpers";
import { Component } from "inferno"; import { Component } from "inferno";
import { T } from "inferno-i18next-dess"; import { T } from "inferno-i18next-dess";
import { Link } from "inferno-router"; import { Link } from "inferno-router";
import { import { CreateComment, EditComment, Language } from "lemmy-js-client";
CommentResponse,
CreateComment,
EditComment,
Language,
} from "lemmy-js-client";
import { CommentNodeI } from "../../interfaces"; import { CommentNodeI } from "../../interfaces";
import { I18NextService, UserService } from "../../services"; import { I18NextService, UserService } from "../../services";
import { Icon } from "../common/icon"; import { Icon } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea"; import { MarkdownTextArea } from "../common/markdown-textarea";
import { RequestState } from "../../services/HttpService";
interface CommentFormProps { interface CommentFormProps {
/** /**
* Can either be the parent, or the editable comment. The right side is a postId. * Can either be the parent, or the editable comment. The right side is a postId.
*/ */
node: CommentNodeI | number; node: CommentNodeI | number;
finished?: boolean;
edit?: boolean; edit?: boolean;
disabled?: boolean; disabled?: boolean;
focus?: boolean; focus?: boolean;
@ -26,9 +21,7 @@ interface CommentFormProps {
allLanguages: Language[]; allLanguages: Language[];
siteLanguages: number[]; siteLanguages: number[];
containerClass?: string; containerClass?: string;
onUpsertComment( onUpsertComment(form: EditComment | CreateComment): void;
form: EditComment | CreateComment,
): Promise<RequestState<CommentResponse>>;
} }
export class CommentForm extends Component<CommentFormProps, any> { export class CommentForm extends Component<CommentFormProps, any> {
@ -57,6 +50,7 @@ export class CommentForm extends Component<CommentFormProps, any> {
initialContent={initialContent} initialContent={initialContent}
showLanguage showLanguage
buttonTitle={this.buttonTitle} buttonTitle={this.buttonTitle}
finished={this.props.finished}
replyType={typeof this.props.node !== "number"} replyType={typeof this.props.node !== "number"}
focus={this.props.focus} focus={this.props.focus}
disabled={this.props.disabled} disabled={this.props.disabled}
@ -74,9 +68,6 @@ export class CommentForm extends Component<CommentFormProps, any> {
<Link className="alert-link" to="/login"> <Link className="alert-link" to="/login">
# #
</Link> </Link>
<Link className="alert-link" to="/signup">
#
</Link>
</T> </T>
</div> </div>
)} )}
@ -92,38 +83,33 @@ export class CommentForm extends Component<CommentFormProps, any> {
: capitalizeFirstLetter(I18NextService.i18n.t("reply")); : capitalizeFirstLetter(I18NextService.i18n.t("reply"));
} }
async handleCommentSubmit( handleCommentSubmit(content: string, language_id?: number) {
content: string,
language_id?: number,
): Promise<boolean> {
const { node, onUpsertComment, edit } = this.props; const { node, onUpsertComment, edit } = this.props;
let response: RequestState<CommentResponse>;
if (typeof node === "number") { if (typeof node === "number") {
const post_id = node; const post_id = node;
response = await onUpsertComment({ onUpsertComment({
content, content,
post_id, post_id,
language_id, language_id,
}); });
} else if (edit) {
const comment_id = node.comment_view.comment.id;
response = await onUpsertComment({
content,
comment_id,
language_id,
});
} else { } else {
const post_id = node.comment_view.post.id; if (edit) {
const parent_id = node.comment_view.comment.id; const comment_id = node.comment_view.comment.id;
response = await onUpsertComment({ onUpsertComment({
content, content,
parent_id, comment_id,
post_id, language_id,
language_id, });
}); } else {
const post_id = node.comment_view.post.id;
const parent_id = node.comment_view.comment.id;
this.props.onUpsertComment({
content,
parent_id,
post_id,
language_id,
});
}
} }
return response.state !== "failed";
} }
} }

View file

@ -1,8 +1,8 @@
import { colorList, getCommentParentId } from "@utils/app"; import { colorList, getCommentParentId, showScores } from "@utils/app";
import { futureDaysToUnixTime, numToSI } from "@utils/helpers"; import { futureDaysToUnixTime, numToSI } from "@utils/helpers";
import classNames from "classnames"; import classNames from "classnames";
import { isBefore, parseISO, subMinutes } from "date-fns"; import { isBefore, parseISO, subMinutes } from "date-fns";
import { Component, linkEvent } from "inferno"; import { Component, InfernoNode, linkEvent } from "inferno";
import { Link } from "inferno-router"; import { Link } from "inferno-router";
import { import {
AddAdmin, AddAdmin,
@ -22,7 +22,6 @@ import {
EditComment, EditComment,
GetComments, GetComments,
Language, Language,
LocalUserVoteDisplayMode,
MarkCommentReplyAsRead, MarkCommentReplyAsRead,
MarkPersonMentionAsRead, MarkPersonMentionAsRead,
PersonMentionView, PersonMentionView,
@ -33,6 +32,7 @@ import {
SaveComment, SaveComment,
TransferCommunity, TransferCommunity,
} from "lemmy-js-client"; } from "lemmy-js-client";
import deepEqual from "lodash.isequal";
import { commentTreeMaxDepth } from "../../config"; import { commentTreeMaxDepth } from "../../config";
import { import {
CommentNodeI, CommentNodeI,
@ -42,7 +42,7 @@ import {
} from "../../interfaces"; } from "../../interfaces";
import { mdToHtml, mdToHtmlNoImages } from "../../markdown"; import { mdToHtml, mdToHtmlNoImages } from "../../markdown";
import { I18NextService, UserService } from "../../services"; import { I18NextService, UserService } from "../../services";
import { tippyMixin } from "../mixins/tippy-mixin"; import { setupTippy } from "../../tippy";
import { Icon, Spinner } from "../common/icon"; import { Icon, Spinner } from "../common/icon";
import { MomentTime } from "../common/moment-time"; import { MomentTime } from "../common/moment-time";
import { UserBadges } from "../common/user-badges"; import { UserBadges } from "../common/user-badges";
@ -51,10 +51,9 @@ import { CommunityLink } from "../community/community-link";
import { PersonListing } from "../person/person-listing"; import { PersonListing } from "../person/person-listing";
import { CommentForm } from "./comment-form"; import { CommentForm } from "./comment-form";
import { CommentNodes } from "./comment-nodes"; import { CommentNodes } from "./comment-nodes";
import { BanUpdateForm } from "../common/modal/mod-action-form-modal"; import { BanUpdateForm } from "../common/mod-action-form-modal";
import CommentActionDropdown from "../common/content-actions/comment-action-dropdown"; import CommentActionDropdown from "../common/content-actions/comment-action-dropdown";
import { RequestState } from "../../services/HttpService"; import { RequestState } from "../../services/HttpService";
import { VoteDisplay } from "../common/vote-display";
type CommentNodeState = { type CommentNodeState = {
showReply: boolean; showReply: boolean;
@ -81,11 +80,11 @@ interface CommentNodeProps {
showContext?: boolean; showContext?: boolean;
showCommunity?: boolean; showCommunity?: boolean;
enableDownvotes?: boolean; enableDownvotes?: boolean;
voteDisplayMode: LocalUserVoteDisplayMode;
viewType: CommentViewType; viewType: CommentViewType;
allLanguages: Language[]; allLanguages: Language[];
siteLanguages: number[]; siteLanguages: number[];
hideImages?: boolean; hideImages?: boolean;
finished: Map<CommentId, boolean | undefined>;
onSaveComment(form: SaveComment): Promise<void>; onSaveComment(form: SaveComment): Promise<void>;
onCommentReplyRead(form: MarkCommentReplyAsRead): void; onCommentReplyRead(form: MarkCommentReplyAsRead): void;
onPersonMentionRead(form: MarkPersonMentionAsRead): void; onPersonMentionRead(form: MarkPersonMentionAsRead): void;
@ -118,7 +117,6 @@ function handleToggleViewSource(i: CommentNode) {
})); }));
} }
@tippyMixin
export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
state: CommentNodeState = { state: CommentNodeState = {
showReply: false, showReply: false,
@ -137,8 +135,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
super(props, context); super(props, context);
this.handleReplyCancel = this.handleReplyCancel.bind(this); this.handleReplyCancel = this.handleReplyCancel.bind(this);
this.handleCreateComment = this.handleCreateComment.bind(this);
this.handleEditComment = this.handleEditComment.bind(this);
this.handleReportComment = this.handleReportComment.bind(this); this.handleReportComment = this.handleReportComment.bind(this);
this.handleRemoveComment = this.handleRemoveComment.bind(this); this.handleRemoveComment = this.handleRemoveComment.bind(this);
this.handleReplyClick = this.handleReplyClick.bind(this); this.handleReplyClick = this.handleReplyClick.bind(this);
@ -164,6 +160,22 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
return this.commentView.comment.id; return this.commentView.comment.id;
} }
componentWillReceiveProps(
nextProps: Readonly<{ children?: InfernoNode } & CommentNodeProps>,
): void {
if (!deepEqual(this.props, nextProps)) {
this.setState({
showEdit: false,
showAdvanced: false,
createOrEditCommentLoading: false,
upvoteLoading: false,
downvoteLoading: false,
readLoading: false,
fetchChildrenLoading: false,
});
}
}
render() { render() {
const node = this.props.node; const node = this.props.node;
const cv = this.commentView; const cv = this.commentView;
@ -251,11 +263,20 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{/* This is an expanding spacer for mobile */} {/* This is an expanding spacer for mobile */}
<div className="me-lg-5 flex-grow-1 flex-lg-grow-0 unselectable pointer mx-2" /> <div className="me-lg-5 flex-grow-1 flex-lg-grow-0 unselectable pointer mx-2" />
<VoteDisplay {showScores() && (
voteDisplayMode={this.props.voteDisplayMode} <>
myVote={my_vote} <span
counts={counts} className={`me-1 fw-bold ${this.scoreColor}`}
/> aria-label={I18NextService.i18n.t("number_of_points", {
count: Number(counts.score),
formattedCount: numToSI(counts.score),
})}
>
{numToSI(counts.score)}
</span>
<span className="me-1"></span>
</>
)}
<span> <span>
<MomentTime published={published} updated={updated} /> <MomentTime published={published} updated={updated} />
</span> </span>
@ -267,11 +288,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
edit edit
onReplyCancel={this.handleReplyCancel} onReplyCancel={this.handleReplyCancel}
disabled={this.props.locked} disabled={this.props.locked}
finished={this.props.finished.get(id)}
focus focus
allLanguages={this.props.allLanguages} allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages} siteLanguages={this.props.siteLanguages}
containerClass="comment-comment-container" containerClass="comment-comment-container"
onUpsertComment={this.handleEditComment} onUpsertComment={this.props.onEditComment}
/> />
)} )}
{!this.state.showEdit && !this.state.collapsed && ( {!this.state.showEdit && !this.state.collapsed && (
@ -294,7 +316,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
/> />
)} )}
</div> </div>
<div className="comment-bottom-btns d-flex justify-content-start column-gap-1.5 flex-wrap text-muted fw-bold mt-1 align-items-center"> <div className="comment-bottom-btns d-flex justify-content-between justify-content-lg-start flex-wrap text-muted fw-bold mt-1">
{this.props.showContext && this.getLinkButton()} {this.props.showContext && this.getLinkButton()}
{this.props.markable && ( {this.props.markable && (
<button <button
@ -331,9 +353,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
id={id} id={id}
onVote={this.props.onCommentVote} onVote={this.props.onCommentVote}
enableDownvotes={this.props.enableDownvotes} enableDownvotes={this.props.enableDownvotes}
voteDisplayMode={this.props.voteDisplayMode}
counts={counts} counts={counts}
myVote={my_vote} my_vote={my_vote}
/> />
<button <button
type="button" type="button"
@ -408,11 +429,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
node={node} node={node}
onReplyCancel={this.handleReplyCancel} onReplyCancel={this.handleReplyCancel}
disabled={this.props.locked} disabled={this.props.locked}
finished={this.props.finished.get(id)}
focus focus
allLanguages={this.props.allLanguages} allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages} siteLanguages={this.props.siteLanguages}
containerClass="comment-comment-container" containerClass="comment-comment-container"
onUpsertComment={this.handleCreateComment} onUpsertComment={this.props.onCreateComment}
/> />
)} )}
{!this.state.collapsed && node.children.length > 0 && ( {!this.state.collapsed && node.children.length > 0 && (
@ -422,13 +444,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
moderators={this.props.moderators} moderators={this.props.moderators}
admins={this.props.admins} admins={this.props.admins}
enableDownvotes={this.props.enableDownvotes} enableDownvotes={this.props.enableDownvotes}
voteDisplayMode={this.props.voteDisplayMode}
viewType={this.props.viewType} viewType={this.props.viewType}
allLanguages={this.props.allLanguages} allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages} siteLanguages={this.props.siteLanguages}
hideImages={this.props.hideImages} hideImages={this.props.hideImages}
isChild={!this.props.isTopLevel} isChild={!this.props.isTopLevel}
depth={this.props.node.depth + 1} depth={this.props.node.depth + 1}
finished={this.props.finished}
onCommentReplyRead={this.props.onCommentReplyRead} onCommentReplyRead={this.props.onCommentReplyRead}
onPersonMentionRead={this.props.onPersonMentionRead} onPersonMentionRead={this.props.onPersonMentionRead}
onCreateComment={this.props.onCreateComment} onCreateComment={this.props.onCreateComment}
@ -479,14 +501,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
? I18NextService.i18n.t("show_context") ? I18NextService.i18n.t("show_context")
: I18NextService.i18n.t("link"); : I18NextService.i18n.t("link");
// The context button should show the parent comment by default
const parentCommentId = getCommentParentId(cv.comment) ?? cv.comment.id;
return ( return (
<> <>
<Link <Link
className={classnames} className={classnames}
to={`/post/${cv.post.id}/${ to={`/comment/${parentCommentId}`}
(this.props.showContext && getCommentParentId(cv.comment)) ||
cv.comment.id
}`}
title={title} title={title}
> >
<Icon icon="link" classes="icon-inline" /> <Icon icon="link" classes="icon-inline" />
@ -513,6 +535,35 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
return this.commentView.creator.id === this.commentView.post.creator_id; return this.commentView.creator.id === this.commentView.post.creator_id;
} }
get scoreColor() {
if (this.commentView.my_vote === 1) {
return "text-info";
} else if (this.commentView.my_vote === -1) {
return "text-danger";
} else {
return "text-muted";
}
}
get pointsTippy(): string {
const points = I18NextService.i18n.t("number_of_points", {
count: Number(this.commentView.counts.score),
formattedCount: numToSI(this.commentView.counts.score),
});
const upvotes = I18NextService.i18n.t("number_of_upvotes", {
count: Number(this.commentView.counts.upvotes),
formattedCount: numToSI(this.commentView.counts.upvotes),
});
const downvotes = I18NextService.i18n.t("number_of_downvotes", {
count: Number(this.commentView.counts.downvotes),
formattedCount: numToSI(this.commentView.counts.downvotes),
});
return `${points}${upvotes}${downvotes}`;
}
get expandText(): string { get expandText(): string {
return this.state.collapsed return this.state.collapsed
? I18NextService.i18n.t("expand") ? I18NextService.i18n.t("expand")
@ -540,26 +591,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.setState({ showReply: false, showEdit: false }); this.setState({ showReply: false, showEdit: false });
} }
async handleCreateComment(
form: CreateComment,
): Promise<RequestState<CommentResponse>> {
const res = await this.props.onCreateComment(form);
if (res.state !== "failed") {
this.setState({ showReply: false, showEdit: false });
}
return res;
}
async handleEditComment(
form: EditComment,
): Promise<RequestState<CommentResponse>> {
const res = await this.props.onEditComment(form);
if (res.state !== "failed") {
this.setState({ showReply: false, showEdit: false });
}
return res;
}
isPersonMentionType(item: CommentNodeView): item is PersonMentionView { isPersonMentionType(item: CommentNodeView): item is PersonMentionView {
return item.person_mention?.id !== undefined; return item.person_mention?.id !== undefined;
} }
@ -576,10 +607,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
handleCommentCollapse(i: CommentNode) { handleCommentCollapse(i: CommentNode) {
i.setState({ collapsed: !i.state.collapsed }); i.setState({ collapsed: !i.state.collapsed });
setupTippy();
} }
handleShowAdvanced(i: CommentNode) { handleShowAdvanced(i: CommentNode) {
i.setState({ showAdvanced: !i.state.showAdvanced }); i.setState({ showAdvanced: !i.state.showAdvanced });
setupTippy();
} }
async handleSaveComment() { async handleSaveComment() {
@ -637,7 +670,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
async handleBanFromCommunity({ async handleBanFromCommunity({
daysUntilExpires, daysUntilExpires,
reason, reason,
shouldRemoveOrRestoreData, shouldRemove,
}: BanUpdateForm) { }: BanUpdateForm) {
const { const {
creator: { id: person_id }, creator: { id: person_id },
@ -646,9 +679,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
} = this.commentView; } = this.commentView;
const ban = !creator_banned_from_community; const ban = !creator_banned_from_community;
// If its an unban, restore all their data // If its an unban, restore all their data
if (ban === false) { if (ban === false) {
shouldRemoveOrRestoreData = true; shouldRemove = false;
} }
const expires = futureDaysToUnixTime(daysUntilExpires); const expires = futureDaysToUnixTime(daysUntilExpires);
@ -656,7 +690,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
community_id, community_id,
person_id, person_id,
ban, ban,
remove_or_restore_data: shouldRemoveOrRestoreData, remove_data: shouldRemove,
reason, reason,
expires, expires,
}); });
@ -665,7 +699,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
async handleBanFromSite({ async handleBanFromSite({
daysUntilExpires, daysUntilExpires,
reason, reason,
shouldRemoveOrRestoreData, shouldRemove,
}: BanUpdateForm) { }: BanUpdateForm) {
const { const {
creator: { id: person_id, banned }, creator: { id: person_id, banned },
@ -675,14 +709,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
// If its an unban, restore all their data // If its an unban, restore all their data
if (ban === false) { if (ban === false) {
shouldRemoveOrRestoreData = true; shouldRemove = false;
} }
const expires = futureDaysToUnixTime(daysUntilExpires); const expires = futureDaysToUnixTime(daysUntilExpires);
this.props.onBanPerson({ this.props.onBanPerson({
person_id, person_id,
ban, ban,
remove_or_restore_data: shouldRemoveOrRestoreData, remove_data: shouldRemove,
reason, reason,
expires, expires,
}); });

View file

@ -7,6 +7,7 @@ import {
BanFromCommunity, BanFromCommunity,
BanPerson, BanPerson,
BlockPerson, BlockPerson,
CommentId,
CommentResponse, CommentResponse,
CommunityModeratorView, CommunityModeratorView,
CreateComment, CreateComment,
@ -17,7 +18,6 @@ import {
EditComment, EditComment,
GetComments, GetComments,
Language, Language,
LocalUserVoteDisplayMode,
MarkCommentReplyAsRead, MarkCommentReplyAsRead,
MarkPersonMentionAsRead, MarkPersonMentionAsRead,
PersonView, PersonView,
@ -44,13 +44,13 @@ interface CommentNodesProps {
showContext?: boolean; showContext?: boolean;
showCommunity?: boolean; showCommunity?: boolean;
enableDownvotes?: boolean; enableDownvotes?: boolean;
voteDisplayMode: LocalUserVoteDisplayMode;
viewType: CommentViewType; viewType: CommentViewType;
allLanguages: Language[]; allLanguages: Language[];
siteLanguages: number[]; siteLanguages: number[];
hideImages?: boolean; hideImages?: boolean;
isChild?: boolean; isChild?: boolean;
depth?: number; depth?: number;
finished: Map<CommentId, boolean | undefined>;
onSaveComment(form: SaveComment): Promise<void>; onSaveComment(form: SaveComment): Promise<void>;
onCommentReplyRead(form: MarkCommentReplyAsRead): void; onCommentReplyRead(form: MarkCommentReplyAsRead): void;
onPersonMentionRead(form: MarkPersonMentionAsRead): void; onPersonMentionRead(form: MarkPersonMentionAsRead): void;
@ -115,13 +115,13 @@ export class CommentNodes extends Component<CommentNodesProps, any> {
showContext={this.props.showContext} showContext={this.props.showContext}
showCommunity={this.props.showCommunity} showCommunity={this.props.showCommunity}
enableDownvotes={this.props.enableDownvotes} enableDownvotes={this.props.enableDownvotes}
voteDisplayMode={this.props.voteDisplayMode}
viewType={this.props.viewType} viewType={this.props.viewType}
allLanguages={this.props.allLanguages} allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages} siteLanguages={this.props.siteLanguages}
hideImages={this.props.hideImages} hideImages={this.props.hideImages}
onCommentReplyRead={this.props.onCommentReplyRead} onCommentReplyRead={this.props.onCommentReplyRead}
onPersonMentionRead={this.props.onPersonMentionRead} onPersonMentionRead={this.props.onPersonMentionRead}
finished={this.props.finished}
onCreateComment={this.props.onCreateComment} onCreateComment={this.props.onCreateComment}
onEditComment={this.props.onEditComment} onEditComment={this.props.onEditComment}
onCommentVote={this.props.onCommentVote} onCommentVote={this.props.onCommentVote}

View file

@ -3,7 +3,6 @@ import { T } from "inferno-i18next-dess";
import { import {
CommentReportView, CommentReportView,
CommentView, CommentView,
LocalUserVoteDisplayMode,
ResolveCommentReport, ResolveCommentReport,
} from "lemmy-js-client"; } from "lemmy-js-client";
import { CommentNodeI, CommentViewType } from "../../interfaces"; import { CommentNodeI, CommentViewType } from "../../interfaces";
@ -12,12 +11,9 @@ import { Icon, Spinner } from "../common/icon";
import { PersonListing } from "../person/person-listing"; import { PersonListing } from "../person/person-listing";
import { CommentNode } from "./comment-node"; import { CommentNode } from "./comment-node";
import { EMPTY_REQUEST } from "../../services/HttpService"; import { EMPTY_REQUEST } from "../../services/HttpService";
import { tippyMixin } from "../mixins/tippy-mixin";
interface CommentReportProps { interface CommentReportProps {
report: CommentReportView; report: CommentReportView;
enableDownvotes?: boolean;
voteDisplayMode: LocalUserVoteDisplayMode;
onResolveReport(form: ResolveCommentReport): void; onResolveReport(form: ResolveCommentReport): void;
} }
@ -25,7 +21,6 @@ interface CommentReportState {
loading: boolean; loading: boolean;
} }
@tippyMixin
export class CommentReport extends Component< export class CommentReport extends Component<
CommentReportProps, CommentReportProps,
CommentReportState CommentReportState
@ -82,14 +77,14 @@ export class CommentReport extends Component<
<CommentNode <CommentNode
node={node} node={node}
viewType={CommentViewType.Flat} viewType={CommentViewType.Flat}
enableDownvotes={this.props.enableDownvotes} enableDownvotes={true}
voteDisplayMode={this.props.voteDisplayMode}
viewOnly={true} viewOnly={true}
showCommunity={true} showCommunity={true}
allLanguages={[]} allLanguages={[]}
siteLanguages={[]} siteLanguages={[]}
hideImages hideImages
// All of these are unused, since its viewonly // All of these are unused, since its viewonly
finished={new Map()}
onSaveComment={async () => {}} onSaveComment={async () => {}}
onBlockPerson={async () => {}} onBlockPerson={async () => {}}
onDeleteComment={async () => {}} onDeleteComment={async () => {}}

View file

@ -1,25 +1,30 @@
import { Component } from "inferno"; import { Component } from "inferno";
import { UserService } from "../../services"; import { UserService } from "../../services";
import { Spinner } from "./icon"; import { Spinner } from "./icon";
import { isBrowser } from "@utils/browser";
class AnonymousGuard extends Component<any, any> { interface AnonymousGuardState {
hasRedirected: boolean;
}
class AnonymousGuard extends Component<any, AnonymousGuardState> {
state = {
hasRedirected: false,
} as AnonymousGuardState;
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
} }
hasAuth() { componentDidMount() {
return UserService.Instance.myUserInfo; if (UserService.Instance.myUserInfo) {
}
componentWillMount() {
if (this.hasAuth() && isBrowser()) {
this.context.router.history.replace(`/`); this.context.router.history.replace(`/`);
} else {
this.setState({ hasRedirected: true });
} }
} }
render() { render() {
return !this.hasAuth() ? this.props.children : <Spinner />; return this.state.hasRedirected ? this.props.children : <Spinner />;
} }
} }

View file

@ -3,12 +3,19 @@ import { RouteComponentProps } from "inferno-router/dist/Route";
import { UserService } from "../../services"; import { UserService } from "../../services";
import { Spinner } from "./icon"; import { Spinner } from "./icon";
import { getQueryString } from "@utils/helpers"; import { getQueryString } from "@utils/helpers";
import { isBrowser } from "@utils/browser";
interface AuthGuardState {
hasRedirected: boolean;
}
class AuthGuard extends Component< class AuthGuard extends Component<
RouteComponentProps<Record<string, string>>, RouteComponentProps<Record<string, string>>,
any AuthGuardState
> { > {
state = {
hasRedirected: false,
} as AuthGuardState;
constructor( constructor(
props: RouteComponentProps<Record<string, string>>, props: RouteComponentProps<Record<string, string>>,
context: any, context: any,
@ -16,21 +23,19 @@ class AuthGuard extends Component<
super(props, context); super(props, context);
} }
hasAuth() { componentDidMount() {
return UserService.Instance.myUserInfo; if (!UserService.Instance.myUserInfo) {
}
componentWillMount() {
if (!this.hasAuth() && isBrowser()) {
const { pathname, search } = this.props.location; const { pathname, search } = this.props.location;
this.context.router.history.replace( this.context.router.history.replace(
`/login${getQueryString({ prev: pathname + search })}`, `/login${getQueryString({ prev: pathname + search })}`,
); );
} else {
this.setState({ hasRedirected: true });
} }
} }
render() { render() {
return this.hasAuth() ? this.props.children : <Spinner />; return this.state.hasRedirected ? this.props.children : <Spinner />;
} }
} }

View file

@ -47,13 +47,13 @@ export class CommentSortSelect extends Component<
<option disabled aria-hidden="true"> <option disabled aria-hidden="true">
{I18NextService.i18n.t("sort_type")} {I18NextService.i18n.t("sort_type")}
</option> </option>
<option value="Hot">{I18NextService.i18n.t("hot")}</option> <option value={"Hot"}>{I18NextService.i18n.t("hot")}</option>,
<option value="Controversial"> <option value={"Controversial"}>
{I18NextService.i18n.t("controversial")} {I18NextService.i18n.t("controversial")}
</option> </option>
<option value="Top">{I18NextService.i18n.t("top")}</option> <option value={"Top"}>{I18NextService.i18n.t("top")}</option>,
<option value="New">{I18NextService.i18n.t("new")}</option> <option value={"New"}>{I18NextService.i18n.t("new")}</option>
<option value="Old">{I18NextService.i18n.t("old")}</option> <option value={"Old"}>{I18NextService.i18n.t("old")}</option>
</select> </select>
<a <a
className="sort-select-help text-muted" className="sort-select-help text-muted"

View file

@ -1,14 +1,12 @@
import { Component, RefObject, createRef, linkEvent } from "inferno"; import { Component, RefObject, createRef, linkEvent } from "inferno";
import { I18NextService } from "../../../services"; import { I18NextService } from "../../services";
import type { Modal } from "bootstrap"; import type { Modal } from "bootstrap";
import { Spinner } from "../icon"; import { Spinner } from "./icon";
import { LoadingEllipses } from "../loading-ellipses"; import { LoadingEllipses } from "./loading-ellipses";
import { modalMixin } from "../../mixins/modal-mixin";
import { MouseEventHandler } from "inferno";
interface ConfirmationModalProps { interface ConfirmationModalProps {
onYes: () => Promise<void>; onYes: () => Promise<void>;
onNo: MouseEventHandler<HTMLButtonElement>; onNo: () => void;
message: string; message: string;
loadingMessage: string; loadingMessage: string;
show: boolean; show: boolean;
@ -24,14 +22,13 @@ async function handleYes(i: ConfirmationModal) {
i.setState({ loading: false }); i.setState({ loading: false });
} }
@modalMixin
export default class ConfirmationModal extends Component< export default class ConfirmationModal extends Component<
ConfirmationModalProps, ConfirmationModalProps,
ConfirmationModalState ConfirmationModalState
> { > {
readonly modalDivRef: RefObject<HTMLDivElement>; readonly modalDivRef: RefObject<HTMLDivElement>;
readonly yesButtonRef: RefObject<HTMLButtonElement>; readonly yesButtonRef: RefObject<HTMLButtonElement>;
modal?: Modal; modal: Modal;
state: ConfirmationModalState = { state: ConfirmationModalState = {
loading: false, loading: false,
}; };
@ -41,6 +38,41 @@ export default class ConfirmationModal extends Component<
this.modalDivRef = createRef(); this.modalDivRef = createRef();
this.yesButtonRef = createRef(); this.yesButtonRef = createRef();
this.handleShow = this.handleShow.bind(this);
}
async componentDidMount() {
this.modalDivRef.current?.addEventListener(
"shown.bs.modal",
this.handleShow,
);
const Modal = (await import("bootstrap/js/dist/modal")).default;
this.modal = new Modal(this.modalDivRef.current!);
if (this.props.show) {
this.modal.show();
}
}
componentWillUnmount() {
this.modalDivRef.current?.removeEventListener(
"shown.bs.modal",
this.handleShow,
);
this.modal.dispose();
}
componentDidUpdate({ show: prevShow }: ConfirmationModalProps) {
if (!!prevShow !== !!this.props.show) {
if (this.props.show) {
this.modal.show();
} else {
this.modal.hide();
}
}
} }
render() { render() {

View file

@ -1,7 +1,6 @@
import { Component, linkEvent } from "inferno"; import { Component, linkEvent } from "inferno";
import { Icon, Spinner } from "../icon"; import { Icon, Spinner } from "../icon";
import classNames from "classnames"; import classNames from "classnames";
import { tippyMixin } from "../../mixins/tippy-mixin";
interface ActionButtonPropsBase { interface ActionButtonPropsBase {
label: string; label: string;
@ -35,7 +34,6 @@ async function handleClick(i: ActionButton) {
i.setState({ loading: false }); i.setState({ loading: false });
} }
@tippyMixin
export default class ActionButton extends Component< export default class ActionButton extends Component<
ActionButtonProps, ActionButtonProps,
ActionButtonState ActionButtonState

View file

@ -10,18 +10,16 @@ import {
amMod, amMod,
canAdmin, canAdmin,
canMod, canMod,
isBanned,
} from "@utils/roles"; } from "@utils/roles";
import ActionButton from "./action-button"; import ActionButton from "./action-button";
import classNames from "classnames"; import classNames from "classnames";
import { Link } from "inferno-router"; import { Link } from "inferno-router";
import ConfirmationModal from "../modal/confirmation-modal"; import ConfirmationModal from "../confirmation-modal";
import ViewVotesModal from "../modal/view-votes-modal"; import ViewVotesModal from "../view-votes-modal";
import ModActionFormModal, { import ModActionFormModal, { BanUpdateForm } from "../mod-action-form-modal";
BanUpdateForm,
} from "../modal/mod-action-form-modal";
import { BanType, CommentNodeView, PurgeType } from "../../../interfaces"; import { BanType, CommentNodeView, PurgeType } from "../../../interfaces";
import { getApubName, hostname } from "@utils/helpers"; import { getApubName, hostname } from "@utils/helpers";
import { tippyMixin } from "../../mixins/tippy-mixin";
interface ContentActionDropdownPropsBase { interface ContentActionDropdownPropsBase {
onSave: () => Promise<void>; onSave: () => Promise<void>;
@ -55,42 +53,29 @@ export type ContentPostProps = {
onLock: () => Promise<void>; onLock: () => Promise<void>;
onFeatureLocal: () => Promise<void>; onFeatureLocal: () => Promise<void>;
onFeatureCommunity: () => Promise<void>; onFeatureCommunity: () => Promise<void>;
onHidePost: () => Promise<void>;
} & ContentActionDropdownPropsBase; } & ContentActionDropdownPropsBase;
type ContentActionDropdownProps = ContentCommentProps | ContentPostProps; type ContentActionDropdownProps = ContentCommentProps | ContentPostProps;
type DialogType = const dialogTypes = [
| "BanDialog" "showBanDialog",
| "RemoveDialog" "showRemoveDialog",
| "PurgeDialog" "showPurgeDialog",
| "ReportDialog" "showReportDialog",
| "TransferCommunityDialog" "showTransferCommunityDialog",
| "AppointModDialog" "showAppointModDialog",
| "AppointAdminDialog" "showAppointAdminDialog",
| "ViewVotesDialog"; "showViewVotesDialog",
] as const;
type ActionTypeState = { type DialogType = (typeof dialogTypes)[number];
type ContentActionDropdownState = {
banType?: BanType; banType?: BanType;
purgeType?: PurgeType; purgeType?: PurgeType;
}; mounted: boolean;
} & { [key in DialogType]: boolean };
type ShowState = {
[key in `show${DialogType}`]: boolean;
};
type RenderState = {
[key in `render${DialogType}`]: boolean;
};
type DropdownState = { dropdownOpenedOnce: boolean };
type ContentActionDropdownState = ActionTypeState &
ShowState &
RenderState &
DropdownState;
@tippyMixin
export default class ContentActionDropdown extends Component< export default class ContentActionDropdown extends Component<
ContentActionDropdownProps, ContentActionDropdownProps,
ContentActionDropdownState ContentActionDropdownState
@ -104,15 +89,7 @@ export default class ContentActionDropdown extends Component<
showReportDialog: false, showReportDialog: false,
showTransferCommunityDialog: false, showTransferCommunityDialog: false,
showViewVotesDialog: false, showViewVotesDialog: false,
renderAppointAdminDialog: false, mounted: false,
renderAppointModDialog: false,
renderBanDialog: false,
renderPurgeDialog: false,
renderRemoveDialog: false,
renderReportDialog: false,
renderTransferCommunityDialog: false,
renderViewVotesDialog: false,
dropdownOpenedOnce: false,
}; };
constructor(props: ContentActionDropdownProps, context: any) { constructor(props: ContentActionDropdownProps, context: any) {
@ -133,7 +110,10 @@ export default class ContentActionDropdown extends Component<
this.toggleAppointAdminShow = this.toggleAppointAdminShow.bind(this); this.toggleAppointAdminShow = this.toggleAppointAdminShow.bind(this);
this.toggleViewVotesShow = this.toggleViewVotesShow.bind(this); this.toggleViewVotesShow = this.toggleViewVotesShow.bind(this);
this.wrapHandler = this.wrapHandler.bind(this); this.wrapHandler = this.wrapHandler.bind(this);
this.handleDropdownToggleClick = this.handleDropdownToggleClick.bind(this); }
componentDidMount() {
this.setState({ mounted: true });
} }
render() { render() {
@ -155,32 +135,12 @@ export default class ContentActionDropdown extends Component<
type === "post" type === "post"
? `post-actions-dropdown-${id}` ? `post-actions-dropdown-${id}`
: `comment-actions-dropdown-${id}`; : `comment-actions-dropdown-${id}`;
const creatorBannedFromLocal = creator.banned; const creatorBannedFromLocal = isBanned(creator);
const showToggleAdmin = !creatorBannedFromLocal && creator.local; const showToggleAdmin = !creatorBannedFromLocal && creator.local;
const canAppointCommunityMod = const canAppointCommunityMod =
(amMod(community.id) || (amAdmin() && community.local)) && (amMod(community.id) || (amAdmin() && community.local)) &&
!creator_banned_from_community; !creator_banned_from_community;
const modHistoryUserTranslation = I18NextService.i18n.t(
"user_moderation_history",
{ user: creator.name },
);
// The link and translation string for the item
const { modHistoryItemLink, modHistoryItemTranslation } =
type === "post"
? {
modHistoryItemLink: `/modlog?postId=${id}`,
modHistoryItemTranslation: I18NextService.i18n.t(
"post_moderation_history",
),
}
: {
modHistoryItemLink: `/modlog?commentId=${id}`,
modHistoryItemTranslation: I18NextService.i18n.t(
"comment_moderation_history",
),
};
return ( return (
<> <>
{type === "comment" && ( {type === "comment" && (
@ -211,323 +171,121 @@ export default class ContentActionDropdown extends Component<
aria-expanded="false" aria-expanded="false"
aria-controls={dropdownId} aria-controls={dropdownId}
aria-label={I18NextService.i18n.t("more")} aria-label={I18NextService.i18n.t("more")}
onClick={this.handleDropdownToggleClick}
> >
<Icon icon="more-vertical" inline /> <Icon icon="more-vertical" inline />
</button> </button>
<ul className="dropdown-menu" id={dropdownId}> <ul className="dropdown-menu" id={dropdownId}>
{this.state.dropdownOpenedOnce && ( {this.amCreator ? (
<> <>
{type === "post" && (
<li>
<ActionButton
icon={this.props.postView.hidden ? "eye" : "eye-slash"}
label={I18NextService.i18n.t(
this.props.postView.hidden
? "unhide_post"
: "hide_post",
)}
onClick={this.props.onHidePost}
/>
</li>
)}
{this.amCreator ? (
<>
<li>
<ActionButton
icon="edit"
label={I18NextService.i18n.t("edit")}
noLoading
onClick={onEdit}
/>
</li>
<li>
<ActionButton
onClick={onDelete}
icon={deleted ? "undo-trash" : "trash"}
label={I18NextService.i18n.t(
deleted ? "undelete" : "delete",
)}
iconClass={`text-${deleted ? "success" : "danger"}`}
/>
</li>
</>
) : (
<>
{type === "comment" && (
<li>
<Link
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
to={`/create_private_message/${creator.id}`}
title={I18NextService.i18n.t("message")}
aria-label={I18NextService.i18n.t("message")}
data-tippy-content={I18NextService.i18n.t("message")}
>
<Icon icon="mail" inline classes="me-2" />
{I18NextService.i18n.t("message")}
</Link>
</li>
)}
<li>
<ActionButton
icon="flag"
label={I18NextService.i18n.t("create_report")}
onClick={this.toggleReportDialogShow}
noLoading
/>
</li>
<li>
<ActionButton
icon="slash"
label={I18NextService.i18n.t("block_user")}
onClick={onBlock}
/>
</li>
</>
)}
{amAdmin() && (
<li>
<ActionButton
onClick={this.toggleViewVotesShow}
label={I18NextService.i18n.t("view_votes")}
icon={"arrow-up"}
noLoading
/>
</li>
)}
{(amMod(community.id) || amAdmin()) && (
<>
<li>
<hr className="dropdown-divider" />
</li>
{type === "post" && (
<>
<li>
<ActionButton
onClick={this.props.onLock}
label={I18NextService.i18n.t(
locked ? "unlock" : "lock",
)}
icon={locked ? "unlock" : "lock"}
/>
</li>
<li>
<ActionButton
onClick={this.props.onFeatureCommunity}
label={I18NextService.i18n.t(
this.props.postView.post.featured_community
? "unfeature_from_community"
: "feature_in_community",
)}
icon={
this.props.postView.post.featured_community
? "pin-off"
: "pin"
}
/>
</li>
{amAdmin() && (
<li>
<ActionButton
onClick={this.props.onFeatureLocal}
label={I18NextService.i18n.t(
this.props.postView.post.featured_local
? "unfeature_from_local"
: "feature_in_local",
)}
icon={
this.props.postView.post.featured_local
? "pin-off"
: "pin"
}
/>
</li>
)}
</>
)}
</>
)}
{type === "comment" &&
this.amCreator &&
(this.canModOnSelf || this.canAdminOnSelf) && (
<li>
<ActionButton
onClick={this.props.onDistinguish}
icon={
this.props.commentView.comment.distinguished
? "shield-off"
: "shield"
}
label={I18NextService.i18n.t(
this.props.commentView.comment.distinguished
? "undistinguish"
: "distinguish",
)}
/>
</li>
)}
<li> <li>
<Link <ActionButton
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item" icon="edit"
to={`/modlog?userId=${creator.id}`} label={I18NextService.i18n.t("edit")}
title={modHistoryUserTranslation} noLoading
aria-label={modHistoryUserTranslation} onClick={onEdit}
data-tippy-content={modHistoryUserTranslation} />
>
<Icon icon="history" inline classes="me-2" />
{modHistoryUserTranslation}
</Link>
<Link
className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
to={modHistoryItemLink}
title={modHistoryItemTranslation}
aria-label={modHistoryItemTranslation}
data-tippy-content={modHistoryItemTranslation}
>
<Icon icon="history" inline classes="me-2" />
{modHistoryItemTranslation}
</Link>
</li> </li>
{(this.canMod || this.canAdmin) && ( <li>
<ActionButton
onClick={onDelete}
icon={deleted ? "undo-trash" : "trash"}
label={I18NextService.i18n.t(
deleted ? "undelete" : "delete",
)}
iconClass={`text-${deleted ? "success" : "danger"}`}
/>
</li>
</>
) : (
<>
{type === "comment" && (
<li> <li>
<ActionButton <Link
label={ className="btn btn-link btn-sm d-flex align-items-center rounded-0 dropdown-item"
removed to={`/create_private_message/${creator.id}`}
? `${I18NextService.i18n.t( title={I18NextService.i18n.t("message")}
"restore", aria-label={I18NextService.i18n.t("message")}
)} ${I18NextService.i18n.t( data-tippy-content={I18NextService.i18n.t("message")}
type === "post" ? "post" : "comment", >
)}` <Icon icon="mail" inline classes="me-2" />
: I18NextService.i18n.t( {I18NextService.i18n.t("message")}
type === "post" </Link>
? "remove_post"
: "remove_comment",
)
}
icon={removed ? "restore" : "x"}
noLoading
onClick={this.toggleRemoveShow}
iconClass={`text-${removed ? "success" : "danger"}`}
/>
</li> </li>
)} )}
{this.canMod && <li>
(!creator_is_moderator || canAppointCommunityMod) && ( <ActionButton
<> icon="flag"
<li> label={I18NextService.i18n.t("create_report")}
<hr className="dropdown-divider" /> onClick={this.toggleReportDialogShow}
</li> noLoading
{!creator_is_moderator && ( />
<li> </li>
<ActionButton <li>
onClick={this.toggleBanFromCommunityShow} <ActionButton
label={I18NextService.i18n.t( icon="slash"
creator_banned_from_community label={I18NextService.i18n.t("block_user")}
? "unban_from_community" onClick={onBlock}
: "ban_from_community", />
)} </li>
icon={ </>
creator_banned_from_community ? "unban" : "ban" )}
} {amAdmin() && (
noLoading <li>
iconClass={`text-${ <ActionButton
creator_banned_from_community onClick={this.toggleViewVotesShow}
? "success" label={I18NextService.i18n.t("view_votes")}
: "danger" icon={"arrow-up"}
}`} noLoading
/> />
</li> </li>
)} )}
{canAppointCommunityMod && (
<li>
<ActionButton
onClick={this.toggleAppointModShow}
label={I18NextService.i18n.t(
`${
creator_is_moderator ? "remove" : "appoint"
}_as_mod`,
)}
icon={creator_is_moderator ? "demote" : "promote"}
iconClass={`text-${
creator_is_moderator ? "danger" : "success"
}`}
noLoading
/>
</li>
)}
</>
)}
{(amCommunityCreator(creator.id, moderators) ||
this.canAdmin) &&
creator_is_moderator && (
<li>
<ActionButton
label={I18NextService.i18n.t("transfer_community")}
onClick={this.toggleTransferCommunityShow}
icon="transfer"
noLoading
/>
</li>
)}
{this.canAdmin && (showToggleAdmin || !creator_is_admin) && ( {(amMod(community.id) || amAdmin()) && (
<>
<li>
<hr className="dropdown-divider" />
</li>
{type === "post" && (
<> <>
<li> <li>
<hr className="dropdown-divider" /> <ActionButton
onClick={this.props.onLock}
label={I18NextService.i18n.t(
locked ? "unlock" : "lock",
)}
icon={locked ? "unlock" : "lock"}
/>
</li> </li>
{!creator_is_admin && ( <li>
<> <ActionButton
<li> onClick={this.props.onFeatureCommunity}
<ActionButton label={I18NextService.i18n.t(
label={I18NextService.i18n.t( this.props.postView.post.featured_community
creatorBannedFromLocal ? "unfeature_from_community"
? "unban_from_site" : "feature_in_community",
: "ban_from_site", )}
)} icon={
onClick={this.toggleBanFromSiteShow} this.props.postView.post.featured_community
icon={creatorBannedFromLocal ? "unban" : "ban"} ? "pin-off"
iconClass={`text-${ : "pin"
creatorBannedFromLocal ? "success" : "danger" }
}`} />
noLoading </li>
/> {amAdmin() && (
</li>
<li>
<ActionButton
label={I18NextService.i18n.t("purge_user")}
onClick={this.togglePurgePersonShow}
icon="purge"
noLoading
iconClass="text-danger"
/>
</li>
<li>
<ActionButton
label={I18NextService.i18n.t(
`purge_${type === "post" ? "post" : "comment"}`,
)}
onClick={this.togglePurgeContentShow}
icon="purge"
noLoading
iconClass="text-danger"
/>
</li>
</>
)}
{showToggleAdmin && (
<li> <li>
<ActionButton <ActionButton
onClick={this.props.onFeatureLocal}
label={I18NextService.i18n.t( label={I18NextService.i18n.t(
`${creator_is_admin ? "remove" : "appoint"}_as_admin`, this.props.postView.post.featured_local
? "unfeature_from_local"
: "feature_in_local",
)} )}
onClick={this.toggleAppointAdminShow} icon={
icon={creator_is_admin ? "demote" : "promote"} this.props.postView.post.featured_local
iconClass={`text-${ ? "pin-off"
creator_is_admin ? "danger" : "success" : "pin"
}`} }
noLoading
/> />
</li> </li>
)} )}
@ -535,6 +293,161 @@ export default class ContentActionDropdown extends Component<
)} )}
</> </>
)} )}
{type === "comment" &&
this.amCreator &&
(this.canModOnSelf || this.canAdminOnSelf) && (
<li>
<ActionButton
onClick={this.props.onDistinguish}
icon={
this.props.commentView.comment.distinguished
? "shield-off"
: "shield"
}
label={I18NextService.i18n.t(
this.props.commentView.comment.distinguished
? "undistinguish"
: "distinguish",
)}
/>
</li>
)}
{(this.canMod || this.canAdmin) && (
<li>
<ActionButton
label={
removed
? `${I18NextService.i18n.t(
"restore",
)} ${I18NextService.i18n.t(
type === "post" ? "post" : "comment",
)}`
: I18NextService.i18n.t(
type === "post" ? "remove_post" : "remove_comment",
)
}
icon={removed ? "restore" : "x"}
noLoading
onClick={this.toggleRemoveShow}
iconClass={`text-${removed ? "success" : "danger"}`}
/>
</li>
)}
{this.canMod &&
(!creator_is_moderator || canAppointCommunityMod) && (
<>
<li>
<hr className="dropdown-divider" />
</li>
{!creator_is_moderator && (
<li>
<ActionButton
onClick={this.toggleBanFromCommunityShow}
label={I18NextService.i18n.t(
creator_banned_from_community
? "unban_from_community"
: "ban_from_community",
)}
icon={creator_banned_from_community ? "unban" : "ban"}
noLoading
iconClass={`text-${
creator_banned_from_community ? "success" : "danger"
}`}
/>
</li>
)}
{canAppointCommunityMod && (
<li>
<ActionButton
onClick={this.toggleAppointModShow}
label={I18NextService.i18n.t(
`${
creator_is_moderator ? "remove" : "appoint"
}_as_mod`,
)}
icon={creator_is_moderator ? "demote" : "promote"}
iconClass={`text-${
creator_is_moderator ? "danger" : "success"
}`}
noLoading
/>
</li>
)}
</>
)}
{(amCommunityCreator(this.id, moderators) || this.canAdmin) &&
creator_is_moderator && (
<li>
<ActionButton
label={I18NextService.i18n.t("transfer_community")}
onClick={this.toggleTransferCommunityShow}
icon="transfer"
noLoading
/>
</li>
)}
{this.canAdmin && (showToggleAdmin || !creator_is_admin) && (
<>
<li>
<hr className="dropdown-divider" />
</li>
{!creator_is_admin && (
<>
<li>
<ActionButton
label={I18NextService.i18n.t(
creatorBannedFromLocal
? "unban_from_site"
: "ban_from_site",
)}
onClick={this.toggleBanFromSiteShow}
icon={creatorBannedFromLocal ? "unban" : "ban"}
iconClass={`text-${
creatorBannedFromLocal ? "success" : "danger"
}`}
noLoading
/>
</li>
<li>
<ActionButton
label={I18NextService.i18n.t("purge_user")}
onClick={this.togglePurgePersonShow}
icon="purge"
noLoading
iconClass="text-danger"
/>
</li>
<li>
<ActionButton
label={I18NextService.i18n.t(
`purge_${type === "post" ? "post" : "comment"}`,
)}
onClick={this.togglePurgeContentShow}
icon="purge"
noLoading
iconClass="text-danger"
/>
</li>
</>
)}
{showToggleAdmin && (
<li>
<ActionButton
label={I18NextService.i18n.t(
`${creator_is_admin ? "remove" : "appoint"}_as_admin`,
)}
onClick={this.toggleAppointAdminShow}
icon={creator_is_admin ? "demote" : "promote"}
iconClass={`text-${
creator_is_admin ? "danger" : "success"
}`}
noLoading
/>
</li>
)}
</>
)}
</ul> </ul>
</div> </div>
{this.moderationDialogs} {this.moderationDialogs}
@ -542,34 +455,28 @@ export default class ContentActionDropdown extends Component<
); );
} }
handleDropdownToggleClick() {
// This only renders the dropdown. Bootstrap handles the show/hide part.
this.setState({ dropdownOpenedOnce: true });
}
toggleModDialogShow( toggleModDialogShow(
dialogType: DialogType, dialogType: DialogType,
stateOverride: Partial<ActionTypeState> = {}, stateOverride: Partial<ContentActionDropdownState> = {},
) { ) {
const showKey: keyof ShowState = `show${dialogType}`; this.setState(prev => ({
const renderKey: keyof RenderState = `render${dialogType}`; ...prev,
this.setState<keyof ShowState>({ [dialogType]: !prev[dialogType],
showBanDialog: false, ...dialogTypes
showRemoveDialog: false, .filter(dt => dt !== dialogType)
showPurgeDialog: false, .reduce(
showReportDialog: false, (acc, dt) => ({
showTransferCommunityDialog: false, ...acc,
showAppointModDialog: false, [dt]: false,
showAppointAdminDialog: false, }),
showViewVotesDialog: false, {},
[showKey]: !this.state[showKey], ),
[renderKey]: true, // for fade out just keep rendering after show becomes false
...stateOverride, ...stateOverride,
}); }));
} }
hideAllDialogs() { hideAllDialogs() {
this.setState<keyof ShowState>({ this.setState({
showBanDialog: false, showBanDialog: false,
showPurgeDialog: false, showPurgeDialog: false,
showRemoveDialog: false, showRemoveDialog: false,
@ -582,52 +489,52 @@ export default class ContentActionDropdown extends Component<
} }
toggleReportDialogShow() { toggleReportDialogShow() {
this.toggleModDialogShow("ReportDialog"); this.toggleModDialogShow("showReportDialog");
} }
toggleRemoveShow() { toggleRemoveShow() {
this.toggleModDialogShow("RemoveDialog"); this.toggleModDialogShow("showRemoveDialog");
} }
toggleBanFromCommunityShow() { toggleBanFromCommunityShow() {
this.toggleModDialogShow("BanDialog", { this.toggleModDialogShow("showBanDialog", {
banType: BanType.Community, banType: BanType.Community,
}); });
} }
toggleBanFromSiteShow() { toggleBanFromSiteShow() {
this.toggleModDialogShow("BanDialog", { this.toggleModDialogShow("showBanDialog", {
banType: BanType.Site, banType: BanType.Site,
}); });
} }
togglePurgePersonShow() { togglePurgePersonShow() {
this.toggleModDialogShow("PurgeDialog", { this.toggleModDialogShow("showPurgeDialog", {
purgeType: PurgeType.Person, purgeType: PurgeType.Person,
}); });
} }
togglePurgeContentShow() { togglePurgeContentShow() {
this.toggleModDialogShow("PurgeDialog", { this.toggleModDialogShow("showPurgeDialog", {
purgeType: purgeType:
this.props.type === "post" ? PurgeType.Post : PurgeType.Comment, this.props.type === "post" ? PurgeType.Post : PurgeType.Comment,
}); });
} }
toggleTransferCommunityShow() { toggleTransferCommunityShow() {
this.toggleModDialogShow("TransferCommunityDialog"); this.toggleModDialogShow("showTransferCommunityDialog");
} }
toggleAppointModShow() { toggleAppointModShow() {
this.toggleModDialogShow("AppointModDialog"); this.toggleModDialogShow("showAppointModDialog");
} }
toggleAppointAdminShow() { toggleAppointAdminShow() {
this.toggleModDialogShow("AppointAdminDialog"); this.toggleModDialogShow("showAppointAdminDialog");
} }
toggleViewVotesShow() { toggleViewVotesShow() {
this.toggleModDialogShow("ViewVotesDialog"); this.toggleModDialogShow("showViewVotesDialog");
} }
get moderationDialogs() { get moderationDialogs() {
@ -642,14 +549,7 @@ export default class ContentActionDropdown extends Component<
showAppointModDialog, showAppointModDialog,
showAppointAdminDialog, showAppointAdminDialog,
showViewVotesDialog, showViewVotesDialog,
renderBanDialog, mounted,
renderPurgeDialog,
renderRemoveDialog,
renderReportDialog,
renderTransferCommunityDialog,
renderAppointModDialog,
renderAppointAdminDialog,
renderViewVotesDialog,
} = this.state; } = this.state;
const { const {
removed, removed,
@ -673,9 +573,10 @@ export default class ContentActionDropdown extends Component<
type, type,
} = this.props; } = this.props;
// Wait until componentDidMount runs (which only happens on the browser) to prevent sending over a gratuitous amount of markup
return ( return (
<> mounted && (
{renderRemoveDialog && ( <>
<ModActionFormModal <ModActionFormModal
onSubmit={this.wrapHandler(onRemove)} onSubmit={this.wrapHandler(onRemove)}
modActionType={ modActionType={
@ -685,8 +586,6 @@ export default class ContentActionDropdown extends Component<
onCancel={this.hideAllDialogs} onCancel={this.hideAllDialogs}
show={showRemoveDialog} show={showRemoveDialog}
/> />
)}
{renderBanDialog && (
<ModActionFormModal <ModActionFormModal
onSubmit={this.wrapHandler( onSubmit={this.wrapHandler(
banType === BanType.Community banType === BanType.Community
@ -708,8 +607,6 @@ export default class ContentActionDropdown extends Component<
community={community} community={community}
show={showBanDialog} show={showBanDialog}
/> />
)}
{renderReportDialog && (
<ModActionFormModal <ModActionFormModal
onSubmit={this.wrapHandler(onReport)} onSubmit={this.wrapHandler(onReport)}
modActionType={ modActionType={
@ -718,8 +615,6 @@ export default class ContentActionDropdown extends Component<
onCancel={this.hideAllDialogs} onCancel={this.hideAllDialogs}
show={showReportDialog} show={showReportDialog}
/> />
)}
{renderPurgeDialog && (
<ModActionFormModal <ModActionFormModal
onSubmit={this.wrapHandler( onSubmit={this.wrapHandler(
purgeType === PurgeType.Person ? onPurgeUser : onPurgeContent, purgeType === PurgeType.Person ? onPurgeUser : onPurgeContent,
@ -735,8 +630,6 @@ export default class ContentActionDropdown extends Component<
onCancel={this.hideAllDialogs} onCancel={this.hideAllDialogs}
show={showPurgeDialog} show={showPurgeDialog}
/> />
)}
{renderTransferCommunityDialog && (
<ConfirmationModal <ConfirmationModal
show={showTransferCommunityDialog} show={showTransferCommunityDialog}
message={I18NextService.i18n.t("transfer_community_are_you_sure", { message={I18NextService.i18n.t("transfer_community_are_you_sure", {
@ -747,8 +640,6 @@ export default class ContentActionDropdown extends Component<
onNo={this.hideAllDialogs} onNo={this.hideAllDialogs}
onYes={this.wrapHandler(onTransferCommunity)} onYes={this.wrapHandler(onTransferCommunity)}
/> />
)}
{renderAppointModDialog && (
<ConfirmationModal <ConfirmationModal
show={showAppointModDialog} show={showAppointModDialog}
message={I18NextService.i18n.t( message={I18NextService.i18n.t(
@ -766,8 +657,6 @@ export default class ContentActionDropdown extends Component<
onNo={this.hideAllDialogs} onNo={this.hideAllDialogs}
onYes={this.wrapHandler(onAppointCommunityMod)} onYes={this.wrapHandler(onAppointCommunityMod)}
/> />
)}
{renderAppointAdminDialog && (
<ConfirmationModal <ConfirmationModal
show={showAppointAdminDialog} show={showAppointAdminDialog}
message={I18NextService.i18n.t( message={I18NextService.i18n.t(
@ -785,16 +674,14 @@ export default class ContentActionDropdown extends Component<
onNo={this.hideAllDialogs} onNo={this.hideAllDialogs}
onYes={this.wrapHandler(onAppointAdmin)} onYes={this.wrapHandler(onAppointAdmin)}
/> />
)}
{renderViewVotesDialog && (
<ViewVotesModal <ViewVotesModal
type={type} type={type}
id={id} id={id}
show={showViewVotesDialog} show={showViewVotesDialog}
onCancel={this.hideAllDialogs} onCancel={this.hideAllDialogs}
/> />
)} </>
</> )
); );
} }
@ -886,6 +773,12 @@ export default class ContentActionDropdown extends Component<
); );
} }
get id() {
return this.props.type === "post"
? this.props.postView.creator.id
: this.props.commentView.creator.id;
}
wrapHandler(handler: (arg?: any) => Promise<void>) { wrapHandler(handler: (arg?: any) => Promise<void>) {
return async (arg?: any) => { return async (arg?: any) => {
await handler(arg); await handler(arg);

View file

@ -2,7 +2,6 @@ import { Component, linkEvent } from "inferno";
import { I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { EmojiMart } from "./emoji-mart"; import { EmojiMart } from "./emoji-mart";
import { Icon } from "./icon"; import { Icon } from "./icon";
import { tippyMixin } from "../mixins/tippy-mixin";
interface EmojiPickerProps { interface EmojiPickerProps {
onEmojiClick?(val: any): any; onEmojiClick?(val: any): any;
@ -13,13 +12,10 @@ interface EmojiPickerState {
showPicker: boolean; showPicker: boolean;
} }
function closeEmojiMartOnEsc(i: EmojiPicker, event: KeyboardEvent): void { function closeEmojiMartOnEsc(i, event): void {
if (event.key === "Escape") { event.key === "Escape" && i.setState({ showPicker: false });
i.setState({ showPicker: false });
}
} }
@tippyMixin
export class EmojiPicker extends Component<EmojiPickerProps, EmojiPickerState> { export class EmojiPicker extends Component<EmojiPickerProps, EmojiPickerState> {
private emptyState: EmojiPickerState = { private emptyState: EmojiPickerState = {
showPicker: false, showPicker: false,
@ -74,11 +70,9 @@ export class EmojiPicker extends Component<EmojiPickerProps, EmojiPickerState> {
e.preventDefault(); e.preventDefault();
i.setState({ showPicker: !i.state.showPicker }); i.setState({ showPicker: !i.state.showPicker });
if (i.state.showPicker) { i.state.showPicker
document.addEventListener("keyup", e => closeEmojiMartOnEsc(i, e)); ? document.addEventListener("keyup", e => closeEmojiMartOnEsc(i, e))
} else { : document.removeEventListener("keyup", e => closeEmojiMartOnEsc(i, e));
document.removeEventListener("keyup", e => closeEmojiMartOnEsc(i, e));
}
} }
handleEmojiClick(e: any) { handleEmojiClick(e: any) {

View file

@ -36,7 +36,7 @@ export class ImageUploadForm extends Component<
<form className="image-upload-form d-inline"> <form className="image-upload-form d-inline">
{this.props.imageSrc && ( {this.props.imageSrc && (
<span className="d-inline-block position-relative mb-2"> <span className="d-inline-block position-relative mb-2">
{/* TODO: Create "Current Image" translation for alt text */} {/* TODO: Create "Current Iamge" translation for alt text */}
<img <img
alt="" alt=""
src={this.props.imageSrc} src={this.props.imageSrc}
@ -77,6 +77,8 @@ export class ImageUploadForm extends Component<
i.setState({ loading: true }); i.setState({ loading: true });
HttpService.client.uploadImage({ image }).then(res => { HttpService.client.uploadImage({ image }).then(res => {
console.log("pictrs upload:");
console.log(res);
if (res.state === "success") { if (res.state === "success") {
if (res.data.msg === "ok") { if (res.data.msg === "ok") {
i.props.onUpload(res.data.url as string); i.props.onUpload(res.data.url as string);

View file

@ -58,6 +58,40 @@ class PostsLoadingSkeletonItem extends Component<any, any> {
} }
} }
export class TrendingCommunitiesLoadingSkeleton extends Component<
LoadingSkeletonProps,
any
> {
render() {
return (
<div className="mb-2">
{Array.from({ length: this.props.itemCount ?? 10 }, (_, index) => (
<TrendingCommunitiesLoadingSkeletonItem key={index} />
))}
</div>
);
}
}
class TrendingCommunitiesLoadingSkeletonItem extends Component<any, any> {
render() {
return (
<div className="col flex-grow-1 mt-2 ps-2 pe-4">
<div className="row">
<div className="col flex-grow-0 pe-0">
<div className="d-flex placeholder-glow img-icon">
<span className="placeholder placeholder-lg w-100 h-100 rounded-circle" />
</div>
</div>
<div className="col flex-grow-1 pe-0">
<LoadingSkeletonLine size={12} />
</div>
</div>
</div>
);
}
}
export class CommentsLoadingSkeleton extends Component<any, any> { export class CommentsLoadingSkeleton extends Component<any, any> {
render() { render() {
return Array.from({ length: this.props.itemCount ?? 10 }, (_, index) => ( return Array.from({ length: this.props.itemCount ?? 10 }, (_, index) => (

View file

@ -15,7 +15,7 @@ import {
} from "../../config"; } from "../../config";
import { customEmojisLookup, mdToHtml, setupTribute } from "../../markdown"; import { customEmojisLookup, mdToHtml, setupTribute } from "../../markdown";
import { HttpService, I18NextService, UserService } from "../../services"; import { HttpService, I18NextService, UserService } from "../../services";
import { tippyMixin } from "../mixins/tippy-mixin"; import { setupTippy } from "../../tippy";
import { pictrsDeleteToast, toast } from "../../toast"; import { pictrsDeleteToast, toast } from "../../toast";
import { EmojiPicker } from "./emoji-picker"; import { EmojiPicker } from "./emoji-picker";
import { Icon, Spinner } from "./icon"; import { Icon, Spinner } from "./icon";
@ -41,15 +41,15 @@ interface MarkdownTextAreaProps {
replyType?: boolean; replyType?: boolean;
focus?: boolean; focus?: boolean;
disabled?: boolean; disabled?: boolean;
finished?: boolean;
/** /**
* Whether to show the language selector * Whether to show the language selector
*/ */
showLanguage?: boolean; showLanguage?: boolean;
hideNavigationWarnings?: boolean; hideNavigationWarnings?: boolean;
onContentChange?(val: string): void; onContentChange?(val: string): void;
onContentBlur?(val: string): void;
onReplyCancel?(): void; onReplyCancel?(): void;
onSubmit?(content: string, languageId?: number): Promise<boolean>; onSubmit?(content: string, languageId?: number): void;
allLanguages: Language[]; // TODO should probably be nullable allLanguages: Language[]; // TODO should probably be nullable
siteLanguages: number[]; // TODO same siteLanguages: number[]; // TODO same
} }
@ -68,7 +68,6 @@ interface MarkdownTextAreaState {
submitted: boolean; submitted: boolean;
} }
@tippyMixin
export class MarkdownTextArea extends Component< export class MarkdownTextArea extends Component<
MarkdownTextAreaProps, MarkdownTextAreaProps,
MarkdownTextAreaState MarkdownTextAreaState
@ -76,6 +75,8 @@ export class MarkdownTextArea extends Component<
private id = `markdown-textarea-${randomStr()}`; private id = `markdown-textarea-${randomStr()}`;
private formId = `markdown-form-${randomStr()}`; private formId = `markdown-form-${randomStr()}`;
private tribute: any;
state: MarkdownTextAreaState = { state: MarkdownTextAreaState = {
content: this.props.initialContent, content: this.props.initialContent,
languageId: this.props.initialLanguageId, languageId: this.props.initialLanguageId,
@ -89,26 +90,49 @@ export class MarkdownTextArea extends Component<
this.handleLanguageChange = this.handleLanguageChange.bind(this); this.handleLanguageChange = this.handleLanguageChange.bind(this);
this.handleEmoji = this.handleEmoji.bind(this); this.handleEmoji = this.handleEmoji.bind(this);
if (isBrowser()) {
this.tribute = setupTribute();
}
} }
async componentDidMount() { componentDidMount() {
if (isBrowser()) { const textarea: any = document.getElementById(this.id);
const tribute = await setupTribute(); if (textarea) {
const textarea: any = document.getElementById(this.id); autosize(textarea);
if (textarea) { this.tribute.attach(textarea);
autosize(textarea); textarea.addEventListener("tribute-replaced", () => {
tribute.attach(textarea); this.setState({ content: textarea.value });
textarea.addEventListener("tribute-replaced", () => { autosize.update(textarea);
this.setState({ content: textarea.value }); });
autosize.update(textarea);
});
this.quoteInsert(); this.quoteInsert();
if (this.props.focus) { if (this.props.focus) {
textarea.focus(); textarea.focus();
}
} }
// TODO this is slow for some reason
setupTippy();
}
}
componentWillReceiveProps(nextProps: MarkdownTextAreaProps) {
if (nextProps.finished) {
this.setState({
previewMode: false,
imageUploadStatus: undefined,
loading: false,
content: undefined,
});
if (this.props.replyType) {
this.props.onReplyCancel?.();
}
const textarea: any = document.getElementById(this.id);
const form: any = document.getElementById(this.formId);
form.reset();
setTimeout(() => autosize.update(textarea), 10);
} }
} }
@ -125,8 +149,8 @@ export class MarkdownTextArea extends Component<
message={I18NextService.i18n.t("block_leaving")} message={I18NextService.i18n.t("block_leaving")}
when={ when={
!this.props.hideNavigationWarnings && !this.props.hideNavigationWarnings &&
((!!this.state.content && !this.state.submitted) || !!this.state.content &&
this.state.loading) !this.state.submitted
} }
/> />
<div className="mb-3 row"> <div className="mb-3 row">
@ -213,7 +237,6 @@ export class MarkdownTextArea extends Component<
)} )}
value={this.state.content} value={this.state.content}
onInput={linkEvent(this, this.handleContentChange)} onInput={linkEvent(this, this.handleContentChange)}
onBlur={linkEvent(this, this.handleContentBlur)}
onPaste={linkEvent(this, this.handlePaste)} onPaste={linkEvent(this, this.handlePaste)}
onKeyDown={linkEvent(this, this.handleKeyBinds)} onKeyDown={linkEvent(this, this.handleKeyBinds)}
required required
@ -223,7 +246,6 @@ export class MarkdownTextArea extends Component<
this.props.maxLength ?? markdownFieldCharacterLimit this.props.maxLength ?? markdownFieldCharacterLimit
} }
placeholder={this.props.placeholder} placeholder={this.props.placeholder}
spellCheck
/> />
{this.state.previewMode && this.state.content && ( {this.state.previewMode && this.state.content && (
<div <div
@ -257,14 +279,29 @@ export class MarkdownTextArea extends Component<
</div> </div>
<div className="col-12 d-flex align-items-center flex-wrap mt-2"> <div className="col-12 d-flex align-items-center flex-wrap mt-2">
{this.props.buttonTitle && ( {this.props.showLanguage && (
<LanguageSelect
iconVersion
allLanguages={this.props.allLanguages}
selectedLanguageIds={
languageId ? Array.of(languageId) : undefined
}
siteLanguages={this.props.siteLanguages}
onChange={this.handleLanguageChange}
disabled={this.isDisabled}
/>
)}
{/* A flex expander */}
<div className="flex-grow-1"></div>
{this.props.replyType && (
<button <button
type="submit" type="button"
className="btn btn-sm btn-secondary ms-2" className="btn btn-sm btn-secondary ms-2"
disabled={this.isDisabled || !this.state.content} onClick={linkEvent(this, this.handleReplyCancel)}
> >
{this.state.loading && <Spinner className="me-1" />} {I18NextService.i18n.t("cancel")}
{this.props.buttonTitle}
</button> </button>
)} )}
<button <button
@ -279,31 +316,16 @@ export class MarkdownTextArea extends Component<
? I18NextService.i18n.t("edit") ? I18NextService.i18n.t("edit")
: I18NextService.i18n.t("preview")} : I18NextService.i18n.t("preview")}
</button> </button>
{this.props.replyType && ( {this.props.buttonTitle && (
<button <button
type="button" type="submit"
className="btn btn-sm btn-secondary ms-2" className="btn btn-sm btn-secondary ms-2"
onClick={linkEvent(this, this.handleReplyCancel)} disabled={this.isDisabled || !this.state.content}
> >
{I18NextService.i18n.t("cancel")} {this.state.loading && <Spinner className="me-1" />}
{this.props.buttonTitle}
</button> </button>
)} )}
{/* A flex expander */}
<div className="flex-grow-1"></div>
{this.props.showLanguage && (
<LanguageSelect
iconVersion
allLanguages={this.props.allLanguages}
selectedLanguageIds={
languageId ? Array.of(languageId) : undefined
}
siteLanguages={this.props.siteLanguages}
onChange={this.handleLanguageChange}
disabled={this.isDisabled}
/>
)}
</div> </div>
</div> </div>
</form> </form>
@ -449,7 +471,7 @@ export class MarkdownTextArea extends Component<
})); }));
}), }),
); );
} catch { } catch (e) {
errorOccurred = true; errorOccurred = true;
} }
} }
@ -457,6 +479,8 @@ export class MarkdownTextArea extends Component<
async uploadSingleImage(i: MarkdownTextArea, image: File) { async uploadSingleImage(i: MarkdownTextArea, image: File) {
const res = await HttpService.client.uploadImage({ image }); const res = await HttpService.client.uploadImage({ image });
console.log("pictrs upload:");
console.log(res);
if (res.state === "success") { if (res.state === "success") {
if (res.data.msg === "ok") { if (res.data.msg === "ok") {
const imageMarkdown = `![](${res.data.url})`; const imageMarkdown = `![](${res.data.url})`;
@ -494,10 +518,6 @@ export class MarkdownTextArea extends Component<
i.contentChange(); i.contentChange();
} }
handleContentBlur(i: MarkdownTextArea, event: any) {
i.props.onContentBlur?.(event.target.value);
}
// Keybind handler // Keybind handler
// Keybinds inspired by github comment area // Keybinds inspired by github comment area
handleKeyBinds(i: MarkdownTextArea, event: KeyboardEvent) { handleKeyBinds(i: MarkdownTextArea, event: KeyboardEvent) {
@ -555,15 +575,11 @@ export class MarkdownTextArea extends Component<
this.setState({ languageId: val[0] }); this.setState({ languageId: val[0] });
} }
async handleSubmit(i: MarkdownTextArea, event: any) { handleSubmit(i: MarkdownTextArea, event: any) {
event.preventDefault(); event.preventDefault();
if (i.state.content) { if (i.state.content) {
i.setState({ loading: true, submitted: true }); i.setState({ loading: true, submitted: true });
const success = await i.props.onSubmit?.( i.props.onSubmit?.(i.state.content, i.state.languageId);
i.state.content,
i.state.languageId,
);
i.setState({ loading: false, submitted: success ?? true });
} }
} }
@ -760,9 +776,7 @@ export class MarkdownTextArea extends Component<
getSelectedText(): string { getSelectedText(): string {
const { selectionStart: start, selectionEnd: end } = const { selectionStart: start, selectionEnd: end } =
document.getElementById(this.id) as any; document.getElementById(this.id) as any;
return start !== end return start !== end ? this.state.content?.substring(start, end) ?? "" : "";
? (this.state.content?.substring(start, end) ?? "")
: "";
} }
get isDisabled() { get isDisabled() {

View file

@ -1,106 +0,0 @@
import { Component, InfernoNode, linkEvent } from "inferno";
import { ListMediaResponse, LocalImage } from "lemmy-js-client";
import { HttpService, I18NextService } from "../../services";
import { PersonListing } from "../person/person-listing";
import { tippyMixin } from "../mixins/tippy-mixin";
import { MomentTime } from "./moment-time";
import { PictrsImage } from "./pictrs-image";
import { getHttpBase } from "@utils/env";
import { toast } from "../../toast";
interface Props {
uploads: ListMediaResponse;
showUploader?: boolean;
}
@tippyMixin
export class MediaUploads extends Component<Props, any> {
constructor(props: any, context: any) {
super(props, context);
}
componentWillReceiveProps(
nextProps: Readonly<{ children?: InfernoNode } & Props>,
): void {
if (this.props !== nextProps) {
this.setState({ loading: false });
}
}
render() {
const images = this.props.uploads.images;
return (
<div className="media-uploads table-responsive">
<table className="table">
<thead>
<tr>
{this.props.showUploader && (
<th>{I18NextService.i18n.t("uploader")}</th>
)}
<th colSpan={3}>{I18NextService.i18n.t("time")}</th>
</tr>
</thead>
<tbody>
{images.map(i => (
<tr key={i.local_image.pictrs_alias}>
{this.props.showUploader && (
<td>
<PersonListing person={i.person} />
</td>
)}
<td>
<MomentTime published={i.local_image.published} />
</td>
<td>
<PictrsImage
src={buildImageUrl(i.local_image.pictrs_alias)}
/>
</td>
<td>{this.deleteImageBtn(i.local_image)}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
deleteImageBtn(image: LocalImage) {
return (
<button
onClick={linkEvent(image, this.handleDeleteImage)}
className="btn btn-danger"
>
{I18NextService.i18n.t("delete")}
</button>
);
}
async handleDeleteImage(image: LocalImage) {
const form = {
token: image.pictrs_delete_token,
filename: image.pictrs_alias,
};
const res = await HttpService.client.deleteImage(form);
const filename = image.pictrs_alias;
if (res.state === "success") {
const deletePictureText = I18NextService.i18n.t("picture_deleted", {
filename,
});
toast(deletePictureText);
} else if (res.state === "failed") {
const failedDeletePictureText = I18NextService.i18n.t(
"failed_to_delete_picture",
{
filename,
},
);
toast(failedDeletePictureText, "danger");
}
}
}
function buildImageUrl(pictrsAlias: string): string {
return `${getHttpBase()}/pictrs/image/${pictrsAlias}`;
}

View file

@ -1,22 +1,15 @@
import { import { Component, RefObject, createRef, linkEvent } from "inferno";
Component, import { I18NextService } from "../../services/I18NextService";
InfernoNode, import { PurgeWarning, Spinner } from "./icon";
RefObject,
createRef,
linkEvent,
} from "inferno";
import { I18NextService } from "../../../services/I18NextService";
import { PurgeWarning, Spinner } from "../icon";
import { getApubName, randomStr } from "@utils/helpers"; import { getApubName, randomStr } from "@utils/helpers";
import type { Modal } from "bootstrap"; import type { Modal } from "bootstrap";
import classNames from "classnames"; import classNames from "classnames";
import { Community, Person } from "lemmy-js-client"; import { Community, Person } from "lemmy-js-client";
import { LoadingEllipses } from "../loading-ellipses"; import { LoadingEllipses } from "./loading-ellipses";
import { modalMixin } from "../../mixins/modal-mixin";
export interface BanUpdateForm { export interface BanUpdateForm {
reason?: string; reason?: string;
shouldRemoveOrRestoreData?: boolean; shouldRemove?: boolean;
daysUntilExpires?: number; daysUntilExpires?: number;
} }
@ -31,7 +24,7 @@ interface ModActionFormModalPropsCommunityBan {
modActionType: "community-ban"; modActionType: "community-ban";
onSubmit: (form: BanUpdateForm) => Promise<void>; onSubmit: (form: BanUpdateForm) => Promise<void>;
creator: Person; creator: Person;
community?: Community; community: Community;
isBanned: boolean; isBanned: boolean;
} }
@ -63,13 +56,13 @@ type ModActionFormModalProps = (
| ModActionFormModalPropsRest | ModActionFormModalPropsRest
| ModActionFormModalPropsPurgePerson | ModActionFormModalPropsPurgePerson
| ModActionFormModalPropsRemove | ModActionFormModalPropsRemove
) & { onCancel: () => void; show: boolean; children?: InfernoNode }; ) & { onCancel: () => void; show: boolean };
interface ModActionFormFormState { interface ModActionFormFormState {
loading: boolean; loading: boolean;
reason: string; reason: string;
daysUntilExpire?: number; daysUntilExpire?: number;
shouldRemoveOrRestoreData?: boolean; shouldRemoveData?: boolean;
shouldPermaBan?: boolean; shouldPermaBan?: boolean;
} }
@ -84,7 +77,7 @@ function handleExpiryChange(i: ModActionFormModal, event: any) {
function handleToggleRemove(i: ModActionFormModal) { function handleToggleRemove(i: ModActionFormModal) {
i.setState(prev => ({ i.setState(prev => ({
...prev, ...prev,
shouldRemoveOrRestoreData: !prev.shouldRemoveOrRestoreData, shouldRemoveData: !prev.shouldRemoveData,
})); }));
} }
@ -104,7 +97,7 @@ async function handleSubmit(i: ModActionFormModal, event: any) {
await i.props.onSubmit({ await i.props.onSubmit({
reason: i.state.reason, reason: i.state.reason,
daysUntilExpires: i.state.daysUntilExpire!, daysUntilExpires: i.state.daysUntilExpire!,
shouldRemoveOrRestoreData: i.state.shouldRemoveOrRestoreData!, shouldRemove: i.state.shouldRemoveData!,
} as BanUpdateForm & string); // Need to & string to handle type weirdness } as BanUpdateForm & string); // Need to & string to handle type weirdness
} else { } else {
await i.props.onSubmit(i.state.reason); await i.props.onSubmit(i.state.reason);
@ -116,14 +109,13 @@ async function handleSubmit(i: ModActionFormModal, event: any) {
}); });
} }
@modalMixin
export default class ModActionFormModal extends Component< export default class ModActionFormModal extends Component<
ModActionFormModalProps, ModActionFormModalProps,
ModActionFormFormState ModActionFormFormState
> { > {
modalDivRef: RefObject<HTMLDivElement>; private modalDivRef: RefObject<HTMLDivElement>;
private reasonRef: RefObject<HTMLInputElement>; private reasonRef: RefObject<HTMLInputElement>;
modal?: Modal; modal: Modal;
state: ModActionFormFormState = { state: ModActionFormFormState = {
loading: false, loading: false,
reason: "", reason: "",
@ -135,7 +127,42 @@ export default class ModActionFormModal extends Component<
this.reasonRef = createRef(); this.reasonRef = createRef();
if (this.isBanModal) { if (this.isBanModal) {
this.state.shouldRemoveOrRestoreData = false; this.state.shouldRemoveData = false;
}
this.handleShow = this.handleShow.bind(this);
}
async componentDidMount() {
this.modalDivRef.current?.addEventListener(
"shown.bs.modal",
this.handleShow,
);
const Modal = (await import("bootstrap/js/dist/modal")).default;
this.modal = new Modal(this.modalDivRef.current!);
if (this.props.show) {
this.modal.show();
}
}
componentWillUnmount() {
this.modalDivRef.current?.removeEventListener(
"shown.bs.modal",
this.handleShow,
);
this.modal.dispose();
}
componentDidUpdate({ show: prevShow }: ModActionFormModalProps) {
if (!!prevShow !== !!this.props.show) {
if (this.props.show) {
this.modal.show();
} else {
this.modal.hide();
}
} }
} }
@ -144,7 +171,7 @@ export default class ModActionFormModal extends Component<
loading, loading,
reason, reason,
daysUntilExpire, daysUntilExpire,
shouldRemoveOrRestoreData, shouldRemoveData,
shouldPermaBan, shouldPermaBan,
} = this.state; } = this.state;
const reasonId = `mod-form-reason-${randomStr()}`; const reasonId = `mod-form-reason-${randomStr()}`;
@ -249,7 +276,7 @@ export default class ModActionFormModal extends Component<
<input <input
className="form-check-input user-select-none" className="form-check-input user-select-none"
type="checkbox" type="checkbox"
checked={shouldRemoveOrRestoreData} checked={shouldRemoveData}
onChange={linkEvent(this, handleToggleRemove)} onChange={linkEvent(this, handleToggleRemove)}
/> />
{I18NextService.i18n.t("remove_content")} {I18NextService.i18n.t("remove_content")}
@ -328,12 +355,7 @@ export default class ModActionFormModal extends Component<
: "ban_from_community_with_name", : "ban_from_community_with_name",
{ {
user: getApubName(this.props.creator), user: getApubName(this.props.creator),
community: getApubName( community: getApubName(this.props.community),
this.props.community ?? {
actor_id: "",
name: "",
},
),
}, },
); );
} }

View file

@ -1,142 +0,0 @@
import { Component, LinkedEvent, createRef, linkEvent } from "inferno";
import { modalMixin } from "../../mixins/modal-mixin";
import { adultConsentCookieKey } from "../../../config";
import { mdToHtml } from "../../../markdown";
import { I18NextService } from "../../../services";
import { isHttps } from "@utils/env";
import { IsoData } from "../../../interfaces";
import { setIsoData } from "@utils/app";
interface AdultConsentModalProps {
contentWarning: string;
show: boolean;
onContinue: LinkedEvent<any, Event> | null;
onBack: LinkedEvent<any, Event> | null;
redirectCountdown: number;
}
@modalMixin
class AdultConsentModalInner extends Component<AdultConsentModalProps, any> {
readonly modalDivRef = createRef<HTMLDivElement>();
readonly continueButtonRef = createRef<HTMLButtonElement>();
render() {
const { contentWarning, onContinue, onBack, redirectCountdown } =
this.props;
return (
<div
className="modal"
id="adultConsentModal"
tabIndex={-1}
aria-hidden
aria-label="Content warning"
data-bs-backdrop="static"
ref={this.modalDivRef}
>
<div
className="modal-dialog modal-fullscreen-sm-down"
data-bs-backdrop="static"
>
<div className="modal-content">
<header className="modal-header justify-content-center">
<h3 className="modal-title">
{I18NextService.i18n.t("content_warning")}
</h3>
</header>
{redirectCountdown === Infinity ? (
<div
className="modal-body text-center align-middle text-body"
dangerouslySetInnerHTML={mdToHtml(contentWarning, () =>
this.forceUpdate(),
)}
/>
) : (
<div className="modal-body text-center align-middle text-body">
{I18NextService.i18n.t("sending_back_message", {
seconds: redirectCountdown,
})}
</div>
)}
<footer className="modal-footer">
<button
type="button"
className="btn btn-success"
onClick={onContinue}
ref={this.continueButtonRef}
>
{I18NextService.i18n.t("continue")}
</button>
<button type="button" className="btn btn-danger" onClick={onBack}>
{I18NextService.i18n.t("go_back")}
</button>
</footer>
</div>
</div>
</div>
);
}
handleShow() {
this.continueButtonRef.current?.focus();
}
}
interface AdultConsentModalState {
show: boolean;
redirectCountdown: number;
}
function handleAdultConsent(i: AdultConsentModal) {
document.cookie = `${adultConsentCookieKey}=true; Path=/; SameSite=Strict${isHttps() ? "; Secure" : ""}`;
i.setState({ show: false });
location.reload();
}
function handleAdultConsentGoBack(i: AdultConsentModal) {
i.setState({ redirectCountdown: 5 });
clearInterval(i.redirectTimeout);
i.redirectTimeout = setInterval(() => {
i.setState(prev => ({
...prev,
redirectCountdown: prev.redirectCountdown - 1,
}));
}, 1000);
}
export default class AdultConsentModal extends Component<
Pick<AdultConsentModalProps, "contentWarning">,
AdultConsentModalState
> {
private isoData: IsoData = setIsoData(this.context);
redirectTimeout: NodeJS.Timeout;
state: AdultConsentModalState = {
show: this.isoData.showAdultConsentModal,
redirectCountdown: Infinity,
};
componentDidUpdate() {
if (this.state.redirectCountdown === 0) {
this.context.router.history.back();
}
}
componentWillUnmount() {
clearInterval(this.redirectTimeout);
}
render() {
const { redirectCountdown, show } = this.state;
return (
<AdultConsentModalInner
contentWarning={this.props.contentWarning}
show={show}
redirectCountdown={redirectCountdown}
onBack={linkEvent(this, handleAdultConsentGoBack)}
onContinue={linkEvent(this, handleAdultConsent)}
/>
);
}
}

View file

@ -1,386 +0,0 @@
import {
Component,
FormEventHandler,
MouseEventHandler,
RefObject,
createRef,
linkEvent,
} from "inferno";
import type { Modal } from "bootstrap";
import { modalMixin } from "../../mixins/modal-mixin";
import { I18NextService } from "../../../services/I18NextService";
import {
CreateOAuthProvider,
EditOAuthProvider,
OAuthProvider,
} from "lemmy-js-client";
import { ProviderToEdit } from "@utils/types/oauth";
export type CreateOrEditOAuthProviderModalData =
| { type: "add"; provider?: ProviderToEdit }
| { type: "edit" | "add"; provider: OAuthProvider };
interface CreateOrEditOAuthProviderModalProps {
onClose: MouseEventHandler<HTMLButtonElement>;
show: boolean;
data: CreateOrEditOAuthProviderModalData;
onSubmit: (
provider: CreateOAuthProvider | EditOAuthProvider,
) => Promise<void>;
}
interface CreateOrEditOAuthProviderModalState {
changed: boolean;
provider: Partial<CreateOAuthProvider>;
loading: boolean;
}
interface ProviderFieldProps {
id: string;
i18nKey: string;
onInput: FormEventHandler<HTMLInputElement>;
}
interface ProviderTextFieldProps extends ProviderFieldProps {
disabled?: boolean;
placeholder?: string;
type?: "text" | "url" | "password";
value?: string;
required?: boolean;
}
type ProviderBooleanProperties =
| "enabled"
| "account_linking_enabled"
| "auto_verify_email";
interface ProviderCheckboxFieldProps extends ProviderFieldProps {
checked?: boolean;
}
const FORM_ID = "create-or-edit-oauth-provider-form-id";
function handleTextPropertyChange(
{
modal,
property,
}: {
modal: CreateOrEditOAuthProviderModal;
property: Exclude<keyof CreateOAuthProvider, ProviderBooleanProperties>;
},
event: any,
) {
modal.setState(prevState => ({
changed: true,
provider: {
...prevState.provider,
[property]: event.target.value,
},
}));
}
function handleBooleanPropertyChange({
modal,
property,
}: {
modal: CreateOrEditOAuthProviderModal;
property: Extract<keyof ProviderToEdit, ProviderBooleanProperties>;
}) {
modal.setState(prevState => ({
changed: true,
provider: {
...prevState.provider,
[property]: !prevState.provider[property],
},
}));
}
function ProviderTextField({
id,
i18nKey,
type = "text",
value,
onInput,
required = true,
disabled,
placeholder,
}: ProviderTextFieldProps) {
return (
<div className="col">
<label className="form-label" htmlFor={id}>
{I18NextService.i18n.t(i18nKey)}
</label>
<input
type={type}
id={id}
className="form-control"
value={value}
onInput={onInput}
required={required}
disabled={disabled}
placeholder={placeholder}
/>
</div>
);
}
function ProviderCheckboxField({
i18nKey,
id,
onInput,
checked,
}: ProviderCheckboxFieldProps) {
return (
<div className="form-check form-check-inline m-2">
<input
id={id}
type="checkbox"
className="form-check-input"
checked={checked}
onInput={onInput}
/>
<label htmlFor={id} className="form-check-label">
{I18NextService.i18n.t(i18nKey)}
</label>
</div>
);
}
@modalMixin
export default class CreateOrEditOAuthProviderModal extends Component<
CreateOrEditOAuthProviderModalProps,
CreateOrEditOAuthProviderModalState
> {
readonly modalDivRef: RefObject<HTMLDivElement>;
modal?: Modal;
state: CreateOrEditOAuthProviderModalState = {
changed: false,
provider: {},
loading: false,
};
constructor(props: CreateOrEditOAuthProviderModalProps, context: any) {
super(props, context);
this.modalDivRef = createRef();
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidUpdate(prevProps: Readonly<CreateOrEditOAuthProviderModalProps>) {
if (this.props.show && this.props.show !== prevProps.show) {
this.setState({ provider: this.props.data.provider ?? {} });
}
}
render(
{ onClose, data }: CreateOrEditOAuthProviderModalProps,
{ provider, changed, loading }: CreateOrEditOAuthProviderModalState,
) {
return (
<div
className="modal fade"
id="create-or-edit-oauth-modal"
tabIndex={-1}
aria-hidden
aria-labelledby="#create-or-edit-oauth-modal-title"
data-bs-backdrop="static"
data-bs-keyboard="false"
ref={this.modalDivRef}
>
<div className="modal-dialog modal-fullscreen-sm-down">
<div className="modal-content">
<div className="modal-header">
<h1
className="modal-title h4"
id="create-or-edit-oauth-modal-title"
>
{data.type === "edit"
? `Edit ${data.provider.display_name}`
: "Add OAuth Provider"}
</h1>
<button
type="button"
className="btn-close"
aria-label={I18NextService.i18n.t("cancel")}
onClick={onClose}
/>
</div>
<div className="modal-body p-2-!important">
<form
id={FORM_ID}
className="container"
onSubmit={this.handleSubmit}
>
<div className="row row-cols-1 mb-3 gy-2">
<ProviderTextField
id="display-name"
i18nKey="oauth_display_name"
value={provider?.display_name}
onInput={linkEvent(
{ modal: this, property: "display_name" },
handleTextPropertyChange,
)}
/>
<ProviderTextField
id="issuer"
i18nKey="oauth_issuer"
value={provider?.issuer}
onInput={linkEvent(
{ modal: this, property: "issuer" },
handleTextPropertyChange,
)}
type="url"
disabled={data.type === "edit"}
/>
<ProviderTextField
id="authorization-endpoint"
i18nKey="oauth_authorization_endpoint"
value={provider?.authorization_endpoint}
onInput={linkEvent(
{ modal: this, property: "authorization_endpoint" },
handleTextPropertyChange,
)}
type="url"
/>
<ProviderTextField
id="token-endpoint"
i18nKey="oauth_token_endpoint"
value={provider?.token_endpoint}
onInput={linkEvent(
{ modal: this, property: "token_endpoint" },
handleTextPropertyChange,
)}
type="url"
/>
<ProviderTextField
id="userinfo-endpoint"
i18nKey="oauth_userinfo_endpoint"
value={provider?.userinfo_endpoint}
onInput={linkEvent(
{ modal: this, property: "userinfo_endpoint" },
handleTextPropertyChange,
)}
type="url"
/>
<ProviderTextField
id="id-claim"
i18nKey="oauth_id_claim"
value={provider?.id_claim}
onInput={linkEvent(
{ modal: this, property: "id_claim" },
handleTextPropertyChange,
)}
/>
<ProviderTextField
id="client-id"
i18nKey="oauth_client_id"
value={provider?.client_id}
disabled={data.type === "edit"}
onInput={linkEvent(
{ modal: this, property: "client_id" },
handleTextPropertyChange,
)}
/>
<ProviderTextField
id="client-secret"
i18nKey="oauth_client_secret"
onInput={linkEvent(
{ modal: this, property: "client_secret" },
handleTextPropertyChange,
)}
type="password"
placeholder={
data.type === "edit"
? I18NextService.i18n.t(
"cannot_view_secret_after_saving",
)
: undefined
}
required={data.type === "add"}
value={provider.client_secret}
/>
<ProviderTextField
id="scopes"
i18nKey="oauth_scopes"
value={provider?.scopes}
onInput={linkEvent(
{ modal: this, property: "scopes" },
handleTextPropertyChange,
)}
/>
</div>
<div className="row">
<div className="col">
<ProviderCheckboxField
id="auto-verfiy-email"
i18nKey="oauth_auto_verify_email"
checked={provider?.auto_verify_email}
onInput={linkEvent(
{
modal: this,
property: "auto_verify_email",
},
handleBooleanPropertyChange,
)}
/>
<ProviderCheckboxField
id="account-linking-enabled"
i18nKey="oauth_account_linking_enabled"
checked={provider?.account_linking_enabled}
onInput={linkEvent(
{
modal: this,
property: "account_linking_enabled",
},
handleBooleanPropertyChange,
)}
/>
<ProviderCheckboxField
id="oauth-enabled"
i18nKey="oauth_enabled"
checked={provider?.enabled ?? true}
onInput={linkEvent(
{
modal: this,
property: "enabled",
},
handleBooleanPropertyChange,
)}
/>
</div>
</div>
</form>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-danger"
onClick={onClose}
>
{I18NextService.i18n.t("cancel")}
</button>
<button
type="submit"
form={FORM_ID}
className="btn btn-success"
disabled={!changed || loading}
>
{I18NextService.i18n.t(data.type === "edit" ? "edit" : "add")}
</button>
</div>
</div>
</div>
</div>
);
}
async handleSubmit(event) {
event.preventDefault();
this.setState({ loading: true });
await this.props.onSubmit(this.state.provider as CreateOAuthProvider);
this.setState({ loading: false, changed: false, provider: {} });
}
}

View file

@ -1,77 +0,0 @@
import {
Component,
InfernoNode,
MouseEventHandler,
RefObject,
createRef,
} from "inferno";
import type { Modal } from "bootstrap";
import { Spinner } from "../icon";
import { LoadingEllipses } from "../loading-ellipses";
import { modalMixin } from "../../mixins/modal-mixin";
interface DisplayModalProps {
children: InfernoNode;
loadingMessage?: string;
title: string;
onClose: MouseEventHandler<HTMLButtonElement>;
show: boolean;
loading?: boolean;
}
@modalMixin
export default class DisplayModal extends Component<DisplayModalProps, any> {
readonly modalDivRef: RefObject<HTMLDivElement>;
modal?: Modal;
constructor(props: DisplayModalProps, context: any) {
super(props, context);
this.modalDivRef = createRef();
}
render() {
const { children, loadingMessage, title, onClose, loading } = this.props;
return (
<div
className="modal fade"
id="display-modal"
tabIndex={-1}
aria-hidden
aria-labelledby="#displayModalTitle"
data-bs-backdrop="static"
ref={this.modalDivRef}
>
<div className="modal-dialog modal-fullscreen-sm-down">
<div className="modal-content">
<header className="modal-header">
<h3 className="modal-title" id="displayModalTitle">
{title}
</h3>
<button
type="button"
className="btn-close"
aria-label="Close"
onClick={onClose}
/>
</header>
<div className="modal-body">
{loading ? (
<div class="text-center align-middle text-body">
<Spinner large />
<div>
{loadingMessage}
<LoadingEllipses />
</div>
</div>
) : (
children
)}
</div>
</div>
</div>
</div>
);
}
}

View file

@ -3,7 +3,6 @@ import { format, parseISO } from "date-fns";
import { Component } from "inferno"; import { Component } from "inferno";
import { I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { Icon } from "./icon"; import { Icon } from "./icon";
import { tippyMixin } from "../mixins/tippy-mixin";
interface MomentTimeProps { interface MomentTimeProps {
published: string; published: string;
@ -17,7 +16,6 @@ function formatDate(input: string) {
return format(parsed, "PPPPpppp"); return format(parsed, "PPPPpppp");
} }
@tippyMixin
export class MomentTime extends Component<MomentTimeProps, any> { export class MomentTime extends Component<MomentTimeProps, any> {
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);

View file

@ -5,7 +5,6 @@ interface PaginatorProps {
page: number; page: number;
onChange(val: number): any; onChange(val: number): any;
nextDisabled: boolean; nextDisabled: boolean;
disabled?: boolean;
} }
export class Paginator extends Component<PaginatorProps, any> { export class Paginator extends Component<PaginatorProps, any> {
@ -19,7 +18,6 @@ export class Paginator extends Component<PaginatorProps, any> {
<button <button
className="btn btn-secondary me-2" className="btn btn-secondary me-2"
onClick={linkEvent(this, this.handlePrev)} onClick={linkEvent(this, this.handlePrev)}
disabled={this.props.disabled}
> >
{I18NextService.i18n.t("prev")} {I18NextService.i18n.t("prev")}
</button> </button>
@ -28,7 +26,6 @@ export class Paginator extends Component<PaginatorProps, any> {
<button <button
className="btn btn-secondary" className="btn btn-secondary"
onClick={linkEvent(this, this.handleNext)} onClick={linkEvent(this, this.handleNext)}
disabled={this.props.disabled}
> >
{I18NextService.i18n.t("next")} {I18NextService.i18n.t("next")}
</button> </button>

View file

@ -5,7 +5,6 @@ import { Component, FormEventHandler, linkEvent } from "inferno";
import { NavLink } from "inferno-router"; import { NavLink } from "inferno-router";
import { I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { Icon } from "./icon"; import { Icon } from "./icon";
import { tippyMixin } from "../mixins/tippy-mixin";
interface PasswordInputProps { interface PasswordInputProps {
id: string; id: string;
@ -16,7 +15,6 @@ interface PasswordInputProps {
label?: string | null; label?: string | null;
showForgotLink?: boolean; showForgotLink?: boolean;
isNew?: boolean; isNew?: boolean;
required?: boolean;
} }
interface PasswordInputState { interface PasswordInputState {
@ -57,7 +55,6 @@ function handleToggleShow(i: PasswordInput) {
})); }));
} }
@tippyMixin
class PasswordInput extends Component<PasswordInputProps, PasswordInputState> { class PasswordInput extends Component<PasswordInputProps, PasswordInputState> {
state: PasswordInputState = { state: PasswordInputState = {
show: false, show: false,
@ -78,7 +75,6 @@ class PasswordInput extends Component<PasswordInputProps, PasswordInputState> {
label, label,
showForgotLink, showForgotLink,
isNew, isNew,
required,
}, },
state: { show }, state: { show },
} = this; } = this;
@ -100,11 +96,9 @@ class PasswordInput extends Component<PasswordInputProps, PasswordInputState> {
autoComplete={isNew ? "new-password" : "current-password"} autoComplete={isNew ? "new-password" : "current-password"}
onInput={onInput} onInput={onInput}
value={value} value={value}
required={required !== false} required
pattern=".+" pattern=".{10,60}"
title={I18NextService.i18n.t("invalid_password")} title={I18NextService.i18n.t("invalid_password")}
minLength={isNew ? 10 : undefined}
maxLength={isNew ? 60 : undefined}
/> />
<button <button
className="btn btn-outline-dark" className="btn btn-outline-dark"

View file

@ -1,10 +1,7 @@
import classNames from "classnames"; import classNames from "classnames";
import { Component, linkEvent } from "inferno"; import { Component } from "inferno";
import { UserService } from "../../services"; import { UserService } from "../../services";
import { setIsoData } from "@utils/app";
import { IsoData } from "../../interfaces";
import { getStaticDir } from "@utils/env";
const iconThumbnailSize = 96; const iconThumbnailSize = 96;
const thumbnailSize = 256; const thumbnailSize = 256;
@ -21,70 +18,49 @@ interface PictrsImageProps {
cardTop?: boolean; cardTop?: boolean;
} }
interface PictrsImageState { export class PictrsImage extends Component<PictrsImageProps, any> {
src: string; constructor(props: any, context: any) {
} super(props, context);
function handleImgLoadError(i: PictrsImage) {
i.setState({
src: `${getStaticDir()}/assets/images/broken-image-fallback.png`,
});
}
export class PictrsImage extends Component<PictrsImageProps, PictrsImageState> {
private readonly isoData: IsoData = setIsoData(this.context);
state: PictrsImageState = {
src: this.props.src,
};
componentDidUpdate(prevProps: PictrsImageProps) {
if (prevProps.src !== this.props.src) {
this.setState({ src: this.props.src });
}
} }
render() { render() {
const { icon, iconOverlay, banner, thumbnail, nsfw, pushup, cardTop } = const { src, icon, iconOverlay, banner, thumbnail, nsfw, pushup, cardTop } =
this.props; this.props;
let user_blur_nsfw = true;
if (UserService.Instance.myUserInfo) {
user_blur_nsfw =
UserService.Instance.myUserInfo?.local_user_view.local_user.blur_nsfw;
}
const { src } = this.state; const blur_image = nsfw && user_blur_nsfw;
const blurImage =
nsfw &&
(UserService.Instance.myUserInfo?.local_user_view.local_user.blur_nsfw ??
true);
return ( return (
!this.isoData.showAdultConsentModal && ( <picture>
<picture> <source srcSet={this.src("webp")} type="image/webp" />
<source srcSet={this.src("webp")} type="image/webp" /> <source srcSet={src} />
<source srcSet={src} /> <source srcSet={this.src("jpg")} type="image/jpeg" />
<source srcSet={this.src("jpg")} type="image/jpeg" /> <img
<img src={src}
src={src} alt={this.alt()}
alt={this.alt()} title={this.alt()}
title={this.alt()} loading="lazy"
loading="lazy" className={classNames("overflow-hidden pictrs-image", {
className={classNames("overflow-hidden pictrs-image", { "img-fluid": !(icon || iconOverlay),
"img-fluid": !(icon || iconOverlay), banner,
banner, "thumbnail rounded object-fit-cover":
"thumbnail rounded object-fit-cover": thumbnail && !(icon || banner),
thumbnail && !(icon || banner), "img-expanded slight-radius": !(thumbnail || icon),
"img-expanded slight-radius": !(thumbnail || icon), "img-blur": thumbnail && nsfw,
"img-blur": thumbnail && nsfw, "object-fit-cover img-icon me-1": icon,
"object-fit-cover img-icon me-1": icon, "img-blur-icon": icon && blur_image,
"img-blur-icon": icon && blurImage, "img-blur-thumb": thumbnail && blur_image,
"img-blur-thumb": thumbnail && blurImage, "ms-2 mb-0 rounded-circle object-fit-cover avatar-overlay":
"ms-2 mb-0 rounded-circle object-fit-cover avatar-overlay": iconOverlay,
iconOverlay, "avatar-pushup": pushup,
"avatar-pushup": pushup, "card-img-top": cardTop,
"card-img-top": cardTop, })}
})} />
onError={linkEvent(this, handleImgLoadError)} </picture>
/>
</picture>
)
); );
} }
@ -94,14 +70,14 @@ export class PictrsImage extends Component<PictrsImageProps, PictrsImageState> {
let url: URL | undefined; let url: URL | undefined;
try { try {
url = new URL(this.state.src); url = new URL(this.props.src);
} catch { } catch {
return this.state.src; return this.props.src;
} }
// If there's no match, then it's not a pictrs image // If theres no match, then its not a pictrs image
if (!url.pathname.includes("/pictrs/image/")) { if (!url.pathname.includes("/pictrs/image/")) {
return this.state.src; return this.props.src;
} }
// Keeps original search params. Could probably do `url.search = ""` here. // Keeps original search params. Could probably do `url.search = ""` here.

View file

@ -1,68 +0,0 @@
import { StringBoolean } from "@utils/types";
import classNames from "classnames";
import { Icon } from "./icon";
import { tippyMixin } from "../mixins/tippy-mixin";
import { Component, linkEvent } from "inferno";
import { I18NextService } from "../../services/I18NextService";
interface PostHiddenSelectProps {
showHidden?: StringBoolean;
onShowHiddenChange: (hidden?: StringBoolean) => void;
}
function handleShowHiddenChange(i: PostHiddenSelect, event: any) {
i.props.onShowHiddenChange(event.target.value);
}
@tippyMixin
export default class PostHiddenSelect extends Component<
PostHiddenSelectProps,
never
> {
render() {
const { showHidden } = this.props;
return (
<div
className="show-hidden-select btn-group btn-group-toggle flex-wrap"
role="group"
>
<label
htmlFor="show-hidden"
className={classNames("pointer btn btn-outline-secondary", {
active: showHidden === "true",
})}
data-tippy-content={I18NextService.i18n.t("show_hidden_posts")}
>
<Icon icon="eye" inline />
<input
id="show-hidden"
type="radio"
className="btn-check"
value="true"
checked={showHidden === "true"}
onChange={linkEvent(this, handleShowHiddenChange)}
/>
</label>
<label
htmlFor="hide-hidden"
className={classNames("pointer btn btn-outline-secondary", {
active: showHidden !== "true",
})}
data-tippy-content={I18NextService.i18n.t("hide_hidden_posts")}
>
<Icon icon="eye-slash" inline />
<input
id="hide-hidden"
type="radio"
className="btn-check"
value="false"
checked={showHidden !== "true"}
onChange={linkEvent(this, handleShowHiddenChange)}
/>
</label>
</div>
);
}
}

View file

@ -39,7 +39,7 @@ function handleSearch(i: SearchableSelect, e: ChangeEvent<HTMLInputElement>) {
} }
function focusSearch(i: SearchableSelect) { function focusSearch(i: SearchableSelect) {
if (i.toggleButtonRef.current?.ariaExpanded === "true") { if (i.toggleButtonRef.current?.ariaExpanded !== "true") {
i.searchInputRef.current?.focus(); i.searchInputRef.current?.focus();
if (i.props.onSearch) { if (i.props.onSearch) {

View file

@ -1,19 +1,19 @@
import { randomStr } from "@utils/helpers"; import { randomStr } from "@utils/helpers";
import { Component, linkEvent } from "inferno"; import { Component, linkEvent } from "inferno";
import { PostSortType } from "lemmy-js-client"; import { SortType } from "lemmy-js-client";
import { relTags, sortingHelpUrl } from "../../config"; import { relTags, sortingHelpUrl } from "../../config";
import { I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { Icon } from "./icon"; import { Icon } from "./icon";
interface SortSelectProps { interface SortSelectProps {
sort: PostSortType; sort: SortType;
onChange(val: PostSortType): void; onChange(val: SortType): void;
hideHot?: boolean; hideHot?: boolean;
hideMostComments?: boolean; hideMostComments?: boolean;
} }
interface SortSelectState { interface SortSelectState {
sort: PostSortType; sort: SortType;
} }
export class SortSelect extends Component<SortSelectProps, SortSelectState> { export class SortSelect extends Component<SortSelectProps, SortSelectState> {
@ -47,53 +47,55 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
{I18NextService.i18n.t("sort_type")} {I18NextService.i18n.t("sort_type")}
</option> </option>
{!this.props.hideHot && [ {!this.props.hideHot && [
<option key="Hot" value="Hot"> <option key={"Hot"} value={"Hot"}>
{I18NextService.i18n.t("hot")} {I18NextService.i18n.t("hot")}
</option>, </option>,
<option key="Active" value="Active"> <option key={"Active"} value={"Active"}>
{I18NextService.i18n.t("active")} {I18NextService.i18n.t("active")}
</option>, </option>,
<option key="Scaled" value="Scaled"> <option key={"Scaled"} value={"Scaled"}>
{I18NextService.i18n.t("scaled")} {I18NextService.i18n.t("scaled")}
</option>, </option>,
]} ]}
<option value="Controversial"> <option value={"Controversial"}>
{I18NextService.i18n.t("controversial")} {I18NextService.i18n.t("controversial")}
</option> </option>
<option value="New">{I18NextService.i18n.t("new")}</option> <option value={"New"}>{I18NextService.i18n.t("new")}</option>
<option value="Old">{I18NextService.i18n.t("old")}</option> <option value={"Old"}>{I18NextService.i18n.t("old")}</option>
{!this.props.hideMostComments && [ {!this.props.hideMostComments && [
<option key="MostComments" value="MostComments"> <option key={"MostComments"} value={"MostComments"}>
{I18NextService.i18n.t("most_comments")} {I18NextService.i18n.t("most_comments")}
</option>, </option>,
<option key="NewComments" value="NewComments"> <option key={"NewComments"} value={"NewComments"}>
{I18NextService.i18n.t("new_comments")} {I18NextService.i18n.t("new_comments")}
</option>, </option>,
]} ]}
<option disabled aria-hidden="true"> <option disabled aria-hidden="true">
</option> </option>
<option value="TopHour">{I18NextService.i18n.t("top_hour")}</option> <option value={"TopHour"}>{I18NextService.i18n.t("top_hour")}</option>
<option value="TopSixHour"> <option value={"TopSixHour"}>
{I18NextService.i18n.t("top_six_hours")} {I18NextService.i18n.t("top_six_hours")}
</option> </option>
<option value="TopTwelveHour"> <option value={"TopTwelveHour"}>
{I18NextService.i18n.t("top_twelve_hours")} {I18NextService.i18n.t("top_twelve_hours")}
</option> </option>
<option value="TopDay">{I18NextService.i18n.t("top_day")}</option> <option value={"TopDay"}>{I18NextService.i18n.t("top_day")}</option>
<option value="TopWeek">{I18NextService.i18n.t("top_week")}</option> <option value={"TopWeek"}>{I18NextService.i18n.t("top_week")}</option>
<option value="TopMonth">{I18NextService.i18n.t("top_month")}</option> <option value={"TopMonth"}>
<option value="TopThreeMonths"> {I18NextService.i18n.t("top_month")}
</option>
<option value={"TopThreeMonths"}>
{I18NextService.i18n.t("top_three_months")} {I18NextService.i18n.t("top_three_months")}
</option> </option>
<option value="TopSixMonths"> <option value={"TopSixMonths"}>
{I18NextService.i18n.t("top_six_months")} {I18NextService.i18n.t("top_six_months")}
</option> </option>
<option value="TopNineMonths"> <option value={"TopNineMonths"}>
{I18NextService.i18n.t("top_nine_months")} {I18NextService.i18n.t("top_nine_months")}
</option> </option>
<option value="TopYear">{I18NextService.i18n.t("top_year")}</option> <option value={"TopYear"}>{I18NextService.i18n.t("top_year")}</option>
<option value="TopAll">{I18NextService.i18n.t("top_all")}</option> <option value={"TopAll"}>{I18NextService.i18n.t("top_all")}</option>
</select> </select>
<a <a
className="sort-select-icon text-muted" className="sort-select-icon text-muted"

View file

@ -1,13 +1,12 @@
import { getQueryString, validInstanceTLD } from "@utils/helpers"; import { getQueryString, validInstanceTLD } from "@utils/helpers";
import classNames from "classnames"; import classNames from "classnames";
import { NoOptionI18nKeys } from "i18next"; import { NoOptionI18nKeys } from "i18next";
import { Component, MouseEventHandler, createRef, linkEvent } from "inferno"; import { Component, MouseEventHandler, linkEvent } from "inferno";
import { CommunityView } from "lemmy-js-client"; import { CommunityView } from "lemmy-js-client";
import { I18NextService, UserService } from "../../services"; import { I18NextService, UserService } from "../../services";
import { VERSION } from "../../version"; import { VERSION } from "../../version";
import { Icon, Spinner } from "./icon"; import { Icon, Spinner } from "./icon";
import { toast } from "../../toast"; import { toast } from "../../toast";
import { modalMixin } from "../mixins/modal-mixin";
interface SubscribeButtonProps { interface SubscribeButtonProps {
communityView: CommunityView; communityView: CommunityView;
@ -94,7 +93,6 @@ export function SubscribeButton({
interface RemoteFetchModalProps { interface RemoteFetchModalProps {
communityActorId: string; communityActorId: string;
show?: boolean;
} }
interface RemoteFetchModalState { interface RemoteFetchModalState {
@ -105,6 +103,10 @@ function handleInput(i: RemoteFetchModal, event: any) {
i.setState({ instanceText: event.target.value }); i.setState({ instanceText: event.target.value });
} }
function focusInput() {
document.getElementById("remoteFetchInstance")?.focus();
}
function submitRemoteFollow( function submitRemoteFollow(
{ state: { instanceText }, props: { communityActorId } }: RemoteFetchModal, { state: { instanceText }, props: { communityActorId } }: RemoteFetchModal,
event: Event, event: Event,
@ -137,7 +139,6 @@ function submitRemoteFollow(
)}`; )}`;
} }
@modalMixin
class RemoteFetchModal extends Component< class RemoteFetchModal extends Component<
RemoteFetchModalProps, RemoteFetchModalProps,
RemoteFetchModalState RemoteFetchModalState
@ -146,15 +147,20 @@ class RemoteFetchModal extends Component<
instanceText: "", instanceText: "",
}; };
modalDivRef = createRef<HTMLDivElement>();
inputRef = createRef<HTMLInputElement>();
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
} }
handleShow() { componentDidMount() {
this.inputRef.current?.focus(); document
.getElementById("remoteFetchModal")
?.addEventListener("shown.bs.modal", focusInput);
}
componentWillUnmount(): void {
document
.getElementById("remoteFetchModal")
?.removeEventListener("shown.bs.modal", focusInput);
} }
render() { render() {
@ -165,7 +171,6 @@ class RemoteFetchModal extends Component<
tabIndex={-1} tabIndex={-1}
aria-hidden aria-hidden
aria-labelledby="#remoteFetchModalTitle" aria-labelledby="#remoteFetchModalTitle"
ref={this.modalDivRef}
> >
<div className="modal-dialog modal-dialog-centered modal-fullscreen-sm-down"> <div className="modal-dialog modal-dialog-centered modal-fullscreen-sm-down">
<div className="modal-content"> <div className="modal-content">
@ -198,7 +203,6 @@ class RemoteFetchModal extends Component<
required required
enterKeyHint="go" enterKeyHint="go"
inputMode="url" inputMode="url"
ref={this.inputRef}
/> />
</form> </form>
<footer className="modal-footer"> <footer className="modal-footer">

View file

@ -20,7 +20,7 @@ function handleSwitchTab({ ctx, tab }: { ctx: Tabs; tab: string }) {
} }
export default class Tabs extends Component<TabsProps, TabsState> { export default class Tabs extends Component<TabsProps, TabsState> {
constructor(props: TabsProps, context: any) { constructor(props: TabsProps, context) {
super(props, context); super(props, context);
this.state = { this.state = {

View file

@ -1,24 +1,21 @@
import { import {
Component, Component,
InfernoNode,
MouseEventHandler, MouseEventHandler,
RefObject, RefObject,
createRef, createRef,
linkEvent, linkEvent,
} from "inferno"; } from "inferno";
import { I18NextService } from "../../../services"; import { I18NextService } from "../../services";
import { toast } from "../../../toast"; import { toast } from "../../toast";
import type { Modal } from "bootstrap"; import type { Modal } from "bootstrap";
import { modalMixin } from "../../mixins/modal-mixin";
interface TotpModalProps { interface TotpModalProps {
children?: InfernoNode;
/**Takes totp as param, returns whether submit was successful*/ /**Takes totp as param, returns whether submit was successful*/
onSubmit: (totp: string) => Promise<boolean>; onSubmit: (totp: string) => Promise<boolean>;
onClose: MouseEventHandler; onClose: MouseEventHandler;
type: "login" | "remove" | "generate"; type: "login" | "remove" | "generate";
secretUrl?: string; secretUrl?: string;
show: boolean; show?: boolean;
} }
interface TotpModalState { interface TotpModalState {
@ -71,14 +68,13 @@ function handlePaste(i: TotpModal, event: any) {
} }
} }
@modalMixin
export default class TotpModal extends Component< export default class TotpModal extends Component<
TotpModalProps, TotpModalProps,
TotpModalState TotpModalState
> { > {
readonly modalDivRef: RefObject<HTMLDivElement>; readonly modalDivRef: RefObject<HTMLDivElement>;
readonly inputRef: RefObject<HTMLInputElement>; readonly inputRef: RefObject<HTMLInputElement>;
modal?: Modal; modal: Modal;
state: TotpModalState = { state: TotpModalState = {
totp: "", totp: "",
pending: false, pending: false,
@ -89,6 +85,52 @@ export default class TotpModal extends Component<
this.modalDivRef = createRef(); this.modalDivRef = createRef();
this.inputRef = createRef(); this.inputRef = createRef();
this.clearTotp = this.clearTotp.bind(this);
this.handleShow = this.handleShow.bind(this);
}
async componentDidMount() {
this.modalDivRef.current?.addEventListener(
"shown.bs.modal",
this.handleShow,
);
this.modalDivRef.current?.addEventListener(
"hidden.bs.modal",
this.clearTotp,
);
const Modal = (await import("bootstrap/js/dist/modal")).default;
this.modal = new Modal(this.modalDivRef.current!);
if (this.props.show) {
this.modal.show();
}
}
componentWillUnmount() {
this.modalDivRef.current?.removeEventListener(
"shown.bs.modal",
this.handleShow,
);
this.modalDivRef.current?.removeEventListener(
"hidden.bs.modal",
this.clearTotp,
);
this.modal.dispose();
}
componentDidUpdate({ show: prevShow }: TotpModalProps) {
if (!!prevShow !== !!this.props.show) {
if (this.props.show) {
this.modal.show();
} else {
this.modal.hide();
}
}
} }
render() { render() {
@ -201,7 +243,7 @@ export default class TotpModal extends Component<
this.inputRef.current?.focus(); this.inputRef.current?.focus();
if (this.props.type === "generate") { if (this.props.type === "generate") {
const { getSVG } = await import("qreator/lib/svg"); const { getSVG } = await import("@shortcm/qr-image/lib/svg");
this.setState({ this.setState({
qrCode: URL.createObjectURL( qrCode: URL.createObjectURL(
@ -212,8 +254,4 @@ export default class TotpModal extends Component<
}); });
} }
} }
handleHide() {
this.clearTotp();
}
} }

View file

@ -1,83 +0,0 @@
import { linkEvent, Component } from "inferno";
import { I18NextService } from "../../services/I18NextService";
interface UrlListTextareaProps {
urls: string[];
onUpdate(urls: string[]): void;
}
interface UrlListTextareaState {
text: string;
}
function handleTextChange(i: UrlListTextarea, event: any) {
i.setState({ text: event.target.value });
}
const URL_SCHEME = "https://";
function processUrl(str: string) {
return new URL(str).toString().replace(URL_SCHEME, "");
}
function handleTextBlur(i: UrlListTextarea, event: any) {
const inputValue: string = event.currentTarget?.value ?? "";
const intermediateText = inputValue.replace(/\s+/g, "\n");
const newUrls: string[] = [];
for (const str of intermediateText.split("\n")) {
let url: string;
try {
url = processUrl(str);
} catch {
try {
url = processUrl(URL_SCHEME + str);
} catch {
continue;
}
}
if (newUrls.every(u => u !== url)) {
newUrls.push(url);
}
}
i.setState({ text: newUrls.join("\n") });
i.props.onUpdate(newUrls);
}
export default class UrlListTextarea extends Component<
UrlListTextareaProps,
UrlListTextareaState
> {
state: UrlListTextareaState = {
text: this.props.urls.join("\n"),
};
render() {
return (
<div className="mb-3 row">
<label
className="col-12 col-form-label"
htmlFor="create-site-block-urls"
>
{I18NextService.i18n.t("block_urls")}
</label>
<div className="col-12">
<textarea
id="create-site-block-urls"
className="form-control"
placeholder={I18NextService.i18n.t("block_urls_placeholder")}
value={this.state.text}
onInput={linkEvent(this, handleTextChange)}
onBlur={linkEvent(this, handleTextBlur)}
rows={4}
/>
</div>
</div>
);
}
}

View file

@ -1,7 +1,6 @@
import classNames from "classnames"; import classNames from "classnames";
import { Component } from "inferno"; import { Component } from "inferno";
import { I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { tippyMixin } from "../mixins/tippy-mixin";
interface UserBadgesProps { interface UserBadgesProps {
isBanned?: boolean; isBanned?: boolean;
@ -13,7 +12,7 @@ interface UserBadgesProps {
classNames?: string; classNames?: string;
} }
function getRoleLabelPill({ export function getRoleLabelPill({
label, label,
tooltip, tooltip,
classes, classes,
@ -35,7 +34,6 @@ function getRoleLabelPill({
); );
} }
@tippyMixin
export class UserBadges extends Component<UserBadgesProps> { export class UserBadges extends Component<UserBadgesProps> {
render() { render() {
return ( return (

View file

@ -1,14 +1,8 @@
import { import { Component, RefObject, createRef, linkEvent } from "inferno";
Component, import { I18NextService } from "../../services";
InfernoNode,
RefObject,
createRef,
linkEvent,
} from "inferno";
import { I18NextService } from "../../../services";
import type { Modal } from "bootstrap"; import type { Modal } from "bootstrap";
import { Icon, Spinner } from "../icon"; import { Icon, Spinner } from "./icon";
import { Paginator } from "../paginator"; import { Paginator } from "../common/paginator";
import { import {
ListCommentLikesResponse, ListCommentLikesResponse,
ListPostLikesResponse, ListPostLikesResponse,
@ -19,15 +13,11 @@ import {
HttpService, HttpService,
LOADING_REQUEST, LOADING_REQUEST,
RequestState, RequestState,
} from "../../../services/HttpService"; } from "../../services/HttpService";
import { fetchLimit } from "../../../config"; import { fetchLimit } from "../../config";
import { PersonListing } from "../../person/person-listing"; import { PersonListing } from "../person/person-listing";
import { modalMixin } from "../../mixins/modal-mixin";
import { UserBadges } from "../user-badges";
import { isBrowser } from "@utils/browser";
interface ViewVotesModalProps { interface ViewVotesModalProps {
children?: InfernoNode;
type: "comment" | "post"; type: "comment" | "post";
id: number; id: number;
show: boolean; show: boolean;
@ -49,12 +39,6 @@ function voteViewTable(votes: VoteView[]) {
<tr key={v.creator.id}> <tr key={v.creator.id}>
<td className="text-start"> <td className="text-start">
<PersonListing person={v.creator} useApubName /> <PersonListing person={v.creator} useApubName />
<UserBadges
classNames="ms-1"
isBot={v.creator.bot_account}
isDeleted={v.creator.deleted}
isBanned={v.creator.banned || v.creator_banned_from_community}
/>
</td> </td>
<td className="text-end">{scoreToIcon(v.score)}</td> <td className="text-end">{scoreToIcon(v.score)}</td>
</tr> </tr>
@ -73,14 +57,13 @@ function scoreToIcon(score: number) {
); );
} }
@modalMixin
export default class ViewVotesModal extends Component< export default class ViewVotesModal extends Component<
ViewVotesModalProps, ViewVotesModalProps,
ViewVotesModalState ViewVotesModalState
> { > {
readonly modalDivRef: RefObject<HTMLDivElement>; readonly modalDivRef: RefObject<HTMLDivElement>;
readonly yesButtonRef: RefObject<HTMLButtonElement>; readonly yesButtonRef: RefObject<HTMLButtonElement>;
modal?: Modal; modal: Modal;
state: ViewVotesModalState = { state: ViewVotesModalState = {
postLikesRes: EMPTY_REQUEST, postLikesRes: EMPTY_REQUEST,
commentLikesRes: EMPTY_REQUEST, commentLikesRes: EMPTY_REQUEST,
@ -93,20 +76,42 @@ export default class ViewVotesModal extends Component<
this.modalDivRef = createRef(); this.modalDivRef = createRef();
this.yesButtonRef = createRef(); this.yesButtonRef = createRef();
this.handleShow = this.handleShow.bind(this);
this.handleDismiss = this.handleDismiss.bind(this); this.handleDismiss = this.handleDismiss.bind(this);
this.handlePageChange = this.handlePageChange.bind(this); this.handlePageChange = this.handlePageChange.bind(this);
} }
async componentWillMount() { async componentDidMount() {
if (this.props.show && isBrowser()) { this.modalDivRef.current?.addEventListener(
"shown.bs.modal",
this.handleShow,
);
const Modal = (await import("bootstrap/js/dist/modal")).default;
this.modal = new Modal(this.modalDivRef.current!);
if (this.props.show) {
this.modal.show();
await this.refetch(); await this.refetch();
} }
} }
async componentWillReceiveProps({ show: nextShow }: ViewVotesModalProps) { componentWillUnmount() {
if (nextShow !== this.props.show) { this.modalDivRef.current?.removeEventListener(
if (nextShow) { "shown.bs.modal",
this.handleShow,
);
this.modal.dispose();
}
async componentDidUpdate({ show: prevShow }: ViewVotesModalProps) {
if (!!prevShow !== !!this.props.show) {
if (this.props.show) {
this.modal.show();
await this.refetch(); await this.refetch();
} else {
this.modal.hide();
} }
} }
} }
@ -186,7 +191,7 @@ export default class ViewVotesModal extends Component<
handleDismiss() { handleDismiss() {
this.props.onCancel(); this.props.onCancel();
this.modal?.hide(); this.modal.hide();
} }
async handlePageChange(page: number) { async handlePageChange(page: number) {

View file

@ -1,18 +1,16 @@
import { calculateUpvotePct, newVote, showScores } from "@utils/app"; import { newVote, showScores } from "@utils/app";
import { numToSI } from "@utils/helpers"; import { numToSI } from "@utils/helpers";
import { Component, InfernoNode, linkEvent } from "inferno"; import classNames from "classnames";
import { Component, linkEvent } from "inferno";
import { import {
CommentAggregates, CommentAggregates,
CreateCommentLike, CreateCommentLike,
CreatePostLike, CreatePostLike,
LocalUserVoteDisplayMode,
PostAggregates, PostAggregates,
} from "lemmy-js-client"; } from "lemmy-js-client";
import { VoteContentType, VoteType } from "../../interfaces"; import { VoteContentType, VoteType } from "../../interfaces";
import { I18NextService, UserService } from "../../services"; import { I18NextService, UserService } from "../../services";
import { Icon, Spinner } from "../common/icon"; import { Icon, Spinner } from "../common/icon";
import { tippyMixin } from "../mixins/tippy-mixin";
import classNames from "classnames";
interface VoteButtonsProps { interface VoteButtonsProps {
voteContentType: VoteContentType; voteContentType: VoteContentType;
@ -20,8 +18,7 @@ interface VoteButtonsProps {
onVote: (i: CreateCommentLike | CreatePostLike) => void; onVote: (i: CreateCommentLike | CreatePostLike) => void;
enableDownvotes?: boolean; enableDownvotes?: boolean;
counts: CommentAggregates | PostAggregates; counts: CommentAggregates | PostAggregates;
voteDisplayMode: LocalUserVoteDisplayMode; my_vote?: number;
myVote?: number;
} }
interface VoteButtonsState { interface VoteButtonsState {
@ -29,83 +26,62 @@ interface VoteButtonsState {
downvoteLoading: boolean; downvoteLoading: boolean;
} }
function tippy( const tippy = (counts: CommentAggregates | PostAggregates): string => {
voteDisplayMode: LocalUserVoteDisplayMode, const points = I18NextService.i18n.t("number_of_points", {
counts: CommentAggregates | PostAggregates, count: Number(counts.score),
): string { formattedCount: Number(counts.score),
const scoreStr = });
voteDisplayMode.score &&
I18NextService.i18n.t("number_of_points", {
count: Number(counts.score),
formattedCount: Number(counts.score),
});
const pct = calculateUpvotePct(counts.upvotes, counts.downvotes); const upvotes = I18NextService.i18n.t("number_of_upvotes", {
count: Number(counts.upvotes),
formattedCount: Number(counts.upvotes),
});
const upvotePctStr = const downvotes = I18NextService.i18n.t("number_of_downvotes", {
voteDisplayMode.upvote_percentage && count: Number(counts.downvotes),
I18NextService.i18n.t("upvote_percentage", { formattedCount: Number(counts.downvotes),
count: Number(pct), });
formattedCount: Number(pct),
});
const upvoteStr = return `${points}${upvotes}${downvotes}`;
voteDisplayMode.upvotes && };
I18NextService.i18n.t("number_of_upvotes", {
count: Number(counts.upvotes),
formattedCount: Number(counts.upvotes),
});
const downvoteStr = const handleUpvote = (i: VoteButtons) => {
voteDisplayMode.downvotes &&
I18NextService.i18n.t("number_of_downvotes", {
count: Number(counts.downvotes),
formattedCount: Number(counts.downvotes),
});
return [scoreStr, upvotePctStr, upvoteStr, downvoteStr]
.filter(Boolean)
.join(" · ");
}
function handleUpvote(i: VoteButtons | VoteButtonsCompact) {
i.setState({ upvoteLoading: true }); i.setState({ upvoteLoading: true });
switch (i.props.voteContentType) { switch (i.props.voteContentType) {
case VoteContentType.Comment: case VoteContentType.Comment:
i.props.onVote({ i.props.onVote({
comment_id: i.props.id, comment_id: i.props.id,
score: newVote(VoteType.Upvote, i.props.myVote), score: newVote(VoteType.Upvote, i.props.my_vote),
}); });
break; break;
case VoteContentType.Post: case VoteContentType.Post:
default: default:
i.props.onVote({ i.props.onVote({
post_id: i.props.id, post_id: i.props.id,
score: newVote(VoteType.Upvote, i.props.myVote), score: newVote(VoteType.Upvote, i.props.my_vote),
}); });
} }
} };
function handleDownvote(i: VoteButtons | VoteButtonsCompact) { const handleDownvote = (i: VoteButtons) => {
i.setState({ downvoteLoading: true }); i.setState({ downvoteLoading: true });
switch (i.props.voteContentType) { switch (i.props.voteContentType) {
case VoteContentType.Comment: case VoteContentType.Comment:
i.props.onVote({ i.props.onVote({
comment_id: i.props.id, comment_id: i.props.id,
score: newVote(VoteType.Downvote, i.props.myVote), score: newVote(VoteType.Downvote, i.props.my_vote),
}); });
break; break;
case VoteContentType.Post: case VoteContentType.Post:
default: default:
i.props.onVote({ i.props.onVote({
post_id: i.props.id, post_id: i.props.id,
score: newVote(VoteType.Downvote, i.props.myVote), score: newVote(VoteType.Downvote, i.props.my_vote),
}); });
} }
} };
@tippyMixin
export class VoteButtonsCompact extends Component< export class VoteButtonsCompact extends Component<
VoteButtonsProps, VoteButtonsProps,
VoteButtonsState VoteButtonsState
@ -119,9 +95,7 @@ export class VoteButtonsCompact extends Component<
super(props, context); super(props, context);
} }
componentWillReceiveProps( componentWillReceiveProps(nextProps: VoteButtonsProps) {
nextProps: VoteButtonsProps & { children?: InfernoNode },
) {
if (this.props !== nextProps) { if (this.props !== nextProps) {
this.setState({ this.setState({
upvoteLoading: false, upvoteLoading: false,
@ -136,28 +110,24 @@ export class VoteButtonsCompact extends Component<
<button <button
type="button" type="button"
className={`btn btn-animate btn-sm btn-link py-0 px-1 ${ className={`btn btn-animate btn-sm btn-link py-0 px-1 ${
this.props.myVote === 1 ? "text-info" : "text-muted" this.props.my_vote === 1 ? "text-info" : "text-muted"
}`} }`}
data-tippy-content={tippy( data-tippy-content={tippy(this.props.counts)}
this.props.voteDisplayMode,
this.props.counts,
)}
disabled={!UserService.Instance.myUserInfo} disabled={!UserService.Instance.myUserInfo}
onClick={linkEvent(this, handleUpvote)} onClick={linkEvent(this, handleUpvote)}
aria-label={I18NextService.i18n.t("upvote")} aria-label={I18NextService.i18n.t("upvote")}
aria-pressed={this.props.myVote === 1} aria-pressed={this.props.my_vote === 1}
> >
{this.state.upvoteLoading ? ( {this.state.upvoteLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
<> <>
<Icon icon="arrow-up1" classes="icon-inline small" /> <Icon icon="arrow-up1" classes="icon-inline small" />
{showScores() && {showScores() && (
this.props.voteContentType === VoteContentType.Post && ( <span className="ms-2">
<span className="ms-2"> {numToSI(this.props.counts.upvotes)}
{numToSI(this.props.counts.upvotes)} </span>
</span> )}
)}
</> </>
)} )}
</button> </button>
@ -165,32 +135,28 @@ export class VoteButtonsCompact extends Component<
<button <button
type="button" type="button"
className={`ms-2 btn btn-sm btn-link btn-animate btn py-0 px-1 ${ className={`ms-2 btn btn-sm btn-link btn-animate btn py-0 px-1 ${
this.props.myVote === -1 ? "text-danger" : "text-muted" this.props.my_vote === -1 ? "text-danger" : "text-muted"
}`} }`}
disabled={!UserService.Instance.myUserInfo} disabled={!UserService.Instance.myUserInfo}
onClick={linkEvent(this, handleDownvote)} onClick={linkEvent(this, handleDownvote)}
data-tippy-content={tippy( data-tippy-content={tippy(this.props.counts)}
this.props.voteDisplayMode,
this.props.counts,
)}
aria-label={I18NextService.i18n.t("downvote")} aria-label={I18NextService.i18n.t("downvote")}
aria-pressed={this.props.myVote === -1} aria-pressed={this.props.my_vote === -1}
> >
{this.state.downvoteLoading ? ( {this.state.downvoteLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
<> <>
<Icon icon="arrow-down1" classes="icon-inline small" /> <Icon icon="arrow-down1" classes="icon-inline small" />
{showScores() && {showScores() && (
this.props.voteContentType === VoteContentType.Post && ( <span
<span className={classNames("ms-2", {
className={classNames("ms-2", { invisible: this.props.counts.downvotes === 0,
invisible: this.props.counts.downvotes === 0, })}
})} >
> {numToSI(this.props.counts.downvotes)}
{numToSI(this.props.counts.downvotes)} </span>
</span> )}
)}
</> </>
)} )}
</button> </button>
@ -200,7 +166,6 @@ export class VoteButtonsCompact extends Component<
} }
} }
@tippyMixin
export class VoteButtons extends Component<VoteButtonsProps, VoteButtonsState> { export class VoteButtons extends Component<VoteButtonsProps, VoteButtonsState> {
state: VoteButtonsState = { state: VoteButtonsState = {
upvoteLoading: false, upvoteLoading: false,
@ -211,9 +176,7 @@ export class VoteButtons extends Component<VoteButtonsProps, VoteButtonsState> {
super(props, context); super(props, context);
} }
componentWillReceiveProps( componentWillReceiveProps(nextProps: VoteButtonsProps) {
nextProps: VoteButtonsProps & { children?: InfernoNode },
) {
if (this.props !== nextProps) { if (this.props !== nextProps) {
this.setState({ this.setState({
upvoteLoading: false, upvoteLoading: false,
@ -228,16 +191,13 @@ export class VoteButtons extends Component<VoteButtonsProps, VoteButtonsState> {
<button <button
type="button" type="button"
className={`btn-animate btn btn-link p-0 ${ className={`btn-animate btn btn-link p-0 ${
this.props.myVote === 1 ? "text-info" : "text-muted" this.props.my_vote === 1 ? "text-info" : "text-muted"
}`} }`}
disabled={!UserService.Instance.myUserInfo} disabled={!UserService.Instance.myUserInfo}
onClick={linkEvent(this, handleUpvote)} onClick={linkEvent(this, handleUpvote)}
data-tippy-content={tippy( data-tippy-content={I18NextService.i18n.t("upvote")}
this.props.voteDisplayMode,
this.props.counts,
)}
aria-label={I18NextService.i18n.t("upvote")} aria-label={I18NextService.i18n.t("upvote")}
aria-pressed={this.props.myVote === 1} aria-pressed={this.props.my_vote === 1}
> >
{this.state.upvoteLoading ? ( {this.state.upvoteLoading ? (
<Spinner /> <Spinner />
@ -248,10 +208,7 @@ export class VoteButtons extends Component<VoteButtonsProps, VoteButtonsState> {
{showScores() ? ( {showScores() ? (
<div <div
className="unselectable pointer text-muted post-score" className="unselectable pointer text-muted post-score"
data-tippy-content={tippy( data-tippy-content={tippy(this.props.counts)}
this.props.voteDisplayMode,
this.props.counts,
)}
> >
{numToSI(this.props.counts.score)} {numToSI(this.props.counts.score)}
</div> </div>
@ -262,16 +219,13 @@ export class VoteButtons extends Component<VoteButtonsProps, VoteButtonsState> {
<button <button
type="button" type="button"
className={`btn-animate btn btn-link p-0 ${ className={`btn-animate btn btn-link p-0 ${
this.props.myVote === -1 ? "text-danger" : "text-muted" this.props.my_vote === -1 ? "text-danger" : "text-muted"
}`} }`}
disabled={!UserService.Instance.myUserInfo} disabled={!UserService.Instance.myUserInfo}
onClick={linkEvent(this, handleDownvote)} onClick={linkEvent(this, handleDownvote)}
data-tippy-content={tippy( data-tippy-content={I18NextService.i18n.t("downvote")}
this.props.voteDisplayMode,
this.props.counts,
)}
aria-label={I18NextService.i18n.t("downvote")} aria-label={I18NextService.i18n.t("downvote")}
aria-pressed={this.props.myVote === -1} aria-pressed={this.props.my_vote === -1}
> >
{this.state.downvoteLoading ? ( {this.state.downvoteLoading ? (
<Spinner /> <Spinner />

View file

@ -1,184 +0,0 @@
import { numToSI } from "@utils/helpers";
import { Component } from "inferno";
import {
CommentAggregates,
LocalUserVoteDisplayMode,
PostAggregates,
} from "lemmy-js-client";
import { I18NextService } from "../../services";
import { tippyMixin } from "../mixins/tippy-mixin";
import { Icon } from "./icon";
import classNames from "classnames";
import { calculateUpvotePct } from "@utils/app";
interface Props {
voteDisplayMode: LocalUserVoteDisplayMode;
counts: CommentAggregates | PostAggregates;
myVote?: number;
}
const BADGE_CLASSES = "unselectable";
const UPVOTE_PCT_THRESHOLD = 90;
@tippyMixin
export class VoteDisplay extends Component<Props, any> {
constructor(props: any, context: any) {
super(props, context);
}
render() {
const {
voteDisplayMode,
counts: { score, upvotes },
} = this.props;
// If the score is the same as the upvotes,
// and both score and upvotes are enabled,
// only show the upvotes.
const hideScore =
voteDisplayMode.score && voteDisplayMode.upvotes && score === upvotes;
return (
<div>
{voteDisplayMode.score && !hideScore && this.score()}
{voteDisplayMode.upvote_percentage && this.upvotePct()}
{this.upvotesAndDownvotes()}
</div>
);
}
score() {
const {
myVote,
counts: { score },
} = this.props;
const scoreStr = numToSI(score);
const scoreTippy = I18NextService.i18n.t("number_of_points", {
count: Number(score),
formattedCount: scoreStr,
});
return (
<span
className={`${BADGE_CLASSES} ${scoreColor(myVote)}`}
aria-label={scoreTippy}
data-tippy-content={scoreTippy}
>
<Icon icon="heart" classes="me-1 icon-inline small" />
{scoreStr}
<span className="mx-2">·</span>
</span>
);
}
upvotePct() {
const { upvotes, downvotes } = this.props.counts;
const pct = calculateUpvotePct(upvotes, downvotes);
const pctStr = `${pct.toFixed(0)}%`;
const thresholdCheck = pct < UPVOTE_PCT_THRESHOLD;
const upvotesPctTippy = I18NextService.i18n.t("upvote_percentage", {
count: Number(pct),
formattedCount: Number(pct),
});
return (
thresholdCheck && (
<span
className={BADGE_CLASSES}
aria-label={upvotesPctTippy}
data-tippy-content={upvotesPctTippy}
>
<Icon icon="smile" classes="me-1 icon-inline small" />
{pctStr}
<span className="mx-2">·</span>
</span>
)
);
}
// A special case since they are both wrapped in a badge
upvotesAndDownvotes() {
const voteDisplayMode = this.props.voteDisplayMode;
const votesCheck = voteDisplayMode.upvotes || voteDisplayMode.downvotes;
const downvotesCheck = this.props.counts.downvotes > 0;
return (
votesCheck && (
<span className={BADGE_CLASSES}>
{voteDisplayMode.upvotes && (
<span className={classNames({ "me-1": downvotesCheck })}>
{this.upvotes()}
</span>
)}
{voteDisplayMode.downvotes && downvotesCheck && this.downvotes()}
<span className="mx-2">·</span>
</span>
)
);
}
upvotes() {
const {
myVote,
counts: { upvotes },
} = this.props;
const upvotesStr = numToSI(upvotes);
const upvotesTippy = I18NextService.i18n.t("number_of_upvotes", {
count: Number(upvotes),
formattedCount: upvotesStr,
});
return (
<span
className={classNames({
"text-info": myVote === 1,
})}
aria-label={upvotesTippy}
data-tippy-content={upvotesTippy}
>
<Icon icon="arrow-up" classes="me-1 icon-inline small" />
{upvotesStr}
</span>
);
}
downvotes() {
const {
myVote,
counts: { downvotes },
} = this.props;
const downvotesStr = numToSI(downvotes);
const downvotesTippy = I18NextService.i18n.t("number_of_downvotes", {
count: Number(downvotes),
formattedCount: downvotesStr,
});
return (
<span
className={classNames({
"text-danger": myVote === -1,
})}
aria-label={downvotesTippy}
data-tippy-content={downvotesTippy}
>
<Icon icon="arrow-down" classes="me-1 icon-inline small" />
{downvotesStr}
</span>
);
}
}
function scoreColor(myVote?: number): string {
if (myVote === 1) {
return "text-info";
} else if (myVote === -1) {
return "text-danger";
} else {
return "text-muted";
}
}

View file

@ -4,7 +4,6 @@ import {
getQueryParams, getQueryParams,
getQueryString, getQueryString,
numToSI, numToSI,
resourcesSettled,
} from "@utils/helpers"; } from "@utils/helpers";
import type { QueryParams } from "@utils/types"; import type { QueryParams } from "@utils/types";
import { RouteDataResponse } from "@utils/types"; import { RouteDataResponse } from "@utils/types";
@ -16,7 +15,7 @@ import {
ListCommunities, ListCommunities,
ListCommunitiesResponse, ListCommunitiesResponse,
ListingType, ListingType,
PostSortType, SortType,
} from "lemmy-js-client"; } from "lemmy-js-client";
import { InitialFetchRequest } from "../../interfaces"; import { InitialFetchRequest } from "../../interfaces";
import { FirstLoadService, I18NextService } from "../../services"; import { FirstLoadService, I18NextService } from "../../services";
@ -39,8 +38,6 @@ import { SubscribeButton } from "../common/subscribe-button";
import { getHttpBaseInternal } from "../../utils/env"; import { getHttpBaseInternal } from "../../utils/env";
import { RouteComponentProps } from "inferno-router/dist/Route"; import { RouteComponentProps } from "inferno-router/dist/Route";
import { IRoutePropsWithFetch } from "../../routes"; import { IRoutePropsWithFetch } from "../../routes";
import { scrollMixin } from "../mixins/scroll-mixin";
import { isBrowser } from "@utils/browser";
type CommunitiesData = RouteDataResponse<{ type CommunitiesData = RouteDataResponse<{
listCommunitiesResponse: ListCommunitiesResponse; listCommunitiesResponse: ListCommunitiesResponse;
@ -55,7 +52,7 @@ interface CommunitiesState {
interface CommunitiesProps { interface CommunitiesProps {
listingType: ListingType; listingType: ListingType;
sort: PostSortType; sort: SortType;
page: number; page: number;
} }
@ -63,8 +60,8 @@ function getListingTypeFromQuery(listingType?: string): ListingType {
return listingType ? (listingType as ListingType) : "Local"; return listingType ? (listingType as ListingType) : "Local";
} }
function getSortTypeFromQuery(type?: string): PostSortType { function getSortTypeFromQuery(type?: string): SortType {
return type ? (type as PostSortType) : "TopMonth"; return type ? (type as SortType) : "TopMonth";
} }
export function getCommunitiesQueryParams(source?: string): CommunitiesProps { export function getCommunitiesQueryParams(source?: string): CommunitiesProps {
@ -87,7 +84,6 @@ export type CommunitiesFetchConfig = IRoutePropsWithFetch<
CommunitiesProps CommunitiesProps
>; >;
@scrollMixin
export class Communities extends Component< export class Communities extends Component<
CommunitiesRouteProps, CommunitiesRouteProps,
CommunitiesState CommunitiesState
@ -100,10 +96,6 @@ export class Communities extends Component<
isIsomorphic: false, isIsomorphic: false,
}; };
loadingSettled() {
return resourcesSettled([this.state.listCommunitiesResponse]);
}
constructor(props: CommunitiesRouteProps, context: any) { constructor(props: CommunitiesRouteProps, context: any) {
super(props, context); super(props, context);
this.handlePageChange = this.handlePageChange.bind(this); this.handlePageChange = this.handlePageChange.bind(this);
@ -122,23 +114,19 @@ export class Communities extends Component<
} }
} }
async componentWillMount() { async componentDidMount() {
if (!this.state.isIsomorphic && isBrowser()) { if (!this.state.isIsomorphic) {
await this.refetch(this.props); await this.refetch();
} }
} }
componentWillReceiveProps(nextProps: CommunitiesRouteProps) {
this.refetch(nextProps);
}
get documentTitle(): string { get documentTitle(): string {
return `${I18NextService.i18n.t("communities")} - ${ return `${I18NextService.i18n.t("communities")} - ${
this.state.siteRes.site_view.site.name this.state.siteRes.site_view.site.name
}`; }`;
} }
renderListingsTable() { renderListings() {
switch (this.state.listCommunitiesResponse.state) { switch (this.state.listCommunitiesResponse.state) {
case "loading": case "loading":
return ( return (
@ -147,114 +135,120 @@ export class Communities extends Component<
</h5> </h5>
); );
case "success": { case "success": {
const { listingType, sort, page } = this.props;
return ( return (
<table id="community_table" className="table table-sm table-hover"> <div>
<thead className="pointer"> <h1 className="h4 mb-4">
<tr> {I18NextService.i18n.t("list_of_communities")}
<th>{I18NextService.i18n.t("name")}</th> </h1>
<th className="text-right"> <div className="row g-3 align-items-center mb-2">
{I18NextService.i18n.t("subscribers")} <div className="col-auto">
</th> <ListingTypeSelect
<th className="text-right"> type_={listingType}
{I18NextService.i18n.t("users")} /{" "} showLocal={showLocal(this.isoData)}
{I18NextService.i18n.t("month")} showSubscribed
</th> onChange={this.handleListingTypeChange}
<th className="text-right d-none d-lg-table-cell"> />
{I18NextService.i18n.t("posts")} </div>
</th> <div className="col-auto me-auto">
<th className="text-right d-none d-lg-table-cell"> <SortSelect sort={sort} onChange={this.handleSortChange} />
{I18NextService.i18n.t("comments")} </div>
</th> <div className="col-auto">{this.searchForm()}</div>
<th></th> </div>
</tr>
</thead> <div className="table-responsive">
<tbody> <table
{this.state.listCommunitiesResponse.data.communities.map(cv => ( id="community_table"
<tr key={cv.community.id}> className="table table-sm table-hover"
<td> >
<CommunityLink community={cv.community} /> <thead className="pointer">
</td> <tr>
<td className="text-right"> <th>{I18NextService.i18n.t("name")}</th>
{numToSI(cv.counts.subscribers)} <th className="text-right">
</td> {I18NextService.i18n.t("subscribers")}
<td className="text-right"> </th>
{numToSI(cv.counts.users_active_month)} <th className="text-right">
</td> {I18NextService.i18n.t("users")} /{" "}
<td className="text-right d-none d-lg-table-cell"> {I18NextService.i18n.t("month")}
{numToSI(cv.counts.posts)} </th>
</td> <th className="text-right d-none d-lg-table-cell">
<td className="text-right d-none d-lg-table-cell"> {I18NextService.i18n.t("posts")}
{numToSI(cv.counts.comments)} </th>
</td> <th className="text-right d-none d-lg-table-cell">
<td className="text-right"> {I18NextService.i18n.t("comments")}
<SubscribeButton </th>
communityView={cv} <th></th>
onFollow={linkEvent( </tr>
{ </thead>
i: this, <tbody>
communityId: cv.community.id, {this.state.listCommunitiesResponse.data.communities.map(
follow: true, cv => (
}, <tr key={cv.community.id}>
this.handleFollow, <td>
)} <CommunityLink community={cv.community} />
onUnFollow={linkEvent( </td>
{ <td className="text-right">
i: this, {numToSI(cv.counts.subscribers)}
communityId: cv.community.id, </td>
follow: false, <td className="text-right">
}, {numToSI(cv.counts.users_active_month)}
this.handleFollow, </td>
)} <td className="text-right d-none d-lg-table-cell">
isLink {numToSI(cv.counts.posts)}
/> </td>
</td> <td className="text-right d-none d-lg-table-cell">
</tr> {numToSI(cv.counts.comments)}
))} </td>
</tbody> <td className="text-right">
</table> <SubscribeButton
communityView={cv}
onFollow={linkEvent(
{
i: this,
communityId: cv.community.id,
follow: true,
},
this.handleFollow,
)}
onUnFollow={linkEvent(
{
i: this,
communityId: cv.community.id,
follow: false,
},
this.handleFollow,
)}
isLink
/>
</td>
</tr>
),
)}
</tbody>
</table>
</div>
<Paginator
page={page}
onChange={this.handlePageChange}
nextDisabled={
communityLimit >
this.state.listCommunitiesResponse.data.communities.length
}
/>
</div>
); );
} }
} }
} }
render() { render() {
const { listingType, sort, page } = this.props;
return ( return (
<div className="communities container-lg"> <div className="communities container-lg">
<HtmlTags <HtmlTags
title={this.documentTitle} title={this.documentTitle}
path={this.context.router.route.match.url} path={this.context.router.route.match.url}
/> />
<div> {this.renderListings()}
<h1 className="h4 mb-4">
{I18NextService.i18n.t("list_of_communities")}
</h1>
<div className="row g-3 align-items-center mb-2">
<div className="col-auto">
<ListingTypeSelect
type_={listingType}
showLocal={showLocal(this.isoData)}
showSubscribed
onChange={this.handleListingTypeChange}
/>
</div>
<div className="col-auto me-auto">
<SortSelect sort={sort} onChange={this.handleSortChange} />
</div>
<div className="col-auto">{this.searchForm()}</div>
</div>
<div className="table-responsive">{this.renderListingsTable()}</div>
<Paginator
page={page}
onChange={this.handlePageChange}
nextDisabled={
this.state.listCommunitiesResponse.state !== "success" ||
communityLimit >
this.state.listCommunitiesResponse.data.communities.length
}
/>
</div>
</div> </div>
); );
} }
@ -286,23 +280,29 @@ export class Communities extends Component<
); );
} }
async updateUrl(props: Partial<CommunitiesProps>) { async updateUrl({ listingType, sort, page }: Partial<CommunitiesProps>) {
const { listingType, sort, page } = { ...this.props, ...props }; const {
listingType: urlListingType,
sort: urlSort,
page: urlPage,
} = this.props;
const queryParams: QueryParams<CommunitiesProps> = { const queryParams: QueryParams<CommunitiesProps> = {
listingType: listingType, listingType: listingType ?? urlListingType,
sort: sort, sort: sort ?? urlSort,
page: page?.toString(), page: (page ?? urlPage)?.toString(),
}; };
this.props.history.push(`/communities${getQueryString(queryParams)}`); this.props.history.push(`/communities${getQueryString(queryParams)}`);
await this.refetch();
} }
handlePageChange(page: number) { handlePageChange(page: number) {
this.updateUrl({ page }); this.updateUrl({ page });
} }
handleSortChange(val: PostSortType) { handleSortChange(val: SortType) {
this.updateUrl({ sort: val, page: 1 }); this.updateUrl({ sort: val, page: 1 });
} }
@ -361,19 +361,21 @@ export class Communities extends Component<
data.i.findAndUpdateCommunity(res); data.i.findAndUpdateCommunity(res);
} }
fetchToken?: symbol; async refetch() {
async refetch({ listingType, sort, page }: CommunitiesProps) {
const token = (this.fetchToken = Symbol());
this.setState({ listCommunitiesResponse: LOADING_REQUEST }); this.setState({ listCommunitiesResponse: LOADING_REQUEST });
const listCommunitiesResponse = await HttpService.client.listCommunities({
type_: listingType, const { listingType, sort, page } = this.props;
sort: sort,
limit: communityLimit, this.setState({
page, listCommunitiesResponse: await HttpService.client.listCommunities({
type_: listingType,
sort: sort,
limit: communityLimit,
page,
}),
}); });
if (token === this.fetchToken) {
this.setState({ listCommunitiesResponse }); window.scrollTo(0, 0);
}
} }
findAndUpdateCommunity(res: RequestState<CommunityResponse>) { findAndUpdateCommunity(res: RequestState<CommunityResponse>) {

View file

@ -13,8 +13,6 @@ import { Icon, Spinner } from "../common/icon";
import { ImageUploadForm } from "../common/image-upload-form"; import { ImageUploadForm } from "../common/image-upload-form";
import { LanguageSelect } from "../common/language-select"; import { LanguageSelect } from "../common/language-select";
import { MarkdownTextArea } from "../common/markdown-textarea"; import { MarkdownTextArea } from "../common/markdown-textarea";
import { tippyMixin } from "../mixins/tippy-mixin";
import { validActorRegexPattern } from "../../config";
interface CommunityFormProps { interface CommunityFormProps {
community_view?: CommunityView; // If a community is given, that means this is an edit community_view?: CommunityView; // If a community is given, that means this is an edit
@ -42,7 +40,6 @@ interface CommunityFormState {
submitted: boolean; submitted: boolean;
} }
@tippyMixin
export class CommunityForm extends Component< export class CommunityForm extends Component<
CommunityFormProps, CommunityFormProps,
CommunityFormState CommunityFormState
@ -130,7 +127,7 @@ export class CommunityForm extends Component<
onInput={linkEvent(this, this.handleCommunityNameChange)} onInput={linkEvent(this, this.handleCommunityNameChange)}
required required
minLength={3} minLength={3}
pattern={validActorRegexPattern} pattern="[a-z0-9_]+"
title={I18NextService.i18n.t("community_reqs")} title={I18NextService.i18n.t("community_reqs")}
/> />
</div> </div>

View file

@ -20,38 +20,42 @@ export class CommunityLink extends Component<CommunityLinkProps, any> {
} }
render() { render() {
const { community, useApubName } = this.props; const community = this.props.community;
let title: string, link: string;
const local = community.local === null ? true : community.local; const local = community.local === null ? true : community.local;
const domain = hostname(community.actor_id);
let link: string;
let serverStr: string | undefined = undefined;
const title = useApubName
? community.name
: (community.title ?? community.name);
if (local) { if (local) {
title = community.title;
link = `/c/${community.name}`; link = `/c/${community.name}`;
} else { } else {
serverStr = `@${hostname(community.actor_id)}`; const name_ = `${community.name}@${domain}`;
link = !this.props.realLink title = `${community.title}@${domain}`;
? `/c/${community.name}${serverStr}` link = !this.props.realLink ? `/c/${name_}` : community.actor_id;
: community.actor_id;
} }
const classes = `community-link ${this.props.muted ? "text-muted" : ""}`;
const apubName = `!${community.name}@${domain}`;
const displayName = this.props.useApubName ? apubName : title;
return !this.props.realLink ? ( return !this.props.realLink ? (
<Link title={title} className={classes} to={link}> <Link
{this.avatarAndName(title, serverStr)} title={apubName}
className={`community-link ${this.props.muted ? "text-muted" : ""}`}
to={link}
>
{this.avatarAndName(displayName)}
</Link> </Link>
) : ( ) : (
<a title={title} className={classes} href={link} rel={relTags}> <a
{this.avatarAndName(title, serverStr)} title={apubName}
className={`community-link ${this.props.muted ? "text-muted" : ""}`}
href={link}
rel={relTags}
>
{this.avatarAndName(displayName)}
</a> </a>
); );
} }
avatarAndName(title: string, serverStr?: string) { avatarAndName(displayName: string) {
const icon = this.props.community.icon; const icon = this.props.community.icon;
const nsfw = this.props.community.nsfw; const nsfw = this.props.community.nsfw;
@ -61,10 +65,7 @@ export class CommunityLink extends Component<CommunityLinkProps, any> {
!this.props.community.removed && !this.props.community.removed &&
showAvatars() && showAvatars() &&
icon && <PictrsImage src={icon} icon nsfw={nsfw} />} icon && <PictrsImage src={icon} icon nsfw={nsfw} />}
<span className="overflow-wrap-anywhere"> <span className="overflow-wrap-anywhere">{displayName}</span>
{title}
{serverStr && <small className="text-muted">{serverStr}</small>}
</span>
</> </>
); );
} }

View file

@ -1,36 +1,23 @@
import { import {
commentsToFlatNodes, commentsToFlatNodes,
commentToPostSortType,
communityRSSUrl, communityRSSUrl,
editComment, editComment,
editPost, editPost,
editWith, editWith,
enableDownvotes, enableDownvotes,
enableNsfw, enableNsfw,
getCommentParentId,
getDataTypeString, getDataTypeString,
postToCommentSortType, postToCommentSortType,
setIsoData, setIsoData,
showLocal, showLocal,
updateCommunityBlock, updateCommunityBlock,
updatePersonBlock, updatePersonBlock,
voteDisplayMode,
} from "@utils/app"; } from "@utils/app";
import { import { getQueryParams, getQueryString } from "@utils/helpers";
getQueryParams, import type { QueryParams } from "@utils/types";
getQueryString,
resourcesSettled,
bareRoutePush,
} from "@utils/helpers";
import { scrollMixin } from "../mixins/scroll-mixin";
import type { QueryParams, StringBoolean } from "@utils/types";
import { RouteDataResponse } from "@utils/types"; import { RouteDataResponse } from "@utils/types";
import { import { Component, RefObject, createRef, linkEvent } from "inferno";
Component,
InfernoNode,
RefObject,
createRef,
linkEvent,
} from "inferno";
import { RouteComponentProps } from "inferno-router/dist/Route"; import { RouteComponentProps } from "inferno-router/dist/Route";
import { import {
AddAdmin, AddAdmin,
@ -42,6 +29,7 @@ import {
BanPersonResponse, BanPersonResponse,
BlockCommunity, BlockCommunity,
BlockPerson, BlockPerson,
CommentId,
CommentReplyResponse, CommentReplyResponse,
CommentResponse, CommentResponse,
CommunityResponse, CommunityResponse,
@ -66,7 +54,6 @@ import {
GetPosts, GetPosts,
GetPostsResponse, GetPostsResponse,
GetSiteResponse, GetSiteResponse,
HidePost,
LemmyHttp, LemmyHttp,
LockPost, LockPost,
MarkCommentReplyAsRead, MarkCommentReplyAsRead,
@ -82,10 +69,9 @@ import {
RemovePost, RemovePost,
SaveComment, SaveComment,
SavePost, SavePost,
PostSortType, SortType,
SuccessResponse, SuccessResponse,
TransferCommunity, TransferCommunity,
CommentSortType,
} from "lemmy-js-client"; } from "lemmy-js-client";
import { fetchLimit, relTags } from "../../config"; import { fetchLimit, relTags } from "../../config";
import { import {
@ -101,13 +87,13 @@ import {
RequestState, RequestState,
wrapClient, wrapClient,
} from "../../services/HttpService"; } from "../../services/HttpService";
import { tippyMixin } from "../mixins/tippy-mixin"; import { setupTippy } from "../../tippy";
import { toast } from "../../toast"; import { toast } from "../../toast";
import { CommentNodes } from "../comment/comment-nodes"; import { CommentNodes } from "../comment/comment-nodes";
import { BannerIconHeader } from "../common/banner-icon-header"; import { BannerIconHeader } from "../common/banner-icon-header";
import { DataTypeSelect } from "../common/data-type-select"; import { DataTypeSelect } from "../common/data-type-select";
import { HtmlTags } from "../common/html-tags"; import { HtmlTags } from "../common/html-tags";
import { Icon } from "../common/icon"; import { Icon, Spinner } from "../common/icon";
import { SortSelect } from "../common/sort-select"; import { SortSelect } from "../common/sort-select";
import { SiteSidebar } from "../home/site-sidebar"; import { SiteSidebar } from "../home/site-sidebar";
import { PostListings } from "../post/post-listings"; import { PostListings } from "../post/post-listings";
@ -120,10 +106,6 @@ import {
} from "../common/loading-skeleton"; } from "../common/loading-skeleton";
import { Sidebar } from "./sidebar"; import { Sidebar } from "./sidebar";
import { IRoutePropsWithFetch } from "../../routes"; import { IRoutePropsWithFetch } from "../../routes";
import PostHiddenSelect from "../common/post-hidden-select";
import { isBrowser } from "@utils/browser";
import { LoadingEllipses } from "../common/loading-ellipses";
import { CommentSortSelect } from "../common/comment-sort-select";
type CommunityData = RouteDataResponse<{ type CommunityData = RouteDataResponse<{
communityRes: GetCommunityResponse; communityRes: GetCommunityResponse;
@ -137,17 +119,17 @@ interface State {
commentsRes: RequestState<GetCommentsResponse>; commentsRes: RequestState<GetCommentsResponse>;
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
showSidebarMobile: boolean; showSidebarMobile: boolean;
finished: Map<CommentId, boolean | undefined>;
isIsomorphic: boolean; isIsomorphic: boolean;
} }
interface CommunityProps { interface CommunityProps {
dataType: DataType; dataType: DataType;
sort: PostSortType; sort: SortType;
pageCursor?: PaginationCursor; pageCursor?: PaginationCursor;
showHidden?: StringBoolean;
} }
type Fallbacks = { sort: PostSortType }; type Fallbacks = { sort: SortType };
export function getCommunityQueryParams( export function getCommunityQueryParams(
source: string | undefined, source: string | undefined,
@ -161,12 +143,10 @@ export function getCommunityQueryParams(
dataType: getDataTypeFromQuery, dataType: getDataTypeFromQuery,
pageCursor: (cursor?: string) => cursor, pageCursor: (cursor?: string) => cursor,
sort: getSortTypeFromQuery, sort: getSortTypeFromQuery,
showHidden: (include?: StringBoolean) => include,
}, },
source, source,
{ {
sort: sort: local_user?.default_sort_type ?? local_site.default_sort_type,
local_user?.default_post_sort_type ?? local_site.default_post_sort_type,
}, },
); );
} }
@ -175,11 +155,12 @@ function getDataTypeFromQuery(type?: string): DataType {
return type ? DataType[type] : DataType.Post; return type ? DataType[type] : DataType.Post;
} }
function getSortTypeFromQuery( function getSortTypeFromQuery(type?: string): SortType {
type: string | undefined, const mySortType =
fallback: PostSortType, UserService.Instance.myUserInfo?.local_user_view.local_user
): PostSortType { .default_sort_type;
return type ? (type as PostSortType) : fallback;
return type ? (type as SortType) : mySortType ?? "Active";
} }
type CommunityPathProps = { name: string }; type CommunityPathProps = { name: string };
@ -191,8 +172,6 @@ export type CommunityFetchConfig = IRoutePropsWithFetch<
CommunityProps CommunityProps
>; >;
@scrollMixin
@tippyMixin
export class Community extends Component<CommunityRouteProps, State> { export class Community extends Component<CommunityRouteProps, State> {
private isoData = setIsoData<CommunityData>(this.context); private isoData = setIsoData<CommunityData>(this.context);
state: State = { state: State = {
@ -201,24 +180,14 @@ export class Community extends Component<CommunityRouteProps, State> {
commentsRes: EMPTY_REQUEST, commentsRes: EMPTY_REQUEST,
siteRes: this.isoData.site_res, siteRes: this.isoData.site_res,
showSidebarMobile: false, showSidebarMobile: false,
finished: new Map(),
isIsomorphic: false, isIsomorphic: false,
}; };
private readonly mainContentRef: RefObject<HTMLElement>; private readonly mainContentRef: RefObject<HTMLElement>;
loadingSettled() {
return resourcesSettled([
this.state.communityRes,
this.props.dataType === DataType.Post
? this.state.postsRes
: this.state.commentsRes,
]);
}
constructor(props: CommunityRouteProps, context: any) { constructor(props: CommunityRouteProps, context: any) {
super(props, context); super(props, context);
this.handleSortChange = this.handleSortChange.bind(this); this.handleSortChange = this.handleSortChange.bind(this);
this.handleCommentSortChange = this.handleCommentSortChange.bind(this);
this.handleDataTypeChange = this.handleDataTypeChange.bind(this); this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
this.handlePageNext = this.handlePageNext.bind(this); this.handlePageNext = this.handlePageNext.bind(this);
this.handlePagePrev = this.handlePagePrev.bind(this); this.handlePagePrev = this.handlePagePrev.bind(this);
@ -256,9 +225,6 @@ export class Community extends Component<CommunityRouteProps, State> {
this.handleSavePost = this.handleSavePost.bind(this); this.handleSavePost = this.handleSavePost.bind(this);
this.handlePurgePost = this.handlePurgePost.bind(this); this.handlePurgePost = this.handlePurgePost.bind(this);
this.handleFeaturePost = this.handleFeaturePost.bind(this); this.handleFeaturePost = this.handleFeaturePost.bind(this);
this.handleHidePost = this.handleHidePost.bind(this);
this.handleShowHiddenChange = this.handleShowHiddenChange.bind(this);
this.mainContentRef = createRef(); this.mainContentRef = createRef();
// Only fetch the data if coming from another route // Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) { if (FirstLoadService.isFirstLoad) {
@ -274,42 +240,26 @@ export class Community extends Component<CommunityRouteProps, State> {
} }
} }
fetchCommunityToken?: symbol; async fetchCommunity() {
async fetchCommunity(props: CommunityRouteProps) {
const token = (this.fetchCommunityToken = Symbol());
this.setState({ communityRes: LOADING_REQUEST }); this.setState({ communityRes: LOADING_REQUEST });
const communityRes = await HttpService.client.getCommunity({ this.setState({
name: props.match.params.name, communityRes: await HttpService.client.getCommunity({
name: this.props.match.params.name,
}),
}); });
if (token === this.fetchCommunityToken) {
this.setState({ communityRes });
}
} }
async componentWillMount() { async componentDidMount() {
if (!this.state.isIsomorphic && isBrowser()) { if (!this.state.isIsomorphic) {
await Promise.all([ await Promise.all([this.fetchCommunity(), this.fetchData()]);
this.fetchCommunity(this.props),
this.fetchData(this.props),
]);
} }
}
componentWillReceiveProps( setupTippy();
nextProps: CommunityRouteProps & { children?: InfernoNode },
) {
if (
bareRoutePush(this.props, nextProps) ||
this.props.match.params.name !== nextProps.match.params.name
) {
this.fetchCommunity(nextProps);
}
this.fetchData(nextProps);
} }
static async fetchInitialData({ static async fetchInitialData({
headers, headers,
query: { dataType, pageCursor, sort, showHidden }, query: { dataType, pageCursor, sort },
match: { match: {
params: { name: communityName }, params: { name: communityName },
}, },
@ -338,7 +288,6 @@ export class Community extends Component<CommunityRouteProps, State> {
sort, sort,
type_: "All", type_: "All",
saved_only: false, saved_only: false,
show_hidden: showHidden === "true",
}; };
postsFetch = client.getPosts(getPostsForm); postsFetch = client.getPosts(getPostsForm);
@ -383,72 +332,78 @@ export class Community extends Component<CommunityRouteProps, State> {
} }
renderCommunity() { renderCommunity() {
const res = switch (this.state.communityRes.state) {
this.state.communityRes.state === "success" && case "loading":
this.state.communityRes.data; return (
return ( <h5>
<> <Spinner large />
{res && ( </h5>
<HtmlTags );
title={this.documentTitle} case "success": {
path={this.context.router.route.match.url} const res = this.state.communityRes.data;
canonicalPath={res.community_view.community.actor_id}
description={res.community_view.community.description}
image={res.community_view.community.icon}
/>
)}
{this.communityInfo()} return (
<div className="d-block d-md-none"> <>
<button <HtmlTags
className="btn btn-secondary d-inline-block mb-2 me-3" title={this.documentTitle}
onClick={linkEvent(this, this.handleShowSidebarMobile)} path={this.context.router.route.match.url}
> canonicalPath={res.community_view.community.actor_id}
{I18NextService.i18n.t("sidebar")}{" "} description={res.community_view.community.description}
<Icon image={res.community_view.community.icon}
icon={
this.state.showSidebarMobile ? `minus-square` : `plus-square`
}
classes="icon-inline"
/> />
</button>
{this.state.showSidebarMobile && this.sidebar()} <div className="row">
</div> <main
</> className="col-12 col-md-8 col-lg-9"
); ref={this.mainContentRef}
>
{this.communityInfo(res)}
<div className="d-block d-md-none">
<button
className="btn btn-secondary d-inline-block mb-2 me-3"
onClick={linkEvent(this, this.handleShowSidebarMobile)}
>
{I18NextService.i18n.t("sidebar")}{" "}
<Icon
icon={
this.state.showSidebarMobile
? `minus-square`
: `plus-square`
}
classes="icon-inline"
/>
</button>
{this.state.showSidebarMobile && this.sidebar(res)}
</div>
{this.selects(res)}
{this.listings(res)}
<PaginatorCursor
nextPage={this.getNextPage}
onNext={this.handlePageNext}
/>
</main>
<aside className="d-none d-md-block col-md-4 col-lg-3">
{this.sidebar(res)}
</aside>
</div>
</>
);
}
}
} }
render() { render() {
return ( return (
<div className="community container-lg"> <div className="community container-lg">{this.renderCommunity()}</div>
<div className="row">
<main className="col-12 col-md-8 col-lg-9" ref={this.mainContentRef}>
{this.renderCommunity()}
{this.selects()}
{this.listings()}
<PaginatorCursor
nextPage={this.getNextPage}
onNext={this.handlePageNext}
/>
</main>
<aside className="d-none d-md-block col-md-4 col-lg-3">
{this.sidebar()}
</aside>
</div>
</div>
); );
} }
sidebar() { sidebar(res: GetCommunityResponse) {
if (this.state.communityRes.state !== "success") { const { site_res } = this.isoData;
return undefined;
}
const res = this.state.communityRes.data;
const siteRes = this.isoData.site_res;
// For some reason, this returns an empty vec if it matches the site langs // For some reason, this returns an empty vec if it matches the site langs
const communityLangs = const communityLangs =
res.discussion_languages.length === 0 res.discussion_languages.length === 0
? siteRes.all_languages.map(({ id }) => id) ? site_res.all_languages.map(({ id }) => id)
: res.discussion_languages; : res.discussion_languages;
return ( return (
@ -456,11 +411,11 @@ export class Community extends Component<CommunityRouteProps, State> {
<Sidebar <Sidebar
community_view={res.community_view} community_view={res.community_view}
moderators={res.moderators} moderators={res.moderators}
admins={siteRes.admins} admins={site_res.admins}
enableNsfw={enableNsfw(siteRes)} enableNsfw={enableNsfw(site_res)}
editable editable
allLanguages={siteRes.all_languages} allLanguages={site_res.all_languages}
siteLanguages={siteRes.discussion_languages} siteLanguages={site_res.discussion_languages}
communityLanguages={communityLangs} communityLanguages={communityLangs}
onDeleteCommunity={this.handleDeleteCommunity} onDeleteCommunity={this.handleDeleteCommunity}
onRemoveCommunity={this.handleRemoveCommunity} onRemoveCommunity={this.handleRemoveCommunity}
@ -477,9 +432,9 @@ export class Community extends Component<CommunityRouteProps, State> {
); );
} }
listings() { listings(communityRes: GetCommunityResponse) {
const { dataType } = this.props; const { dataType } = this.props;
const siteRes = this.isoData.site_res; const { site_res } = this.isoData;
if (dataType === DataType.Post) { if (dataType === DataType.Post) {
switch (this.state.postsRes.state) { switch (this.state.postsRes.state) {
@ -489,11 +444,11 @@ export class Community extends Component<CommunityRouteProps, State> {
return ( return (
<PostListings <PostListings
posts={this.state.postsRes.data.posts} posts={this.state.postsRes.data.posts}
enableDownvotes={enableDownvotes(siteRes)} removeDuplicates
voteDisplayMode={voteDisplayMode(siteRes)} enableDownvotes={enableDownvotes(site_res)}
enableNsfw={enableNsfw(siteRes)} enableNsfw={enableNsfw(site_res)}
allLanguages={siteRes.all_languages} allLanguages={site_res.all_languages}
siteLanguages={siteRes.discussion_languages} siteLanguages={site_res.discussion_languages}
onBlockPerson={this.handleBlockPerson} onBlockPerson={this.handleBlockPerson}
onPostEdit={this.handlePostEdit} onPostEdit={this.handlePostEdit}
onPostVote={this.handlePostVote} onPostVote={this.handlePostVote}
@ -511,14 +466,10 @@ export class Community extends Component<CommunityRouteProps, State> {
onTransferCommunity={this.handleTransferCommunity} onTransferCommunity={this.handleTransferCommunity}
onFeaturePost={this.handleFeaturePost} onFeaturePost={this.handleFeaturePost}
onMarkPostAsRead={async () => {}} onMarkPostAsRead={async () => {}}
onHidePost={this.handleHidePost}
/> />
); );
} }
} else { } else {
if (this.state.communityRes.state !== "success") {
return;
}
switch (this.state.commentsRes.state) { switch (this.state.commentsRes.state) {
case "loading": case "loading":
return <CommentsLoadingSkeleton />; return <CommentsLoadingSkeleton />;
@ -527,14 +478,14 @@ export class Community extends Component<CommunityRouteProps, State> {
<CommentNodes <CommentNodes
nodes={commentsToFlatNodes(this.state.commentsRes.data.comments)} nodes={commentsToFlatNodes(this.state.commentsRes.data.comments)}
viewType={CommentViewType.Flat} viewType={CommentViewType.Flat}
finished={this.state.finished}
isTopLevel isTopLevel
showContext showContext
enableDownvotes={enableDownvotes(siteRes)} enableDownvotes={enableDownvotes(site_res)}
voteDisplayMode={voteDisplayMode(siteRes)} moderators={communityRes.moderators}
moderators={this.state.communityRes.data.moderators} admins={site_res.admins}
admins={siteRes.admins} allLanguages={site_res.all_languages}
allLanguages={siteRes.all_languages} siteLanguages={site_res.discussion_languages}
siteLanguages={siteRes.discussion_languages}
onSaveComment={this.handleSaveComment} onSaveComment={this.handleSaveComment}
onBlockPerson={this.handleBlockPerson} onBlockPerson={this.handleBlockPerson}
onDeleteComment={this.handleDeleteComment} onDeleteComment={this.handleDeleteComment}
@ -559,40 +510,28 @@ export class Community extends Component<CommunityRouteProps, State> {
} }
} }
communityInfo() { communityInfo(res: GetCommunityResponse) {
const res = const community = res.community_view.community;
(this.state.communityRes.state === "success" &&
this.state.communityRes.data) ||
undefined;
const community = res && res.community_view.community;
const urlCommunityName = this.props.match.params.name;
return ( return (
<div className="mb-2"> community && (
{community && ( <div className="mb-2">
<BannerIconHeader banner={community.banner} icon={community.icon} /> <BannerIconHeader banner={community.banner} icon={community.icon} />
)} <div>
<div> <h1
<h1 className="h4 mb-0 overflow-wrap-anywhere d-inline"
className="h4 mb-0 overflow-wrap-anywhere d-inline" data-tippy-content={
data-tippy-content={ community.posting_restricted_to_mods
community?.posting_restricted_to_mods ? I18NextService.i18n.t("community_locked")
? I18NextService.i18n.t("community_locked") : ""
: "" }
} >
> {community.title}
{community?.title ?? ( </h1>
<> {community.posting_restricted_to_mods && (
{urlCommunityName} <Icon icon="lock" inline classes="text-danger fs-4 ms-2" />
<LoadingEllipses />
</>
)} )}
</h1> </div>
{community?.posting_restricted_to_mods && (
<Icon icon="lock" inline classes="text-danger fs-4 ms-2" />
)}
</div>
{(community && (
<CommunityLink <CommunityLink
community={community} community={community}
realLink realLink
@ -600,17 +539,16 @@ export class Community extends Component<CommunityRouteProps, State> {
muted muted
hideAvatar hideAvatar
/> />
)) ?? </div>
urlCommunityName} )
</div>
); );
} }
selects() { selects(res: GetCommunityResponse) {
const res = // let communityRss = this.state.communityRes.map(r =>
this.state.communityRes.state === "success" && // communityRSSUrl(r.community_view.community.actor_id, this.state.sort)
this.state.communityRes.data; // );
const { dataType, sort, showHidden } = this.props; const { dataType, sort } = this.props;
const communityRss = res const communityRss = res
? communityRSSUrl(res.community_view.community.actor_id, sort) ? communityRSSUrl(res.community_view.community.actor_id, sort)
: undefined; : undefined;
@ -623,23 +561,8 @@ export class Community extends Component<CommunityRouteProps, State> {
onChange={this.handleDataTypeChange} onChange={this.handleDataTypeChange}
/> />
</span> </span>
{dataType === DataType.Post && UserService.Instance.myUserInfo && (
<span className="me-3">
<PostHiddenSelect
showHidden={showHidden}
onShowHiddenChange={this.handleShowHiddenChange}
/>
</span>
)}
<span className="me-2"> <span className="me-2">
{this.props.dataType === DataType.Post ? ( <SortSelect sort={sort} onChange={this.handleSortChange} />
<SortSelect sort={sort} onChange={this.handleSortChange} />
) : (
<CommentSortSelect
sort={postToCommentSortType(sort)}
onChange={this.handleCommentSortChange}
/>
)}
</span> </span>
{communityRss && ( {communityRss && (
<> <>
@ -663,31 +586,17 @@ export class Community extends Component<CommunityRouteProps, State> {
handlePageNext(nextPage: PaginationCursor) { handlePageNext(nextPage: PaginationCursor) {
this.updateUrl({ pageCursor: nextPage }); this.updateUrl({ pageCursor: nextPage });
window.scrollTo(0, 0);
} }
handleSortChange(sort: PostSortType) { handleSortChange(sort: SortType) {
this.updateUrl({ this.updateUrl({ sort, pageCursor: undefined });
sort: sort, window.scrollTo(0, 0);
pageCursor: undefined,
});
}
handleCommentSortChange(sort: CommentSortType) {
this.updateUrl({
sort: commentToPostSortType(sort),
pageCursor: undefined,
});
} }
handleDataTypeChange(dataType: DataType) { handleDataTypeChange(dataType: DataType) {
this.updateUrl({ dataType, pageCursor: undefined }); this.updateUrl({ dataType, pageCursor: undefined });
} window.scrollTo(0, 0);
handleShowHiddenChange(show?: StringBoolean) {
this.updateUrl({
showHidden: show,
pageCursor: undefined,
});
} }
handleShowSidebarMobile(i: Community) { handleShowSidebarMobile(i: Community) {
@ -696,63 +605,52 @@ export class Community extends Component<CommunityRouteProps, State> {
})); }));
} }
async updateUrl(props: Partial<CommunityProps>) { async updateUrl({ dataType, pageCursor, sort }: Partial<CommunityProps>) {
const { const { dataType: urlDataType, sort: urlSort } = this.props;
dataType,
pageCursor,
sort,
showHidden,
match: {
params: { name },
},
} = {
...this.props,
...props,
};
const queryParams: QueryParams<CommunityProps> = { const queryParams: QueryParams<CommunityProps> = {
dataType: getDataTypeString(dataType ?? DataType.Post), dataType: getDataTypeString(dataType ?? urlDataType),
pageCursor: pageCursor, pageCursor: pageCursor,
sort: sort, sort: sort ?? urlSort,
showHidden: showHidden,
}; };
this.props.history.push(`/c/${name}${getQueryString(queryParams)}`); this.props.history.push(
`/c/${this.props.match.params.name}${getQueryString(queryParams)}`,
);
await this.fetchData();
} }
fetchDataToken?: symbol; async fetchData() {
async fetchData(props: CommunityRouteProps) { const { dataType, pageCursor, sort } = this.props;
const token = (this.fetchDataToken = Symbol()); const { name } = this.props.match.params;
const { dataType, pageCursor, sort, showHidden } = props;
const { name } = props.match.params;
if (dataType === DataType.Post) { if (dataType === DataType.Post) {
this.setState({ postsRes: LOADING_REQUEST, commentsRes: EMPTY_REQUEST }); this.setState({ postsRes: LOADING_REQUEST });
const postsRes = await HttpService.client.getPosts({ this.setState({
page_cursor: pageCursor, postsRes: await HttpService.client.getPosts({
limit: fetchLimit, page_cursor: pageCursor,
sort, limit: fetchLimit,
type_: "All", sort,
community_name: name, type_: "All",
saved_only: false, community_name: name,
show_hidden: showHidden === "true", saved_only: false,
}),
}); });
if (token === this.fetchDataToken) {
this.setState({ postsRes });
}
} else { } else {
this.setState({ commentsRes: LOADING_REQUEST, postsRes: EMPTY_REQUEST }); this.setState({ commentsRes: LOADING_REQUEST });
const commentsRes = await HttpService.client.getComments({ this.setState({
limit: fetchLimit, commentsRes: await HttpService.client.getComments({
sort: postToCommentSortType(sort), limit: fetchLimit,
type_: "All", sort: postToCommentSortType(sort),
community_name: name, type_: "All",
saved_only: false, community_name: name,
saved_only: false,
}),
}); });
if (token === this.fetchDataToken) {
this.setState({ commentsRes });
}
} }
setupTippy();
} }
async handleDeleteCommunity(form: DeleteCommunity) { async handleDeleteCommunity(form: DeleteCommunity) {
@ -835,9 +733,6 @@ export class Community extends Component<CommunityRouteProps, State> {
const createCommentRes = await HttpService.client.createComment(form); const createCommentRes = await HttpService.client.createComment(form);
this.createAndUpdateComments(createCommentRes); this.createAndUpdateComments(createCommentRes);
if (createCommentRes.state === "failed") {
toast(I18NextService.i18n.t(createCommentRes.err.message), "danger");
}
return createCommentRes; return createCommentRes;
} }
@ -845,9 +740,6 @@ export class Community extends Component<CommunityRouteProps, State> {
const editCommentRes = await HttpService.client.editComment(form); const editCommentRes = await HttpService.client.editComment(form);
this.findAndUpdateCommentEdit(editCommentRes); this.findAndUpdateCommentEdit(editCommentRes);
if (editCommentRes.state === "failed") {
toast(I18NextService.i18n.t(editCommentRes.err.message), "danger");
}
return editCommentRes; return editCommentRes;
} }
@ -922,26 +814,6 @@ export class Community extends Component<CommunityRouteProps, State> {
this.findAndUpdatePost(lockRes); this.findAndUpdatePost(lockRes);
} }
async handleHidePost(form: HidePost) {
const hideRes = await HttpService.client.hidePost(form);
if (hideRes.state === "success") {
this.setState(prev => {
if (prev.postsRes.state === "success") {
for (const post of prev.postsRes.data.posts.filter(p =>
form.post_ids.some(id => id === p.post.id),
)) {
post.hidden = form.hide;
}
}
return prev;
});
toast(I18NextService.i18n.t(form.hide ? "post_hidden" : "post_unhidden"));
}
}
async handleDistinguishComment(form: DistinguishComment) { async handleDistinguishComment(form: DistinguishComment) {
const distinguishRes = await HttpService.client.distinguishComment(form); const distinguishRes = await HttpService.client.distinguishComment(form);
this.findAndUpdateComment(distinguishRes); this.findAndUpdateComment(distinguishRes);
@ -1059,6 +931,7 @@ export class Community extends Component<CommunityRouteProps, State> {
res.data.comment_view, res.data.comment_view,
s.commentsRes.data.comments, s.commentsRes.data.comments,
); );
s.finished.set(res.data.comment_view.comment.id, true);
} }
return s; return s;
}); });
@ -1080,6 +953,12 @@ export class Community extends Component<CommunityRouteProps, State> {
this.setState(s => { this.setState(s => {
if (s.commentsRes.state === "success" && res.state === "success") { if (s.commentsRes.state === "success" && res.state === "success") {
s.commentsRes.data.comments.unshift(res.data.comment_view); s.commentsRes.data.comments.unshift(res.data.comment_view);
// Set finished for the parent
s.finished.set(
getCommentParentId(res.data.comment_view.comment) ?? 0,
true,
);
} }
return s; return s;
}); });

View file

@ -4,22 +4,16 @@ import {
CreateCommunity as CreateCommunityI, CreateCommunity as CreateCommunityI,
GetSiteResponse, GetSiteResponse,
} from "lemmy-js-client"; } from "lemmy-js-client";
import { HttpService, I18NextService, UserService } from "../../services"; import { HttpService, I18NextService } from "../../services";
import { HtmlTags } from "../common/html-tags"; import { HtmlTags } from "../common/html-tags";
import { CommunityForm } from "./community-form"; import { CommunityForm } from "./community-form";
import { simpleScrollMixin } from "../mixins/scroll-mixin";
import { RouteComponentProps } from "inferno-router/dist/Route";
interface CreateCommunityState { interface CreateCommunityState {
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
loading: boolean; loading: boolean;
} }
@simpleScrollMixin export class CreateCommunity extends Component<any, CreateCommunityState> {
export class CreateCommunity extends Component<
RouteComponentProps<Record<string, never>>,
CreateCommunityState
> {
private isoData = setIsoData(this.context); private isoData = setIsoData(this.context);
state: CreateCommunityState = { state: CreateCommunityState = {
siteRes: this.isoData.site_res, siteRes: this.isoData.site_res,
@ -68,11 +62,6 @@ export class CreateCommunity extends Component<
const res = await HttpService.client.createCommunity(form); const res = await HttpService.client.createCommunity(form);
if (res.state === "success") { if (res.state === "success") {
const myUser = UserService.Instance.myUserInfo!;
UserService.Instance.myUserInfo?.moderates.push({
community: res.data.community_view.community,
moderator: myUser.local_user_view.person,
});
const name = res.data.community_view.community.name; const name = res.data.community_view.community.name;
this.props.history.replace(`/c/${name}`); this.props.history.replace(`/c/${name}`);
} else { } else {

View file

@ -25,7 +25,6 @@ import { SubscribeButton } from "../common/subscribe-button";
import { CommunityForm } from "../community/community-form"; import { CommunityForm } from "../community/community-form";
import { CommunityLink } from "../community/community-link"; import { CommunityLink } from "../community/community-link";
import { PersonListing } from "../person/person-listing"; import { PersonListing } from "../person/person-listing";
import { tippyMixin } from "../mixins/tippy-mixin";
interface SidebarProps { interface SidebarProps {
community_view: CommunityView; community_view: CommunityView;
@ -61,7 +60,6 @@ interface SidebarState {
purgeCommunityLoading: boolean; purgeCommunityLoading: boolean;
} }
@tippyMixin
export class Sidebar extends Component<SidebarProps, SidebarState> { export class Sidebar extends Component<SidebarProps, SidebarState> {
state: SidebarState = { state: SidebarState = {
showEdit: false, showEdit: false,
@ -80,21 +78,6 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
this.handleEditCancel = this.handleEditCancel.bind(this); this.handleEditCancel = this.handleEditCancel.bind(this);
} }
unlisten = () => {};
componentWillMount() {
// Leave edit mode on navigation
this.unlisten = this.context.router.history.listen(() => {
if (this.state.showEdit) {
this.setState({ showEdit: false });
}
});
}
componentWillUnmount(): void {
this.unlisten();
}
componentWillReceiveProps( componentWillReceiveProps(
nextProps: Readonly<{ children?: InfernoNode } & SidebarProps>, nextProps: Readonly<{ children?: InfernoNode } & SidebarProps>,
): void { ): void {

View file

@ -1,22 +1,21 @@
import { fetchThemeList, setIsoData, showLocal } from "@utils/app"; import { fetchThemeList, setIsoData, showLocal } from "@utils/app";
import { capitalizeFirstLetter, resourcesSettled } from "@utils/helpers"; import { capitalizeFirstLetter } from "@utils/helpers";
import { scrollMixin } from "../mixins/scroll-mixin";
import { RouteDataResponse } from "@utils/types"; import { RouteDataResponse } from "@utils/types";
import classNames from "classnames"; import classNames from "classnames";
import { Component } from "inferno"; import { Component, linkEvent } from "inferno";
import { import {
BannedPersonsResponse, BannedPersonsResponse,
CreateOAuthProvider, CreateCustomEmoji,
DeleteOAuthProvider, DeleteCustomEmoji,
EditOAuthProvider, EditCustomEmoji,
EditSite, EditSite,
GetFederatedInstancesResponse, GetFederatedInstancesResponse,
GetSiteResponse, GetSiteResponse,
LemmyHttp, LemmyHttp,
ListMediaResponse,
PersonView, PersonView,
} from "lemmy-js-client"; } from "lemmy-js-client";
import { InitialFetchRequest } from "../../interfaces"; import { InitialFetchRequest } from "../../interfaces";
import { removeFromEmojiDataModel, updateEmojiDataModel } from "../../markdown";
import { FirstLoadService, I18NextService } from "../../services"; import { FirstLoadService, I18NextService } from "../../services";
import { import {
EMPTY_REQUEST, EMPTY_REQUEST,
@ -37,28 +36,19 @@ import { TaglineForm } from "./tagline-form";
import { getHttpBaseInternal } from "../../utils/env"; import { getHttpBaseInternal } from "../../utils/env";
import { RouteComponentProps } from "inferno-router/dist/Route"; import { RouteComponentProps } from "inferno-router/dist/Route";
import { IRoutePropsWithFetch } from "../../routes"; import { IRoutePropsWithFetch } from "../../routes";
import { MediaUploads } from "../common/media-uploads";
import { Paginator } from "../common/paginator";
import { snapToTop } from "@utils/browser";
import { isBrowser } from "@utils/browser";
import ConfirmationModal from "../common/modal/confirmation-modal";
import OAuthProvidersTab from "./oauth/oauth-providers-tab";
type AdminSettingsData = RouteDataResponse<{ type AdminSettingsData = RouteDataResponse<{
bannedRes: BannedPersonsResponse; bannedRes: BannedPersonsResponse;
instancesRes: GetFederatedInstancesResponse; instancesRes: GetFederatedInstancesResponse;
uploadsRes: ListMediaResponse;
}>; }>;
interface AdminSettingsState { interface AdminSettingsState {
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
banned: PersonView[]; banned: PersonView[];
currentTab: string;
instancesRes: RequestState<GetFederatedInstancesResponse>; instancesRes: RequestState<GetFederatedInstancesResponse>;
bannedRes: RequestState<BannedPersonsResponse>; bannedRes: RequestState<BannedPersonsResponse>;
leaveAdminTeamRes: RequestState<GetSiteResponse>; leaveAdminTeamRes: RequestState<GetSiteResponse>;
showConfirmLeaveAdmin: boolean;
uploadsRes: RequestState<ListMediaResponse>;
uploadsPage: number;
loading: boolean; loading: boolean;
themeList: string[]; themeList: string[];
isIsomorphic: boolean; isIsomorphic: boolean;
@ -72,7 +62,6 @@ export type AdminSettingsFetchConfig = IRoutePropsWithFetch<
Record<string, never> Record<string, never>
>; >;
@scrollMixin
export class AdminSettings extends Component< export class AdminSettings extends Component<
AdminSettingsRouteProps, AdminSettingsRouteProps,
AdminSettingsState AdminSettingsState
@ -81,46 +70,31 @@ export class AdminSettings extends Component<
state: AdminSettingsState = { state: AdminSettingsState = {
siteRes: this.isoData.site_res, siteRes: this.isoData.site_res,
banned: [], banned: [],
currentTab: "site",
bannedRes: EMPTY_REQUEST, bannedRes: EMPTY_REQUEST,
instancesRes: EMPTY_REQUEST, instancesRes: EMPTY_REQUEST,
leaveAdminTeamRes: EMPTY_REQUEST, leaveAdminTeamRes: EMPTY_REQUEST,
showConfirmLeaveAdmin: false,
uploadsRes: EMPTY_REQUEST,
uploadsPage: 1,
loading: false, loading: false,
themeList: [], themeList: [],
isIsomorphic: false, isIsomorphic: false,
}; };
loadingSettled() {
return resourcesSettled([
this.state.bannedRes,
this.state.instancesRes,
this.state.uploadsRes,
]);
}
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.handleEditSite = this.handleEditSite.bind(this); this.handleEditSite = this.handleEditSite.bind(this);
this.handleUploadsPageChange = this.handleUploadsPageChange.bind(this); this.handleEditEmoji = this.handleEditEmoji.bind(this);
this.handleToggleShowLeaveAdminConfirmation = this.handleDeleteEmoji = this.handleDeleteEmoji.bind(this);
this.handleToggleShowLeaveAdminConfirmation.bind(this); this.handleCreateEmoji = this.handleCreateEmoji.bind(this);
this.handleLeaveAdminTeam = this.handleLeaveAdminTeam.bind(this);
this.handleEditOAuthProvider = this.handleEditOAuthProvider.bind(this);
this.handleDeleteOAuthProvider = this.handleDeleteOAuthProvider.bind(this);
this.handleCreateOAuthProvider = this.handleCreateOAuthProvider.bind(this);
// Only fetch the data if coming from another route // Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) { if (FirstLoadService.isFirstLoad) {
const { bannedRes, instancesRes, uploadsRes } = this.isoData.routeData; const { bannedRes, instancesRes } = this.isoData.routeData;
this.state = { this.state = {
...this.state, ...this.state,
bannedRes, bannedRes,
instancesRes, instancesRes,
uploadsRes,
isIsomorphic: true, isIsomorphic: true,
}; };
} }
@ -135,18 +109,15 @@ export class AdminSettings extends Component<
return { return {
bannedRes: await client.getBannedPersons(), bannedRes: await client.getBannedPersons(),
instancesRes: await client.getFederatedInstances(), instancesRes: await client.getFederatedInstances(),
uploadsRes: await client.listAllMedia(),
}; };
} }
async componentWillMount() { async componentDidMount() {
if (isBrowser()) { if (!this.state.isIsomorphic) {
if (!this.state.isIsomorphic) { await this.fetchData();
await this.fetchData(); } else {
} else { const themeList = await fetchThemeList();
const themeList = await fetchThemeList(); this.setState({ themeList });
this.setState({ themeList });
}
} }
} }
@ -249,7 +220,11 @@ export class AdminSettings extends Component<
id="taglines-tab-pane" id="taglines-tab-pane"
> >
<div className="row"> <div className="row">
<TaglineForm /> <TaglineForm
taglines={this.state.siteRes.taglines}
onSaveSite={this.handleEditSite}
loading={this.state.loading}
/>
</div> </div>
</div> </div>
), ),
@ -266,48 +241,15 @@ export class AdminSettings extends Component<
id="emojis-tab-pane" id="emojis-tab-pane"
> >
<div className="row"> <div className="row">
<EmojiForm /> <EmojiForm
onCreate={this.handleCreateEmoji}
onDelete={this.handleDeleteEmoji}
onEdit={this.handleEditEmoji}
/>
</div> </div>
</div> </div>
), ),
}, },
{
key: "uploads",
label: I18NextService.i18n.t("uploads"),
getNode: isSelected => (
<div
className={classNames("tab-pane", {
active: isSelected,
})}
role="tabpanel"
id="uploads-tab-pane"
>
{this.uploads()}
</div>
),
},
{
key: "auth",
label: I18NextService.i18n.t("authentication"),
getNode: isSelected => (
<div
className={classNames("tab-pane", {
active: isSelected,
})}
role="tabpanel"
id="auth-tab-pane"
>
<OAuthProvidersTab
oauthProviders={
this.state.siteRes.admin_oauth_providers ?? []
}
onCreate={this.handleCreateOAuthProvider}
onDelete={this.handleDeleteOAuthProvider}
onEdit={this.handleEditOAuthProvider}
/>
</div>
),
},
]} ]}
/> />
</div> </div>
@ -318,34 +260,22 @@ export class AdminSettings extends Component<
this.setState({ this.setState({
bannedRes: LOADING_REQUEST, bannedRes: LOADING_REQUEST,
instancesRes: LOADING_REQUEST, instancesRes: LOADING_REQUEST,
uploadsRes: LOADING_REQUEST,
themeList: [], themeList: [],
}); });
const [bannedRes, instancesRes, uploadsRes, themeList] = await Promise.all([ const [bannedRes, instancesRes, themeList] = await Promise.all([
HttpService.client.getBannedPersons(), HttpService.client.getBannedPersons(),
HttpService.client.getFederatedInstances(), HttpService.client.getFederatedInstances(),
HttpService.client.listAllMedia({
page: this.state.uploadsPage,
}),
fetchThemeList(), fetchThemeList(),
]); ]);
this.setState({ this.setState({
bannedRes, bannedRes,
instancesRes, instancesRes,
uploadsRes,
themeList, themeList,
}); });
} }
async fetchUploadsOnly() {
const uploadsRes = await HttpService.client.listAllMedia({
page: this.state.uploadsPage,
});
this.setState({ uploadsRes });
}
admins() { admins() {
return ( return (
<> <>
@ -360,13 +290,6 @@ export class AdminSettings extends Component<
))} ))}
</ul> </ul>
{this.leaveAdmin()} {this.leaveAdmin()}
<ConfirmationModal
message={I18NextService.i18n.t("leave_admin_team_confirmation")}
loadingMessage={I18NextService.i18n.t("leaving_admin_team")}
onNo={this.handleToggleShowLeaveAdminConfirmation}
onYes={this.handleLeaveAdminTeam}
show={this.state.showConfirmLeaveAdmin}
/>
</> </>
); );
} }
@ -374,7 +297,7 @@ export class AdminSettings extends Component<
leaveAdmin() { leaveAdmin() {
return ( return (
<button <button
onClick={this.handleToggleShowLeaveAdminConfirmation} onClick={linkEvent(this, this.handleLeaveAdminTeam)}
className="btn btn-danger mb-2" className="btn btn-danger mb-2"
> >
{this.state.leaveAdminTeamRes.state === "loading" ? ( {this.state.leaveAdminTeamRes.state === "loading" ? (
@ -412,30 +335,6 @@ export class AdminSettings extends Component<
} }
} }
uploads() {
switch (this.state.uploadsRes.state) {
case "loading":
return (
<h5>
<Spinner large />
</h5>
);
case "success": {
const uploadsRes = this.state.uploadsRes.data;
return (
<div>
<MediaUploads showUploader uploads={uploadsRes} />
<Paginator
page={this.state.uploadsPage}
onChange={this.handleUploadsPageChange}
nextDisabled={false}
/>
</div>
);
}
}
}
async handleEditSite(form: EditSite) { async handleEditSite(form: EditSite) {
this.setState({ loading: true }); this.setState({ loading: true });
@ -445,12 +344,10 @@ export class AdminSettings extends Component<
this.setState(s => { this.setState(s => {
s.siteRes.site_view = editRes.data.site_view; s.siteRes.site_view = editRes.data.site_view;
// TODO: Where to get taglines from? // TODO: Where to get taglines from?
s.siteRes.taglines = editRes.data.taglines;
return s; return s;
}); });
toast(I18NextService.i18n.t("site_saved")); toast(I18NextService.i18n.t("site_saved"));
// You need to reload the page, to properly update the siteRes everywhere
setTimeout(() => location.reload(), 500);
} }
this.setState({ loading: false }); this.setState({ loading: false });
@ -458,90 +355,40 @@ export class AdminSettings extends Component<
return editRes; return editRes;
} }
handleToggleShowLeaveAdminConfirmation() { handleSwitchTab(i: { ctx: AdminSettings; tab: string }) {
this.setState(prev => ({ i.ctx.setState({ currentTab: i.tab });
showConfirmLeaveAdmin: !prev.showConfirmLeaveAdmin,
}));
} }
async handleLeaveAdminTeam() { async handleLeaveAdminTeam(i: AdminSettings) {
this.setState({ leaveAdminTeamRes: LOADING_REQUEST }); i.setState({ leaveAdminTeamRes: LOADING_REQUEST });
this.setState({ this.setState({
leaveAdminTeamRes: await HttpService.client.leaveAdmin(), leaveAdminTeamRes: await HttpService.client.leaveAdmin(),
}); });
if (this.state.leaveAdminTeamRes.state === "success") { if (this.state.leaveAdminTeamRes.state === "success") {
toast(I18NextService.i18n.t("left_admin_team")); toast(I18NextService.i18n.t("left_admin_team"));
this.setState({ showConfirmLeaveAdmin: false });
this.context.router.history.replace("/"); this.context.router.history.replace("/");
} }
} }
async handleUploadsPageChange(val: number) { async handleEditEmoji(form: EditCustomEmoji) {
this.setState({ uploadsPage: val }); const res = await HttpService.client.editCustomEmoji(form);
snapToTop(); if (res.state === "success") {
await this.fetchUploadsOnly(); updateEmojiDataModel(res.data.custom_emoji);
}
} }
async handleEditOAuthProvider(form: EditOAuthProvider) { async handleDeleteEmoji(form: DeleteCustomEmoji) {
this.setState({ loading: true }); const res = await HttpService.client.deleteCustomEmoji(form);
const res = await HttpService.client.editOAuthProvider(form);
if (res.state === "success") { if (res.state === "success") {
const newOAuthProvider = res.data; removeFromEmojiDataModel(form.id);
this.setState(s => {
s.siteRes.admin_oauth_providers = (
s.siteRes.admin_oauth_providers ?? []
).map(p => {
return p?.id === newOAuthProvider.id ? newOAuthProvider : p;
});
return s;
});
toast(I18NextService.i18n.t("site_saved"));
} else {
toast(I18NextService.i18n.t("couldnt_edit_oauth_provider"), "danger");
} }
this.setState({ loading: false });
} }
async handleDeleteOAuthProvider(form: DeleteOAuthProvider) { async handleCreateEmoji(form: CreateCustomEmoji) {
this.setState({ loading: true }); const res = await HttpService.client.createCustomEmoji(form);
const res = await HttpService.client.deleteOAuthProvider(form);
if (res.state === "success") { if (res.state === "success") {
this.setState(s => { updateEmojiDataModel(res.data.custom_emoji);
s.siteRes.admin_oauth_providers = (
s.siteRes.admin_oauth_providers ?? []
).filter(p => p.id !== form.id);
return s;
});
toast(I18NextService.i18n.t("site_saved"));
} else {
toast(I18NextService.i18n.t("couldnt_delete_oauth_provider"), "danger");
} }
this.setState({ loading: false });
}
async handleCreateOAuthProvider(form: CreateOAuthProvider) {
this.setState({ loading: true });
const res = await HttpService.client.createOAuthProvider(form);
if (res.state === "success") {
this.setState(s => {
s.siteRes.admin_oauth_providers = [
...(s.siteRes.admin_oauth_providers ?? []),
res.data,
];
});
toast(I18NextService.i18n.t("site_saved"));
} else {
toast(I18NextService.i18n.t("couldnt_create_oauth_provider"), "danger");
}
this.setState({ loading: false });
} }
} }

View file

@ -1,81 +1,77 @@
import { setIsoData } from "@utils/app";
import { capitalizeFirstLetter } from "@utils/helpers"; import { capitalizeFirstLetter } from "@utils/helpers";
import { Component, linkEvent } from "inferno"; import { Component, linkEvent } from "inferno";
import { CustomEmojiView } from "lemmy-js-client"; import {
import { emojiMartCategories, EmojiMartCategory } from "../../markdown"; CreateCustomEmoji,
DeleteCustomEmoji,
EditCustomEmoji,
GetSiteResponse,
} from "lemmy-js-client";
import { customEmojisLookup } from "../../markdown";
import { HttpService, I18NextService } from "../../services"; import { HttpService, I18NextService } from "../../services";
import { pictrsDeleteToast, toast } from "../../toast"; import { pictrsDeleteToast, toast } from "../../toast";
import { EmojiMart } from "../common/emoji-mart"; import { EmojiMart } from "../common/emoji-mart";
import { Icon, Spinner } from "../common/icon"; import { Icon, Spinner } from "../common/icon";
import { Paginator } from "../common/paginator"; import { Paginator } from "../common/paginator";
import { tippyMixin } from "../mixins/tippy-mixin";
import { isBrowser } from "@utils/browser";
import classNames from "classnames";
import { amAdmin } from "@utils/roles";
import { Prompt } from "inferno-router";
interface EditableEmoji { interface EmojiFormProps {
change?: "update" | "delete" | "create"; onEdit(form: EditCustomEmoji): void;
emoji: CustomEmojiView; onCreate(form: CreateCustomEmoji): void;
loading?: boolean; onDelete(form: DeleteCustomEmoji): void;
}
function markForUpdate(editable: EditableEmoji) {
if (editable.change !== "create") {
editable.change = "update";
}
} }
interface EmojiFormState { interface EmojiFormState {
emojis: EditableEmoji[]; // Emojis for the current page siteRes: GetSiteResponse;
allEmojis: CustomEmojiView[]; // All emojis for emoji lookup across pages customEmojis: CustomEmojiViewForm[];
emojiMartCustom: EmojiMartCategory[]; page: number;
emojiMartKey: number; }
interface CustomEmojiViewForm {
id: number;
category: string;
shortcode: string;
image_url: string;
alt_text: string;
keywords: string;
changed: boolean;
page: number; page: number;
loading: boolean; loading: boolean;
} }
@tippyMixin export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
export class EmojiForm extends Component<Record<never, never>, EmojiFormState> { private isoData = setIsoData(this.context);
private itemsPerPage = 15; private itemsPerPage = 15;
private needsRefetch = true; private emptyState: EmojiFormState = {
state: EmojiFormState = { siteRes: this.isoData.site_res,
emojis: [], customEmojis: this.isoData.site_res.custom_emojis.map((x, index) => ({
allEmojis: [], id: x.custom_emoji.id,
emojiMartCustom: [], category: x.custom_emoji.category,
emojiMartKey: 1, shortcode: x.custom_emoji.shortcode,
loading: false, image_url: x.custom_emoji.image_url,
alt_text: x.custom_emoji.alt_text,
keywords: x.keywords.map(x => x.keyword).join(" "),
changed: false,
page: 1 + Math.floor(index / this.itemsPerPage),
loading: false,
})),
page: 1, page: 1,
}; };
state: EmojiFormState;
private scrollRef: any = {}; private scrollRef: any = {};
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.state = this.emptyState;
this.handlePageChange = this.handlePageChange.bind(this); this.handlePageChange = this.handlePageChange.bind(this);
this.handleEmojiClick = this.handleEmojiClick.bind(this); this.handleEmojiClick = this.handleEmojiClick.bind(this);
} }
async componentWillMount() {
if (isBrowser()) {
this.handlePageChange(1);
}
}
hasPendingChanges() {
return this.state.emojis.some(x => x.change);
}
render() { render() {
return ( return (
<div className="home-emojis-form col-12"> <div className="home-emojis-form col-12">
<Prompt
message={I18NextService.i18n.t("block_leaving")}
when={this.hasPendingChanges()}
/>
<h1 className="h4 mb-4">{I18NextService.i18n.t("custom_emojis")}</h1> <h1 className="h4 mb-4">{I18NextService.i18n.t("custom_emojis")}</h1>
{this.state.emojiMartCustom.length > 0 && ( {customEmojisLookup.size > 0 && (
<div> <div>
<EmojiMart <EmojiMart
key={this.state.emojiMartKey}
onEmojiClick={this.handleEmojiClick} onEmojiClick={this.handleEmojiClick}
pickerOptions={this.configurePicker()} pickerOptions={this.configurePicker()}
></EmojiMart> ></EmojiMart>
@ -89,10 +85,6 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
<thead className="pointer"> <thead className="pointer">
<tr> <tr>
<th>{I18NextService.i18n.t("column_emoji")}</th> <th>{I18NextService.i18n.t("column_emoji")}</th>
<th
className="text-right"
// Upload button
/>
<th className="text-right"> <th className="text-right">
{I18NextService.i18n.t("column_shortcode")} {I18NextService.i18n.t("column_shortcode")}
</th> </th>
@ -108,15 +100,20 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
<th className="text-right d-lg-table-cell"> <th className="text-right d-lg-table-cell">
{I18NextService.i18n.t("column_keywords")} {I18NextService.i18n.t("column_keywords")}
</th> </th>
<th></th>
<th style="width:121px"></th> <th style="width:121px"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{this.state.emojis.map((editable: EditableEmoji, index) => { {this.state.customEmojis
const cv = editable.emoji.custom_emoji; .slice(
return ( Number((this.state.page - 1) * this.itemsPerPage),
<tr key={index}> Number(
(this.state.page - 1) * this.itemsPerPage +
this.itemsPerPage,
),
)
.map((cv, index) => (
<tr key={index} ref={e => (this.scrollRef[cv.shortcode] = e)}>
<td style="text-align:center;"> <td style="text-align:center;">
{cv.image_url.length > 0 && ( {cv.image_url.length > 0 && (
<img <img
@ -125,9 +122,7 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
alt={cv.alt_text} alt={cv.alt_text}
/> />
)} )}
</td> {cv.image_url.length === 0 && (
<td>
{
<label <label
// TODO: Fix this linting violation // TODO: Fix this linting violation
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
@ -153,7 +148,7 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
)} )}
/> />
</label> </label>
} )}
</td> </td>
<td className="text-right"> <td className="text-right">
<input <input
@ -170,7 +165,6 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
</td> </td>
<td className="text-right"> <td className="text-right">
<input <input
ref={e => (this.scrollRef[cv.shortcode] = e)}
type="text" type="text"
placeholder="Category" placeholder="Category"
className="form-control" className="form-control"
@ -210,54 +204,31 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
type="text" type="text"
placeholder="Keywords" placeholder="Keywords"
className="form-control" className="form-control"
value={editable.emoji.keywords value={cv.keywords}
.map(k => k.keyword)
.join(" ")}
onInput={linkEvent( onInput={linkEvent(
{ form: this, index: index }, { form: this, index: index },
this.handleEmojiKeywordChange, this.handleEmojiKeywordChange,
)} )}
/> />
</td> </td>
<td
className={classNames("", {
"border-info": editable.change === "update",
"border-danger": editable.change === "delete",
"border-warning": editable.change === "create",
})}
>
{editable.change === "update" && (
<span>
<Icon icon="transfer" />
</span>
)}
{editable.change === "delete" && (
<span>
<Icon icon="trash" />
</span>
)}
{editable.change === "create" && (
<span>
<Icon icon="add" />
</span>
)}
</td>
<td> <td>
<div class="row flex-nowrap g-0"> <div>
<span class="col" title={this.getEditTooltip(editable)}> <span title={this.getEditTooltip(cv)}>
<button <button
className={classNames("btn btn-link btn-animate", { className={
"text-success": this.canSave(editable), (this.canEdit(cv)
})} ? "text-success "
: "text-muted ") + "btn btn-link btn-animate"
}
onClick={linkEvent( onClick={linkEvent(
{ i: this, cv: editable }, { i: this, cv: cv },
this.handleSaveEmojiClick, this.handleEditEmojiClick,
)} )}
data-tippy-content={I18NextService.i18n.t("save")} data-tippy-content={I18NextService.i18n.t("save")}
aria-label={I18NextService.i18n.t("save")} aria-label={I18NextService.i18n.t("save")}
disabled={!this.canSave(editable)} disabled={!this.canEdit(cv)}
> >
{editable.loading ? ( {cv.loading ? (
<Spinner /> <Spinner />
) : ( ) : (
capitalizeFirstLetter( capitalizeFirstLetter(
@ -267,14 +238,14 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
</button> </button>
</span> </span>
<button <button
className="col btn btn-link btn-animate text-muted" className="btn btn-link btn-animate text-muted"
onClick={linkEvent( onClick={linkEvent(
{ i: this, index: index, cv: editable }, { i: this, index: index, cv: cv },
this.handleDeleteEmojiClick, this.handleDeleteEmojiClick,
)} )}
data-tippy-content={I18NextService.i18n.t("delete")} data-tippy-content={I18NextService.i18n.t("delete")}
aria-label={I18NextService.i18n.t("delete")} aria-label={I18NextService.i18n.t("delete")}
disabled={editable.loading} disabled={cv.loading}
title={I18NextService.i18n.t("delete")} title={I18NextService.i18n.t("delete")}
> >
<Icon <Icon
@ -282,28 +253,10 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
classes="icon-inline text-danger" classes="icon-inline text-danger"
/> />
</button> </button>
<button
className={classNames(
"col btn btn-link btn-animate",
{
"text-danger": !!editable.change,
},
)}
onClick={linkEvent(
{ i: this, cv: editable },
this.handleCancelEmojiClick,
)}
data-tippy-content={I18NextService.i18n.t("cancel")}
aria-label={I18NextService.i18n.t("cancel")}
disabled={!editable.change}
>
{I18NextService.i18n.t("cancel")}
</button>
</div> </div>
</td> </td>
</tr> </tr>
); ))}
})}
</tbody> </tbody>
</table> </table>
<br /> <br />
@ -318,91 +271,43 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
page={this.state.page} page={this.state.page}
onChange={this.handlePageChange} onChange={this.handlePageChange}
nextDisabled={false} nextDisabled={false}
disabled={this.hasPendingChanges()}
/> />
</div> </div>
</div> </div>
); );
} }
canSave(cv: EditableEmoji) { canEdit(cv: CustomEmojiViewForm) {
const requiredFields = const noEmptyFields =
cv.emoji.custom_emoji.image_url.length > 0 && cv.alt_text.length > 0 &&
cv.emoji.custom_emoji.shortcode.length > 0; cv.category.length > 0 &&
return requiredFields && !cv.loading; cv.image_url.length > 0 &&
cv.shortcode.length > 0;
const noDuplicateShortCodes =
this.state.customEmojis.filter(
x => x.shortcode === cv.shortcode && x.id !== cv.id,
).length === 0;
return noEmptyFields && noDuplicateShortCodes && !cv.loading && cv.changed;
} }
getEditTooltip(cv: EditableEmoji) { getEditTooltip(cv: CustomEmojiViewForm) {
if (this.canSave(cv)) return I18NextService.i18n.t("save"); if (this.canEdit(cv)) return I18NextService.i18n.t("save");
else return I18NextService.i18n.t("custom_emoji_save_validation"); else return I18NextService.i18n.t("custom_emoji_save_validation");
} }
async handlePageChange(page: number) { handlePageChange(page: number) {
this.setState({ loading: true }); this.setState({ page: page });
let allEmojis: CustomEmojiView[] = this.state.allEmojis;
let emojiMartCustom: EmojiMartCategory[] = this.state.emojiMartCustom;
let emojiMartKey: number = this.state.emojiMartKey;
if (this.needsRefetch) {
const emojiRes = await HttpService.client.listCustomEmojis({
ignore_page_limits: true,
});
if (emojiRes.state === "success") {
this.needsRefetch = false;
allEmojis = emojiRes.data.custom_emojis;
allEmojis.sort((a, b) => {
const categoryOrder = a.custom_emoji.category.localeCompare(
b.custom_emoji.category,
);
if (categoryOrder === 0) {
return a.custom_emoji.shortcode.localeCompare(
b.custom_emoji.shortcode,
);
}
return categoryOrder;
});
}
emojiMartCustom = emojiMartCategories(allEmojis);
emojiMartKey++;
}
if (allEmojis) {
const startIndex = (page - 1) * this.itemsPerPage;
const emojis = allEmojis
.slice(startIndex, startIndex + this.itemsPerPage)
.map(x => ({ emoji: structuredClone(x) })); // clone for restore after cancel
this.setState({
loading: false,
allEmojis,
emojiMartCustom,
emojiMartKey,
emojis,
page,
});
} else {
this.setState({ loading: false, page });
}
} }
async handleEmojiClick(e: any) { handleEmojiClick(e: any) {
const emojiIndex = this.state.allEmojis.findIndex( const view = customEmojisLookup.get(e.id);
x => x.custom_emoji.shortcode === e.id, if (view) {
); const page = this.state.customEmojis.find(
if (emojiIndex >= 0) { x => x.id === view.custom_emoji.id,
const { shortcode } = this.state.allEmojis[emojiIndex].custom_emoji; )?.page;
const page = Math.floor(emojiIndex / this.itemsPerPage) + 1; if (page) {
if (page !== this.state.page) { this.setState({ page: page });
if ( this.scrollRef[view.custom_emoji.shortcode].scrollIntoView();
this.hasPendingChanges() &&
!confirm(I18NextService.i18n.t("block_leaving"))
) {
return;
}
await this.handlePageChange(page);
await new Promise(r => setTimeout(r));
}
if (shortcode) {
const categoryInput: HTMLInputElement | undefined =
this.scrollRef[shortcode];
categoryInput?.focus();
} }
} }
} }
@ -411,22 +316,32 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
props: { form: EmojiForm; index: number }, props: { form: EmojiForm; index: number },
event: any, event: any,
) { ) {
const editable: EditableEmoji = props.form.state.emojis[props.index]; const custom_emojis = [...props.form.state.customEmojis];
props.form.setState(() => { const pagedIndex =
markForUpdate(editable); (props.form.state.page - 1) * props.form.itemsPerPage + props.index;
editable.emoji.custom_emoji.category = event.target.value; const item = {
}); ...props.form.state.customEmojis[pagedIndex],
category: event.target.value,
changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
props.form.setState({ customEmojis: custom_emojis });
} }
handleEmojiShortCodeChange( handleEmojiShortCodeChange(
props: { form: EmojiForm; index: number }, props: { form: EmojiForm; index: number },
event: any, event: any,
) { ) {
const editable: EditableEmoji = props.form.state.emojis[props.index]; const custom_emojis = [...props.form.state.customEmojis];
props.form.setState(() => { const pagedIndex =
markForUpdate(editable); (props.form.state.page - 1) * props.form.itemsPerPage + props.index;
editable.emoji.custom_emoji.shortcode = event.target.value; const item = {
}); ...props.form.state.customEmojis[pagedIndex],
shortcode: event.target.value,
changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
props.form.setState({ customEmojis: custom_emojis });
} }
handleEmojiImageUrlChange( handleEmojiImageUrlChange(
@ -437,11 +352,28 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
}: { form: EmojiForm; index: number; overrideValue: string | null }, }: { form: EmojiForm; index: number; overrideValue: string | null },
event: any, event: any,
) { ) {
const editable: EditableEmoji = form.state.emojis[index]; form.setState(prevState => {
form.setState(() => { const custom_emojis = [...form.state.customEmojis];
markForUpdate(editable); const pagedIndex = (form.state.page - 1) * form.itemsPerPage + index;
editable.emoji.custom_emoji.image_url = const item = {
overrideValue ?? event.target.value; ...form.state.customEmojis[pagedIndex],
image_url: overrideValue ?? event.target.value,
changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
return {
...prevState,
customEmojis: prevState.customEmojis.map((ce, i) =>
i === pagedIndex
? {
...ce,
image_url: overrideValue ?? event.target.value,
changed: true,
loading: false,
}
: ce,
),
};
}); });
} }
@ -449,117 +381,97 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
props: { form: EmojiForm; index: number }, props: { form: EmojiForm; index: number },
event: any, event: any,
) { ) {
const editable: EditableEmoji = props.form.state.emojis[props.index]; const custom_emojis = [...props.form.state.customEmojis];
props.form.setState(() => { const pagedIndex =
markForUpdate(editable); (props.form.state.page - 1) * props.form.itemsPerPage + props.index;
editable.emoji.custom_emoji.alt_text = event.target.value; const item = {
}); ...props.form.state.customEmojis[pagedIndex],
alt_text: event.target.value,
changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
props.form.setState({ customEmojis: custom_emojis });
} }
handleEmojiKeywordChange( handleEmojiKeywordChange(
props: { form: EmojiForm; index: number }, props: { form: EmojiForm; index: number },
event: any, event: any,
) { ) {
const editable: EditableEmoji = props.form.state.emojis[props.index]; const custom_emojis = [...props.form.state.customEmojis];
props.form.setState(() => { const pagedIndex =
markForUpdate(editable); (props.form.state.page - 1) * props.form.itemsPerPage + props.index;
editable.emoji.keywords = event.target.value const item = {
.split(" ") ...props.form.state.customEmojis[pagedIndex],
.map((x: string) => ({ id: -1, keyword: x })); keywords: event.target.value,
}); changed: true,
};
custom_emojis[Number(pagedIndex)] = item;
props.form.setState({ customEmojis: custom_emojis });
} }
handleDeleteEmojiClick(d: { handleDeleteEmojiClick(d: {
i: EmojiForm; i: EmojiForm;
index: number; index: number;
cv: EditableEmoji; cv: CustomEmojiViewForm;
}) { }) {
if (d.cv.change === "create") { const pagedIndex = (d.i.state.page - 1) * d.i.itemsPerPage + d.index;
// This drops the entry immediately, other deletes have to be saved. if (d.cv.id !== 0) {
d.i.setState(prev => ({ d.i.props.onDelete({
emojis: prev.emojis.filter(x => x !== d.cv), id: d.cv.id,
})); });
} else { } else {
d.i.setState(() => { const custom_emojis = [...d.i.state.customEmojis];
d.cv.change = "delete"; custom_emojis.splice(Number(pagedIndex), 1);
d.i.setState({ customEmojis: custom_emojis });
}
}
handleEditEmojiClick(d: { i: EmojiForm; cv: CustomEmojiViewForm }) {
const keywords = d.cv.keywords
.split(" ")
.filter(x => x.length > 0) as string[];
const uniqueKeywords = Array.from(new Set(keywords));
if (d.cv.id !== 0) {
d.i.props.onEdit({
id: d.cv.id,
category: d.cv.category,
image_url: d.cv.image_url,
alt_text: d.cv.alt_text,
keywords: uniqueKeywords,
});
} else {
d.i.props.onCreate({
category: d.cv.category,
shortcode: d.cv.shortcode,
image_url: d.cv.image_url,
alt_text: d.cv.alt_text,
keywords: uniqueKeywords,
}); });
} }
} }
async handleSaveEmojiClick(d: { i: EmojiForm; cv: EditableEmoji }) { handleAddEmojiClick(form: EmojiForm, event: any) {
d.i.needsRefetch = true;
const editable = d.cv;
if (editable.change === "update") {
const resp = await HttpService.client.editCustomEmoji({
...editable.emoji.custom_emoji,
keywords: editable.emoji.keywords.map(x => x.keyword),
});
if (resp.state === "success") {
d.i.setState(() => {
editable.emoji = resp.data.custom_emoji;
editable.change = undefined;
});
}
} else if (editable.change === "delete") {
const resp = await HttpService.client.deleteCustomEmoji(
editable.emoji.custom_emoji,
);
if (resp.state === "success") {
d.i.setState(prev => ({
emojis: prev.emojis.filter(x => x !== editable),
}));
}
} else if (editable.change === "create") {
const resp = await HttpService.client.createCustomEmoji({
...editable.emoji.custom_emoji,
keywords: editable.emoji.keywords.map(x => x.keyword),
});
if (resp.state === "success") {
d.i.setState(() => {
editable.emoji = resp.data.custom_emoji;
editable.change = undefined;
});
}
}
}
async handleCancelEmojiClick(d: { i: EmojiForm; cv: EditableEmoji }) {
if (d.cv.change === "create") {
d.i.setState(() => {
return {
emojis: d.i.state.emojis.filter(x => x !== d.cv),
};
});
} else if (d.cv.change === "update" || d.cv.change === "delete") {
const original = d.i.state.allEmojis.find(
x => x.custom_emoji.id === d.cv.emoji.custom_emoji.id,
);
if (original) {
d.i.setState(() => {
d.cv.emoji = structuredClone(original);
d.cv.change = undefined;
});
}
}
}
async handleAddEmojiClick(form: EmojiForm, event: any) {
event.preventDefault(); event.preventDefault();
form.setState(prev => { form.setState(prevState => {
prev.emojis.push({ const page =
emoji: { 1 + Math.floor(prevState.customEmojis.length / form.itemsPerPage);
custom_emoji: { const item: CustomEmojiViewForm = {
id: -1, id: 0,
published: "", shortcode: "",
category: "", alt_text: "",
shortcode: "", category: "",
image_url: "", image_url: "",
alt_text: "", keywords: "",
}, changed: false,
keywords: [], page: page,
}, loading: false,
change: "create", };
});
return {
...prevState,
customEmojis: [...prevState.customEmojis, item],
page,
};
}); });
} }
@ -575,15 +487,16 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
file = event; file = event;
} }
const editable = form.state.emojis[index]; form.setState(prevState => ({
form.setState(() => { ...prevState,
editable.loading = true; customEmojis: prevState.customEmojis.map((cv, i) =>
}); i === index ? { ...cv, loading: true } : cv,
),
}));
HttpService.client.uploadImage({ image: file }).then(res => { HttpService.client.uploadImage({ image: file }).then(res => {
form.setState(() => { console.log("pictrs upload:");
editable.loading = false; console.log(res);
});
if (res.state === "success") { if (res.state === "success") {
if (res.data.msg === "ok") { if (res.data.msg === "ok") {
pictrsDeleteToast(file.name, res.data.delete_url as string); pictrsDeleteToast(file.name, res.data.delete_url as string);
@ -604,20 +517,10 @@ export class EmojiForm extends Component<Record<never, never>, EmojiFormState> {
} }
configurePicker(): any { configurePicker(): any {
const custom = this.state.emojiMartCustom;
if (process.env["NODE_ENV"] === "development") {
// Once an emoji-mart Picker is initialized with these options, other
// instances also only show the custom emojis.
console.assert(
amAdmin(),
"EmojiMart doesn't deal well with differently configured instances.",
);
}
return { return {
data: { categories: [], emojis: [], aliases: [] }, data: { categories: [], emojis: [], aliases: [] },
maxFrequentRows: 0, maxFrequentRows: 0,
dynamicWidth: true, dynamicWidth: true,
custom,
}; };
} }
} }

View file

@ -1,29 +1,28 @@
import { import {
commentsToFlatNodes, commentsToFlatNodes,
commentToPostSortType,
editComment, editComment,
editPost, editPost,
editWith, editWith,
enableDownvotes, enableDownvotes,
enableNsfw, enableNsfw,
getCommentParentId,
getDataTypeString, getDataTypeString,
myAuth, myAuth,
postToCommentSortType, postToCommentSortType,
setIsoData, setIsoData,
showLocal, showLocal,
updatePersonBlock, updatePersonBlock,
voteDisplayMode,
} from "@utils/app"; } from "@utils/app";
import { import {
getQueryParams, getQueryParams,
getQueryString, getQueryString,
resourcesSettled, getRandomFromList,
} from "@utils/helpers"; } from "@utils/helpers";
import { scrollMixin } from "../mixins/scroll-mixin"; import { canCreateCommunity } from "@utils/roles";
import type { QueryParams, StringBoolean } from "@utils/types"; import type { QueryParams } from "@utils/types";
import { RouteDataResponse } from "@utils/types"; import { RouteDataResponse } from "@utils/types";
import { NoOptionI18nKeys } from "i18next"; import { NoOptionI18nKeys } from "i18next";
import { Component, InfernoNode, MouseEventHandler, linkEvent } from "inferno"; import { Component, MouseEventHandler, linkEvent } from "inferno";
import { T } from "inferno-i18next-dess"; import { T } from "inferno-i18next-dess";
import { Link } from "inferno-router"; import { Link } from "inferno-router";
import { import {
@ -34,6 +33,7 @@ import {
BanPerson, BanPerson,
BanPersonResponse, BanPersonResponse,
BlockPerson, BlockPerson,
CommentId,
CommentReplyResponse, CommentReplyResponse,
CommentResponse, CommentResponse,
CreateComment, CreateComment,
@ -52,8 +52,9 @@ import {
GetPosts, GetPosts,
GetPostsResponse, GetPostsResponse,
GetSiteResponse, GetSiteResponse,
HidePost,
LemmyHttp, LemmyHttp,
ListCommunities,
ListCommunitiesResponse,
ListingType, ListingType,
LockPost, LockPost,
MarkCommentReplyAsRead, MarkCommentReplyAsRead,
@ -67,12 +68,11 @@ import {
RemovePost, RemovePost,
SaveComment, SaveComment,
SavePost, SavePost,
PostSortType, SortType,
SuccessResponse, SuccessResponse,
TransferCommunity, TransferCommunity,
CommentSortType,
} from "lemmy-js-client"; } from "lemmy-js-client";
import { fetchLimit, relTags } from "../../config"; import { fetchLimit, relTags, trendingFetchLimit } from "../../config";
import { import {
CommentViewType, CommentViewType,
DataType, DataType,
@ -87,7 +87,7 @@ import {
RequestState, RequestState,
wrapClient, wrapClient,
} from "../../services/HttpService"; } from "../../services/HttpService";
import { tippyMixin } from "../mixins/tippy-mixin"; import { setupTippy } from "../../tippy";
import { toast } from "../../toast"; import { toast } from "../../toast";
import { CommentNodes } from "../comment/comment-nodes"; import { CommentNodes } from "../comment/comment-nodes";
import { DataTypeSelect } from "../common/data-type-select"; import { DataTypeSelect } from "../common/data-type-select";
@ -103,38 +103,40 @@ import { getHttpBaseInternal } from "../../utils/env";
import { import {
CommentsLoadingSkeleton, CommentsLoadingSkeleton,
PostsLoadingSkeleton, PostsLoadingSkeleton,
TrendingCommunitiesLoadingSkeleton,
} from "../common/loading-skeleton"; } from "../common/loading-skeleton";
import { RouteComponentProps } from "inferno-router/dist/Route"; import { RouteComponentProps } from "inferno-router/dist/Route";
import { IRoutePropsWithFetch } from "../../routes"; import { IRoutePropsWithFetch } from "../../routes";
import PostHiddenSelect from "../common/post-hidden-select";
import { isBrowser, snapToTop } from "@utils/browser";
import { CommentSortSelect } from "../common/comment-sort-select";
interface HomeState { interface HomeState {
postsRes: RequestState<GetPostsResponse>; postsRes: RequestState<GetPostsResponse>;
commentsRes: RequestState<GetCommentsResponse>; commentsRes: RequestState<GetCommentsResponse>;
trendingCommunitiesRes: RequestState<ListCommunitiesResponse>;
showSubscribedMobile: boolean; showSubscribedMobile: boolean;
showTrendingMobile: boolean;
showSidebarMobile: boolean; showSidebarMobile: boolean;
subscribedCollapsed: boolean; subscribedCollapsed: boolean;
scrolled: boolean;
tagline?: string; tagline?: string;
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
finished: Map<CommentId, boolean | undefined>;
isIsomorphic: boolean; isIsomorphic: boolean;
} }
interface HomeProps { interface HomeProps {
listingType?: ListingType; listingType?: ListingType;
dataType: DataType; dataType: DataType;
sort: PostSortType; sort: SortType;
pageCursor?: PaginationCursor; pageCursor?: PaginationCursor;
showHidden?: StringBoolean;
} }
type HomeData = RouteDataResponse<{ type HomeData = RouteDataResponse<{
postsRes: GetPostsResponse; postsRes: GetPostsResponse;
commentsRes: GetCommentsResponse; commentsRes: GetCommentsResponse;
trendingCommunitiesRes: ListCommunitiesResponse;
}>; }>;
function getRss(listingType: ListingType, sort: PostSortType) { function getRss(listingType: ListingType, sort: SortType) {
let rss: string | undefined = undefined; let rss: string | undefined = undefined;
const queryString = getQueryString({ sort }); const queryString = getQueryString({ sort });
@ -179,13 +181,13 @@ function getListingTypeFromQuery(
function getSortTypeFromQuery( function getSortTypeFromQuery(
type: string | undefined, type: string | undefined,
fallback: PostSortType, fallback: SortType,
): PostSortType { ): SortType {
return type ? (type as PostSortType) : fallback; return type ? (type as SortType) : fallback;
} }
type Fallbacks = { type Fallbacks = {
sort: PostSortType; sort: SortType;
listingType: ListingType; listingType: ListingType;
}; };
@ -202,12 +204,10 @@ export function getHomeQueryParams(
listingType: getListingTypeFromQuery, listingType: getListingTypeFromQuery,
pageCursor: (cursor?: string) => cursor, pageCursor: (cursor?: string) => cursor,
dataType: getDataTypeFromQuery, dataType: getDataTypeFromQuery,
showHidden: (include?: StringBoolean) => include,
}, },
source, source,
{ {
sort: sort: local_user?.default_sort_type ?? local_site.default_sort_type,
local_user?.default_post_sort_type ?? local_site.default_post_sort_type,
listingType: listingType:
local_user?.default_listing_type ?? local_user?.default_listing_type ??
local_site.default_post_listing_type, local_site.default_post_listing_type,
@ -233,6 +233,18 @@ const MobileButton = ({
</button> </button>
); );
const LinkButton = ({
path,
translationKey,
}: {
path: string;
translationKey: NoOptionI18nKeys;
}) => (
<Link className="btn btn-secondary d-block" to={path}>
{I18NextService.i18n.t(translationKey)}
</Link>
);
type HomePathProps = Record<string, never>; type HomePathProps = Record<string, never>;
type HomeRouteProps = RouteComponentProps<HomePathProps> & HomeProps; type HomeRouteProps = RouteComponentProps<HomePathProps> & HomeProps;
export type HomeFetchConfig = IRoutePropsWithFetch< export type HomeFetchConfig = IRoutePropsWithFetch<
@ -241,36 +253,28 @@ export type HomeFetchConfig = IRoutePropsWithFetch<
HomeProps HomeProps
>; >;
@scrollMixin
@tippyMixin
export class Home extends Component<HomeRouteProps, HomeState> { export class Home extends Component<HomeRouteProps, HomeState> {
private isoData = setIsoData<HomeData>(this.context); private isoData = setIsoData<HomeData>(this.context);
state: HomeState = { state: HomeState = {
postsRes: EMPTY_REQUEST, postsRes: EMPTY_REQUEST,
commentsRes: EMPTY_REQUEST, commentsRes: EMPTY_REQUEST,
trendingCommunitiesRes: EMPTY_REQUEST,
scrolled: true,
siteRes: this.isoData.site_res, siteRes: this.isoData.site_res,
showSubscribedMobile: false, showSubscribedMobile: false,
showTrendingMobile: false,
showSidebarMobile: false, showSidebarMobile: false,
subscribedCollapsed: false, subscribedCollapsed: false,
finished: new Map(),
isIsomorphic: false, isIsomorphic: false,
}; };
loadingSettled(): boolean {
return resourcesSettled([
this.props.dataType === DataType.Post
? this.state.postsRes
: this.state.commentsRes,
]);
}
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.handleSortChange = this.handleSortChange.bind(this); this.handleSortChange = this.handleSortChange.bind(this);
this.handleCommentSortChange = this.handleCommentSortChange.bind(this);
this.handleListingTypeChange = this.handleListingTypeChange.bind(this); this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
this.handleDataTypeChange = this.handleDataTypeChange.bind(this); this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
this.handleShowHiddenChange = this.handleShowHiddenChange.bind(this);
this.handlePageNext = this.handlePageNext.bind(this); this.handlePageNext = this.handlePageNext.bind(this);
this.handlePagePrev = this.handlePagePrev.bind(this); this.handlePagePrev = this.handlePagePrev.bind(this);
@ -301,43 +305,41 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.handleSavePost = this.handleSavePost.bind(this); this.handleSavePost = this.handleSavePost.bind(this);
this.handlePurgePost = this.handlePurgePost.bind(this); this.handlePurgePost = this.handlePurgePost.bind(this);
this.handleFeaturePost = this.handleFeaturePost.bind(this); this.handleFeaturePost = this.handleFeaturePost.bind(this);
this.handleHidePost = this.handleHidePost.bind(this);
// Only fetch the data if coming from another route // Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) { if (FirstLoadService.isFirstLoad) {
const { commentsRes, postsRes } = this.isoData.routeData; const { trendingCommunitiesRes, commentsRes, postsRes } =
this.isoData.routeData;
this.state = { this.state = {
...this.state, ...this.state,
trendingCommunitiesRes,
commentsRes, commentsRes,
postsRes, postsRes,
isIsomorphic: true, isIsomorphic: true,
}; };
} }
this.state.tagline = this.state?.siteRes?.tagline?.content; this.state.tagline = getRandomFromList(
this.state?.siteRes?.taglines ?? [],
)?.content;
} }
async componentWillMount() { async componentDidMount() {
if ( if (
(!this.state.isIsomorphic || !this.state.isIsomorphic ||
!Object.values(this.isoData.routeData).some( !Object.values(this.isoData.routeData).some(
res => res.state === "success" || res.state === "failed", res => res.state === "success" || res.state === "failed",
)) && )
isBrowser()
) { ) {
await this.fetchData(this.props); await Promise.all([this.fetchTrendingCommunities(), this.fetchData()]);
} }
}
componentWillReceiveProps( setupTippy();
nextProps: HomeRouteProps & { children?: InfernoNode },
) {
this.fetchData(nextProps);
} }
static async fetchInitialData({ static async fetchInitialData({
query: { listingType, dataType, sort, pageCursor, showHidden }, query: { listingType, dataType, sort, pageCursor },
headers, headers,
}: InitialFetchRequest<HomePathProps, HomeProps>): Promise<HomeData> { }: InitialFetchRequest<HomePathProps, HomeProps>): Promise<HomeData> {
const client = wrapClient( const client = wrapClient(
@ -356,7 +358,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
limit: fetchLimit, limit: fetchLimit,
sort, sort,
saved_only: false, saved_only: false,
show_hidden: showHidden === "true",
}; };
postsFetch = client.getPosts(getPostsForm); postsFetch = client.getPosts(getPostsForm);
@ -371,12 +372,24 @@ export class Home extends Component<HomeRouteProps, HomeState> {
commentsFetch = client.getComments(getCommentsForm); commentsFetch = client.getComments(getCommentsForm);
} }
const [postsRes, commentsRes] = await Promise.all([ const trendingCommunitiesForm: ListCommunities = {
type_: "Local",
sort: "Hot",
limit: trendingFetchLimit,
};
const trendingCommunitiesFetch = client.listCommunities(
trendingCommunitiesForm,
);
const [postsRes, commentsRes, trendingCommunitiesRes] = await Promise.all([
postsFetch, postsFetch,
commentsFetch, commentsFetch,
trendingCommunitiesFetch,
]); ]);
return { return {
trendingCommunitiesRes,
commentsRes, commentsRes,
postsRes, postsRes,
}; };
@ -439,6 +452,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
admins, admins,
}, },
showSubscribedMobile, showSubscribedMobile,
showTrendingMobile,
showSidebarMobile, showSidebarMobile,
} = this.state; } = this.state;
@ -452,6 +466,11 @@ export class Home extends Component<HomeRouteProps, HomeState> {
onClick={linkEvent(this, this.handleShowSubscribedMobile)} onClick={linkEvent(this, this.handleShowSubscribedMobile)}
/> />
)} )}
<MobileButton
textKey="trending"
show={showTrendingMobile}
onClick={linkEvent(this, this.handleShowTrendingMobile)}
/>
<MobileButton <MobileButton
textKey="sidebar" textKey="sidebar"
show={showSidebarMobile} show={showSidebarMobile}
@ -466,6 +485,11 @@ export class Home extends Component<HomeRouteProps, HomeState> {
isMobile={true} isMobile={true}
/> />
)} )}
{showTrendingMobile && (
<div className="card border-secondary mb-3">
{this.trendingCommunities()}
</div>
)}
{showSubscribedMobile && ( {showSubscribedMobile && (
<div className="card border-secondary mb-3"> <div className="card border-secondary mb-3">
{this.subscribedCommunities(true)} {this.subscribedCommunities(true)}
@ -486,6 +510,9 @@ export class Home extends Component<HomeRouteProps, HomeState> {
return ( return (
<div id="sidebarContainer"> <div id="sidebarContainer">
<section id="sidebarMain" className="card border-secondary mb-3">
{this.trendingCommunities()}
</section>
<SiteSidebar <SiteSidebar
site={site} site={site}
admins={admins} admins={admins}
@ -506,6 +533,51 @@ export class Home extends Component<HomeRouteProps, HomeState> {
); );
} }
trendingCommunities() {
switch (this.state.trendingCommunitiesRes?.state) {
case "loading":
return <TrendingCommunitiesLoadingSkeleton itemCount={5} />;
case "success": {
const trending = this.state.trendingCommunitiesRes.data.communities;
return (
<>
<header className="card-header d-flex align-items-center">
<h5 className="mb-0">
<T i18nKey="trending_communities">
#
<Link className="text-body" to="/communities">
#
</Link>
</T>
</h5>
</header>
<div className="card-body">
{trending.length > 0 && (
<ul className="list-inline">
{trending.map(cv => (
<li key={cv.community.id} className="list-inline-item">
<CommunityLink community={cv.community} />
</li>
))}
</ul>
)}
{canCreateCommunity(this.state.siteRes) && (
<LinkButton
path="/create_community"
translationKey="create_a_community"
/>
)}
<LinkButton
path="/communities"
translationKey="explore_communities"
/>
</div>
</>
);
}
}
}
subscribedCommunities(isMobile = false) { subscribedCommunities(isMobile = false) {
const { subscribedCollapsed } = this.state; const { subscribedCollapsed } = this.state;
@ -571,23 +643,36 @@ export class Home extends Component<HomeRouteProps, HomeState> {
); );
} }
async updateUrl(props: Partial<HomeProps>) { async updateUrl({
const { dataType, listingType, pageCursor, sort, showHidden } = { dataType,
...this.props, listingType,
...props, pageCursor,
}; sort,
}: Partial<HomeProps>) {
const {
dataType: urlDataType,
listingType: urlListingType,
sort: urlSort,
} = this.props;
const queryParams: QueryParams<HomeProps> = { const queryParams: QueryParams<HomeProps> = {
dataType: getDataTypeString(dataType ?? DataType.Post), dataType: getDataTypeString(dataType ?? urlDataType),
listingType: listingType, listingType: listingType ?? urlListingType,
pageCursor: pageCursor, pageCursor: pageCursor,
sort: sort, sort: sort ?? urlSort,
showHidden: showHidden,
}; };
this.props.history.push({ this.props.history.push({
pathname: "/", pathname: "/",
search: getQueryString(queryParams), search: getQueryString(queryParams),
}); });
if (!this.state.scrolled) {
this.setState({ scrolled: true });
setTimeout(() => window.scrollTo(0, 0), 0);
}
await this.fetchData();
} }
get posts() { get posts() {
@ -629,7 +714,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
showCommunity showCommunity
removeDuplicates removeDuplicates
enableDownvotes={enableDownvotes(siteRes)} enableDownvotes={enableDownvotes(siteRes)}
voteDisplayMode={voteDisplayMode(siteRes)}
enableNsfw={enableNsfw(siteRes)} enableNsfw={enableNsfw(siteRes)}
allLanguages={siteRes.all_languages} allLanguages={siteRes.all_languages}
siteLanguages={siteRes.discussion_languages} siteLanguages={siteRes.discussion_languages}
@ -650,7 +734,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
onTransferCommunity={this.handleTransferCommunity} onTransferCommunity={this.handleTransferCommunity}
onFeaturePost={this.handleFeaturePost} onFeaturePost={this.handleFeaturePost}
onMarkPostAsRead={async () => {}} onMarkPostAsRead={async () => {}}
onHidePost={this.handleHidePost}
/> />
); );
} }
@ -665,11 +748,11 @@ export class Home extends Component<HomeRouteProps, HomeState> {
<CommentNodes <CommentNodes
nodes={commentsToFlatNodes(comments)} nodes={commentsToFlatNodes(comments)}
viewType={CommentViewType.Flat} viewType={CommentViewType.Flat}
finished={this.state.finished}
isTopLevel isTopLevel
showCommunity showCommunity
showContext showContext
enableDownvotes={enableDownvotes(siteRes)} enableDownvotes={enableDownvotes(siteRes)}
voteDisplayMode={voteDisplayMode(siteRes)}
allLanguages={siteRes.all_languages} allLanguages={siteRes.all_languages}
siteLanguages={siteRes.discussion_languages} siteLanguages={siteRes.discussion_languages}
onSaveComment={this.handleSaveComment} onSaveComment={this.handleSaveComment}
@ -698,7 +781,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
} }
get selects() { get selects() {
const { listingType, dataType, sort, showHidden } = this.props; const { listingType, dataType, sort } = this.props;
return ( return (
<div className="row align-items-center mb-3 g-3"> <div className="row align-items-center mb-3 g-3">
@ -708,14 +791,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
onChange={this.handleDataTypeChange} onChange={this.handleDataTypeChange}
/> />
</div> </div>
{dataType === DataType.Post && UserService.Instance.myUserInfo && (
<div className="col-auto">
<PostHiddenSelect
showHidden={showHidden}
onShowHiddenChange={this.handleShowHiddenChange}
/>
</div>
)}
<div className="col-auto"> <div className="col-auto">
<ListingTypeSelect <ListingTypeSelect
type_={ type_={
@ -728,14 +803,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
/> />
</div> </div>
<div className="col-auto"> <div className="col-auto">
{this.props.dataType === DataType.Post ? ( <SortSelect sort={sort} onChange={this.handleSortChange} />
<SortSelect sort={sort} onChange={this.handleSortChange} />
) : (
<CommentSortSelect
sort={postToCommentSortType(sort)}
onChange={this.handleCommentSortChange}
/>
)}
</div> </div>
<div className="col-auto ps-0"> <div className="col-auto ps-0">
{getRss( {getRss(
@ -748,46 +816,54 @@ export class Home extends Component<HomeRouteProps, HomeState> {
); );
} }
fetchDataToken?: symbol; async fetchTrendingCommunities() {
async fetchData({ this.setState({ trendingCommunitiesRes: LOADING_REQUEST });
dataType, this.setState({
pageCursor, trendingCommunitiesRes: await HttpService.client.listCommunities({
listingType, type_: "Local",
sort, sort: "Hot",
showHidden, limit: trendingFetchLimit,
}: HomeProps) { }),
const token = (this.fetchDataToken = Symbol()); });
}
async fetchData() {
const { dataType, pageCursor, listingType, sort } = this.props;
if (dataType === DataType.Post) { if (dataType === DataType.Post) {
this.setState({ postsRes: LOADING_REQUEST, commentsRes: EMPTY_REQUEST }); this.setState({ postsRes: LOADING_REQUEST });
const postsRes = await HttpService.client.getPosts({ this.setState({
page_cursor: pageCursor, postsRes: await HttpService.client.getPosts({
limit: fetchLimit, page_cursor: pageCursor,
sort, limit: fetchLimit,
saved_only: false, sort,
type_: listingType, saved_only: false,
show_hidden: showHidden === "true", type_: listingType,
}),
}); });
if (token === this.fetchDataToken) {
this.setState({ postsRes });
}
} else { } else {
this.setState({ commentsRes: LOADING_REQUEST, postsRes: EMPTY_REQUEST }); this.setState({ commentsRes: LOADING_REQUEST });
const commentsRes = await HttpService.client.getComments({ this.setState({
limit: fetchLimit, commentsRes: await HttpService.client.getComments({
sort: postToCommentSortType(sort), limit: fetchLimit,
saved_only: false, sort: postToCommentSortType(sort),
type_: listingType, saved_only: false,
type_: listingType,
}),
}); });
if (token === this.fetchDataToken) {
this.setState({ commentsRes });
}
} }
setupTippy();
} }
handleShowSubscribedMobile(i: Home) { handleShowSubscribedMobile(i: Home) {
i.setState({ showSubscribedMobile: !i.state.showSubscribedMobile }); i.setState({ showSubscribedMobile: !i.state.showSubscribedMobile });
} }
handleShowTrendingMobile(i: Home) {
i.setState({ showTrendingMobile: !i.state.showTrendingMobile });
}
handleShowSidebarMobile(i: Home) { handleShowSidebarMobile(i: Home) {
i.setState({ showSidebarMobile: !i.state.showSidebarMobile }); i.setState({ showSidebarMobile: !i.state.showSidebarMobile });
} }
@ -800,37 +876,30 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.props.history.back(); this.props.history.back();
// A hack to scroll to top // A hack to scroll to top
setTimeout(() => { setTimeout(() => {
snapToTop(); window.scrollTo(0, 0);
}, 50); }, 50);
} }
handlePageNext(nextPage: PaginationCursor) { handlePageNext(nextPage: PaginationCursor) {
this.setState({ scrolled: false });
this.updateUrl({ pageCursor: nextPage }); this.updateUrl({ pageCursor: nextPage });
} }
handleSortChange(val: PostSortType) { handleSortChange(val: SortType) {
this.setState({ scrolled: false });
this.updateUrl({ sort: val, pageCursor: undefined }); this.updateUrl({ sort: val, pageCursor: undefined });
} }
handleCommentSortChange(val: CommentSortType) {
this.updateUrl({ sort: commentToPostSortType(val), pageCursor: undefined });
}
handleListingTypeChange(val: ListingType) { handleListingTypeChange(val: ListingType) {
this.setState({ scrolled: false });
this.updateUrl({ listingType: val, pageCursor: undefined }); this.updateUrl({ listingType: val, pageCursor: undefined });
} }
handleDataTypeChange(val: DataType) { handleDataTypeChange(val: DataType) {
this.setState({ scrolled: false });
this.updateUrl({ dataType: val, pageCursor: undefined }); this.updateUrl({ dataType: val, pageCursor: undefined });
} }
handleShowHiddenChange(show?: StringBoolean) {
this.updateUrl({
showHidden: show,
pageCursor: undefined,
});
}
async handleAddModToCommunity(form: AddModToCommunity) { async handleAddModToCommunity(form: AddModToCommunity) {
// TODO not sure what to do here // TODO not sure what to do here
await HttpService.client.addModToCommunity(form); await HttpService.client.addModToCommunity(form);
@ -862,9 +931,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
const createCommentRes = await HttpService.client.createComment(form); const createCommentRes = await HttpService.client.createComment(form);
this.createAndUpdateComments(createCommentRes); this.createAndUpdateComments(createCommentRes);
if (createCommentRes.state === "failed") {
toast(I18NextService.i18n.t(createCommentRes.err.message), "danger");
}
return createCommentRes; return createCommentRes;
} }
@ -872,9 +938,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
const editCommentRes = await HttpService.client.editComment(form); const editCommentRes = await HttpService.client.editComment(form);
this.findAndUpdateCommentEdit(editCommentRes); this.findAndUpdateCommentEdit(editCommentRes);
if (editCommentRes.state === "failed") {
toast(I18NextService.i18n.t(editCommentRes.err.message), "danger");
}
return editCommentRes; return editCommentRes;
} }
@ -987,26 +1050,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.updateBan(banRes); this.updateBan(banRes);
} }
async handleHidePost(form: HidePost) {
const hideRes = await HttpService.client.hidePost(form);
if (hideRes.state === "success") {
this.setState(prev => {
if (prev.postsRes.state === "success") {
for (const post of prev.postsRes.data.posts.filter(p =>
form.post_ids.some(id => id === p.post.id),
)) {
post.hidden = form.hide;
}
}
return prev;
});
toast(I18NextService.i18n.t(form.hide ? "post_hidden" : "post_unhidden"));
}
}
updateBanFromCommunity(banRes: RequestState<BanFromCommunityResponse>) { updateBanFromCommunity(banRes: RequestState<BanFromCommunityResponse>) {
// Maybe not necessary // Maybe not necessary
if (banRes.state === "success") { if (banRes.state === "success") {
@ -1063,6 +1106,7 @@ export class Home extends Component<HomeRouteProps, HomeState> {
res.data.comment_view, res.data.comment_view,
s.commentsRes.data.comments, s.commentsRes.data.comments,
); );
s.finished.set(res.data.comment_view.comment.id, true);
} }
return s; return s;
}); });
@ -1084,6 +1128,12 @@ export class Home extends Component<HomeRouteProps, HomeState> {
this.setState(s => { this.setState(s => {
if (s.commentsRes.state === "success" && res.state === "success") { if (s.commentsRes.state === "success" && res.state === "success") {
s.commentsRes.data.comments.unshift(res.data.comment_view); s.commentsRes.data.comments.unshift(res.data.comment_view);
// Set finished for the parent
s.finished.set(
getCommentParentId(res.data.comment_view.comment) ?? 0,
true,
);
} }
return s; return s;
}); });

View file

@ -24,9 +24,6 @@ import Tabs from "../common/tabs";
import { getHttpBaseInternal } from "../../utils/env"; import { getHttpBaseInternal } from "../../utils/env";
import { RouteComponentProps } from "inferno-router/dist/Route"; import { RouteComponentProps } from "inferno-router/dist/Route";
import { IRoutePropsWithFetch } from "../../routes"; import { IRoutePropsWithFetch } from "../../routes";
import { resourcesSettled } from "@utils/helpers";
import { scrollMixin } from "../mixins/scroll-mixin";
import { isBrowser } from "@utils/browser";
type InstancesData = RouteDataResponse<{ type InstancesData = RouteDataResponse<{
federatedInstancesResponse: GetFederatedInstancesResponse; federatedInstancesResponse: GetFederatedInstancesResponse;
@ -46,7 +43,6 @@ export type InstancesFetchConfig = IRoutePropsWithFetch<
Record<string, never> Record<string, never>
>; >;
@scrollMixin
export class Instances extends Component<InstancesRouteProps, InstancesState> { export class Instances extends Component<InstancesRouteProps, InstancesState> {
private isoData = setIsoData<InstancesData>(this.context); private isoData = setIsoData<InstancesData>(this.context);
state: InstancesState = { state: InstancesState = {
@ -55,10 +51,6 @@ export class Instances extends Component<InstancesRouteProps, InstancesState> {
isIsomorphic: false, isIsomorphic: false,
}; };
loadingSettled() {
return resourcesSettled([this.state.instancesRes]);
}
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
@ -72,8 +64,8 @@ export class Instances extends Component<InstancesRouteProps, InstancesState> {
} }
} }
async componentWillMount() { async componentDidMount() {
if (!this.state.isIsomorphic && isBrowser()) { if (!this.state.isIsomorphic) {
await this.fetchInstances(); await this.fetchInstances();
} }
} }

View file

@ -6,8 +6,6 @@ import { HttpService, I18NextService } from "../../services";
import { toast } from "../../toast"; import { toast } from "../../toast";
import { HtmlTags } from "../common/html-tags"; import { HtmlTags } from "../common/html-tags";
import { Spinner } from "../common/icon"; import { Spinner } from "../common/icon";
import { simpleScrollMixin } from "../mixins/scroll-mixin";
import { RouteComponentProps } from "inferno-router/dist/Route";
interface State { interface State {
form: { form: {
@ -17,11 +15,7 @@ interface State {
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
} }
@simpleScrollMixin export class LoginReset extends Component<any, State> {
export class LoginReset extends Component<
RouteComponentProps<Record<string, never>>,
State
> {
private isoData = setIsoData(this.context); private isoData = setIsoData(this.context);
state: State = { state: State = {

View file

@ -3,12 +3,7 @@ import { isBrowser, refreshTheme } from "@utils/browser";
import { getQueryParams } from "@utils/helpers"; import { getQueryParams } from "@utils/helpers";
import { Component, linkEvent } from "inferno"; import { Component, linkEvent } from "inferno";
import { RouteComponentProps } from "inferno-router/dist/Route"; import { RouteComponentProps } from "inferno-router/dist/Route";
import { import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
GetSiteResponse,
LoginResponse,
OAuthProvider,
PublicOAuthProvider,
} from "lemmy-js-client";
import { I18NextService, UserService } from "../../services"; import { I18NextService, UserService } from "../../services";
import { import {
EMPTY_REQUEST, EMPTY_REQUEST,
@ -20,11 +15,10 @@ import { toast } from "../../toast";
import { HtmlTags } from "../common/html-tags"; import { HtmlTags } from "../common/html-tags";
import { Spinner } from "../common/icon"; import { Spinner } from "../common/icon";
import PasswordInput from "../common/password-input"; import PasswordInput from "../common/password-input";
import TotpModal from "../common/modal/totp-modal"; import TotpModal from "../common/totp-modal";
import { UnreadCounterService } from "../../services"; import { UnreadCounterService } from "../../services";
import { RouteData } from "../../interfaces"; import { RouteData } from "../../interfaces";
import { IRoutePropsWithFetch } from "../../routes"; import { IRoutePropsWithFetch } from "../../routes";
import { simpleScrollMixin } from "../mixins/scroll-mixin";
interface LoginProps { interface LoginProps {
prev?: string; prev?: string;
@ -47,7 +41,6 @@ interface State {
}; };
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
show2faModal: boolean; show2faModal: boolean;
showOAuthModal: boolean;
} }
async function handleLoginSuccess(i: Login, loginRes: LoginResponse) { async function handleLoginSuccess(i: Login, loginRes: LoginResponse) {
@ -58,21 +51,16 @@ async function handleLoginSuccess(i: Login, loginRes: LoginResponse) {
if (site.state === "success") { if (site.state === "success") {
UserService.Instance.myUserInfo = site.data.my_user; UserService.Instance.myUserInfo = site.data.my_user;
const isoData = setIsoData(i.context);
isoData.site_res.oauth_providers = site.data.oauth_providers;
isoData.site_res.admin_oauth_providers = site.data.admin_oauth_providers;
refreshTheme(); refreshTheme();
} }
const { prev } = i.props; const { prev } = i.props;
if (prev) { prev
i.props.history.replace(prev); ? i.props.history.replace(prev)
} else if (i.props.history.action === "PUSH") { : i.props.history.action === "PUSH"
i.props.history.back(); ? i.props.history.back()
} else { : i.props.history.replace("/");
i.props.history.replace("/");
}
UnreadCounterService.Instance.updateAll(); UnreadCounterService.Instance.updateAll();
} }
@ -116,45 +104,6 @@ async function handleLoginSubmit(i: Login, event: any) {
} }
} }
export async function handleUseOAuthProvider(params: {
oauth_provider: OAuthProvider;
username?: string;
prev?: string;
answer?: string;
show_nsfw?: boolean;
}) {
const redirectUri = `${window.location.origin}/oauth/callback`;
const state = crypto.randomUUID();
const requestUri =
params.oauth_provider.authorization_endpoint +
"?" +
[
`client_id=${encodeURIComponent(params.oauth_provider.client_id)}`,
`response_type=code`,
`scope=${encodeURIComponent(params.oauth_provider.scopes)}`,
`redirect_uri=${encodeURIComponent(redirectUri)}`,
`state=${state}`,
].join("&");
// store state in local storage
localStorage.setItem(
"oauth_state",
JSON.stringify({
state,
oauth_provider_id: params.oauth_provider.id,
redirect_uri: redirectUri,
prev: params.prev ?? "/",
username: params.username,
answer: params.answer,
show_nsfw: params.show_nsfw,
expires_at: Date.now() + 5 * 60_000,
}),
);
window.location.assign(requestUri);
}
function handleLoginUsernameChange(i: Login, event: any) { function handleLoginUsernameChange(i: Login, event: any) {
i.setState( i.setState(
prevState => (prevState.form.username_or_email = event.target.value.trim()), prevState => (prevState.form.username_or_email = event.target.value.trim()),
@ -176,7 +125,6 @@ export type LoginFetchConfig = IRoutePropsWithFetch<
LoginProps LoginProps
>; >;
@simpleScrollMixin
export class Login extends Component<LoginRouteProps, State> { export class Login extends Component<LoginRouteProps, State> {
private isoData = setIsoData(this.context); private isoData = setIsoData(this.context);
@ -188,14 +136,12 @@ export class Login extends Component<LoginRouteProps, State> {
}, },
siteRes: this.isoData.site_res, siteRes: this.isoData.site_res,
show2faModal: false, show2faModal: false,
showOAuthModal: false,
}; };
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.handleSubmitTotp = this.handleSubmitTotp.bind(this); this.handleSubmitTotp = this.handleSubmitTotp.bind(this);
this.handleLoginWithProvider = this.handleLoginWithProvider.bind(this);
} }
get documentTitle(): string { get documentTitle(): string {
@ -224,35 +170,6 @@ export class Login extends Component<LoginRouteProps, State> {
<div className="row"> <div className="row">
<div className="col-12 col-lg-6 offset-lg-3">{this.loginForm()}</div> <div className="col-12 col-lg-6 offset-lg-3">{this.loginForm()}</div>
</div> </div>
{(this.state.siteRes.oauth_providers?.length || 0) > 0 && (
<>
<div className="row mt-3 mb-2">
<div className="col-12 col-lg-6 offset-lg-3">
{I18NextService.i18n.t("or")}
</div>
</div>
<div className="row">
<div className="col col-12 col-lgl6 offset-lg-3">
<h2 className="h4 mb-3">
{I18NextService.i18n.t("oauth_login_with_provider")}
</h2>
{(this.state.siteRes.oauth_providers ?? []).map(
(provider: PublicOAuthProvider) => (
<button
className="btn btn-primary my-2 d-block"
onClick={linkEvent(
{ oauth_provider: provider },
this.handleLoginWithProvider,
)}
>
{provider.display_name}
</button>
),
)}
</div>
</div>
</>
)}
</div> </div>
); );
} }
@ -275,13 +192,6 @@ export class Login extends Component<LoginRouteProps, State> {
return successful; return successful;
} }
async handleLoginWithProvider(params: { oauth_provider: OAuthProvider }) {
handleUseOAuthProvider({
oauth_provider: params.oauth_provider,
prev: this.props.prev ?? "/",
});
}
loginForm() { loginForm() {
return ( return (
<div> <div>

View file

@ -1,175 +0,0 @@
import { setIsoData } from "@utils/app";
import { Component } from "inferno";
import { refreshTheme } from "@utils/browser";
import { GetSiteResponse, LoginResponse } from "lemmy-js-client";
import { Spinner } from "../../common/icon";
import { getQueryParams } from "@utils/helpers";
import { IRoutePropsWithFetch } from "../../../routes";
import { RouteData } from "../../../interfaces";
import { I18NextService, UserService } from "../../../services";
import { RouteComponentProps } from "inferno-router/dist/Route";
import { UnreadCounterService } from "../../../services";
import { HttpService } from "../../../services/HttpService";
import { toast } from "../../../toast";
interface OAuthCallbackProps {
code?: string;
state?: string;
}
export function getOAuthCallbackQueryParams(
source?: string,
): OAuthCallbackProps {
return getQueryParams<OAuthCallbackProps>(
{
code: (code?: string) => code,
state: (state?: string) => state,
},
source,
);
}
type OAuthCallbackRouteProps = RouteComponentProps<Record<string, never>> &
OAuthCallbackProps;
export type OAuthCallbackConfig = IRoutePropsWithFetch<
RouteData,
Record<string, never>,
OAuthCallbackProps
>;
interface State {
siteRes: GetSiteResponse;
}
export class OAuthCallback extends Component<OAuthCallbackRouteProps, State> {
private isoData = setIsoData(this.context);
state: State = {
siteRes: this.isoData.site_res,
};
constructor(props: any, context: any) {
super(props, context);
}
async componentDidMount() {
// store state in local storage
const local_oauth_state = JSON.parse(
localStorage.getItem("oauth_state") || "{}",
);
if (
!(
this.props.state &&
this.props.code &&
local_oauth_state?.state &&
local_oauth_state?.oauth_provider_id &&
local_oauth_state?.expires_at &&
this.props.state === local_oauth_state.state
) ||
local_oauth_state.expires_at < Date.now()
) {
// oauth failed or expired
toast(I18NextService.i18n.t("oauth_authorization_invalid"), "danger");
this.props.history.replace("/login");
} else {
const loginRes = await HttpService.client.authenticateWithOAuth({
code: this.props.code,
oauth_provider_id: local_oauth_state.oauth_provider_id,
redirect_uri: local_oauth_state.redirect_uri,
show_nsfw: local_oauth_state.show_nsfw,
username: local_oauth_state.username,
answer: local_oauth_state.answer,
});
switch (loginRes.state) {
case "success": {
if (loginRes.data.jwt) {
handleOAuthLoginSuccess(
this,
local_oauth_state.prev,
loginRes.data,
);
} else {
if (loginRes.data.verify_email_sent) {
toast(I18NextService.i18n.t("verify_email_sent"));
}
if (loginRes.data.registration_created) {
toast(I18NextService.i18n.t("registration_application_sent"));
}
this.props.history.push("/login");
}
break;
}
case "failed": {
let err_redirect = "/login";
switch (loginRes.err.message) {
case "registration_username_required":
case "registration_application_answer_required":
err_redirect = `/signup?sso_provider_id=${local_oauth_state.oauth_provider_id}`;
toast(I18NextService.i18n.t(loginRes.err.message), "danger");
break;
case "registration_application_is_pending":
toast(
I18NextService.i18n.t("registration_application_pending"),
"danger",
);
break;
case "registration_denied":
case "oauth_authorization_invalid":
case "oauth_login_failed":
case "oauth_registration_closed":
case "email_already_exists":
case "username_already_exists":
case "no_email_setup":
toast(I18NextService.i18n.t(loginRes.err.message), "danger");
break;
default:
toast(I18NextService.i18n.t("incorrect_login"), "danger");
break;
}
this.props.history.push(err_redirect);
}
}
}
}
get documentTitle(): string {
return `${I18NextService.i18n.t("login")} - ${
this.state.siteRes.site_view.site.name
}`;
}
render() {
return (
<div className="container-lg">
<Spinner />
</div>
);
}
}
async function handleOAuthLoginSuccess(
i: OAuthCallback,
prev: string,
loginRes: LoginResponse,
) {
UserService.Instance.login({
res: loginRes,
});
const site = await HttpService.client.getSite();
if (site.state === "success") {
UserService.Instance.myUserInfo = site.data.my_user;
refreshTheme();
}
if (prev) {
i.props.history.replace(prev);
} else if (i.props.history.action === "PUSH") {
i.props.history.back();
} else {
i.props.history.replace("/");
}
UnreadCounterService.Instance.updateAll();
}

View file

@ -1,98 +0,0 @@
import { OAuthProvider } from "lemmy-js-client";
import { I18NextService } from "../../../services/I18NextService";
import { Icon } from "../../common/icon";
import { MouseEventHandler } from "inferno";
type OAuthProviderListItemProps = {
provider: OAuthProvider;
onEdit: MouseEventHandler<HTMLButtonElement>;
onDelete: MouseEventHandler<HTMLButtonElement>;
};
type TextInfoFieldProps = {
i18nKey: string;
data: string;
};
function TextInfoField({ i18nKey, data }: TextInfoFieldProps) {
return (
<div className="col overflow-auto">
<dt>{I18NextService.i18n.t(i18nKey)}</dt>
<dd className="text-truncate">{data}</dd>
</div>
);
}
function boolToYesNo(value?: boolean) {
return I18NextService.i18n.t(value ? "yes" : "no");
}
export default function OAuthProviderListItem({
provider,
onEdit,
onDelete,
}: OAuthProviderListItemProps) {
return (
<li className="oauth-item list-group-item">
<details>
<summary className="d-flex justify-content-between align-items-center">
<div className="fw-semibold">
<Icon icon="caret-right" classes="oauth-item-caret me-1" />
{provider.display_name}
</div>
<div>
<button
className="d-inline-block btn btn-outline-secondary me-2"
onClick={onEdit}
>
<Icon icon="edit" classes="me-1" />
{I18NextService.i18n.t("edit")}
</button>
<button
className="d-inline-block btn btn-outline-danger"
onClick={onDelete}
>
<Icon icon="trash" classes="me-1" />
{I18NextService.i18n.t("delete")}
</button>
</div>
</summary>
<div className="container">
<dl className="row row-cols-1 row-cols-sm-2 row-cols-md-3">
<TextInfoField i18nKey="oauth_issuer" data={provider.issuer} />
<TextInfoField
i18nKey="oauth_authorization_endpoint"
data={provider.authorization_endpoint}
/>
<TextInfoField
i18nKey="oauth_token_endpoint"
data={provider.token_endpoint}
/>
<TextInfoField
i18nKey="oauth_userinfo_endpoint"
data={provider.userinfo_endpoint}
/>
<TextInfoField i18nKey="oauth_id_claim" data={provider.id_claim} />
<TextInfoField
i18nKey="oauth_client_id"
data={provider.client_id}
/>
<TextInfoField i18nKey="oauth_scopes" data={provider.scopes} />
<TextInfoField
i18nKey="oauth_auto_verify_email"
data={boolToYesNo(provider.auto_verify_email)}
/>
<TextInfoField
i18nKey="oauth_account_linking_enabled"
data={boolToYesNo(provider.account_linking_enabled)}
/>
<TextInfoField
i18nKey="oauth_enabled"
data={boolToYesNo(provider.enabled)}
/>
</dl>
</div>
</details>
</li>
);
}

View file

@ -1,204 +0,0 @@
import { Component, linkEvent } from "inferno";
import { I18NextService } from "../../../services/I18NextService";
import {
CreateOAuthProvider,
DeleteOAuthProvider,
EditOAuthProvider,
OAuthProvider,
} from "lemmy-js-client";
import OAuthProviderListItem from "./oauth-provider-list-item";
import CreateOrEditOAuthProviderModal, {
CreateOrEditOAuthProviderModalData,
} from "../../common/modal/create-or-edit-oauth-provider-modal";
import ConfirmationModal from "../../common/modal/confirmation-modal";
import { ProviderToEdit } from "@utils/types/oauth";
type OAuthProvidersTabProps = {
oauthProviders: OAuthProvider[];
onEdit(form: EditOAuthProvider): Promise<void>;
onCreate(form: CreateOAuthProvider): Promise<void>;
onDelete(form: DeleteOAuthProvider): Promise<void>;
};
type OAuthProvidersTabState = {
providerToDelete?: OAuthProvider;
createOrEditModalData?: CreateOrEditOAuthProviderModalData;
};
const PRESET_OAUTH_PROVIDERS: ProviderToEdit[] = [
{
display_name: "Privacy Portal",
issuer: "https://api.privacyportal.org/",
authorization_endpoint: "https://app.privacyportal.org/oauth/authorize",
token_endpoint: "https://api.privacyportal.org/oauth/token",
userinfo_endpoint: "https://api.privacyportal.org/oauth/userinfo",
id_claim: "sub",
scopes: "openid email",
auto_verify_email: true,
account_linking_enabled: true,
enabled: true,
},
// additional preset providers can be added here
];
function handleShowCreateOrEditProviderModal({
data,
tab,
}: {
tab: OAuthProvidersTab;
data: CreateOrEditOAuthProviderModalData;
}) {
tab.setState({
createOrEditModalData: data,
});
}
function handleCloseCreateOrEditModal(tab: OAuthProvidersTab) {
tab.setState({
createOrEditModalData: undefined,
});
}
function handleTryDeleteOauthProvider({
tab,
provider,
}: {
tab: OAuthProvidersTab;
provider: OAuthProvider;
}) {
tab.setState({ providerToDelete: provider });
}
function handleCloseDeleteConfirmationModal(tab: OAuthProvidersTab) {
tab.setState({ providerToDelete: undefined });
}
export default class OAuthProvidersTab extends Component<
OAuthProvidersTabProps,
OAuthProvidersTabState
> {
state: OAuthProvidersTabState = {};
constructor(props: OAuthProvidersTabProps, context: any) {
super(props, context);
this.handleDeleteProvider = this.handleDeleteProvider.bind(this);
this.handleCreateOrEditProviderSubmit =
this.handleCreateOrEditProviderSubmit.bind(this);
}
render(
{ oauthProviders }: Readonly<OAuthProvidersTabProps>,
{
providerToDelete,
createOrEditModalData,
}: Readonly<OAuthProvidersTabState>,
) {
return (
<div className="oauth-providers-tab">
<h1 className="h4 mb-4">{I18NextService.i18n.t("oauth_config")}</h1>
{oauthProviders.length > 0 ? (
<>
<h2 className="h5 mb-2">
{I18NextService.i18n.t("oauth_providers")}
</h2>
<ul className="list-group">
{oauthProviders.map(provider => (
<OAuthProviderListItem
provider={provider}
key={provider.id}
onEdit={linkEvent(
{ data: { type: "edit", provider }, tab: this },
handleShowCreateOrEditProviderModal,
)}
onDelete={linkEvent(
{ provider, tab: this },
handleTryDeleteOauthProvider,
)}
/>
))}
</ul>
</>
) : (
<div>{I18NextService.i18n.t("no_oauth_providers_blurb")}</div>
)}
<button
type="button"
className="btn btn-secondary btn-small mt-3"
onClick={linkEvent(
{ data: { type: "add" }, tab: this },
handleShowCreateOrEditProviderModal,
)}
>
{I18NextService.i18n.t("add_oauth_provider")}
</button>
{PRESET_OAUTH_PROVIDERS.length > 0 && (
<section className="default-oauth-providers-section mt-4">
<h2 className="h5 mb-3">
{I18NextService.i18n.t("oauth_provider_presets")}
</h2>
<ul className="d-flex flex-wrap gap-3 ps-0">
{PRESET_OAUTH_PROVIDERS.map(provider => {
const isAlreadyUsed = oauthProviders.some(
p => p.issuer === provider.issuer,
);
return (
<li key={provider.issuer}>
<button
className="btn btn-secondary btn-small"
disabled={isAlreadyUsed}
onClick={linkEvent(
{ data: { type: "add", provider }, tab: this },
handleShowCreateOrEditProviderModal,
)}
>
{provider.display_name}
</button>
</li>
);
})}
</ul>
</section>
)}
<CreateOrEditOAuthProviderModal
show={!!createOrEditModalData}
onClose={linkEvent(this, handleCloseCreateOrEditModal)}
onSubmit={this.handleCreateOrEditProviderSubmit}
data={createOrEditModalData ?? { type: "add" }}
/>
<ConfirmationModal
show={!!providerToDelete}
message={I18NextService.i18n.t("delete_oauth_provider_are_you_sure")}
loadingMessage={I18NextService.i18n.t("deleting_oauth_provider")}
onNo={linkEvent(this, handleCloseDeleteConfirmationModal)}
onYes={this.handleDeleteProvider}
/>
</div>
);
}
async handleDeleteProvider() {
const id = this.state.providerToDelete?.id;
if (id !== undefined) {
await this.props.onDelete({ id });
}
this.setState({ providerToDelete: undefined });
}
async handleCreateOrEditProviderSubmit(
provider: CreateOAuthProvider | EditOAuthProvider,
) {
if (this.state.createOrEditModalData?.type === "edit") {
await this.props.onEdit(provider as EditOAuthProvider);
} else {
await this.props.onCreate(provider as CreateOAuthProvider);
}
this.setState({
createOrEditModalData: undefined,
});
}
}

View file

@ -3,7 +3,7 @@ import classNames from "classnames";
import { Component, FormEventHandler, linkEvent } from "inferno"; import { Component, FormEventHandler, linkEvent } from "inferno";
import { EditSite, LocalSiteRateLimit } from "lemmy-js-client"; import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
import { I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { Icon, Spinner } from "../common/icon"; import { Spinner } from "../common/icon";
import Tabs from "../common/tabs"; import Tabs from "../common/tabs";
const rateLimitTypes = [ const rateLimitTypes = [
@ -144,10 +144,6 @@ export default class RateLimitsForm extends Component<
<h1 className="h4 mb-4"> <h1 className="h4 mb-4">
{I18NextService.i18n.t("rate_limit_header")} {I18NextService.i18n.t("rate_limit_header")}
</h1> </h1>
<div className="alert small alert-info" role="alert">
<Icon icon="info" classes="icon-inline me-2" />
{I18NextService.i18n.t("rate_limit_info")}
</div>
<Tabs <Tabs
tabs={rateLimitTypes.map(rateLimitType => ({ tabs={rateLimitTypes.map(rateLimitType => ({
key: rateLimitType, key: rateLimitType,

View file

@ -17,9 +17,6 @@ import {
import { Spinner } from "../common/icon"; import { Spinner } from "../common/icon";
import PasswordInput from "../common/password-input"; import PasswordInput from "../common/password-input";
import { SiteForm } from "./site-form"; import { SiteForm } from "./site-form";
import { simpleScrollMixin } from "../mixins/scroll-mixin";
import { RouteComponentProps } from "inferno-router/dist/Route";
import { isBrowser } from "@utils/browser";
interface State { interface State {
form: { form: {
@ -39,11 +36,7 @@ interface State {
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
} }
@simpleScrollMixin export class Setup extends Component<any, State> {
export class Setup extends Component<
RouteComponentProps<Record<string, never>>,
State
> {
private isoData = setIsoData(this.context); private isoData = setIsoData(this.context);
state: State = { state: State = {
@ -62,10 +55,8 @@ export class Setup extends Component<
this.handleCreateSite = this.handleCreateSite.bind(this); this.handleCreateSite = this.handleCreateSite.bind(this);
} }
async componentWillMount() { async componentDidMount() {
if (isBrowser()) { this.setState({ themeList: await fetchThemeList() });
this.setState({ themeList: await fetchThemeList() });
}
} }
get documentTitle(): string { get documentTitle(): string {

View file

@ -1,7 +1,6 @@
import { setIsoData } from "@utils/app"; import { setIsoData } from "@utils/app";
import { isBrowser } from "@utils/browser"; import { isBrowser } from "@utils/browser";
import { getQueryParams, resourcesSettled, validEmail } from "@utils/helpers"; import { validEmail } from "@utils/helpers";
import { scrollMixin } from "../mixins/scroll-mixin";
import { Component, linkEvent } from "inferno"; import { Component, linkEvent } from "inferno";
import { T } from "inferno-i18next-dess"; import { T } from "inferno-i18next-dess";
import { import {
@ -11,7 +10,7 @@ import {
LoginResponse, LoginResponse,
SiteView, SiteView,
} from "lemmy-js-client"; } from "lemmy-js-client";
import { joinLemmyUrl, validActorRegexPattern } from "../../config"; import { joinLemmyUrl } from "../../config";
import { mdToHtml } from "../../markdown"; import { mdToHtml } from "../../markdown";
import { I18NextService, UserService } from "../../services"; import { I18NextService, UserService } from "../../services";
import { import {
@ -25,14 +24,6 @@ import { HtmlTags } from "../common/html-tags";
import { Icon, Spinner } from "../common/icon"; import { Icon, Spinner } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea"; import { MarkdownTextArea } from "../common/markdown-textarea";
import PasswordInput from "../common/password-input"; import PasswordInput from "../common/password-input";
import { RouteComponentProps } from "inferno-router/dist/Route";
import { RouteData } from "../../interfaces";
import { IRoutePropsWithFetch } from "../../routes";
import { handleUseOAuthProvider } from "./login";
interface SignupProps {
sso_provider_id?: string;
}
interface State { interface State {
registerRes: RequestState<LoginResponse>; registerRes: RequestState<LoginResponse>;
@ -52,25 +43,7 @@ interface State {
siteRes: GetSiteResponse; siteRes: GetSiteResponse;
} }
export function getSignupQueryParams(source?: string): SignupProps { export class Signup extends Component<any, State> {
return getQueryParams<SignupProps>(
{
sso_provider_id: (param?: string) => param,
},
source,
);
}
type SignupRouteProps = RouteComponentProps<Record<string, never>> &
SignupProps;
export type SignupFetchConfig = IRoutePropsWithFetch<
RouteData,
Record<string, never>,
SignupProps
>;
@scrollMixin
export class Signup extends Component<SignupRouteProps, State> {
private isoData = setIsoData(this.context); private isoData = setIsoData(this.context);
private audio?: HTMLAudioElement; private audio?: HTMLAudioElement;
@ -78,30 +51,20 @@ export class Signup extends Component<SignupRouteProps, State> {
registerRes: EMPTY_REQUEST, registerRes: EMPTY_REQUEST,
captchaRes: EMPTY_REQUEST, captchaRes: EMPTY_REQUEST,
form: { form: {
show_nsfw: !!this.isoData.site_res.site_view.site.content_warning, show_nsfw: false,
}, },
captchaPlaying: false, captchaPlaying: false,
siteRes: this.isoData.site_res, siteRes: this.isoData.site_res,
}; };
loadingSettled() {
return (
!this.state.siteRes.site_view.local_site.captcha_enabled ||
resourcesSettled([this.state.captchaRes])
);
}
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.handleAnswerChange = this.handleAnswerChange.bind(this); this.handleAnswerChange = this.handleAnswerChange.bind(this);
} }
async componentWillMount() { async componentDidMount() {
if ( if (this.state.siteRes.site_view.local_site.captcha_enabled) {
this.state.siteRes.site_view.local_site.captcha_enabled &&
isBrowser()
) {
await this.fetchCaptcha(); await this.fetchCaptcha();
} }
} }
@ -153,8 +116,6 @@ export class Signup extends Component<SignupRouteProps, State> {
registerForm() { registerForm() {
const siteView = this.state.siteRes.site_view; const siteView = this.state.siteRes.site_view;
const oauth_provider = getOAuthProvider(this);
return ( return (
<form <form
className="was-validated" className="was-validated"
@ -189,85 +150,63 @@ export class Signup extends Component<SignupRouteProps, State> {
onInput={linkEvent(this, this.handleRegisterUsernameChange)} onInput={linkEvent(this, this.handleRegisterUsernameChange)}
required required
minLength={3} minLength={3}
pattern={validActorRegexPattern} pattern="[a-zA-Z0-9_]+"
title={I18NextService.i18n.t("community_reqs")} title={I18NextService.i18n.t("community_reqs")}
/> />
</div> </div>
</div> </div>
{!oauth_provider && ( <div className="mb-3 row">
<> <label className="col-sm-2 col-form-label" htmlFor="register-email">
{ {I18NextService.i18n.t("email")}
<div className="mb-3 row"> </label>
<label <div className="col-sm-10">
className="col-sm-2 col-form-label" <input
htmlFor="register-email" type="email"
> id="register-email"
{I18NextService.i18n.t("email")} className="form-control"
</label> placeholder={
<div className="col-sm-10"> siteView.local_site.require_email_verification
<input ? I18NextService.i18n.t("required")
type="email" : I18NextService.i18n.t("optional")
id="register-email" }
className="form-control" value={this.state.form.email}
placeholder={ autoComplete="email"
siteView.local_site.require_email_verification onInput={linkEvent(this, this.handleRegisterEmailChange)}
? I18NextService.i18n.t("required") required={siteView.local_site.require_email_verification}
: I18NextService.i18n.t("optional") minLength={3}
} />
value={this.state.form.email} {!siteView.local_site.require_email_verification &&
autoComplete="email" this.state.form.email &&
onInput={linkEvent(this, this.handleRegisterEmailChange)} !validEmail(this.state.form.email) && (
required={siteView.local_site.require_email_verification} <div className="mt-2 mb-0 alert alert-warning" role="alert">
minLength={3} <Icon icon="alert-triangle" classes="icon-inline me-2" />
/> {I18NextService.i18n.t("no_password_reset")}
{!siteView.local_site.require_email_verification &&
this.state.form.email &&
!validEmail(this.state.form.email) && (
<div
className="mt-2 mb-0 alert alert-warning"
role="alert"
>
<Icon
icon="alert-triangle"
classes="icon-inline me-2"
/>
{I18NextService.i18n.t("no_password_reset")}
</div>
)}
</div> </div>
</div> )}
} </div>
</div>
{ <div className="mb-3">
<div className="mb-3"> <PasswordInput
<PasswordInput id="register-password"
id="register-password" value={this.state.form.password}
value={this.state.form.password} onInput={linkEvent(this, this.handleRegisterPasswordChange)}
onInput={linkEvent(this, this.handleRegisterPasswordChange)} showStrength
showStrength label={I18NextService.i18n.t("password")}
label={I18NextService.i18n.t("password")} isNew
isNew />
/> </div>
</div>
}
{ <div className="mb-3">
<div className="mb-3"> <PasswordInput
<PasswordInput id="register-verify-password"
id="register-verify-password" value={this.state.form.password_verify}
value={this.state.form.password_verify} onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
onInput={linkEvent( label={I18NextService.i18n.t("verify_password")}
this, isNew
this.handleRegisterPasswordVerifyChange, />
)} </div>
label={I18NextService.i18n.t("verify_password")}
isNew
/>
</div>
}
</>
)}
{siteView.local_site.registration_mode === "RequireApplication" && ( {siteView.local_site.registration_mode === "RequireApplication" && (
<> <>
@ -341,12 +280,7 @@ export class Signup extends Component<SignupRouteProps, State> {
{this.state.registerRes.state === "loading" ? ( {this.state.registerRes.state === "loading" ? (
<Spinner /> <Spinner />
) : ( ) : (
[ this.titleName(siteView)
this.titleName(siteView),
...(oauth_provider
? [`(${oauth_provider.display_name})`]
: []),
].join(" ")
)} )}
</button> </button>
</div> </div>
@ -439,19 +373,6 @@ export class Signup extends Component<SignupRouteProps, State> {
password_verify, password_verify,
username, username,
} = i.state.form; } = i.state.form;
const oauthProvider = getOAuthProvider(i);
// oauth registration
if (username && oauthProvider)
return handleUseOAuthProvider({
oauth_provider: oauthProvider,
username,
answer,
show_nsfw,
});
// normal registration
if (username && password && password_verify) { if (username && password && password_verify) {
i.setState({ registerRes: LOADING_REQUEST }); i.setState({ registerRes: LOADING_REQUEST });
@ -579,9 +500,3 @@ export class Signup extends Component<SignupRouteProps, State> {
return `data:image/png;base64,${captcha.png}`; return `data:image/png;base64,${captcha.png}`;
} }
} }
function getOAuthProvider(signup: Signup) {
return (signup.state.siteRes.oauth_providers ?? []).find(
provider => provider.id === Number(signup.props?.sso_provider_id ?? -1),
);
}

View file

@ -2,6 +2,7 @@ import { capitalizeFirstLetter, validInstanceTLD } from "@utils/helpers";
import { import {
Component, Component,
InfernoKeyboardEvent, InfernoKeyboardEvent,
InfernoMouseEvent,
InfernoNode, InfernoNode,
linkEvent, linkEvent,
} from "inferno"; } from "inferno";
@ -20,7 +21,6 @@ import { ImageUploadForm } from "../common/image-upload-form";
import { LanguageSelect } from "../common/language-select"; import { LanguageSelect } from "../common/language-select";
import { ListingTypeSelect } from "../common/listing-type-select"; import { ListingTypeSelect } from "../common/listing-type-select";
import { MarkdownTextArea } from "../common/markdown-textarea"; import { MarkdownTextArea } from "../common/markdown-textarea";
import UrlListTextarea from "../common/url-list-textarea";
interface SiteFormProps { interface SiteFormProps {
blockedInstances?: Instance[]; blockedInstances?: Instance[];
@ -63,7 +63,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
description: site.description, description: site.description,
enable_downvotes: ls.enable_downvotes, enable_downvotes: ls.enable_downvotes,
registration_mode: ls.registration_mode, registration_mode: ls.registration_mode,
oauth_registration: ls.oauth_registration, enable_nsfw: ls.enable_nsfw,
community_creation_admin_only: ls.community_creation_admin_only, community_creation_admin_only: ls.community_creation_admin_only,
icon: site.icon, icon: site.icon,
banner: site.banner, banner: site.banner,
@ -84,8 +84,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
captcha_difficulty: ls.captcha_difficulty, captcha_difficulty: ls.captcha_difficulty,
allowed_instances: this.props.allowedInstances?.map(i => i.domain), allowed_instances: this.props.allowedInstances?.map(i => i.domain),
blocked_instances: this.props.blockedInstances?.map(i => i.domain), blocked_instances: this.props.blockedInstances?.map(i => i.domain),
blocked_urls: this.props.siteRes.blocked_urls.map(u => u.url),
content_warning: this.props.siteRes.site_view.site.content_warning,
}; };
} }
@ -114,10 +112,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
this.handleInstanceEnterPress = this.handleInstanceEnterPress.bind(this); this.handleInstanceEnterPress = this.handleInstanceEnterPress.bind(this);
this.handleInstanceTextChange = this.handleInstanceTextChange.bind(this); this.handleInstanceTextChange = this.handleInstanceTextChange.bind(this);
this.handleBlockedUrlsUpdate = this.handleBlockedUrlsUpdate.bind(this);
this.handleSiteContentWarningChange =
this.handleSiteContentWarningChange.bind(this);
} }
render() { render() {
@ -271,26 +265,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
</div> </div>
</div> </div>
</div> </div>
{this.state.siteForm.enable_nsfw && (
<div className="mb-3 row">
<div className="alert small alert-info" role="alert">
<Icon icon="info" classes="icon-inline me-2" />
{I18NextService.i18n.t("content_warning_setting_blurb")}
</div>
<label className="col-12 col-form-label">
{I18NextService.i18n.t("content_warning")}
</label>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.content_warning}
onContentChange={this.handleSiteContentWarningChange}
hideNavigationWarnings
allLanguages={[]}
siteLanguages={[]}
/>
</div>
</div>
)}
<div className="mb-3 row"> <div className="mb-3 row">
<div className="col-12"> <div className="col-12">
<label <label
@ -333,25 +307,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
</div> </div>
</div> </div>
)} )}
<div className="mb-3 row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-oauth-registration"
type="checkbox"
checked={this.state.siteForm.oauth_registration}
onChange={linkEvent(this, this.handleSiteOauthRegistration)}
/>
<label
className="form-check-label"
htmlFor="create-site-oauth-registration"
>
{I18NextService.i18n.t("oauth_registration")}
</label>
</div>
</div>
</div>
<div className="mb-3 row"> <div className="mb-3 row">
<div className="col-12"> <div className="col-12">
<div className="form-check"> <div className="form-check">
@ -545,10 +500,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
onChange={this.handleDiscussionLanguageChange} onChange={this.handleDiscussionLanguageChange}
showAll showAll
/> />
<UrlListTextarea
urls={this.state.siteForm.blocked_urls ?? []}
onUpdate={this.handleBlockedUrlsUpdate}
/>
<div className="mb-3 row"> <div className="mb-3 row">
<label <label
className="col-12 col-form-label" className="col-12 col-form-label"
@ -801,7 +752,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
enable_downvotes: stateSiteForm.enable_downvotes, enable_downvotes: stateSiteForm.enable_downvotes,
application_question: stateSiteForm.application_question, application_question: stateSiteForm.application_question,
registration_mode: stateSiteForm.registration_mode, registration_mode: stateSiteForm.registration_mode,
oauth_registration: stateSiteForm.oauth_registration,
require_email_verification: stateSiteForm.require_email_verification, require_email_verification: stateSiteForm.require_email_verification,
private_instance: stateSiteForm.private_instance, private_instance: stateSiteForm.private_instance,
default_theme: stateSiteForm.default_theme, default_theme: stateSiteForm.default_theme,
@ -897,6 +847,42 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
this.setState(s => ((s.siteForm.legal_information = val), s)); this.setState(s => ((s.siteForm.legal_information = val), s));
} }
handleTaglineChange(i: SiteForm, index: number, val: string) {
const taglines = i.state.siteForm.taglines;
if (taglines) {
taglines[index] = val;
i.setState(i.state);
}
}
handleDeleteTaglineClick(
i: SiteForm,
index: number,
event: InfernoMouseEvent<HTMLButtonElement>,
) {
event.preventDefault();
const taglines = i.state.siteForm.taglines;
if (taglines) {
taglines.splice(index, 1);
i.state.siteForm.taglines = undefined;
i.setState(i.state);
i.state.siteForm.taglines = taglines;
i.setState(i.state);
}
}
handleAddTaglineClick(
i: SiteForm,
event: InfernoMouseEvent<HTMLButtonElement>,
) {
event.preventDefault();
if (!i.state.siteForm.taglines) {
i.state.siteForm.taglines = [];
}
i.state.siteForm.taglines.push("");
i.setState(i.state);
}
handleSiteApplicationQuestionChange(val: string) { handleSiteApplicationQuestionChange(val: string) {
this.setState(s => ((s.siteForm.application_question = val), s)); this.setState(s => ((s.siteForm.application_question = val), s));
} }
@ -916,11 +902,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
i.setState(i.state); i.setState(i.state);
} }
handleSiteOauthRegistration(i: SiteForm, event: any) {
i.state.siteForm.oauth_registration = event.target.checked;
i.setState(i.state);
}
handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) { handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) {
i.state.siteForm.community_creation_admin_only = event.target.checked; i.state.siteForm.community_creation_admin_only = event.target.checked;
i.setState(i.state); i.setState(i.state);
@ -1013,18 +994,4 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
handleDefaultPostListingTypeChange(val: ListingType) { handleDefaultPostListingTypeChange(val: ListingType) {
this.setState(s => ((s.siteForm.default_post_listing_type = val), s)); this.setState(s => ((s.siteForm.default_post_listing_type = val), s));
} }
handleBlockedUrlsUpdate(newBlockedUrls: string[]) {
this.setState(prev => ({
...prev,
siteForm: {
...prev.siteForm,
blocked_urls: newBlockedUrls,
},
}));
}
handleSiteContentWarningChange(val: string) {
this.setState(s => ((s.siteForm.content_warning = val), s));
}
} }

View file

@ -7,7 +7,6 @@ import { Badges } from "../common/badges";
import { BannerIconHeader } from "../common/banner-icon-header"; import { BannerIconHeader } from "../common/banner-icon-header";
import { Icon } from "../common/icon"; import { Icon } from "../common/icon";
import { PersonListing } from "../person/person-listing"; import { PersonListing } from "../person/person-listing";
import { tippyMixin } from "../mixins/tippy-mixin";
interface SiteSidebarProps { interface SiteSidebarProps {
site: Site; site: Site;
@ -21,7 +20,6 @@ interface SiteSidebarState {
collapsed: boolean; collapsed: boolean;
} }
@tippyMixin
export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> { export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
state: SiteSidebarState = { state: SiteSidebarState = {
collapsed: false, collapsed: false,

View file

@ -1,84 +1,47 @@
import { capitalizeFirstLetter } from "@utils/helpers"; import { capitalizeFirstLetter } from "@utils/helpers";
import { Component, InfernoMouseEvent, linkEvent } from "inferno"; import { Component, InfernoMouseEvent, linkEvent } from "inferno";
import { Tagline } from "lemmy-js-client"; import { EditSite, Tagline } from "lemmy-js-client";
import { HttpService, I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { Icon, Spinner } from "../common/icon"; import { Icon, Spinner } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea"; import { MarkdownTextArea } from "../common/markdown-textarea";
import { tippyMixin } from "../mixins/tippy-mixin";
import { Paginator } from "../common/paginator";
import classNames from "classnames";
import { isBrowser } from "@utils/browser";
import { Prompt } from "inferno-router";
interface EditableTagline { interface TaglineFormProps {
change?: "update" | "delete" | "create"; taglines: Array<Tagline>;
editMode?: boolean; onSaveSite(form: EditSite): void;
tagline: Tagline;
}
function markForUpdate(editable: EditableTagline) {
if (editable.change !== "create") {
editable.change = "update";
}
}
interface TaglineFormState {
taglines: Array<EditableTagline>;
page: number;
loading: boolean; loading: boolean;
} }
@tippyMixin interface TaglineFormState {
export class TaglineForm extends Component< taglines: Array<string>;
Record<never, never>, editingRow?: number;
TaglineFormState }
> {
export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
state: TaglineFormState = { state: TaglineFormState = {
taglines: [], editingRow: undefined,
page: 1, taglines: this.props.taglines.map(x => x.content),
loading: false,
}; };
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.handlePageChange = this.handlePageChange.bind(this);
}
componentWillMount(): void {
if (isBrowser()) {
this.handlePageChange(1);
}
}
hasPendingChanges(): boolean {
return this.state.taglines.some(x => x.change);
} }
render() { render() {
return ( return (
<div className="tagline-form col-12"> <div className="tagline-form col-12">
<Prompt
message={I18NextService.i18n.t("block_leaving")}
when={this.hasPendingChanges()}
/>
<h1 className="h4 mb-4">{I18NextService.i18n.t("taglines")}</h1> <h1 className="h4 mb-4">{I18NextService.i18n.t("taglines")}</h1>
<div className="table-responsive col-12"> <div className="table-responsive col-12">
<table <table id="taglines_table" className="table table-sm table-hover">
id="taglines_table"
className="table table-sm table-hover align-middle"
>
<thead className="pointer"> <thead className="pointer">
<th></th> <th></th>
<th style="width:60px"></th>
<th style="width:121px"></th> <th style="width:121px"></th>
</thead> </thead>
<tbody> <tbody>
{this.state.taglines.map((cv, index) => ( {this.state.taglines.map((cv, index) => (
<tr key={index}> <tr key={index}>
<td> <td>
{cv.editMode ? ( {this.state.editingRow === index && (
<MarkdownTextArea <MarkdownTextArea
initialContent={cv.tagline.content} initialContent={cv}
focus={true}
onContentChange={s => onContentChange={s =>
this.handleTaglineChange(this, index, s) this.handleTaglineChange(this, index, s)
} }
@ -86,32 +49,8 @@ export class TaglineForm extends Component<
allLanguages={[]} allLanguages={[]}
siteLanguages={[]} siteLanguages={[]}
/> />
) : (
<div>{cv.tagline.content}</div>
)}
</td>
<td
className={classNames("text-center", {
"border-info": cv.change === "update",
"border-danger": cv.change === "delete",
"border-warning": cv.change === "create",
})}
>
{cv.change === "update" && (
<span>
<Icon icon="transfer" />
</span>
)}
{cv.change === "delete" && (
<span>
<Icon icon="trash" />
</span>
)}
{cv.change === "create" && (
<span>
<Icon icon="add" inline />
</span>
)} )}
{this.state.editingRow !== index && <div>{cv}</div>}
</td> </td>
<td className="text-right"> <td className="text-right">
<button <button
@ -158,153 +97,65 @@ export class TaglineForm extends Component<
<button <button
onClick={linkEvent(this, this.handleSaveClick)} onClick={linkEvent(this, this.handleSaveClick)}
className="btn btn-secondary me-2" className="btn btn-secondary me-2"
disabled={this.state.loading || !this.hasPendingChanges()} disabled={this.props.loading}
> >
{this.state.loading ? ( {this.props.loading ? (
<Spinner /> <Spinner />
) : ( ) : (
capitalizeFirstLetter(I18NextService.i18n.t("save")) capitalizeFirstLetter(I18NextService.i18n.t("save"))
)} )}
</button> </button>
{this.hasPendingChanges() && (
<button
onClick={linkEvent(this, this.handleCancelClick)}
className="btn btn-secondary me-2"
>
{I18NextService.i18n.t("cancel")}
</button>
)}
</div> </div>
</div> </div>
<div>
<Paginator
page={this.state.page}
onChange={this.handlePageChange}
nextDisabled={false}
disabled={this.hasPendingChanges()}
/>
</div>
</div> </div>
</div> </div>
); );
} }
handleTaglineChange(i: TaglineForm, index: number, val: string) { handleTaglineChange(i: TaglineForm, index: number, val: string) {
const editable = i.state.taglines[index]; if (i.state.taglines) {
i.setState(() => { i.setState(prev => ({
markForUpdate(editable); ...prev,
const tagline: Tagline = editable.tagline; taglines: prev.taglines.map((tl, i) => (i === index ? val : tl)),
tagline.content = val; }));
}); }
} }
async handleDeleteTaglineClick( handleDeleteTaglineClick(d: { i: TaglineForm; index: number }, event: any) {
d: { i: TaglineForm; index: number },
event: any,
) {
event.preventDefault(); event.preventDefault();
const editable = d.i.state.taglines[d.index]; d.i.setState(prev => ({
if (editable.change === "create") { ...prev,
// This drops the entry immediately, other deletes have to be saved. taglines: prev.taglines.filter((_, i) => i !== d.index),
d.i.setState(prev => { editingRow: undefined,
return { taglines: prev.taglines.filter(x => x !== editable) }; }));
});
} else {
d.i.setState(() => {
editable.change = "delete";
editable.editMode = false;
});
}
} }
handleEditTaglineClick(d: { i: TaglineForm; index: number }, event: any) { handleEditTaglineClick(d: { i: TaglineForm; index: number }, event: any) {
event.preventDefault(); event.preventDefault();
const editable = d.i.state.taglines[d.index]; if (d.i.state.editingRow === d.index) {
d.i.setState(prev => { d.i.setState({ editingRow: undefined });
prev.taglines } else {
.filter(x => x !== editable) d.i.setState({ editingRow: d.index });
.forEach(x => { }
x.editMode = false;
});
editable.editMode = !editable.editMode;
});
} }
async handleSaveClick(i: TaglineForm) { async handleSaveClick(i: TaglineForm) {
const promises: Promise<any>[] = []; i.props.onSaveSite({
for (const editable of i.state.taglines) { taglines: i.state.taglines,
if (editable.change === "update") { });
promises.push(
HttpService.client.editTagline(editable.tagline).then(res => {
if (res.state === "success") {
i.setState(() => {
editable.change = undefined;
editable.tagline = res.data.tagline;
});
}
}),
);
} else if (editable.change === "delete") {
promises.push(
HttpService.client.deleteTagline(editable.tagline).then(res => {
if (res.state === "success") {
i.setState(() => {
editable.change = undefined;
return {
taglines: this.state.taglines.filter(x => x !== editable),
};
});
}
}),
);
} else if (editable.change === "create") {
promises.push(
HttpService.client.createTagline(editable.tagline).then(res => {
if (res.state === "success") {
i.setState(() => {
editable.change = undefined;
editable.tagline = res.data.tagline;
});
}
}),
);
}
}
await Promise.all(promises);
} }
async handleCancelClick(i: TaglineForm) { handleAddTaglineClick(
i.handlePageChange(i.state.page);
}
async handleAddTaglineClick(
i: TaglineForm, i: TaglineForm,
event: InfernoMouseEvent<HTMLButtonElement>, event: InfernoMouseEvent<HTMLButtonElement>,
) { ) {
event.preventDefault(); event.preventDefault();
i.setState(prev => { const newTaglines = [...i.state.taglines];
prev.taglines.forEach(x => { newTaglines.push("");
x.editMode = false;
}); i.setState({
prev.taglines.push({ taglines: newTaglines,
tagline: { id: -1, content: "", published: "" }, editingRow: newTaglines.length - 1,
change: "create",
editMode: true,
});
}); });
} }
async handlePageChange(val: number) {
this.setState({ loading: true });
const taglineRes = await HttpService.client.listTaglines({ page: val });
if (taglineRes.state === "success") {
this.setState({
page: val,
loading: false,
taglines: taglineRes.data.taglines.map(t => ({ tagline: t })),
});
} else {
this.setState({ loading: false });
}
}
} }

View file

@ -1,81 +0,0 @@
import { Modal } from "bootstrap";
import { Component, InfernoNode, RefObject } from "inferno";
export function modalMixin<
P extends { show?: boolean },
S,
Base extends new (...args: any[]) => Component<P, S> & {
readonly modalDivRef: RefObject<HTMLDivElement>;
handleShow?(): void;
handleHide?(): void;
},
>(base: Base, _context?: ClassDecoratorContext<Base>) {
return class extends base {
modal?: Modal;
constructor(...args: any[]) {
super(...args);
this.handleHide = this.handleHide?.bind(this);
this.handleShow = this.handleShow?.bind(this);
}
private addModalListener(type: string, listener?: () => void) {
if (listener) {
this.modalDivRef.current?.addEventListener(type, listener);
}
}
private removeModalListener(type: string, listener?: () => void) {
if (listener) {
this.modalDivRef.current?.addEventListener(type, listener);
}
}
componentDidMount() {
// Keeping this sync to allow the super implementation to be sync
import("bootstrap/js/dist/modal").then(
(res: { default: typeof Modal }) => {
if (!this.modalDivRef.current) {
return;
}
// bootstrap tries to touch `document` during import, which makes
// the import fail on the server.
const Modal = res.default;
this.addModalListener("shown.bs.modal", this.handleShow);
this.addModalListener("hidden.bs.modal", this.handleHide);
this.modal = new Modal(this.modalDivRef.current!);
if (this.props.show) {
this.modal.show();
}
},
);
return super.componentDidMount?.();
}
componentWillUnmount() {
this.removeModalListener("shown.bs.modal", this.handleShow);
this.removeModalListener("hidden.bs.modal", this.handleHide);
this.modal?.dispose();
return super.componentWillUnmount?.();
}
componentWillReceiveProps(
nextProps: Readonly<{ children?: InfernoNode } & P>,
nextContext: any,
) {
if (nextProps.show !== this.props.show) {
if (nextProps.show) {
this.modal?.show();
} else {
this.modal?.hide();
}
}
return super.componentWillReceiveProps?.(nextProps, nextContext);
}
};
}

View file

@ -1,146 +0,0 @@
import { isBrowser, nextUserAction, snapToTop } from "../../utils/browser";
import { Component, InfernoNode } from "inferno";
import { Location, History, Action } from "history";
function restoreScrollPosition(props: { location: Location }) {
const key: string = props.location.key;
const y = sessionStorage.getItem(`scrollPosition_${key}`);
if (y !== null) {
window.scrollTo({ left: 0, top: Number(y), behavior: "instant" });
}
}
function saveScrollPosition(props: { location: Location }) {
const key: string = props.location.key;
const y = window.scrollY;
sessionStorage.setItem(`scrollPosition_${key}`, y.toString());
}
function dropScrollPosition(props: { location: Location }) {
const key: string = props.location.key;
sessionStorage.removeItem(`scrollPosition_${key}`);
}
export function scrollMixin<
P extends { location: Location; history: History },
S,
Base extends new (
...args: any
) => Component<P, S> & { loadingSettled(): boolean },
>(base: Base, _context?: ClassDecoratorContext<Base>) {
return class extends base {
private stopUserListener: (() => void) | undefined;
private blocked?: string;
constructor(...args: any[]) {
super(...args);
if (!isBrowser()) {
return;
}
this.reset();
}
componentDidMount() {
this.restoreIfLoaded();
return super.componentDidMount?.();
}
componentDidUpdate(
prevProps: Readonly<{ children?: InfernoNode } & P>,
prevState: S,
snapshot: any,
) {
this.restoreIfLoaded();
return super.componentDidUpdate?.(prevProps, prevState, snapshot);
}
componentWillUnmount() {
this.saveFinalPosition();
return super.componentWillUnmount?.();
}
componentWillReceiveProps(
nextProps: Readonly<{ children?: InfernoNode } & P>,
nextContext: any,
) {
if (this.props.location.key !== nextProps.location.key) {
if (nextProps.history.action !== Action.Replace) {
this.saveFinalPosition();
this.reset();
}
}
return super.componentWillReceiveProps?.(nextProps, nextContext);
}
unloadListeners = () => {
// Browsers restore the position after reload, but not after pressing
// Enter in the url bar. It's hard to distinguish the two, let the
// browser do its thing.
window.history.scrollRestoration = "auto";
dropScrollPosition(this.props);
};
reset() {
this.blocked = undefined;
this.stopUserListener?.();
// While inferno is rendering no events are dispatched. This only catches
// user interactions when network responses are slow/late.
this.stopUserListener = nextUserAction(() => {
this.preventRestore();
});
window.removeEventListener("beforeunload", this.unloadListeners);
window.addEventListener("beforeunload", this.unloadListeners);
}
savePosition() {
saveScrollPosition(this.props);
}
saveFinalPosition() {
this.savePosition();
snapToTop();
window.removeEventListener("beforeunload", this.unloadListeners);
}
preventRestore() {
this.blocked = this.props.location.key;
this.stopUserListener?.();
this.stopUserListener = undefined;
}
restore() {
restoreScrollPosition(this.props);
this.preventRestore();
}
restoreIfLoaded() {
if (!this.isPending() || !this.loadingSettled()) {
return;
}
this.restore();
}
isPending() {
return this.blocked !== this.props.location.key;
}
};
}
export function simpleScrollMixin<
P extends { location: Location; history: History },
S,
Base extends new (...args: any) => Component<P, S>,
>(base: Base, _context?: ClassDecoratorContext<Base>) {
@scrollMixin
class SimpleScrollMixin extends base {
loadingSettled() {
return true;
}
}
return SimpleScrollMixin;
}

View file

@ -1,25 +0,0 @@
import { Component, InfernoNode } from "inferno";
import { cleanupTippy } from "../../tippy";
export function tippyMixin<
P,
S,
Base extends new (...args: any) => Component<P, S>,
>(base: Base, _context?: ClassDecoratorContext<Base>) {
return class extends base {
componentDidUpdate(
prevProps: P & { children?: InfernoNode },
prevState: S,
snapshot: any,
) {
// For conditional rendering, old tippy instances aren't reused
cleanupTippy();
return super.componentDidUpdate?.(prevProps, prevState, snapshot);
}
componentWillUnmount() {
cleanupTippy();
return super.componentWillUnmount?.();
}
};
}

View file

@ -1,4 +1,9 @@
import { fetchUsers, personToChoice, setIsoData } from "@utils/app"; import {
fetchUsers,
getUpdatedSearchId,
personToChoice,
setIsoData,
} from "@utils/app";
import { import {
debounce, debounce,
formatPastDate, formatPastDate,
@ -6,10 +11,7 @@ import {
getPageFromString, getPageFromString,
getQueryParams, getQueryParams,
getQueryString, getQueryString,
resourcesSettled,
bareRoutePush,
} from "@utils/helpers"; } from "@utils/helpers";
import { scrollMixin } from "./mixins/scroll-mixin";
import { amAdmin, amMod } from "@utils/roles"; import { amAdmin, amMod } from "@utils/roles";
import type { QueryParams } from "@utils/types"; import type { QueryParams } from "@utils/types";
import { Choice, RouteDataResponse } from "@utils/types"; import { Choice, RouteDataResponse } from "@utils/types";
@ -62,8 +64,6 @@ import { CommunityLink } from "./community/community-link";
import { PersonListing } from "./person/person-listing"; import { PersonListing } from "./person/person-listing";
import { getHttpBaseInternal } from "../utils/env"; import { getHttpBaseInternal } from "../utils/env";
import { IRoutePropsWithFetch } from "../routes"; import { IRoutePropsWithFetch } from "../routes";
import { isBrowser } from "@utils/browser";
import { LoadingEllipses } from "./common/loading-ellipses";
type FilterType = "mod" | "user"; type FilterType = "mod" | "user";
@ -105,8 +105,6 @@ export function getModlogQueryParams(source?: string): ModlogProps {
modId: getIdFromString, modId: getIdFromString,
userId: getIdFromString, userId: getIdFromString,
page: getPageFromString, page: getPageFromString,
commentId: getIdFromString,
postId: getIdFromString,
}, },
source, source,
); );
@ -127,8 +125,6 @@ interface ModlogProps {
userId?: number; userId?: number;
modId?: number; modId?: number;
actionType: ModlogActionType; actionType: ModlogActionType;
postId?: number;
commentId?: number;
} }
function getActionFromString(action?: string): ModlogActionType { function getActionFromString(action?: string): ModlogActionType {
@ -649,7 +645,6 @@ export type ModlogFetchConfig = IRoutePropsWithFetch<
ModlogProps ModlogProps
>; >;
@scrollMixin
export class Modlog extends Component<ModlogRouteProps, ModlogState> { export class Modlog extends Component<ModlogRouteProps, ModlogState> {
private isoData = setIsoData<ModlogData>(this.context); private isoData = setIsoData<ModlogData>(this.context);
@ -663,10 +658,6 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
isIsomorphic: false, isIsomorphic: false,
}; };
loadingSettled() {
return resourcesSettled([this.state.res]);
}
constructor(props: ModlogRouteProps, context: any) { constructor(props: ModlogRouteProps, context: any) {
super(props, context); super(props, context);
this.handlePageChange = this.handlePageChange.bind(this); this.handlePageChange = this.handlePageChange.bind(this);
@ -701,68 +692,40 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
} }
} }
async componentWillMount() { async componentDidMount() {
if (!this.state.isIsomorphic && isBrowser()) { if (!this.state.isIsomorphic) {
await Promise.all([ const { modId, userId } = this.props;
this.fetchModlog(this.props), const promises = [this.refetch()];
this.fetchCommunity(this.props),
this.fetchUser(this.props),
this.fetchMod(this.props),
]);
}
}
componentWillReceiveProps(nextProps: ModlogRouteProps) { if (userId) {
this.fetchModlog(nextProps); promises.push(
HttpService.client
const reload = bareRoutePush(this.props, nextProps); .getPersonDetails({ person_id: userId })
.then(res => {
if (nextProps.modId !== this.props.modId || reload) { if (res.state === "success") {
this.fetchMod(nextProps); this.setState({
} userSearchOptions: [personToChoice(res.data.person_view)],
if (nextProps.userId !== this.props.userId || reload) { });
this.fetchUser(nextProps); }
} }),
if ( );
nextProps.match.params.communityId !==
this.props.match.params.communityId ||
reload
) {
this.fetchCommunity(nextProps);
}
}
fetchUserToken?: symbol;
async fetchUser(props: ModlogRouteProps) {
const token = (this.fetchUserToken = Symbol());
const { userId } = props;
if (userId) {
const res = await HttpService.client.getPersonDetails({
person_id: userId,
});
if (res.state === "success" && token === this.fetchUserToken) {
this.setState({
userSearchOptions: [personToChoice(res.data.person_view)],
});
} }
}
}
fetchModToken?: symbol; if (modId) {
async fetchMod(props: ModlogRouteProps) { promises.push(
const token = (this.fetchModToken = Symbol()); HttpService.client
const { modId } = props; .getPersonDetails({ person_id: modId })
.then(res => {
if (modId) { if (res.state === "success") {
const res = await HttpService.client.getPersonDetails({ this.setState({
person_id: modId, modSearchOptions: [personToChoice(res.data.person_view)],
}); });
if (res.state === "success" && token === this.fetchModToken) { }
this.setState({ }),
modSearchOptions: [personToChoice(res.data.person_view)], );
});
} }
await Promise.all(promises);
} }
} }
@ -819,11 +782,6 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
modSearchOptions, modSearchOptions,
} = this.state; } = this.state;
const { actionType, modId, userId } = this.props; const { actionType, modId, userId } = this.props;
const { communityId } = this.props.match.params;
const communityState = this.state.communityRes.state;
const communityResp =
communityState === "success" && this.state.communityRes.data;
return ( return (
<div className="modlog container-lg"> <div className="modlog container-lg">
@ -847,26 +805,15 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
#<strong>#</strong># #<strong>#</strong>#
</T> </T>
</div> </div>
{communityId && ( {this.state.communityRes.state === "success" && (
<h5> <h5>
{communityResp ? ( <Link
<> className="text-body"
<Link to={`/c/${this.state.communityRes.data.community_view.community.name}`}
className="text-body" >
to={`/c/${communityResp.community_view.community.name}`} /c/{this.state.communityRes.data.community_view.community.name}{" "}
> </Link>
/c/{communityResp.community_view.community.name} <span>{I18NextService.i18n.t("modlog")}</span>
</Link>{" "}
<span>{I18NextService.i18n.t("modlog")}</span>
</>
) : (
communityState === "loading" && (
<>
<LoadingEllipses />
&nbsp;
</>
)
)}
</h5> </h5>
)} )}
<div className="row mb-2"> <div className="row mb-2">
@ -907,9 +854,8 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
options={userSearchOptions} options={userSearchOptions}
loading={loadingUserSearch} loading={loadingUserSearch}
/> />
{(this.amAdminOrMod || {!this.isoData.site_res.site_view.local_site
!this.isoData.site_res.site_view.local_site .hide_modlog_mod_names && (
.hide_modlog_mod_names) && (
<Filter <Filter
filterType="mod" filterType="mod"
onChange={this.handleModChange} onChange={this.handleModChange}
@ -978,10 +924,6 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
} }
handleSearchUsers = debounce(async (text: string) => { handleSearchUsers = debounce(async (text: string) => {
if (!text.length) {
return;
}
const { userId } = this.props; const { userId } = this.props;
const { userSearchOptions } = this.state; const { userSearchOptions } = this.state;
this.setState({ loadingUserSearch: true }); this.setState({ loadingUserSearch: true });
@ -999,10 +941,6 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
}); });
handleSearchMods = debounce(async (text: string) => { handleSearchMods = debounce(async (text: string) => {
if (!text.length) {
return;
}
const { modId } = this.props; const { modId } = this.props;
const { modSearchOptions } = this.state; const { modSearchOptions } = this.state;
this.setState({ loadingModSearch: true }); this.setState({ loadingModSearch: true });
@ -1019,79 +957,65 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
}); });
}); });
async updateUrl(props: Partial<ModlogProps>) { async updateUrl({ actionType, modId, page, userId }: Partial<ModlogProps>) {
const { const {
actionType, page: urlPage,
modId, actionType: urlActionType,
page, modId: urlModId,
userId, userId: urlUserId,
match: { } = this.props;
params: { communityId },
},
} = { ...this.props, ...props };
const queryParams: QueryParams<ModlogProps> = { const queryParams: QueryParams<ModlogProps> = {
page: page.toString(), page: (page ?? urlPage).toString(),
actionType: actionType, actionType: actionType ?? urlActionType,
modId: modId?.toString(), modId: getUpdatedSearchId(modId, urlModId),
userId: userId?.toString(), userId: getUpdatedSearchId(userId, urlUserId),
}; };
const communityId = this.props.match.params.communityId;
this.props.history.push( this.props.history.push(
`/modlog${communityId ? `/${communityId}` : ""}${getQueryString( `/modlog${communityId ? `/${communityId}` : ""}${getQueryString(
queryParams, queryParams,
)}`, )}`,
); );
await this.refetch();
} }
fetchModlogToken?: symbol; async refetch() {
async fetchModlog(props: ModlogRouteProps) { const { actionType, page, modId, userId } = this.props;
const token = (this.fetchModlogToken = Symbol()); const { communityId: urlCommunityId } = this.props.match.params;
const { actionType, page, modId, userId, postId, commentId } = props;
const { communityId: urlCommunityId } = props.match.params;
const communityId = getIdFromString(urlCommunityId); const communityId = getIdFromString(urlCommunityId);
this.setState({ res: LOADING_REQUEST }); this.setState({ res: LOADING_REQUEST });
const res = await HttpService.client.getModlog({ this.setState({
community_id: communityId, res: await HttpService.client.getModlog({
page, community_id: communityId,
limit: fetchLimit, page,
type_: actionType, limit: fetchLimit,
other_person_id: userId, type_: actionType,
mod_person_id: !this.isoData.site_res.site_view.local_site other_person_id: userId,
.hide_modlog_mod_names mod_person_id: !this.isoData.site_res.site_view.local_site
? modId .hide_modlog_mod_names
: undefined, ? modId
comment_id: commentId, : undefined,
post_id: postId, }),
}); });
if (token === this.fetchModlogToken) {
this.setState({ res });
}
}
fetchCommunityToken?: symbol;
async fetchCommunity(props: ModlogRouteProps) {
const token = (this.fetchCommunityToken = Symbol());
const { communityId: urlCommunityId } = props.match.params;
const communityId = getIdFromString(urlCommunityId);
if (communityId) { if (communityId) {
this.setState({ communityRes: LOADING_REQUEST }); this.setState({ communityRes: LOADING_REQUEST });
const communityRes = await HttpService.client.getCommunity({ this.setState({
id: communityId, communityRes: await HttpService.client.getCommunity({
id: communityId,
}),
}); });
if (token === this.fetchCommunityToken) {
this.setState({ communityRes });
}
} else {
this.setState({ communityRes: EMPTY_REQUEST });
} }
} }
static async fetchInitialData({ static async fetchInitialData({
headers, headers,
query: { page, userId, modId: modId_, actionType, commentId, postId }, query: { page, userId, modId: modId_, actionType },
match: { match: {
params: { communityId: urlCommunityId }, params: { communityId: urlCommunityId },
}, },
@ -1112,8 +1036,6 @@ export class Modlog extends Component<ModlogRouteProps, ModlogState> {
type_: actionType, type_: actionType,
mod_person_id: modId, mod_person_id: modId,
other_person_id: userId, other_person_id: userId,
comment_id: commentId,
post_id: postId,
}; };
let communityResponse: RequestState<GetCommunityResponse> = EMPTY_REQUEST; let communityResponse: RequestState<GetCommunityResponse> = EMPTY_REQUEST;

View file

@ -1,13 +1,11 @@
import { Component } from "inferno"; import { Component } from "inferno";
import { I18NextService } from "../../services"; import { I18NextService } from "../../services";
import { Icon } from "../common/icon"; import { Icon } from "../common/icon";
import { tippyMixin } from "../mixins/tippy-mixin";
interface CakeDayProps { interface CakeDayProps {
creatorName: string; creatorName: string;
} }
@tippyMixin
export class CakeDay extends Component<CakeDayProps, any> { export class CakeDay extends Component<CakeDayProps, any> {
render() { render() {
return ( return (

Some files were not shown because too many files have changed in this diff Show more