kopia lustrzana https://github.com/wagtail/wagtail
Porównaj commity
65 Commity
Autor | SHA1 | Data |
---|---|---|
![]() |
96729c5168 | |
![]() |
89ac3f5cb0 | |
![]() |
ed19954c8d | |
![]() |
e592b8e9c6 | |
![]() |
538c5089e9 | |
![]() |
2271d86fc7 | |
![]() |
37c2224f35 | |
![]() |
81f14114a7 | |
![]() |
0aaec0d7ae | |
![]() |
c6863527ec | |
![]() |
81701ada3e | |
![]() |
f60b58fea3 | |
![]() |
ce24331966 | |
![]() |
2ef5767692 | |
![]() |
b5473dccca | |
![]() |
d24bedc961 | |
![]() |
1f92b10bfb | |
![]() |
a4b957c4a6 | |
![]() |
187b354a18 | |
![]() |
2c9003ba7b | |
![]() |
ebbad32cea | |
![]() |
910dea7044 | |
![]() |
ff01041f52 | |
![]() |
4ec9220916 | |
![]() |
5d0bb0636f | |
![]() |
15863a6aa1 | |
![]() |
6a42ab9b02 | |
![]() |
e9556b3169 | |
![]() |
15d68776b8 | |
![]() |
4604ec8a5b | |
![]() |
950104592e | |
![]() |
37bc8c8cb7 | |
![]() |
1d4bd11612 | |
![]() |
f97fe1c047 | |
![]() |
ab6bed2954 | |
![]() |
e76d04dfb2 | |
![]() |
f53be91b90 | |
![]() |
14a57215ed | |
![]() |
e7c7b971b2 | |
![]() |
1ab4f45b18 | |
![]() |
37a5e8dabc | |
![]() |
4a79d853ba | |
![]() |
6161b09644 | |
![]() |
f051c873ac | |
![]() |
c47bea2e15 | |
![]() |
3d03794048 | |
![]() |
0833e7bf22 | |
![]() |
bd952219b0 | |
![]() |
85961c314f | |
![]() |
1e517bac27 | |
![]() |
43ede8879b | |
![]() |
72a4884ee4 | |
![]() |
b758007587 | |
![]() |
46c78be145 | |
![]() |
de2c06281c | |
![]() |
e20624a482 | |
![]() |
b4ba3d635d | |
![]() |
84c9ab416b | |
![]() |
9dea339727 | |
![]() |
b7dacf52ea | |
![]() |
fe9a2c493f | |
![]() |
6e1645b86d | |
![]() |
7b30436be4 | |
![]() |
b8d85175e4 | |
![]() |
6c11616bd6 |
.circleci
.github
client
scss
components
elements
src
components
ComboBox
ComboBoxPreview
|
@ -1,7 +1,16 @@
|
|||
{
|
||||
"sourceType": "unambiguous",
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"chrome": 100,
|
||||
"safari": 15,
|
||||
"firefox": 91
|
||||
}
|
||||
}
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-react"
|
||||
],
|
||||
|
|
|
@ -3,39 +3,37 @@ version: 2
|
|||
jobs:
|
||||
backend:
|
||||
docker:
|
||||
- image: cimg/python:3.12
|
||||
- image: cimg/python:3.8.11
|
||||
environment:
|
||||
PIPENV_VENV_IN_PROJECT: true
|
||||
steps:
|
||||
- checkout
|
||||
- run: python --version > .python_version
|
||||
- restore_cache:
|
||||
key: &venv-cache venv-v1-{{ checksum "pyproject.toml" }}-{{ checksum ".python_version" }}
|
||||
key: pipenv-v1-{{ checksum "setup.py" }}
|
||||
# Only install if .venv wasn’t cached.
|
||||
- run: |
|
||||
if [[ ! -e ".venv" ]]; then
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -e .[testing,docs]
|
||||
pipenv install -e .[testing,docs]
|
||||
fi
|
||||
echo "source $(pwd)/.venv/bin/activate" >> $BASH_ENV
|
||||
- save_cache:
|
||||
key: *venv-cache
|
||||
key: pipenv-v1-{{ checksum "setup.py" }}
|
||||
paths:
|
||||
- .venv
|
||||
- run: ruff check .
|
||||
- run: ruff format --check .
|
||||
- run: semgrep --config .semgrep.yml --error .
|
||||
- run: git ls-files '*.html' | xargs djhtml --check
|
||||
- run: curlylint --parse-only wagtail
|
||||
- run: doc8 docs
|
||||
- run: pipenv run ruff check .
|
||||
- run: pipenv run ruff format --check .
|
||||
- run: pipenv run semgrep --config .semgrep.yml --error .
|
||||
- run: git ls-files '*.html' | xargs pipenv run djhtml --check
|
||||
- run: pipenv run curlylint --parse-only wagtail
|
||||
- run: pipenv run doc8 docs
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
export PYTHONUNBUFFERED=1
|
||||
WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1 python -u runtests.py --parallel=2
|
||||
pipenv run python -u runtests.py --parallel=2
|
||||
|
||||
frontend:
|
||||
docker:
|
||||
- image: cimg/node:22.11
|
||||
- image: cimg/node:20.9
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
|
@ -64,50 +62,44 @@ jobs:
|
|||
|
||||
ui_tests:
|
||||
docker:
|
||||
- image: cimg/python:3.12-browsers
|
||||
- image: cimg/python:3.8.11-browsers
|
||||
environment:
|
||||
PIPENV_VENV_IN_PROJECT: true
|
||||
DJANGO_SETTINGS_MODULE: wagtail.test.settings_ui
|
||||
DJANGO_DEBUG: 'true'
|
||||
DJANGO_DEBUG: true
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ~/project
|
||||
- run: python --version > .python_version
|
||||
- restore_cache:
|
||||
key: &ui_tests-venv-cache ui_tests-venv-v1-{{ checksum "pyproject.toml" }}-{{ checksum ".python_version" }}
|
||||
key: pipenv-v1-{{ checksum "setup.py" }}
|
||||
# Only install if .venv wasn’t cached.
|
||||
- run: |
|
||||
if [[ ! -e ".venv" ]]; then
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -e .[testing]
|
||||
pipenv install -e .[testing]
|
||||
fi
|
||||
echo "source $(pwd)/.venv/bin/activate" >> $BASH_ENV
|
||||
- save_cache:
|
||||
key: *ui_tests-venv-cache
|
||||
key: pipenv-v1-{{ checksum "setup.py" }}
|
||||
paths:
|
||||
- .venv
|
||||
- restore_cache:
|
||||
key: &ui_tests-npm-cache ui_tests-npm_integration-v3-{{ checksum "client/tests/integration/package-lock.json" }}
|
||||
key: ui_tests-npm_integration-v1-{{ checksum "client/tests/integration/package-lock.json" }}
|
||||
# Only install if node_modules wasn’t cached.
|
||||
- run: |
|
||||
if [[ ! -e "client/tests/integration/node_modules" ]]; then
|
||||
npm --prefix ./client/tests/integration ci
|
||||
fi
|
||||
- save_cache:
|
||||
key: *ui_tests-npm-cache
|
||||
key: ui_tests-npm_integration-v1-{{ checksum "client/tests/integration/package-lock.json" }}
|
||||
paths:
|
||||
- client/tests/integration/node_modules
|
||||
# Also cache the global location where Puppeteer stores browsers.
|
||||
# https://pptr.dev/guides/configuration/#changing-the-default-cache-directory
|
||||
- ~/.cache/puppeteer
|
||||
- run: ./wagtail/test/manage.py migrate
|
||||
- run: pipenv run ./wagtail/test/manage.py migrate
|
||||
- run:
|
||||
command: ./wagtail/test/manage.py runserver 0:8000
|
||||
command: pipenv run ./wagtail/test/manage.py runserver 0:8000
|
||||
background: true
|
||||
- run: ./wagtail/test/manage.py createcachetable
|
||||
- run: pipenv run ./wagtail/test/manage.py createcachetable
|
||||
- run:
|
||||
command: ./wagtail/test/manage.py createsuperuser --noinput
|
||||
command: pipenv run ./wagtail/test/manage.py createsuperuser --noinput
|
||||
environment:
|
||||
DJANGO_SUPERUSER_EMAIL: admin@example.com
|
||||
DJANGO_SUPERUSER_USERNAME: admin
|
||||
|
@ -117,23 +109,24 @@ jobs:
|
|||
environment:
|
||||
JEST_JUNIT_OUTPUT_DIR: reports/jest
|
||||
- run:
|
||||
command: ./wagtail/test/manage.py collectstatic --noinput
|
||||
command: pipenv run ./wagtail/test/manage.py collectstatic --noinput
|
||||
environment:
|
||||
DJANGO_DEBUG: 'false'
|
||||
DJANGO_DEBUG: false
|
||||
STATICFILES_STORAGE: manifest
|
||||
- store_test_results:
|
||||
path: ./reports/jest
|
||||
|
||||
nightly-build:
|
||||
docker:
|
||||
- image: cimg/python:3.12-node
|
||||
- image: cimg/python:3.8.11-node
|
||||
steps:
|
||||
- checkout
|
||||
- run: pip install --user build boto3
|
||||
- run: pip install --user wheel boto3
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
- run: PYTHONPATH=. python scripts/nightly/get_version.py > __init__.py
|
||||
- run: mv __init__.py wagtail/__init__.py
|
||||
- run: python -m build
|
||||
- run: python setup.py bdist_wheel
|
||||
- run: python scripts/nightly/upload.py
|
||||
|
||||
workflows:
|
||||
|
|
|
@ -11,6 +11,7 @@ wagtail/images/static
|
|||
wagtail/embeds/static
|
||||
wagtail/search/static
|
||||
wagtail/snippets/static
|
||||
wagtail/users/static
|
||||
wagtail/contrib/*/static
|
||||
.mypy_cache
|
||||
/storybook-static
|
||||
|
|
12
.eslintrc.js
12
.eslintrc.js
|
@ -132,14 +132,14 @@ module.exports = {
|
|||
files: [
|
||||
'client/extract-translatable-strings.js',
|
||||
'client/tests/**',
|
||||
'tailwind.config.js',
|
||||
'webpack.config.js',
|
||||
'*.stories.js',
|
||||
'*.stories.tsx',
|
||||
'*.test.js',
|
||||
'tailwind.config.js',
|
||||
'storybook/**/*',
|
||||
'*.test.ts',
|
||||
'*.test.tsx',
|
||||
'**/storybook/**',
|
||||
'*.test.js',
|
||||
'*.stories.js',
|
||||
'*.stories.tsx',
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
|
@ -167,6 +167,7 @@ module.exports = {
|
|||
'wagtail/images/static_src/wagtailimages/js/add-multiple.js',
|
||||
'wagtail/images/static_src/wagtailimages/js/focal-point-chooser.js',
|
||||
'wagtail/images/static_src/wagtailimages/js/image-url-generator.js',
|
||||
'wagtail/users/static_src/wagtailusers/js/group-form.js',
|
||||
],
|
||||
globals: { $: 'readonly', jQuery: 'readonly' },
|
||||
},
|
||||
|
@ -174,6 +175,7 @@ module.exports = {
|
|||
{
|
||||
files: ['wagtail/**/**'],
|
||||
globals: {
|
||||
buildExpandingFormset: 'readonly',
|
||||
escapeHtml: 'readonly',
|
||||
ModalWorkflow: 'readonly',
|
||||
DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS: 'writable',
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
# Make GitHub highlight html files as Django templates
|
||||
*.html linguist-language=django
|
|
@ -1,4 +1,4 @@
|
|||
# Contributing
|
||||
# Contributing to Wagtail
|
||||
|
||||
Thank you for considering to help Wagtail.
|
||||
|
||||
|
|
|
@ -24,9 +24,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
|
|
|
@ -13,25 +13,24 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
# Our test suite should cover:
|
||||
# - all supported databases against current Python and Django (including psycopg v2 and v3)
|
||||
# - all supported databases against current Python and Django
|
||||
# - at least one test run for each older supported version of Python and Django
|
||||
# - at least one test run for each supported Elasticsearch version
|
||||
# - a test run against Django's git main and active stable branch (allowing failures)
|
||||
# - test runs with USE_EMAIL_USER_MODEL=yes, DISABLE_TIMEZONE=yes and WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1
|
||||
# - test runs with USE_EMAIL_USER_MODEL=yes and DISABLE_TIMEZONE=yes
|
||||
|
||||
# Current configuration:
|
||||
# - django 4.2, python 3.9, postgres:12, psycopg 2, parallel
|
||||
# - django 4.2, python 3.10, mysql:8.0
|
||||
# - django 4.2, python 3.11, mariadb:10.5
|
||||
# - django 5.1, python 3.12, mysql:8.4, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 5.1, python 3.12, mariadb:11.4, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 5.2, python 3.13, sqlite, parallel, WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT=1
|
||||
# - django 5.2, python 3.13, postgres:15, psycopg 3, parallel, DISABLE_TIMEZONE=yes
|
||||
# - django stable/5.2.x, python 3.12, postgres:15, psycopg 3 (allow failures)
|
||||
# - django main, python 3.13, postgres:latest, psycopg 3, parallel (allow failures)
|
||||
# - elasticsearch 7, django 4.2, python 3.9, postgres:latest, psycopg 2
|
||||
# - opensearch 2, django 5.2, python 3.10, sqlite
|
||||
# - elasticsearch 8, django 5.1, python 3.13, sqlite, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 4.2, python 3.8, postgres:12, parallel
|
||||
# - django 4.2, python 3.9, mysql:8.0
|
||||
# - django 4.2, python 3.10, sqlite
|
||||
# - django 5.0, python 3.12, mysql:8.1, parallel
|
||||
# - django 5.0, python 3.11, postgres:12, parallel, USE_EMAIL_USER_MODEL=yes
|
||||
# - django 5.0, python 3.12, postgres:15, parallel, DISABLE_TIMEZONE=yes
|
||||
# - django stable/5.1.x, python 3.11, postgres:15 (allow failures)
|
||||
# - django main, python 3.12, postgres:latest, parallel (allow failures)
|
||||
# - elasticsearch 7, django 4.2, python 3.8, postgres:latest
|
||||
# - opensearch 2, django 4.2, python 3.9, sqlite
|
||||
# - elasticsearch 8, django 5.0, python 3.11, sqlite, USE_EMAIL_USER_MODEL=yes
|
||||
|
||||
# Some tests are run in parallel by passing --parallel to runtests.py.
|
||||
# When running tests in parallel, some errors cannot be pickled and result in
|
||||
|
@ -48,17 +47,13 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: '3.13'
|
||||
django: 'Django>=5.2,<5.3'
|
||||
check_template_number_format: '1'
|
||||
parallel: '--parallel'
|
||||
- python: '3.10'
|
||||
django: 'Django>=4.2,<4.3'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
cache: 'pip'
|
||||
|
@ -70,17 +65,14 @@ jobs:
|
|||
- name: Test
|
||||
run: |
|
||||
WAGTAIL_FAIL_ON_VERSIONED_STATIC=1 DJANGO_SETTINGS_MODULE=wagtail.test.settings django-admin check
|
||||
coverage run --parallel-mode --source wagtail runtests.py ${{ matrix.parallel }}
|
||||
coverage run --parallel-mode --source wagtail runtests.py
|
||||
env:
|
||||
DATABASE_ENGINE: django.db.backends.sqlite3
|
||||
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
|
||||
WAGTAIL_CHECK_TEMPLATE_NUMBER_FORMAT: ${{ matrix.check_template_number_format }}
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
|
||||
name: coverage-data
|
||||
path: .coverage.*
|
||||
include-hidden-files: true
|
||||
|
||||
test-postgres:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -88,32 +80,30 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: '3.9'
|
||||
- python: '3.8'
|
||||
django: 'Django>=4.2,<4.3'
|
||||
psycopg: 'psycopg2>=2.6'
|
||||
experimental: false
|
||||
parallel: '--parallel'
|
||||
- python: '3.13'
|
||||
django: 'Django>=5.2,<5.3'
|
||||
psycopg: 'psycopg>=3.1.8'
|
||||
- python: '3.11'
|
||||
django: 'Django>=5.0,<5.1'
|
||||
experimental: false
|
||||
emailuser: emailuser
|
||||
parallel: '--parallel'
|
||||
- python: '3.12'
|
||||
django: 'Django>=5.0,<5.1'
|
||||
postgres: 'postgres:15'
|
||||
notz: notz
|
||||
experimental: false
|
||||
parallel: '--parallel'
|
||||
- python: '3.12'
|
||||
django: 'git+https://github.com/django/django.git@stable/5.2.x#egg=Django'
|
||||
psycopg: 'psycopg>=3.1.8'
|
||||
- python: '3.11'
|
||||
django: 'git+https://github.com/django/django.git@stable/5.1.x#egg=Django'
|
||||
postgres: 'postgres:15'
|
||||
experimental: true
|
||||
- python: '3.13'
|
||||
- python: '3.12'
|
||||
django: 'git+https://github.com/django/django.git@main#egg=Django'
|
||||
psycopg: 'psycopg>=3.1.8'
|
||||
experimental: true
|
||||
postgres: 'postgres:latest'
|
||||
parallel: '--parallel'
|
||||
install_extras: |
|
||||
pip uninstall -y django-modelcluster
|
||||
pip install "git+https://github.com/wagtail/django-modelcluster.git@main#egg=django-modelcluster"
|
||||
services:
|
||||
postgres:
|
||||
image: ${{ matrix.postgres || 'postgres:12' }}
|
||||
|
@ -124,18 +114,16 @@ jobs:
|
|||
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
cache: 'pip'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install "${{ matrix.psycopg }}"
|
||||
pip install "psycopg2>=2.6"
|
||||
pip install -e '.[testing]' --config-settings editable_mode=strict
|
||||
pip install "${{ matrix.django }}"
|
||||
${{ matrix.install_extras }}
|
||||
|
@ -151,29 +139,10 @@ jobs:
|
|||
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
|
||||
DISABLE_TIMEZONE: ${{ matrix.notz }}
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
|
||||
name: coverage-data
|
||||
path: .coverage.*
|
||||
include-hidden-files: true
|
||||
- name: Test project template
|
||||
if: ${{ matrix.experimental }}
|
||||
env:
|
||||
PYTHONWARNINGS: error
|
||||
run: |
|
||||
wagtail start testproject
|
||||
cd testproject
|
||||
tee -a testproject/settings/local.py << EOF
|
||||
from warnings import filterwarnings
|
||||
SILENCED_SYSTEM_CHECKS = ["wagtailadmin.W001"]
|
||||
# Remove when https://github.com/wagtail/Willow/issues/166 is resolved
|
||||
filterwarnings(
|
||||
"ignore", "The AVIF support in this library is marked as deprecated"
|
||||
)
|
||||
EOF
|
||||
python manage.py makemigrations --check --dry-run
|
||||
python manage.py migrate
|
||||
python manage.py check --fail-level WARNING
|
||||
|
||||
test-mysql:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -181,42 +150,28 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: '3.10'
|
||||
- python: '3.9'
|
||||
django: 'Django>=4.2,<4.3'
|
||||
experimental: false
|
||||
- python: '3.11'
|
||||
django: 'Django>=4.2,<4.3'
|
||||
experimental: false
|
||||
mysql: 'mariadb:10.5'
|
||||
- python: '3.12'
|
||||
django: 'Django>=5.1,<5.2'
|
||||
django: 'Django>=5.0,<5.1'
|
||||
experimental: false
|
||||
mysql: 'mariadb:11.4'
|
||||
emailuser: emailuser
|
||||
- python: '3.12'
|
||||
django: 'Django>=5.1,<5.2'
|
||||
experimental: false
|
||||
mysql: 'mysql:8.4'
|
||||
emailuser: emailuser
|
||||
parallel: '--parallel'
|
||||
mysql: 'mysql:8.1'
|
||||
services:
|
||||
mysql:
|
||||
image: ${{ matrix.mysql || 'mysql:8.0' }}
|
||||
env:
|
||||
MARIADB_ROOT_PASSWORD: root
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: wagtail
|
||||
HEALTH_CMD: ${{ startsWith(matrix.mysql, 'mariadb') && 'healthcheck.sh --connect --innodb_initialized' || 'mysqladmin --protocol=tcp ping' }}
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd=$HEALTH_CMD --health-interval=10s --health-timeout=5s --health-retries=3 --cap-add=sys_nice
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 --cap-add=sys_nice
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
cache: 'pip'
|
||||
|
@ -234,23 +189,19 @@ jobs:
|
|||
DATABASE_ENGINE: django.db.backends.mysql
|
||||
DATABASE_HOST: '127.0.0.1'
|
||||
DATABASE_USER: root
|
||||
DATABASE_PASSWORD: root
|
||||
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
|
||||
DISABLE_TIMEZONE: ${{ matrix.notz }}
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
|
||||
name: coverage-data
|
||||
path: .coverage.*
|
||||
include-hidden-files: true
|
||||
|
||||
test-sqlite-elasticsearch8:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: '3.13'
|
||||
django: 'Django>=5.2,<5.3'
|
||||
- python: '3.11'
|
||||
django: 'Django>=5.0,<5.1'
|
||||
emailuser: emailuser
|
||||
steps:
|
||||
- name: Configure sysctl limits
|
||||
|
@ -259,7 +210,7 @@ jobs:
|
|||
sudo sysctl -w vm.swappiness=1
|
||||
sudo sysctl -w fs.file-max=262144
|
||||
sudo sysctl -w vm.max_map_count=262144
|
||||
- uses: getong/elasticsearch-action@v1.3
|
||||
- uses: getong/elasticsearch-action@v1.2
|
||||
with:
|
||||
elasticsearch version: 8.8.0
|
||||
host port: 9200
|
||||
|
@ -267,11 +218,9 @@ jobs:
|
|||
host node port: 9300
|
||||
node port: 9300
|
||||
discovery type: 'single-node'
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
cache: 'pip'
|
||||
|
@ -289,11 +238,10 @@ jobs:
|
|||
DATABASE_ENGINE: django.db.backends.sqlite3
|
||||
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
|
||||
name: coverage-data
|
||||
path: .coverage.*
|
||||
include-hidden-files: true
|
||||
|
||||
test-postgres-elasticsearch7:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -301,7 +249,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: '3.9'
|
||||
- python: '3.8'
|
||||
django: 'Django>=4.2,<4.3'
|
||||
experimental: false
|
||||
|
||||
|
@ -324,12 +272,9 @@ jobs:
|
|||
- uses: elastic/elastic-github-actions/elasticsearch@master
|
||||
with:
|
||||
stack-version: 7.6.1
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
cache: 'pip'
|
||||
|
@ -351,11 +296,10 @@ jobs:
|
|||
DATABASE_PASSWORD: postgres
|
||||
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
|
||||
name: coverage-data
|
||||
path: .coverage.*
|
||||
include-hidden-files: true
|
||||
|
||||
test-sqlite-opensearch2:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -363,8 +307,8 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- python: '3.10'
|
||||
django: 'Django>=5.1,<5.2'
|
||||
- python: '3.9'
|
||||
django: 'Django>=4.2,<4.3'
|
||||
experimental: false
|
||||
|
||||
steps:
|
||||
|
@ -377,11 +321,9 @@ jobs:
|
|||
- uses: ankane/setup-opensearch@v1
|
||||
with:
|
||||
opensearch-version: 2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
cache: 'pip'
|
||||
|
@ -399,11 +341,10 @@ jobs:
|
|||
DATABASE_ENGINE: django.db.backends.sqlite3
|
||||
USE_EMAIL_USER_MODEL: ${{ matrix.emailuser }}
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-data-${{ github.job }}-${{ strategy.job-index }}
|
||||
name: coverage-data
|
||||
path: .coverage.*
|
||||
include-hidden-files: true
|
||||
|
||||
coverage:
|
||||
needs:
|
||||
|
@ -416,12 +357,10 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
|
@ -431,10 +370,9 @@ jobs:
|
|||
pip install coverage
|
||||
|
||||
- name: Download coverage data
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
pattern: coverage-data-*
|
||||
merge-multiple: true
|
||||
name: coverage-data
|
||||
|
||||
- name: Combine coverage data
|
||||
run: |
|
||||
|
@ -446,14 +384,12 @@ jobs:
|
|||
coverage html --skip-covered --skip-empty
|
||||
|
||||
- name: Upload HTML report as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-report
|
||||
path: coverage_html_report
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
flags: backend
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
|
|
@ -18,7 +18,6 @@ npm-debug.log*
|
|||
/.cache/
|
||||
/.pytest_cache/
|
||||
/storybook-static
|
||||
/wagtail/tests/test-media/
|
||||
|
||||
### JetBrains
|
||||
.idea/
|
||||
|
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
|||
22
|
||||
20
|
||||
|
|
|
@ -3,7 +3,7 @@ default_language_version:
|
|||
python: python3
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.9.6'
|
||||
rev: 'v0.1.5'
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
|
|
|
@ -9,11 +9,5 @@ python:
|
|||
path: .
|
||||
extra_requirements:
|
||||
- docs
|
||||
formats: all
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
fail_on_warning: True
|
||||
search:
|
||||
ranking:
|
||||
releases/*: -1
|
||||
releases/upgrading.html: 0
|
||||
|
|
|
@ -39,9 +39,6 @@ rules:
|
|||
- metavariable-regex:
|
||||
metavariable: $STRING_ID
|
||||
regex: ".*%\\w.*"
|
||||
paths:
|
||||
exclude:
|
||||
- 'wagtail/test/numberformat.py'
|
||||
message: >
|
||||
Do not use anonymous placeholders for translations.
|
||||
Use printf style formatting with named placeholders instead.
|
||||
|
|
|
@ -3,7 +3,7 @@ deployments:
|
|||
dockerimage: python:3.11.4-slim-bullseye
|
||||
build_steps:
|
||||
- apt-get update && apt-get install -y libssl-dev libpq-dev git build-essential libfontconfig1 libfontconfig1-dev curl
|
||||
- RUN bash -c "curl -sL https://deb.nodesource.com/setup_22.x | bash -"
|
||||
- RUN bash -c "curl -sL https://deb.nodesource.com/setup_20.x | bash -"
|
||||
- apt install -y nodejs
|
||||
- pip install setuptools pip --upgrade --force-reinstall
|
||||
- cd /code
|
||||
|
|
|
@ -23,7 +23,12 @@ module.exports = {
|
|||
// Would be valuable for strict BEM components but is too hard to enforce with legacy code.
|
||||
'no-descending-specificity': null,
|
||||
// Refined ordering to align with media mixin usage - see https://github.com/wagtail/stylelint-config-wagtail/issues/37
|
||||
'order/order': ['dollar-variables', 'custom-properties', 'declarations'],
|
||||
'order/order': [
|
||||
'dollar-variables',
|
||||
'custom-properties',
|
||||
{ type: 'at-rule', hasBlock: false }, // @-rules that have no nesting.
|
||||
'declarations',
|
||||
],
|
||||
// Some parts of declaration-strict-value commented out until we are in a position to enforce them.
|
||||
'scale-unlimited/declaration-strict-value': [
|
||||
[
|
||||
|
@ -51,7 +56,6 @@ module.exports = {
|
|||
'none',
|
||||
'unset',
|
||||
'transparent',
|
||||
'normal',
|
||||
// System colors for forced-colors styling.
|
||||
// See https://drafts.csswg.org/css-color-4/#css-system-colors.
|
||||
'Canvas',
|
||||
|
|
392
CHANGELOG.txt
392
CHANGELOG.txt
|
@ -1,369 +1,6 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
7.0 LTS (xx.xx.xxxx) - IN DEVELOPMENT
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Add formal support for Django 5.2 (Matt Westcott)
|
||||
* Allow validation of required fields to be deferred on saving drafts (Matt Westcott, Sage Abdullah)
|
||||
* Add `WAGTAIL_` prefix to Wagtail-specific tag settings (Aayushman Singh)
|
||||
* Implement `normalize` on `TypedTableBlock` to assist with setting `default` and `preview_value` (Sage Abdullah)
|
||||
* Apply normalization when modifying a `StreamBlock`'s value to assist with programmatic changes to `StreamField` (Matt Westcott)
|
||||
* Allow a custom image rendition model to define its unique constraint with `models.UniqueConstraint` instead of `unique_together` (Oliver Parker, Cynthia Kiser, Sage Abdullah)
|
||||
* Default to the `standard` tokenizer on Elasticsearch, to correctly handle numbers as tokens (Matt Westcott)
|
||||
* Add color-scheme meta tag to Wagtail admin (Ashish Nagmoti)
|
||||
* Add the ability to set the default privacy restriction for new pages using `get_default_privacy_setting` (Shlomo Markowitz)
|
||||
* Improve performance of batch purging page urls in the frontend cache, avoiding n+1 query issues (Andy Babic)
|
||||
* Add better support and documentation for overriding or extending icons used in the in the userbar (Sébastien Corbin)
|
||||
* List the comments action, if comments are enabled, within the admin keyboard shortcuts dialog (Dhruvi Patel)
|
||||
* Add better support and documentation for overriding the default field widgets used within form pages (Baptiste Mispelon)
|
||||
* Allow workflow tasks to specify a template for the action modal via `get_template_for_action` (Sage Abdullah)
|
||||
* Change 'Publish' button label to 'Schedule to publish' if go-live schedule is set (Sage Abdullah)
|
||||
* Exclude snippets that have their own menu items from the "Snippets" menu (Andy Chosak, Matt Westcott)
|
||||
* Fix: Take preferred language into account for translatable strings in client-side code (Bernhard Bliem, Sage Abdullah)
|
||||
* Fix: Do not show the content type column as sortable when searching pages (Srishti Jaiswal, Sage Abdullah)
|
||||
* Fix: Support simple subqueries for `in` and `exact` lookup on Elasticsearch (Sage Abdullah)
|
||||
* Fix: Force preview panel scroll behavior to instant to avoid flickering (Sage Abdullah)
|
||||
* Fix: Support translating with the preferred language for rich text formatting labels (Bernhard Bliem, Sage Abdullah)
|
||||
* Fix: Make "Actions" label translatable within the rich text toolbar (Bernhard Bliem, Sage Abdullah)
|
||||
* Fix: Fix incorrect "Views (past week)" heading on promoted search results listing (Baptiste Mispelon)
|
||||
* Fix: Ensure `InlinePanel` will be correctly ordered after the first save when `min_num` is used (Elhussein Almasri, Joel William)
|
||||
* Fix: Avoid deprecation warnings about URLField `assume_scheme` on Django 5.x (Sage Abdullah)
|
||||
* Fix: Fix setup.cfg syntax for setuptools v78 (Sage Abdullah)
|
||||
* Fix: Ensure `ImproperlyConfigured` is thrown from `db_field` on unbound `FieldPanel`s as intended (Matt Westcott)
|
||||
* Fix: Refine the positioning of the add comment button next to select, radio, checkbox fields and between field row columns (Srishti Jaiswal)
|
||||
* Fix: Show the correct privacy status for child collections of private collections (Shlomo Markowitz)
|
||||
* Fix: Ensure reference index correctly handles models with primary keys not named `id` (Sage Abdullah)
|
||||
* Fix: On "move page" bulk action, do not prefill the destination with the root page (Stefan Hammer)
|
||||
* Docs: Add missing `django.contrib.admin` to list of apps in "add to Django project" guide (Mohamed Rabiaa)
|
||||
* Docs: Add tutorial on deploying on Ubuntu to third-party tutorials (Mohammad Fathi Rahman)
|
||||
* Docs: Document that request_or_site is optional on BaseGenericSetting.load (Matt Westcott)
|
||||
* Docs: Mention third-party StreamField based form builder packages in the form builder documentation (Matt Westcott)
|
||||
* Docs: Clarify that `insert_editor_js` hook applies to all core editing/creation views (LB (Ben) Johnston)
|
||||
* Docs: Clarify requirement for non-page models using model mixins to be registered as snippets (Sage Abdullah)
|
||||
* Maintenance: Migrate away from deprecated Sass import rules to module system (Srishti Jaiswal)
|
||||
* Maintenance: Apply Sass mixed declarations migration in preparation for CSS nesting (Prabhpreet Kaur)
|
||||
* Maintenance: Refactor styles for Draftail, minimap, and comments to fix remaining Sass migration warnings (Thibaud Colas)
|
||||
* Maintenance: npm package updates; `downshift`, `focus-trap-react`, `immer`, `redux`, `uuid` (LB (Ben) Johnston)
|
||||
* Maintenance: Validate against invalid characters in Lexeme values (Matt Westcott)
|
||||
* Maintenance: Split up `wagtail.models` module into submodules (Matt Westcott)
|
||||
* Maintenance: Update `ruff` to 0.9.6 (Sage Abdullah)
|
||||
* Maintenance: Fix up `stubs` & `adapter` contents to better support Jest testing (LB (Ben) Johnston)
|
||||
* Maintenance: Cleanup Stimulus controller imports, JSDoc & linting (LB (Ben) Johnston)
|
||||
* Maintenance: Rename `SkipLinkController` to `FocusController` with improved reusability, updated unit tests, and added story (LB (Ben) Johnston)
|
||||
* Maintenance: Fix CI testing issues with the Stimulus `LocaleController` time zones & non-deterministic page ordering tests (Sage Abdullah)
|
||||
* Maintenance: Make GitHub highlight `.html` files as Django templates (Jake Howard)
|
||||
* Maintenance: Remove admin JavaScript imports from shared template includes, moving the imports to the appropriate core admin inclusion locations (Sai Srikar Dumpeti)
|
||||
* Maintenance: Remove non-editing view inclusions of the `insert_editor_js` hook output, deprecate the wrapper template tag `_editor_js.html` (Sai Srikar Dumpeti, LB (Ben) Johnston)
|
||||
* Maintenance: Remove upper bound on Django dependency (Matt Westcott)
|
||||
* Maintenance: Add `default_auto_field` setting to home app in project template (Sylvain Boissel)
|
||||
* Maintenance: Migrate setuptools configuration from `setup.py` and `setup.cfg` to `pyproject.toml` (Sage Abdullah)
|
||||
* Maintenance: Refactor `move_choose_destination` to a class-based view (Chiemezuo Akujobi)
|
||||
* Maintenance: Remove deprecated `wagtailadmin/shared/ajax_pagination_nav.html` template (Sage Abdullah)
|
||||
* Maintenance: Formally deprecate support for listing views with no breadcrumbs (Sage Abdullah)
|
||||
|
||||
|
||||
6.4.2 (xx.xx.xxxx) - IN DEVELOPMENT
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Do not show upgrade notification if the installed version is the latest (Sage Abdullah)
|
||||
|
||||
|
||||
6.4.1 (21.02.2025)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Prevent error when filtering by locale and searching with Elasticsearch (Sage Abdullah)
|
||||
* Fix: Support searching `none()` querysets (Matt Westcott)
|
||||
* Fix: Correctly handle UUID primary keys when invoking background tasks (Matt Westcott)
|
||||
* Fix: Fix regression where nested sub-menu items would not be visible (Sage Abdullah)
|
||||
* Fix: Ensure the top of the minimap correctly adjusts when resizing the browser viewport (Thibaud Colas)
|
||||
* Fix: Remove obsolete SubqueryConstraint check in search backends, for provisional Django 5.2 compatibility (Sage Abdullah)
|
||||
* Fix: Add missing “Close” label to the upgrade notification dismiss button (Sage Abdullah)
|
||||
* Fix: Fix white text on white background in previews for sites that use color-scheme without a background-color (Sage Abdullah)
|
||||
* Docs: Fix typo in the headless documentation page (Mahmoud Nasser)
|
||||
* Docs: Fix typo in `Page.get_route_paths` docstring (Baptiste Mispelon)
|
||||
* Docs: Upgrade sphinx-wagtail-theme to v6.5.0 (Sage Abdullah)
|
||||
* Maintenance: Remove upper version boundary for django-filter (Dan Braghis)
|
||||
* Maintenance: Relax upper version boundaries for django-taggit and beautifulsoup4 (Matt Westcott)
|
||||
|
||||
|
||||
6.4 (03.02.2025)
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
* Support for background tasks using `django-tasks` (Jake Howard)
|
||||
* Add search terms report (Noah van der Meer, Sage Abdullah)
|
||||
* Add the ability to apply basic Page QuerySet optimizations to `specific()` sub-queries using `select_related` & `prefetch_related` (Andy Babic)
|
||||
* Increase `DATA_UPLOAD_MAX_NUMBER_FIELDS` in project template (Matt Westcott)
|
||||
* Stop invalid Site hostname records from breaking preview (Matt Westcott)
|
||||
* Set sensible defaults for InlinePanel heading and label (Matt Westcott)
|
||||
* Limit tags autocompletion to 10 items and add delay to avoid performance issues with large number of matching tags (Aayushman Singh)
|
||||
* Add the ability to restrict what types of requests a Pages supports via `allowed_http_methods` (Andy Babic)
|
||||
* Allow plain strings in panel definitions as shorthand for `FieldPanel` / `InlinePanel` (Matt Westcott)
|
||||
* Only allow selection of valid new parents within the copy Page view (Mauro Soche)
|
||||
* Add `on_serve_page` hook to modify the serving chain of pages (Krystian Magdziarz, Dawid Bugajewski)
|
||||
* Add support for `WAGTAIL_GRAVATAR_PROVIDER_URL` URLs with query string parameters (Ayaan Qadri, Guilhem Saurel)
|
||||
* Add `get_avatar_url` hook to customise user avatars (James Harrington)
|
||||
* Set content security policy (CSP) headers to block embedded content when serving images and documents (Jake Howard, with thanks to Ali İltizar for the initial report)
|
||||
* Add `page` as a third parameter to the `construct_wagtail_userbar` hook (claudobahn)
|
||||
* Enable breadcrumbs in revisions compare view (Sage Abdullah)
|
||||
* Skip loading of unused JavaScript to speed up 404 page rendering (Sage Abdullah)
|
||||
* Replace l18n library with JavaScript Intl API for time zone options in Account view (Sage Abdullah)
|
||||
* Use explicit label for defaulting to server language in account settings (Sage Abdullah)
|
||||
* Add support for specifying an operator on `Fuzzy` queries (Tom Usher)
|
||||
* Remove support for Safari 15 (Thibaud Colas)
|
||||
* Populate the ImageBlock alt text from the image’s default alt text when selecting a new image (Matt Westcott)
|
||||
* Prevent main menu from re-rendering when clicking outside while the menu is closed (Sage Abdullah)
|
||||
* Fill in the ImageBlock alt text from the image’s default alt text when converting from ImageChooserBlock (Cynthia Kiser)
|
||||
* Make sure typing text at the bottom of the page editor always scrolls enough to keep the text into view (Jatin Bhardwaj)
|
||||
* Add StreamField and InlinePanel interfaces support for drag-and-drop reordering of items (Thibaud Colas, Sage Abdullah)
|
||||
* Add previews support for StreamField blocks inside the block picker (Sage Abdullah, Thibaud Colas)
|
||||
* Fix: Improve handling of translations for bulk page action confirmation messages (Matt Westcott)
|
||||
* Fix: Ensure custom rich text feature icons are correctly handled when provided as a list of SVG paths (Temidayo Azeez, Joel William, LB (Ben) Johnston)
|
||||
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
|
||||
* Fix: Fix sub-menus within the main menu cannot be closed on mobile (Bojan Mihelac)
|
||||
* Fix: Fix animation overflow transition when navigating through subpages in the sidebar page explorer (manu)
|
||||
* Fix: Ensure form builder supports custom admin form validation (John-Scott Atlakson, LB (Ben) Johnston)
|
||||
* Fix: Ensure form builder correctly checks for duplicate field names when using a custom related name (John-Scott Atlakson, LB (Ben) Johnston)
|
||||
* Fix: Normalize `StreamField.get_default()` to prevent creation forms from breaking (Matt Westcott)
|
||||
* Fix: Prevent out-of-order migrations from skipping creation of image/document choose permissions (Matt Westcott)
|
||||
* Fix: Use correct connections on multi-database setups in database search backends (Jake Howard)
|
||||
* Fix: Ensure CloudFront cache invalidation is called with a list, for compatibility with current botocore versions (Jake Howard)
|
||||
* Fix: Show the correct privacy status in the sidebar when creating a new page (Joel William)
|
||||
* Fix: Prevent generic model edit view from unquoting non-integer primary keys multiple times (Matt Westcott)
|
||||
* Fix: Ensure comments are functional when editing Page models with `read_only` `Fieldpanel`s in use (Strapchay)
|
||||
* Fix: Ensure the accessible labels and tooltips reflect the correct private/public status on the live link button within pages after changing the privacy (Ayaan Qadri)
|
||||
* Fix: Fix empty `th` (table heading) elements that are not compliant with accessibility standards (Jai Vignesh J)
|
||||
* Fix: Ensure `MultipleChooserPanel` using images or documents work when nested within an `InlinePanel` when no other choosers are in use within the model (Elhussein Almasri)
|
||||
* Fix: Ensure `MultipleChooserPanel` works after doing a search in the page chooser modal (Matt Westcott)
|
||||
* Fix: Ensure new `ListBlock` instances get created with unique IDs in the admin client for accessibility and mini-map element references (Srishti Jaiswal)
|
||||
* Fix: Return never-cache HTTP headers when serving pages and documents with view restrictions (Krystian Magdziarz, Dawid Bugajewski)
|
||||
* Fix: Implement `get_block_by_content_path` on `ImageBlock` to prevent errors on commenting (Matt Westcott)
|
||||
* Fix: Add `aria-expanded` attribute to new column button on `TypedTableBlock` to reflect menu state (Ayaan Qadri, Scott Cranfill)
|
||||
* Fix: Allow page models to extend base `Page` panel definitions without importing `wagtail.admin` (Matt Westcott)
|
||||
* Fix: Fix crash when loading the dashboard with only the "unlock" or "bulk delete" page permissions (Unyime Emmanuel Udoh, Sage Abdullah)
|
||||
* Fix: Improve deprecation warning for `WidgetWithScript` by raising it with `stacklevel=3` (Joren Hammudoglu)
|
||||
* Fix: Correctly place comment buttons next to date / datetime / time fields. (Srishti Jaiswal)
|
||||
* Fix: Add missing heading and breadcrumbs in Account view (Sage Abdullah)
|
||||
* Fix: Reduce confusing spacing below StreamField blocks help text (Rishabh Sharma)
|
||||
* Fix: Prevent redundant calls to `Site.find_for_request()` from `Page.get_url_parts()` (Andy Babic)
|
||||
* Fix: Prevent error on listings when searching and filtering by locale (Matt Westcott, Sage Abdullah)
|
||||
* Fix: Add missing space in panels check warning message (Stéphane Blondon)
|
||||
* Fix: Make sure alt text quality check is on by default as documented (Thibaud Colas)
|
||||
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
|
||||
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
|
||||
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
|
||||
* Docs: Move the model reference page from reference/pages to the references section as it covers all Wagtail core models (Srishti Jaiswal)
|
||||
* Docs: Move the panels reference page from references/pages to the references section as panels are available for any model editing, merge panels API into this page (Srishti Jaiswal)
|
||||
* Docs: Move the tags documentation to standalone advanced topic, instead of being inside the reference/pages section (Srishti Jaiswal)
|
||||
* Docs: Refine the adding reports page so that common (page/non-page) class references are at the top and the full page only example has correct heading nesting (Alessandro Chitarrini)
|
||||
* Docs: Add the `wagtail start` command to the management commands reference page (Damilola Oladele)
|
||||
* Docs: Refine the project template page sections and document common issues encountered when creating custom templates (Damilola Oladele)
|
||||
* Docs: Refine titles, references and URLS to better align with the documentation style guide, including US spelling (Srishti Jaiswal)
|
||||
* Docs: Recommend a larger `DATA_UPLOAD_MAX_NUMBER_FIELDS` when integrating Wagtail into Django (Matt Westcott)
|
||||
* Docs: Improve code highlighting and formatting for Python docstrings in core models (Srishti Jaiswal)
|
||||
* Docs: Update all JavaScript inline scripts & some CSS inline style tags to a CSP compliant approach by using external scripts/styles (Aayushman Singh)
|
||||
* Docs: Update usage of `mark_safe` to `format_html` for any script inclusions, to better avoid XSS issues from example code (Aayushman Singh)
|
||||
* Docs: Update documentation writing guidelines to encourage better considerations of security, accessibility and good practice when writing code examples (Aayushman Singh, LB (Ben) Johnston)
|
||||
* Docs: Update documentation guidelines on writing links and API reference (Sage Abdullah)
|
||||
* Docs: Replace absolute URLs with intersphinx links where possible to avoid broken links (Sage Abdullah)
|
||||
* Docs: Update upgrading guide and release process to better reflect the current practices (Sage Abdullah)
|
||||
* Docs: Document usage of custom validation for admin form pages when using `AbstractEmailForm` or `AbstractForm` pages (John-Scott Atlakson, LB (Ben) Johnston)
|
||||
* Docs: Reword `BlogTagIndexPage` example for clarity (Clifford Gama)
|
||||
* Docs: Change title of blog index page in tutorial to avoid slug issues (Thibaud Colas)
|
||||
* Docs: Fix `wagtailcache` and `wagtailpagecache` examples to not use quotes for the `fragment_name` (Shiv)
|
||||
* Docs: Update tutorial to reflect the move of the "Add child page" action to a top-level button in the header as a '+' icon (Clifford Gama)
|
||||
* Docs: Fix link to `HTTPMethod` in `Page.handle_options_request()` docs (Sage Abdullah)
|
||||
* Docs: Improve the Pages Theory page with added & more consistent section headings and admonitions to aid in readability (Clifford Gama)
|
||||
* Docs: Fix non-functional link to the community guidelines in the Your first contribution page (Ankit Kumar)
|
||||
* Docs: Introduce tags and filters by name in "Writing templates" docs (Clifford Gama)
|
||||
* Docs: Add a new headless section to the documentation, incorporating parts of the 'are we headless' website content (Sævar Öfjörð Magnússon, Alex Fulcher)
|
||||
* Docs: Fix Django HTML syntax formatting issue on the documents overview page (LB (Ben) Johnston)
|
||||
* Docs: Separate virtual environment creation and activation steps in tutorial (Ankit Kumar)
|
||||
* Docs: Update tutorial to use plain strings in place of `FieldPanel` / `InlinePanel` where appropriate (Unyime Emmanuel Udoh)
|
||||
* Docs: Update example for customizing "p-as-heading" accessibility check without overriding built-in checks (Cynthia Kiser)
|
||||
* Docs: Document `get_template` method on StreamField blocks (Matt Westcott)
|
||||
* Docs: Update accessibility considerations on alt text in light of contextual alt text improvements (Cynthia Kiser)
|
||||
* Docs: Revert incorrect example of appending a `RichTextBlock` to a `StreamField` (Matt Westcott)
|
||||
* Maintenance: Close open files when reading within utils/setup.py (Ataf Fazledin Ahamed)
|
||||
* Maintenance: Avoid redundant `ALLOWED_HOSTS` check in `Site.find_for_request` (Jake Howard)
|
||||
* Maintenance: Update `CloneController` to ensure that `added`/`cleared` events are not dispatched as cancelable (LB (Ben) Johnston)
|
||||
* Maintenance: Remove unused `uuid` UMD module as all code is now using the NPM module (LB (Ben) Johnston)
|
||||
* Maintenance: Clean up JS comments throughout codebase to be aligned to JSDoc where practical (LB (Ben) Johnston)
|
||||
* Maintenance: Replace `eslint-disable no-undef` linter directives with `global` comments (LB (Ben) Johnston)
|
||||
* Maintenance: Upgrade Node tooling to active LTS version 22 (LB (Ben) Johnston)
|
||||
* Maintenance: Remove defunct oEmbed providers (Rahul Samant)
|
||||
* Maintenance: Remove obsolete non-upsert-based code for Postgres search indexing (Jake Howard)
|
||||
* Maintenance: Remove unused Rangy JS library (LB (Ben) Johnston)
|
||||
* Maintenance: Update `PreviewController` usage to leverage Stimulus actions instead of calling `preventDefault` manually (Ayaan Qadri)
|
||||
* Maintenance: Various performance optimizations to page publishing (Jake Howard)
|
||||
* Maintenance: Remove unnecessary DOM canvas.toBlob polyfill (LB (Ben) Johnston)
|
||||
* Maintenance: Ensure Storybook core files are correctly running through Eslint (LB (Ben) Johnston)
|
||||
* Maintenance: Add a new Stimulus `ZoneController` (`w-zone`) to support dynamic class name changes & event handling on container elements (Ayaan Qadri)
|
||||
* Maintenance: Migrate jQuery class toggling & drag/drop event handling within the multiple upload views to the Stimulus ZoneController usage (Ayaan Qadri)
|
||||
* Maintenance: Test project template for warnings when run against Django pre-release versions (Sage Abdullah)
|
||||
* Maintenance: Refactor redirects create/delete views to use generic views (Sage Abdullah)
|
||||
* Maintenance: Add JSDoc description, adopt linting recommendations, and add more unit tests for `ModalWorkflow` (LB (Ben) Johnston)
|
||||
* Maintenance: Add support for for a `delay` value in `TagController` to debounce async autocomplete tag fetch requests (Aayushman Singh)
|
||||
* Maintenance: Add unit tests, Storybook stories & JSDoc items for the Stimulus `DrilldownController` (Srishti Jaiswal)
|
||||
* Maintenance: Enhance sidebar preview performance by eliminating duplicate asset loads on preview error (Sage Abdullah)
|
||||
* Maintenance: Remove unused `LinkController` (`w-link`) (Sage Abdullah)
|
||||
* Maintenance: Refactor settings `EditView` to make better use of generic `EditView` (Sage Abdullah)
|
||||
* Maintenance: Add a new Stimulus `RulesController` (`w-rules`) to support declarative conditional field enabling from other field values in a form (LB (Ben) Johnston)
|
||||
* Maintenance: Migrate the conditional enabling of fields in the image URL builder view away from ad-hoc jQuery to use the `RulesController` (`w-rules`) approach (LB (Ben) Johnston)
|
||||
* Maintenance: Enhance the Stimulus `ZoneController` (`w-zone`) to support inactive class and a mechanism to switch the mode based on data within events (Ayaan Qadri)
|
||||
* Maintenance: Use the Stimulus `ZoneController` (`w-zone`) to remove ad-hoc jQuery for the privacy switch when toggling visibility of private/public elements (Ayaan Qadri)
|
||||
* Maintenance: Remove unused `is_active` & `active_menu_items` from `wagtail.admin.menu.MenuItem` (Srishti Jaiswal)
|
||||
* Maintenance: Only call `openpyxl` at runtime to improve performance for projects that do not use `ReportView`, `SpreadsheetExportMixin` and `wagtail.contrib.redirects` (Sébastien Corbin)
|
||||
* Maintenance: Adopt the update value `mp` instead of `mm` for 'mystery person' as the default Gravatar if no avatar found (Harsh Dange)
|
||||
* Maintenance: Refactor search promotions views to use generic views and templates (Sage Abdullah, Rohit Sharma)
|
||||
* Maintenance: Use built-in `venv` instead of `pipenv` in CircleCI (Sage Abdullah)
|
||||
* Maintenance: Add a new Stimulus `FormsetController` (`w-formset`) to support dynamic formset insertion/deletion behavior (LB (Ben) Johnston)
|
||||
* Maintenance: Enable breadcrumbs by default on admin views using generic templates (Sage Abdullah)
|
||||
* Maintenance: Refactor pages `revisions_revert` view to be a subclass of `EditView` (Sage Abdullah)
|
||||
* Maintenance: Move images and documents `get_usage().count()` call to view code (Sage Abdullah)
|
||||
* Maintenance: Upgrade sass-loader to resolve Sass deprecation warnings (Ayaan Qadri)
|
||||
|
||||
|
||||
6.3.4 (xx.xx.xxxx) - IN DEVELOPMENT
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Added support for Django 5.2
|
||||
* Fix: Add missing “Close” label to the upgrade notification dismiss button (Sage Abdullah)
|
||||
* Fix: Fix white text on white background in previews for sites that use color-scheme without a background-color (Sage Abdullah)
|
||||
* Maintenance: Remove upper version boundary for django-filter (Dan Braghis)
|
||||
|
||||
|
||||
6.3.3 (03.02.2025)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Correctly place comment buttons next to date / datetime / time fields. (Srishti Jaiswal)
|
||||
* Fix: Reduce confusing spacing below StreamField blocks help text (Rishabh Sharma)
|
||||
* Fix: Make sure alt text quality check is on by default as documented (Thibaud Colas)
|
||||
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
|
||||
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
|
||||
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
|
||||
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
|
||||
* Docs: Update example for customizing "p-as-heading" accessibility check without overriding built-in checks (Cynthia Kiser)
|
||||
* Docs: Update accessibility considerations on alt text in light of contextual alt text improvements (Cynthia Kiser)
|
||||
* Docs: Revert incorrect example of appending a `RichTextBlock` to a `StreamField` (Matt Westcott)
|
||||
|
||||
|
||||
6.3.2 (02.01.2025)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Ensure CloudFront cache invalidation is called with a list, for compatibility with current botocore versions (Jake Howard)
|
||||
* Fix: Ensure Draftail features wrap when a large amount of features are added (Bart Cieliński)
|
||||
* Fix: Implement `get_block_by_content_path` on `ImageBlock` to prevent errors on commenting (Matt Westcott)
|
||||
* Docs: Update tutorial to reflect the move of the "Add child page" action to a top-level button in the header as a '+' icon (Clifford Gama)
|
||||
|
||||
|
||||
6.3.1 (19.11.2024)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Restore ability to upload profile picture through account settings (Sage Abdullah)
|
||||
* Fix: Correctly handle `ImageChooserBlock` to `ImageBlock` data conversions where all inputs to `bulk_to_python` are null (Storm Heg, Matt Westcott)
|
||||
* Fix: Improve spacing of page / collection permissions table in Group settings (Sage Abdullah)
|
||||
* Fix: Remove forced capitalization of site name on admin dashboard (Thibaud Colas)
|
||||
* Docs: Reword `BlogTagIndexPage` example for clarity (Clifford Gama)
|
||||
* Docs: Change title of blog index page in tutorial to avoid slug issues (Thibaud Colas)
|
||||
* Docs: Fix `wagtailcache` and `wagtailpagecache` examples to not use quotes for the `fragment_name` (Shiv)
|
||||
* Docs: Lower search result ranking for release notes on readthedocs search (Sage Abdullah)
|
||||
|
||||
|
||||
6.3 LTS (01.11.2024)
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Add support for Python 3.13 (Matt Westcott)
|
||||
* Add formal support for Django 5.1 (Matt Westcott)
|
||||
* Add `ImageBlock` with alt text support (Chiemezuo Akujobi for Google Summer of Code, mentored by Storm Heg, Saptak Sengupta, Thibaud Colas and Matt Westcott)
|
||||
* Implement incremental dashboard design enhancements (Albina Starykova, Ben Enright)
|
||||
* Add a new enhanced contrast admin theming option for the admin interface (Albina Starykova, Victoria Ottah)
|
||||
* Migrate workflow history views to universal listings (Sage Abdullah)
|
||||
* Refactor documents views to use universal designs (Sage Abdullah)
|
||||
* Refactor images views to use universal designs (Sage Abdullah)
|
||||
* Implement universal listings for workflow usage and page type usage views (Sage Abdullah)
|
||||
* Add search and filters to form pages listing (Sage Abdullah)
|
||||
* Add support for uploading HEIC / HEIF images (Matt Westcott)
|
||||
* Allow customization of preview device sizes in the live preview panel (Bart Cieliński, alexkiro, Sage Abdullah)
|
||||
* Formalize support for MariaDB (Sage Abdullah, Daniel Black)
|
||||
* Redirect to the last viewed listing page after deleting form submissions (Matthias Brück)
|
||||
* Provide `getTextLabel` method on date / time StreamField blocks (Vaughn Dickson)
|
||||
* Purge frontend cache when modifying redirects (Jake Howard)
|
||||
* Deprecate the `WAGTAIL_AUTO_UPDATE_PREVIEW` setting, use `WAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL = 0` instead (Sage Abdullah)
|
||||
* Consistently use `capfirst` for title-casing model verbose names (Sébastien Corbin)
|
||||
* Fire `copy_for_translation_done` signal when copying translatable models as well as pages (Coen van der Kamp)
|
||||
* Add support for an image `description` field across all images, to better support accessible image descriptions (Chiemezuo Akujobi)
|
||||
* Prompt the user about unsaved changes when editing snippets (Sage Abdullah)
|
||||
* Make dashboard upgrade banners dismissible (Sage Abdullah)
|
||||
* Add support for specifying different preview modes to the "View draft" URL for pages (Robin Varghese)
|
||||
* Implement new designs for the footer actions dropdown with more contrast and larger text (Sage Abdullah)
|
||||
* All create/edit admin forms now use a sticky submit button, for consistency and to speed up edits (Sage Abdullah)
|
||||
* Secondary form actions such as "Delete" are now in the header actions menu (Sage Abdullah)
|
||||
* Allow setting page privacy rules when a restriction already exists on an ancestor page (Bojan Mihelac)
|
||||
* Automatically create links when pasting content that contain URLs into a rich text input (Thibaud Colas)
|
||||
* Add Uyghur language support
|
||||
* Fix: Prevent page type business rules from blocking reordering of pages (Andy Babic, Sage Abdullah)
|
||||
* Fix: Improve layout of object permissions table (Sage Abdullah)
|
||||
* Fix: Fix typo in aria-label attribute of page explorer navigation link (Sébastien Corbin)
|
||||
* Fix: Reinstate transparency indicator on image chooser widgets (Sébastien Corbin)
|
||||
* Fix: Remove table headers that have no text (Matt Westcott)
|
||||
* Fix: Fix broken link to user search (Shlomo Markowitz)
|
||||
* Fix: Ensure that JS slugify function strips Unicode characters disallowed by Django slug validation (Atif Khan)
|
||||
* Fix: Do not show notices about root / unroutable pages when searching or filtering in the page explorer (Matt Westcott)
|
||||
* Fix: Resolve contrast issue for page deletion warning (Sanjeev Holla S)
|
||||
* Fix: Make sure content metrics falls back to body element only when intended (Sage Abdullah)
|
||||
* Fix: Remove wrongly-added filters from redirects index (Matt Westcott)
|
||||
* Fix: Prevent popular tags filter from generating overly complex queries when not filtering (Matt Westcott)
|
||||
* Fix: Fix content path links in usage view to scroll to the correct element (Sage Abdullah)
|
||||
* Fix: Always show the minimap toggle button (Albina Starykova)
|
||||
* Fix: Ensure that dropdown button toggles show with a border in high contrast mode (Ishwari8104, LB (Ben) Johnston)
|
||||
* Fix: Update email notification header to the new logo design (Rahul Samant)
|
||||
* Fix: Change `file_size` field on document model to avoid artificial 2Gb limit (Gabriel Getzie)
|
||||
* Fix: Ensure that `TypedTableBlock` uses the correct API representations of child blocks (Matt Westcott)
|
||||
* Fix: Footer action buttons now include their `media` definitions (Sage Abdullah)
|
||||
* Fix: Improve the text contrast of the bulk actions "Select all" button (Sage Abdullah)
|
||||
* Fix: Fix error on workflow settings view with multiple snippet types assigned to the same workflow on Postgres (Sage Abdullah)
|
||||
* Fix: Fix datetime fields overflowing its parent wrapper in listing filters (Rohit Singh)
|
||||
* Fix: Prevent multiple URLs from being combined into one when pasting links into a rich text input (Thibaud Colas)
|
||||
* Fix: Improve layout of report listing tables (Sage Abdullah)
|
||||
* Fix: Fix regression from creation of `AbstractGroupApprovalTask` to ensure `can_handle` checks for the abstract class correctly (Sumana Sree Angajala)
|
||||
* Docs: Upgrade Sphinx to 7.3 (Matt Westcott)
|
||||
* Docs: Upgrade sphinx-wagtail-theme to v6.4.0, with a new search integration and Read the Docs Addons bug fixes (Thibaud Colas)
|
||||
* Docs: Document how to customize date/time format settings (Vince Salvino)
|
||||
* Docs: Create a new documentation section for deployment and move fly.io deployment from the tutorial to this section (Vince Salvino)
|
||||
* Docs: Clarify process for UserViewSet customization (Sage Abdullah)
|
||||
* Docs: Correct `WAGTAIL_WORKFLOW_REQUIRE_REAPPROVAL_ON_EDIT` documentation to state that it defaults to `False` (Matt Westcott)
|
||||
* Docs: Add an example of customizing a default accessibility check (Cynthia Kiser)
|
||||
* Docs: Demonstrate access protection with `TokenAuthentication` in the Wagtail API v2 Configuration Guide (Krzysztof Jeziorny)
|
||||
* Docs: Replace X links with Mastodon in the README (Alex Morega)
|
||||
* Docs: Re-enable building offline formats in online documentation (Read the docs) for EPUB/PDF/HTML downloads (Joel William, Sage Abdullah)
|
||||
* Docs: Resolve multiple output errors in the documentation ePub format (Sage Abdullah)
|
||||
* Docs: Update social media examples to use LinkedIn, Reddit, Facebook (Ayaan Qadri)
|
||||
* Maintenance: Removed support for Python 3.8 (Matt Westcott)
|
||||
* Maintenance: Drop pytz dependency in favour of `zoneinfo.available_timezones` (Sage Abdullah)
|
||||
* Maintenance: Relax django-taggit dependency to allow 6.0 (Matt Westcott)
|
||||
* Maintenance: Improve page listing performance (Sage Abdullah)
|
||||
* Maintenance: Phase out usage of SECRET_KEY in version and icon hashes (Jake Howard)
|
||||
* Maintenance: Audit all use of localized and non-localized numbers in templates (Matt Westcott)
|
||||
* Maintenance: Refactor StreamField `get_prep_value` for closer alignment with JSONField (Sage Abdullah)
|
||||
* Maintenance: Move search implementation logic from generic `IndexView` to `BaseListingView` (Sage Abdullah)
|
||||
* Maintenance: Upgrade Puppeteer integration tests for reliability (Matt Westcott)
|
||||
* Maintenance: Restore ability to use `.in_bulk()` on specific querysets under Django 5.2a0 (Sage Abdullah)
|
||||
* Maintenance: Add generated `test-media` to .gitignore (Shlomo Markowitz)
|
||||
* Maintenance: Improve `debounce` util's return type for better TypeScript usage (Sage Abdullah)
|
||||
* Maintenance: Ensure the side panel's show event is dispatched after any hide events (Sage Abdullah)
|
||||
* Maintenance: Migrate preview-panel JavaScript to Stimulus & TypeScript, add full unit testing (Sage Abdullah)
|
||||
* Maintenance: Move `wagtailConfig` values from inline scripts to the `wagtail_config` template tag (LB (Ben) Johnston, Sage Abdullah)
|
||||
* Maintenance: Deprecate the `{% locales %}` and `{% js_translation_strings %}` template tags (LB (Ben) Johnston, Sage Abdullah)
|
||||
* Maintenance: Ensure multi-line comments are cleaned from custom icons in addition to just single line comments (Jake Howard)
|
||||
* Maintenance: Deprecate `window.wagtailConfig.BULK_ACTION_ITEM_TYPE` usage in JavaScript to reduce reliance on inline scripts (LB (Ben) Johnston)
|
||||
* Maintenance: Remove `window.fileupload_opts` usage in JavaScript, use data attributes on fields instead to reduce reliance on inline scripts (LB (Ben) Johnston)
|
||||
* Maintenance: Remove `image_format_name_to_content_type` helper function that duplicates Willow functionality (Matt Westcott)
|
||||
* Maintenance: Improve code reuse for footer actions markup across generic views (Sage Abdullah)
|
||||
* Maintenance: Deprecate internal `DeleteMenuItem` API for footer actions (Sage Abdullah)
|
||||
* Maintenance: Update Pillow dependency to allow 11.x (Storm Heg)
|
||||
|
||||
|
||||
6.2.3 (01.11.2024)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -421,7 +58,6 @@ Changelog
|
|||
* Add "soft" client-side validation for `StreamBlock` / `ListBlock` `min_num` / `max_num` (Matt Westcott)
|
||||
* Log accessibility checker results in the console to help developers with troubleshooting (Thibaud Colas)
|
||||
* Disable pointer events on checker highlights to simplify DevTools inspections (Thibaud Colas)
|
||||
* `StaticBlock` now renders nothing by default when no template is specified (Sævar Öfjörð Magnússon)
|
||||
* Fix: Make `WAGTAILIMAGES_CHOOSER_PAGE_SIZE` setting functional again (Rohit Sharma)
|
||||
* Fix: Enable `richtext` template tag to convert lazy translation values (Benjamin Bach)
|
||||
* Fix: Ensure permission labels on group permissions page are translated where available (Matt Westcott)
|
||||
|
@ -446,8 +82,6 @@ Changelog
|
|||
* Fix: Fix focal point chooser when localization enabled (Sébastien Corbin)
|
||||
* Fix: Ensure that system checks for `WAGTAIL_DATE_FORMAT`, `WAGTAIL_DATETIME_FORMAT` and `WAGTAIL_TIME_FORMAT` take `FORMAT_MODULE_PATH` into account (Sébastien Corbin)
|
||||
* Fix: Prevent rich text fields inside choosers from being duplicated when opened repeatedly (Sage Abdullah)
|
||||
* Fix: Prevent history view from breaking if a log entry's revision is missing (Matt Westcott)
|
||||
* Fix: Prevent long filenames from breaking layout on document chooser listings (Frank Yiu, Shaurya Panchal)
|
||||
* Docs: Remove duplicate section on frontend caching proxies from performance page (Jake Howard)
|
||||
* Docs: Document `restriction_type` field on PageViewRestriction (Shlomo Markowitz)
|
||||
* Docs: Document Wagtail's bug bounty policy (Jake Howard)
|
||||
|
@ -465,7 +99,7 @@ Changelog
|
|||
* Maintenance: Split `contrib.frontend_cache.backends` into dedicated sub-modules (Andy Babic)
|
||||
* Maintenance: Remove unused `docs/autobuild.sh` script (Sævar Öfjörð Magnússon)
|
||||
* Maintenance: Replace `urlparse` with `urlsplit` to improve performance (Jake Howard)
|
||||
* Maintenance: Optimize embed finder lookups (Jake Howard)
|
||||
* Maintenance: Optimise embed finder lookups (Jake Howard)
|
||||
* Maintenance: Improve performance of initial admin loading by moving sprite hashing out of module import time (Jake Howard)
|
||||
* Maintenance: Remove workaround and inline scripts for activating workflow actions (Sage Abdullah)
|
||||
* Maintenance: Prevent `'BlockWidget' object has no attribute '_block_json'` from masking errors during StreamField serialization (Matt Westcott)
|
||||
|
@ -530,7 +164,7 @@ Changelog
|
|||
* Update the minimum version of `djangorestframework` to 3.15.1 (Sage Abdullah)
|
||||
* Add support for related fields in generic `IndexView.list_display` (Abdelrahman Hamada)
|
||||
* Improve page fetching logic and cache route results per request (Gordon Pendleton)
|
||||
* Optimize rewriting of links / embeds in rich text using bulk database lookups (Andy Chosak)
|
||||
* Optimise rewriting of links / embeds in rich text using bulk database lookups (Andy Chosak)
|
||||
* Add normalization mechanism to StreamField so that assignments and defaults can be passed in a wider range of data types (Joshua Munn, Matt Westcott)
|
||||
* Allow specifying a `STORAGES` alias name for `WAGTAILIMAGES_RENDITION_STORAGE` (Alec Baron)
|
||||
* Update `PASSWORD_REQUIRED_TEMPLATE` setting to `WAGTAIL_PASSWORD_REQUIRED_TEMPLATE` with deprecation of previous naming (Saksham Misra, LB (Ben) Johnston)
|
||||
|
@ -562,9 +196,6 @@ Changelog
|
|||
* Fix: Use correct URL when redirecting back to page search results after an AJAX search (Sage Abdullah)
|
||||
* Fix: Reinstate missing static files in style guide (Sage Abdullah)
|
||||
* Fix: Provide `convert_mariadb_uuids` management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)
|
||||
* Fix: Ensure invalid submissions are marked as dirty edits on load to trigger UI and browser warnings for unsaved changes, restoring previous behavior from Wagtail 5.2 (Sage Abdullah)
|
||||
* Fix: Update polldaddy oEmbed provider to use the crowdsignal URL (Matthew Scouten)
|
||||
* Fix: Remove polleverywhere oEmbed provider as it this application longer supports oEmbed (Matthew Scouten)
|
||||
* Docs: Add contributing development documentation on how to work with a fork of Wagtail (Nix Asteri, Dan Braghis)
|
||||
* Docs: Make sure the settings panel is listed in tabbed interface examples (Tibor Leupold)
|
||||
* Docs: Update content and page names to their US spelling instead of UK spelling (Victoria Poromon)
|
||||
|
@ -605,7 +236,6 @@ Changelog
|
|||
* Maintenance: Remove jQuery usage in telepath widget classes (Matt Westcott)
|
||||
* Maintenance: Remove `xregexp` (IE11 polyfill) along with `window.XRegExp` global util (LB (Ben) Johnston)
|
||||
* Maintenance: Refactor the Django port of `urlify` to use TypeScript, officially deprecate `window.URLify` global util (LB (Ben) Johnston)
|
||||
* Maintenance: Adopt the modern best practice for `beforeunload` usage in `UnsavedController` to trigger a leave page warning when edits have been made (Shubham Mukati, Sage Abdullah)
|
||||
|
||||
|
||||
6.0.6 (11.07.2024)
|
||||
|
@ -828,16 +458,6 @@ Changelog
|
|||
* Maintenance: Remove support for Django 4.1 and below (Sage Abdullah)
|
||||
|
||||
|
||||
5.2.8 (03.02.2025)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
|
||||
* Fix: Handle StreamField migrations where the field value is null (Joshua Munn)
|
||||
* Fix: Prevent `StreamChildrenToListBlockOperation` from duplicating data across multiple StreamField instances (Joshua Munn)
|
||||
* Fix: Prevent error on lazily loading StreamField blocks after the stream has been modified (Stefan Hammer)
|
||||
* Fix: Prevent syntax error on MySQL search when query includes symbols (Matt Westcott)
|
||||
|
||||
|
||||
5.2.7 (01.11.2024)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -960,7 +580,7 @@ Changelog
|
|||
* Support extending Wagtail client-side with Stimulus (LB (Ben) Johnston)
|
||||
* Update all `FieldPanel('title')` examples to use the recommended `TitleFieldPanel('title')` panel (Chinedu Ihedioha)
|
||||
* The `purge_revisions` management command now respects revisions that have a `on_delete=PROTECT` foreign key relation and won't delete them (Neeraj P Yetheendran, Meghana Reddy, Sage Abdullah, Storm Heg)
|
||||
* Add support for Shift + Click behavior in form submissions and simple translations submissions (LB (Ben) Johnston)
|
||||
* Add support for Shift + Click behaviour in form submissions and simple translations submissions (LB (Ben) Johnston)
|
||||
* Improve filtering of audit logging based on the user's permissions (Stefan Hammer)
|
||||
* Fix: Ensure that StreamField's `FieldBlock`s correctly set the `required` and `aria-describedby` attributes (Storm Heg)
|
||||
* Fix: Avoid an error when the moderation panel (admin dashboard) contains both snippets and private pages (Matt Westcott)
|
||||
|
@ -1022,7 +642,7 @@ Changelog
|
|||
* Maintenance: Deprecate legacy URL redirects in `ModelViewSet` and `SnippetViewSet` (Sage Abdullah)
|
||||
* Maintenance: Simplify code for registering page listing action buttons (Matt Westcott)
|
||||
* Maintenance: Removed the unused, legacy, Wagtail userbar views set up for an old iframe approach (Sage Abdullah)
|
||||
* Maintenance: Optimize `lru_cache` usage (Jake Howard)
|
||||
* Maintenance: Optimise `lru_cache` usage (Jake Howard)
|
||||
* Maintenance: Implement `date_since` in `get_most_popular` inside `search_promotions.models.Query` (TopDevPros)
|
||||
* Maintenance: Refactor generic view subclasses to better reuse the generic templates and breadcrumbs (Sage Abdullah)
|
||||
* Maintenance: Adopt consistent `classname` (not `classnames`) attributes for all `MenuItem` usage, including deprecation warnings (LB (Ben) Johnston)
|
||||
|
@ -1162,7 +782,7 @@ Changelog
|
|||
* Maintenance: Optimise use of `specific` on Task and TaskState (Matt Westcott)
|
||||
* Maintenance: Use table UI component for workflow task index view (Matt Westcott)
|
||||
* Maintenance: Make header search available on generic index view (Matt Westcott)
|
||||
* Maintenance: Update pagination behavior to reject out-of-range / invalid page numbers (Matt Westcott)
|
||||
* Maintenance: Update pagination behaviour to reject out-of-range / invalid page numbers (Matt Westcott)
|
||||
* Maintenance: Remove color tokens which are duplicates / unused (Thibaud Colas)
|
||||
* Maintenance: Add tests to help with maintenance of theme color tokens (Thibaud Colas)
|
||||
* Maintenance: Split out a base listing view from generic index view (Matt Westcott)
|
||||
|
@ -4401,7 +4021,7 @@ Changelog
|
|||
* Fix: Fixed TypeError when getting embed HTML with oembed on Python 3 (John-Scott Atlakson)
|
||||
* Fix: Made HTML whitelisting in rich text fields more robust at catching disallowed URL schemes such as "jav\tascript:" (Tim Heap)
|
||||
* Fix: created_at timestamps on page revisions were not being preserved on page copy, causing revisions to get out of sequence
|
||||
* Fix: When copying pages recursively, revisions of subpages were being copied regardless of the copy_revisions flag
|
||||
* Fix: When copying pages recursively, revisions of sub-pages were being copied regardless of the copy_revisions flag
|
||||
* Fix: Updated the migration dependencies within the project template to ensure that Wagtail's own migrations consistently apply first.
|
||||
* Fix: The cache of site root paths is now cleared when a site is deleted.
|
||||
* Fix: Search indexing now prevents pages from being indexed multiple times, as both the base Page model and the specific subclass
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Cynthia Kiser (Caltech)
|
||||
* Dan Braghis (Torchbox)
|
||||
* Dawn Wages (The Wharton School)
|
||||
* Emily Topp-Mugglestone (Torchbox)
|
||||
* Jacob Topp-Mugglestone (Torchbox)
|
||||
* Jake Howard (Torchbox)
|
||||
* Kalob Taulien
|
||||
* LB Johnston
|
||||
|
@ -15,7 +15,6 @@
|
|||
* Sævar Öfjörð Magnússon (Overcast)
|
||||
* Sage Abdullah (Torchbox)
|
||||
* Scott Cranfill (JPL)
|
||||
* Sébastien Corbin
|
||||
* Stefan Hammer (wunderweiss)
|
||||
* Storm Heg
|
||||
* Thibaud Colas (Torchbox)
|
||||
|
@ -720,6 +719,7 @@
|
|||
* Kevin Chung (kev-odin)
|
||||
* valnuro
|
||||
* Vitaly Babiy
|
||||
* Sébastien Corbin
|
||||
* Sahil Jangra
|
||||
* Henry Harutyunyan
|
||||
* Alex Morega
|
||||
|
@ -743,6 +743,7 @@
|
|||
* Sandro Rodrigues
|
||||
* Brian Mugo
|
||||
* Panagiotis H.M. Issaris
|
||||
* Damilola Oladele
|
||||
* Olumide Micheal
|
||||
* Chiemezuo Akujobi
|
||||
* Krish Soni
|
||||
|
@ -826,63 +827,11 @@
|
|||
* Romein van Buren
|
||||
* Chris Shenton
|
||||
* Nathanaël Jourdane
|
||||
* Vaughn Dickson
|
||||
* Ansuman Shukla
|
||||
* Nayanshi Singh
|
||||
* Daniel Black
|
||||
* Atif Khan
|
||||
* Sanjeev Holla S
|
||||
* Shubham Mukati
|
||||
* Matthew Scouten
|
||||
* Ishwari8104
|
||||
* Rahul Samant
|
||||
* Gabriel Getzie
|
||||
* Rohit Singh
|
||||
* Robin Varghese
|
||||
* Victoria Ottah
|
||||
* Bart Cieliński
|
||||
* alexkiro
|
||||
* Ankit Kumar
|
||||
* Frank Yiu
|
||||
* Shaurya Panchal
|
||||
* Sumana Sree Angajala
|
||||
* Srishti Jaiswal
|
||||
* Alessandro Chitarrini
|
||||
* Joel William
|
||||
* Ataf Fazledin Ahamed
|
||||
* Ayaan Qadri
|
||||
* manu
|
||||
* Aayushman Singh
|
||||
* Steven Steinwand
|
||||
* Clifford Gama
|
||||
* Noah van der Meer
|
||||
* Strapchay
|
||||
* Alex Fulcher
|
||||
* Harsh Dange
|
||||
* Mauro Soche
|
||||
* Krystian Magdziarz
|
||||
* Guilhem Saurel
|
||||
* James Harrington
|
||||
* Unyime Emmanuel Udoh
|
||||
* Joren Hammudoglu
|
||||
* Rishabh Sharma
|
||||
* Mike Gifford
|
||||
* Stéphane Blondon
|
||||
* Jatin Bhardwaj
|
||||
* Mohamed Rabiaa
|
||||
* Bernhard Bliem
|
||||
* Mahmoud Nasser
|
||||
* Prabhpreet Kaur
|
||||
* Baptiste Mispelon
|
||||
* Mohammad Fathi Rahman
|
||||
* Ashish Nagmoti
|
||||
* Dhruvi Patel
|
||||
* Sylvain Boissel
|
||||
|
||||
## Translators
|
||||
|
||||
* Afrikaans: Jaco du Plessis, Jared Osborn
|
||||
* Arabic: Bashar Al-Abdulhadi, Abdulaziz Alfuhigi, Roger Allen, Khaled Arnaout, Amr Awad, Tarek Berkane, Mohammed Abdul Gadir, Mohamed HossamElDin, Ahmad Kiswani, Waseem Kntar, Mahmoud Marayef, Mohamed Mayla, Ahmed Miske Sidi Med, Younes Oumakhou, Ultraify Media
|
||||
* Arabic: Bashar Al-Abdulhadi, Abdulaziz Alfuhigi, Roger Allen, Khaled Arnaout, Amr Awad, Mohammed Abdul Gadir, Mohamed HossamElDin, Ahmad Kiswani, Waseem Kntar, Mahmoud Marayef, Mohamed Mayla, Ahmed Miske Sidi Med, Younes Oumakhou, Ultraify Media
|
||||
* Armenian: Vachagan
|
||||
* Azerbaijani: Mirza Iskandarov
|
||||
* Bangla: Mahmud Abdur Rahman
|
||||
|
@ -898,11 +847,11 @@
|
|||
* Czech: Ales Dvorak, Jan Feřtek, Martin Galda, IT Management, Tomáš Jeřábek, Vláďa Macek, Eva Mikesova, Mořeplavec, Sophy O, Martina Oleksakova, Kryštof Pilnáček, Tomáš Podivínský, Ivan Pomykacz, Jiri Stepanek, Marek Turnovec, Mirek Zvolský
|
||||
* Danish: Benjamin Bach, Mads Kronborg, MRostgaard, Asger Sørensen
|
||||
* Divehi: Fauzaan Gasim
|
||||
* Dutch: benny_AT_it_digin.com, Bram, Ramon de Jezus Brecht Dervaux, Harmen, Storm Heg, Kees Hink, Huib Keemink, Franklin Kingma, Maarten Kling, Thijs Kramer, Samuel Leeuwenburg, mahulst, Meteor0id, Rob Moorman, Benjamin van Renterghem, Michael van Tellingen, Arne Turpyn, Coen van der Kamp, Joeri Vlekken, Richard Voorhorst
|
||||
* Dutch: benny_AT_it_digin.com, Bram, Ramon de Jezus Brecht Dervaux, Harmen, Storm Heg, Kees Hink, Huib Keemink, Franklin Kingma, Maarten Kling, Thijs Kramer, Samuel Leeuwenburg, mahulst, Meteor0id, Rob Moorman, Benjamin van Renterghem, Michael van Tellingen, Arne Turpyn, Coen van der Kamp, Richard Voorhorst
|
||||
* English (India): Neeraj PY, Apoorv Saini
|
||||
* Estonian: Erlend Eelmets, Martin, Ragnar Rebase
|
||||
* Finnish: Jiri Grönroos, Eetu Häivälä, Niklas Jerva, Aarni Koskela, Rauli Laine, Valter Maasalo, Glen Somerville, Juha Yrjölä
|
||||
* French: Adrien, Timothy Allen, Sebastien Andrivet, Bertrand Bordage, André Bouatchidzé, Christophe Chauvet, Sébastien Corbin, Aurélien Debord, Romain Dorgueil, Tom Dyson, Antonin Enfrun, Axel Haustant, Renaud Kern, Fabien Le Frapper, Léo, Pierre Marfoure, nahuel, Sophy O, Aurel Pere, Dominique Peretti, fpoulain, Loïc Teixeira, Benoît Vogel
|
||||
* French: Adrien, Timothy Allen, Sebastien Andrivet, Bertrand Bordage, André Bouatchidzé, Sébastien Corbin, Aurélien Debord, Romain Dorgueil, Tom Dyson, Antonin Enfrun, Axel Haustant, Renaud Kern, Fabien Le Frapper, Léo, Pierre Marfoure, nahuel, Sophy O, Aurel Pere, Dominique Peretti, fpoulain, Loïc Teixeira, Benoît Vogel
|
||||
* Galician: X Bello, Amós Oviedo
|
||||
* Georgian: André Bouatchidzé
|
||||
* German: Ettore Atalan, Bohreromir, Matti Borchers, Benedikt Breinbauer, Donald Buczek, Patrick Craston, Peter Dreuw, Oliver Engel, Stefan Hammer, Patrick Hebner, Krzysztof Jeziorny, Benjamin Kaspar, Henrik Kröger, Tibor L, Tammo van Lessen, Martin Löhle, Wasilis Mandratzis-Walz, Daniel Manser, Matthias Martin, m0rph3u5, Max Pfeiffer, Moritz Pfeiffer, Herbert Poul, Karl Sander, Tobias Schmidt, Scriptim, Johannes Spielmann, Raphael Stolt, Benjamin Thurm, Norman Uekermann, unicode_it, Jannis Vajen, Florian Vogt, Alexander Weiß, Matthew Westcott, Benedikt Willi
|
||||
|
@ -940,4 +889,4 @@
|
|||
* Ukrainian: Yuri Fabirovsky, Vladislav Herasimenko, Mikolai Incognito, Anastasiia La, Sergiy Shkodenko, Viktor Shytiuk, Ivan Tyshchenko, Zoriana Zaiats, Mykola Zamkovoi
|
||||
* Uyghur: Abduqadir Abliz, Azat
|
||||
* Vietnamese: Amelia Dao, Duc Huynh, Hồng Quân Nguyễn, Luan Nguyen, Vu Pham, stdpi
|
||||
* Welsh: Philip Lindsay-Crisp, Adam Hughes
|
||||
* Welsh: Philip Crisp, Adam Hughes
|
||||
|
|
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@ clean-pyc:
|
|||
find . -name '*~' -exec rm -f {} +
|
||||
|
||||
develop: clean-pyc
|
||||
pip install -e .[testing,docs] --config-settings editable-mode=strict
|
||||
pip install -e .[testing,docs]
|
||||
npm install --no-save && npm run build
|
||||
|
||||
lint-server:
|
||||
|
|
21
README.md
21
README.md
|
@ -19,8 +19,8 @@
|
|||
<a href="https://pypi.python.org/pypi/wagtail/">
|
||||
<img src="https://img.shields.io/pypi/dm/wagtail?logo=Downloads" alt="Monthly downloads" />
|
||||
</a>
|
||||
<a href="https://fosstodon.org/@wagtail">
|
||||
<img src="https://img.shields.io/mastodon/follow/109308882653647818?domain=https%3A%2F%2Ffosstodon.org&style=social" alt="Follow @wagtail@fosstodon.org">
|
||||
<a href="https://twitter.com/WagtailCMS">
|
||||
<img src="https://img.shields.io/twitter/follow/WagtailCMS?style=social&logo=twitter" alt="follow on Twitter">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
@ -28,6 +28,13 @@ Wagtail is an open source content management system built on Django, with a stro
|
|||
|
||||

|
||||
|
||||
### Join the Community at Wagtail Space! 🚀
|
||||
|
||||
Wagtail Space is coming in June 2024! Don't miss your chance to meet other Wagtailers in person. The Call for Participation and registration for both Wagtail Space 2024 events is open. We'd love to have you give a talk, contribute to a sprint, or join us as an attendee in June.
|
||||
|
||||
* [Wagtail Space NL](https://nl.wagtail.space/), Arnhem, The Netherlands. 2024-06-12 - 2024-06-14
|
||||
* [Wagtail Space US](https://us.wagtail.space/), Philadelphia, PA. 2024-06-20 to 2024-06-22
|
||||
|
||||
### 🔥 Features
|
||||
|
||||
- A fast, attractive interface for authors
|
||||
|
@ -70,7 +77,7 @@ Wagtail is used by [NASA](https://www.nasa.gov/), [Google](https://www.google.co
|
|||
|
||||
### 📖 Documentation
|
||||
|
||||
[docs.wagtail.org](https://docs.wagtail.org/) is the full reference for Wagtail, and includes guides for developers, designers and editors, alongside [release notes](https://docs.wagtail.org/en/stable/releases/) and our [roadmap](https://wagtail.org/roadmap/).
|
||||
[docs.wagtail.org](https://docs.wagtail.org/) is the full reference for Wagtail, and includes guides for developers, designers and editors, alongside release notes and our roadmap.
|
||||
|
||||
For those who are **new to Wagtail**, the [Zen of Wagtail](https://docs.wagtail.org/en/stable/getting_started/the_zen_of_wagtail.html) will help you understand what Wagtail is, and what Wagtail is _not_.
|
||||
|
||||
|
@ -84,11 +91,11 @@ _(If you are reading this on GitHub, the details here may not be indicative of t
|
|||
|
||||
Wagtail supports:
|
||||
|
||||
- Django 4.2.x and 5.1.x
|
||||
- Python 3.9, 3.10, 3.11, 3.12 and 3.13
|
||||
- PostgreSQL, MySQL, MariaDB and SQLite (with JSON1) as database backends
|
||||
- Django 4.2.x and 5.0.x
|
||||
- Python 3.8, 3.9, 3.10, 3.11 and 3.12
|
||||
- PostgreSQL, MySQL and SQLite (with JSON1) as database backends
|
||||
|
||||
[Previous versions of Wagtail](https://docs.wagtail.org/en/stable/releases/upgrading.html#compatible-django-python-versions) additionally supported Python 2.7, 3.8 and earlier Django versions.
|
||||
[Previous versions of Wagtail](https://docs.wagtail.org/en/stable/releases/upgrading.html#compatible-django-python-versions) additionally supported Python 2.7, 3.7 and earlier Django versions.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ The following organisations and individuals supported the [Wagtail's First Hatch
|
|||
- [Taywa](https://www.taywa.ch/)
|
||||
- [Rock Kitchen Harris](https://www.rkh.co.uk/)
|
||||
- [The Motley Fool](https://www.fool.com/)
|
||||
- [R Strother Scott](https://x.com/rstrotherscott)
|
||||
- [R Strother Scott](https://twitter.com/rstrotherscott)
|
||||
- [Beyond Media](https://www.beyond.works/)
|
||||
|
||||
The features below were developed thanks to the sponsorship of these organsations:
|
||||
|
@ -38,7 +38,7 @@ The features below were developed thanks to the sponsorship of these organsation
|
|||
|
||||
- Page aliases - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
|
||||
|
||||
- Hooks for Snippet customization - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
|
||||
- Hooks for Snippet customisation - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
|
||||
|
||||
- Utility for testing hooks - [The Mozilla Foundation](https://foundation.mozilla.org/en/)
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
@forward 'settings/variables';
|
||||
@import 'settings/variables';
|
||||
|
|
|
@ -3,8 +3,8 @@ These are functions and mixins.
|
|||
No CSS should be produced by these files.
|
||||
*/
|
||||
|
||||
@forward 'tools/functions.breakpoints';
|
||||
@forward 'tools/mixins.breakpoints';
|
||||
@forward 'tools/mixins.general';
|
||||
@forward 'tools/mixins.grid';
|
||||
@forward 'tools/mixins.guide-line';
|
||||
@import 'tools/functions.breakpoints';
|
||||
@import 'tools/mixins.breakpoints';
|
||||
@import 'tools/mixins.general';
|
||||
@import 'tools/mixins.grid';
|
||||
@import 'tools/mixins.guide-line';
|
||||
|
|
|
@ -1,22 +1,13 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-a11y-result__row {
|
||||
@include box;
|
||||
padding: theme('spacing.4');
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: theme('colors.surface-page');
|
||||
padding: theme('spacing.4');
|
||||
border-radius: theme('borderRadius.DEFAULT');
|
||||
color: theme('colors.text-context');
|
||||
border: 1px solid theme('colors.border-furniture');
|
||||
|
||||
// Shows additional details within the CMS only.
|
||||
.form-side--checks & {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@include more-contrast() {
|
||||
border-color: theme('colors.border-furniture-more-contrast');
|
||||
}
|
||||
}
|
||||
|
||||
.w-a11y-result__header {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
// user avatars
|
||||
.avatar {
|
||||
border-radius: 100%;
|
||||
|
@ -31,12 +29,9 @@
|
|||
}
|
||||
|
||||
&.large {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,33 +39,3 @@
|
|||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar--edit {
|
||||
overflow: visible;
|
||||
flex-shrink: 0;
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
z-index: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar__edit-link {
|
||||
width: theme('spacing.5');
|
||||
height: theme('spacing.5');
|
||||
border-radius: 50%;
|
||||
border: theme('spacing.px') solid theme('colors.border-furniture');
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
inset-inline-start: 50%;
|
||||
transform: translate(calc(var(--w-direction-factor) * -50%), -50%);
|
||||
background-color: theme('colors.surface-page');
|
||||
|
||||
.icon {
|
||||
width: theme('spacing.[2.5]');
|
||||
height: theme('spacing.[2.5]');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-breadcrumbs:not(.editor-view .w-breadcrumbs) {
|
||||
@apply sm:w-py-2.5;
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.bulk-actions-filter-checkbox {
|
||||
.table-headers & {
|
||||
> div {
|
||||
|
@ -65,10 +63,7 @@
|
|||
}
|
||||
|
||||
.num-objects-in-listing {
|
||||
// This is inside the footer, which has a dark indigo background in light
|
||||
// mode, so we want to use the absolute value of dark mode's
|
||||
// text-link-default instead of its dynamic value.
|
||||
color: theme('colors.secondary.100');
|
||||
color: theme('colors.text-link-default');
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
font-family: theme('fontFamily.sans');
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
// Core button styles
|
||||
|
||||
@use 'sass:color';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.button {
|
||||
border-radius: theme('borderRadius.sm');
|
||||
|
@ -327,8 +325,7 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: theme('spacing.1');
|
||||
height: theme('spacing.8');
|
||||
min-width: theme('spacing.8');
|
||||
height: theme('spacing.7');
|
||||
appearance: none;
|
||||
background-color: initial;
|
||||
border: 1px solid transparent;
|
||||
|
@ -338,8 +335,6 @@
|
|||
font-weight: theme('fontWeight.medium');
|
||||
cursor: pointer;
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
.icon {
|
||||
width: theme('spacing.4');
|
||||
height: theme('spacing.4');
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@use 'sass:math';
|
||||
@use '../tools' as *;
|
||||
|
||||
$preview-size: 2.625rem; // 42px
|
||||
|
||||
|
@ -23,8 +22,6 @@ $preview-size: 2.625rem; // 42px
|
|||
border-color: transparent;
|
||||
padding: theme('spacing.[1.5]');
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
.icon {
|
||||
@include svg-icon(theme('spacing.4'), initial);
|
||||
color: inherit;
|
||||
|
@ -84,6 +81,11 @@ $preview-size: 2.625rem; // 42px
|
|||
width: auto;
|
||||
}
|
||||
|
||||
.chooser .w-dropdown__toggle--icon {
|
||||
width: $preview-size;
|
||||
height: $preview-size;
|
||||
}
|
||||
|
||||
// Display these as inline block so that action icons such as comments can appear as close as possible
|
||||
.w-field--admin_task_chooser,
|
||||
.w-field--admin_page_chooser,
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-dialog {
|
||||
--w-dialog-close-icon-color: theme('colors.icon-primary');
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
// stylelint-disable selector-attribute-name-disallowed-list
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
$separator: 1px solid theme('colors.white-15');
|
||||
$radius: theme('borderRadius.sm');
|
||||
|
||||
|
@ -29,7 +26,17 @@ $radius: theme('borderRadius.sm');
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
&:has(:not([hidden]) > [data-placement^='bottom']) {
|
||||
@supports not selector(:has(*)) {
|
||||
// Use no corner radius and always-on borders if `:has` is not supported.
|
||||
--primary-button-radius-top: 0;
|
||||
--primary-button-radius-bottom: 0;
|
||||
--toggle-button-radius-top: 0;
|
||||
--toggle-button-radius-bottom: 0;
|
||||
--first-item-border-top: #{$separator};
|
||||
--last-item-border-top: #{$separator};
|
||||
}
|
||||
|
||||
&:has([data-placement^='bottom']) {
|
||||
--primary-button-radius-top: #{$radius};
|
||||
--primary-button-radius-bottom: 0;
|
||||
--toggle-button-radius-top: #{$radius};
|
||||
|
@ -39,7 +46,7 @@ $radius: theme('borderRadius.sm');
|
|||
--first-item-border-top: #{$separator};
|
||||
}
|
||||
|
||||
&:has(:not([hidden]) > [data-placement^='top']) {
|
||||
&:has([data-placement^='top']) {
|
||||
--primary-button-radius-top: 0;
|
||||
--primary-button-radius-bottom: #{$radius};
|
||||
--toggle-button-radius-top: 0;
|
||||
|
@ -118,3 +125,8 @@ $radius: theme('borderRadius.sm');
|
|||
border-bottom-color: theme('colors.warning.100');
|
||||
}
|
||||
}
|
||||
|
||||
// Reduces the visibility of secondary actions like "Unpublish" or "Delete".
|
||||
.w-dropdown-button .action-secondary {
|
||||
color: theme('colors.text-label-menus-default');
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
.w-dropdown__toggle {
|
||||
@apply w-px-2 w-text-text-label w-bg-transparent w-border-2 w-border-transparent;
|
||||
@apply w-px-2 w-text-text-label w-bg-transparent;
|
||||
}
|
||||
|
||||
.w-dropdown__toggle--icon {
|
||||
@apply w-w-8 w-h-8 more-contrast:w-p-0 more-contrast:w-border more-contrast:w-rounded-sm more-contrast:w-border-border-interactive-more-contrast hover:more-contrast:w-border-border-interactive-more-contrast-hover;
|
||||
@apply w-w-8 w-h-8;
|
||||
}
|
||||
|
||||
.w-dropdown__toggle-icon {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.filterable {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr minmax(theme('spacing.48'), theme('spacing.64'));
|
||||
|
@ -36,8 +34,6 @@
|
|||
color: theme('colors.text-link-default');
|
||||
background-color: theme('backgroundColor.surface-header');
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
.icon {
|
||||
width: theme('fontSize.16');
|
||||
height: theme('fontSize.16');
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
@use 'sass:math';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.footer {
|
||||
@include transition(bottom 0.5s ease 1s);
|
||||
|
@ -32,9 +30,8 @@
|
|||
.footer__container {
|
||||
border-radius: theme('borderRadius.sm') theme('borderRadius.sm') 0 0;
|
||||
background: theme('colors.surface-menus');
|
||||
color: theme('colors.text-button');
|
||||
color: theme('colors.text-label-menus-default');
|
||||
transition: transform 1s;
|
||||
padding: theme('spacing.1');
|
||||
|
||||
@include media-breakpoint-down(xs) {
|
||||
width: 100%;
|
||||
|
@ -63,18 +60,22 @@
|
|||
}
|
||||
|
||||
.footer__save-warning {
|
||||
font-size: theme('fontSize.14');
|
||||
height: 100%;
|
||||
font-size: 0.95em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
|
||||
.icon {
|
||||
font-size: 1.2em;
|
||||
margin-inline-end: 0.5em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
margin: -0.2em 0 0 0;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin-inline-end: theme('spacing[1.5]');
|
||||
margin-inline-end: 50px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
@ -133,13 +134,7 @@
|
|||
.actions .w-dropdown-button {
|
||||
width: 100%;
|
||||
|
||||
.w-dropdown .button {
|
||||
font-size: theme('fontSize.14');
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
> .button {
|
||||
font-size: theme('fontSize.16');
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
@use 'sass:color';
|
||||
@use 'sass:map';
|
||||
@use 'sass:math';
|
||||
@use '../tools' as *;
|
||||
|
||||
.side-panel-open {
|
||||
@apply w-overflow-y-hidden sm:w-overflow-y-auto;
|
||||
|
@ -37,8 +36,7 @@
|
|||
sm:w-max-w-[22.5rem]
|
||||
md:w-max-w-[35.937rem]
|
||||
lg:w-max-w-[31.25rem]
|
||||
xl:w-max-w-[46.875rem]
|
||||
more-contrast:w-border-border-furniture-more-contrast;
|
||||
xl:w-max-w-[46.875rem];
|
||||
z-index: calc(theme('zIndex.header') - 10);
|
||||
width: var(--side-panel-width, 100%);
|
||||
|
||||
|
@ -86,6 +84,13 @@
|
|||
&:focus-within:has(:focus-visible) {
|
||||
@include focus-outline;
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
&:focus-within {
|
||||
/* Fallback for browsers without :focus-visible support */
|
||||
@include focus-outline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__resize-grip-icon {
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.wrapper {
|
||||
@include clearfix();
|
||||
@apply w-transition-sidebar;
|
||||
|
@ -17,30 +14,27 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Increase the scroll offset to account for pages with sticky areas - header or footer.
|
||||
* Increase the scroll offset to account for pages with a sticky header.
|
||||
* We apply this to all pages for simplicity.
|
||||
*/
|
||||
@mixin sticky-areas-scroll-offset() {
|
||||
@mixin slim-header-scroll-offset() {
|
||||
$gap: theme('spacing.4');
|
||||
// For mobile viewports, expect a sticky header over two rows.
|
||||
scroll-padding-top: calc(theme('spacing.slim-header') * 2 + $gap);
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
scroll-padding-top: calc(theme('spacing.slim-header') + $gap);
|
||||
// Increase the scroll offset to account for pages with sticky bottom button
|
||||
scroll-padding-bottom: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
@include slim-header-scroll-offset();
|
||||
scroll-behavior: smooth;
|
||||
width: 100%;
|
||||
height: 100%; // this has no effect on desktop, but on mobile it helps aesthetics of menu popout action
|
||||
float: inline-start;
|
||||
position: relative;
|
||||
border-bottom: 1px solid theme('colors.border-furniture');
|
||||
|
||||
@include sticky-areas-scroll-offset();
|
||||
}
|
||||
|
||||
.content {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
@use 'sass:math';
|
||||
@use 'sass:color';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.w-header {
|
||||
@apply w-text-text-label;
|
||||
|
@ -29,6 +27,10 @@
|
|||
max-width: 1em;
|
||||
max-height: 1em;
|
||||
}
|
||||
|
||||
&.avatar {
|
||||
margin-inline-start: calc(0 - theme('spacing.2'));
|
||||
}
|
||||
}
|
||||
|
||||
.w-header__subtitle {
|
||||
|
@ -36,6 +38,11 @@
|
|||
font-weight: theme('fontWeight.normal');
|
||||
}
|
||||
|
||||
.w-header__description {
|
||||
font-size: theme('fontSize.18');
|
||||
font-weight: theme('fontWeight.normal');
|
||||
}
|
||||
|
||||
// Give padding to the rows inside of headers so that nested breadcrumbs aren't padded by their parent header el.
|
||||
// Use w-header--with-padding for headers that don't contain .row elements.
|
||||
&.w-header--with-padding,
|
||||
|
@ -97,6 +104,10 @@
|
|||
margin-inline-end: 2em;
|
||||
}
|
||||
|
||||
.avatar.small {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: theme('fontWeight.bold');
|
||||
}
|
||||
|
@ -115,6 +126,12 @@
|
|||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
.w-header__glyph {
|
||||
&.avatar {
|
||||
margin-inline-start: calc(0 - theme('spacing.9'));
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
float: inline-start;
|
||||
margin-inline-end: 0;
|
||||
|
@ -153,10 +170,6 @@
|
|||
}
|
||||
|
||||
.w-slim-header {
|
||||
@include more-contrast() {
|
||||
border-color: theme('colors.border-furniture-more-contrast');
|
||||
}
|
||||
|
||||
&__search-form {
|
||||
@apply w-mx-2 w-flex w-items-center w-gap-2;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@use 'sass:color';
|
||||
@use 'sass:map';
|
||||
@use '../tools' as *;
|
||||
// Help text formatters
|
||||
.help-block {
|
||||
padding: 1em;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
@use 'sass:string';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
// Set SVG icons to use the current text color in the location they appear as
|
||||
// their default fill color. Can be overridden for a specific icon by either
|
||||
|
|
|
@ -1,17 +1,3 @@
|
|||
.indicator {
|
||||
margin-inline-end: 0;
|
||||
opacity: theme('opacity.70');
|
||||
|
||||
.icon {
|
||||
padding: 2px;
|
||||
vertical-align: middle; // reset vertical-align set by icon.initial
|
||||
}
|
||||
|
||||
&--is-dimmed {
|
||||
opacity: theme('opacity.50');
|
||||
}
|
||||
}
|
||||
|
||||
.privacy-indicator {
|
||||
&.public {
|
||||
.label-private {
|
||||
|
@ -25,3 +11,31 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.indicator {
|
||||
font-size: 1em;
|
||||
margin-inline-end: 0;
|
||||
opacity: theme('opacity.70');
|
||||
|
||||
.icon {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 50%;
|
||||
font-size: 1.25em;
|
||||
padding: 2px;
|
||||
vertical-align: middle; // reset vertical-align set by icon.initial
|
||||
|
||||
@media (forced-colors: active) {
|
||||
background-color: ButtonText;
|
||||
}
|
||||
}
|
||||
|
||||
&.indicator--is-inverse {
|
||||
.icon {
|
||||
border-color: theme(
|
||||
'colors.surface-page'
|
||||
); // ensure border is available for high contrast mode
|
||||
background-color: theme('colors.text-context');
|
||||
color: theme('colors.surface-page');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
/* stylelint-disable selector-max-combinators */
|
||||
// General listings, like for pages, images or snippets
|
||||
ul.listing {
|
||||
|
@ -29,7 +27,6 @@ ul.listing {
|
|||
|
||||
td,
|
||||
th {
|
||||
text-align: start;
|
||||
padding: calc(1em * var(--w-density-factor)) 0.3em;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
|
@ -52,7 +49,6 @@ ul.listing {
|
|||
|
||||
td {
|
||||
vertical-align: middle;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
td.title {
|
||||
|
@ -66,6 +62,7 @@ ul.listing {
|
|||
|
||||
th {
|
||||
font-size: 0.9em;
|
||||
text-align: start;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -90,8 +87,8 @@ ul.listing {
|
|||
}
|
||||
|
||||
&:has(
|
||||
td:first-child input[type='checkbox']:only-child,
|
||||
th:first-child input[type='checkbox']:only-child
|
||||
td:first-child input[type='checkbox'],
|
||||
th:first-child input[type='checkbox']
|
||||
) {
|
||||
td:first-child,
|
||||
th:first-child {
|
||||
|
@ -100,7 +97,6 @@ ul.listing {
|
|||
width: theme('spacing.10');
|
||||
text-align: center;
|
||||
|
||||
// stylelint-disable-next-line selector-max-specificity
|
||||
input[type='checkbox'] {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
@ -368,79 +364,6 @@ ul.listing {
|
|||
@include transition(border-color 0.2s ease);
|
||||
border: 3px solid theme('colors.surface-page');
|
||||
}
|
||||
|
||||
&--dashboard {
|
||||
margin-bottom: 0;
|
||||
|
||||
tbody {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
td:first-child {
|
||||
padding-inline-start: theme('spacing.6');
|
||||
}
|
||||
|
||||
td:last-child {
|
||||
padding-inline-end: theme('spacing.6');
|
||||
}
|
||||
|
||||
.title a {
|
||||
font-weight: theme('fontWeight.medium');
|
||||
}
|
||||
|
||||
.w-status--label {
|
||||
float: inline-end;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.indicator .icon {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.privacy-indicator {
|
||||
margin-inline-end: theme('spacing.2');
|
||||
|
||||
// Adjust icon size to closely match the appearance of the adjacent 'locked' icon
|
||||
.icon-no-view {
|
||||
width: 1.1em;
|
||||
height: 1.1em;
|
||||
}
|
||||
}
|
||||
|
||||
.tasks {
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
|
||||
.actions li {
|
||||
float: inline-end;
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
display: grid;
|
||||
|
||||
tr {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: theme('spacing.2');
|
||||
padding: theme('spacing.5');
|
||||
}
|
||||
|
||||
td,
|
||||
td:first-child,
|
||||
td:last-child {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.actions-container {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.image-choice {
|
||||
|
@ -651,8 +574,8 @@ table.listing {
|
|||
}
|
||||
|
||||
&:has(
|
||||
td:first-child input[type='checkbox']:only-child,
|
||||
th:first-child input[type='checkbox']:only-child
|
||||
td:first-child input[type='checkbox'],
|
||||
th:first-child input[type='checkbox']
|
||||
) {
|
||||
// Bulk actions, match the width of the header spacing up until
|
||||
// the page title (final breadcrumb item):
|
||||
|
@ -673,8 +596,8 @@ table.listing {
|
|||
// custom ordering is active, as the padding to match the breadcrumbs is
|
||||
// already handled by the first column.
|
||||
&:has(
|
||||
td:first-child input[type='checkbox']:only-child,
|
||||
th:first-child input[type='checkbox']:only-child,
|
||||
td:first-child input[type='checkbox'],
|
||||
th:first-child input[type='checkbox'],
|
||||
.ord
|
||||
) {
|
||||
th:nth-child(2),
|
||||
|
@ -687,19 +610,17 @@ table.listing {
|
|||
// - no nice padding is applied,
|
||||
// - we're not in a report listing,
|
||||
// - we're not in the editor view,
|
||||
// - we're not in the dashboard view,
|
||||
// and:
|
||||
// - no bulk actions are present,
|
||||
// - we're not in the "custom ordering" mode,
|
||||
// then apply the same 80px padding via the first column's left padding.
|
||||
&:not(.nice-padding &, .report &, .editor-view &, .w-dashboard &):not(
|
||||
&:not(.nice-padding &, .report &, .editor-view &):not(
|
||||
:has(
|
||||
td:first-child input[type='checkbox']:only-child,
|
||||
th:first-child input[type='checkbox']:only-child,
|
||||
td:first-child input[type='checkbox'],
|
||||
th:first-child input[type='checkbox'],
|
||||
.ord
|
||||
)
|
||||
) {
|
||||
// stylelint-disable-next-line selector-max-specificity
|
||||
th:first-child,
|
||||
td:first-child {
|
||||
padding-inline-start: theme('spacing.20');
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@use 'sass:map';
|
||||
@use '../settings' as *;
|
||||
// Loading mask: overlays a certain area with a loading spinner and a faded out cover to prevent interaction
|
||||
.loading-mask {
|
||||
&.loading {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
// Messages are specific to Django's 'Messaging' system which adds messages into the session,
|
||||
// for display on the next page visited. These appear as an animated banner at the top of the page.
|
||||
// For inline help text, see typography.scss
|
||||
|
@ -60,10 +58,6 @@
|
|||
.warning {
|
||||
background-color: theme('colors.warning.100');
|
||||
color: theme('colors.grey.600');
|
||||
|
||||
@include more-contrast() {
|
||||
background-color: theme('colors.warning.75');
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
$zindex-modal-background: 500;
|
||||
|
||||
.fade {
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
$header-icon-size: theme('spacing.4');
|
||||
$header-button-size: theme('spacing.6');
|
||||
|
||||
|
@ -74,8 +71,6 @@ $header-button-size: theme('spacing.6');
|
|||
width: $header-button-size;
|
||||
height: $header-button-size;
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
&:focus-visible,
|
||||
&:hover {
|
||||
color: theme('colors.icon-primary-hover');
|
||||
|
@ -165,26 +160,3 @@ $header-button-size: theme('spacing.6');
|
|||
.w-panel__wrapper {
|
||||
@include max-form-width();
|
||||
}
|
||||
|
||||
.w-panel--dashboard {
|
||||
background-color: theme('colors.surface-dashboard-panel');
|
||||
border: 1px solid theme('colors.border-furniture');
|
||||
border-radius: 5px;
|
||||
margin-bottom: calc(
|
||||
theme('spacing.4') + theme('spacing.4') * var(--w-density-factor)
|
||||
);
|
||||
|
||||
.w-panel__header {
|
||||
padding: theme('spacing.5');
|
||||
margin-inline-start: 0;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin-inline-start: calc(-1 * theme('spacing.5'));
|
||||
}
|
||||
}
|
||||
|
||||
.w-panel__heading {
|
||||
margin-inline-start: theme('spacing.2');
|
||||
white-space: wrap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-preview {
|
||||
.preview-panel {
|
||||
--w-preview-background-color: var(--w-color-white);
|
||||
--w-preview-color-scheme: normal;
|
||||
--preview-width-ratio: min(
|
||||
1,
|
||||
var(--preview-panel-width, 450) / var(--preview-device-width, 375)
|
||||
|
@ -40,16 +37,6 @@
|
|||
&:empty {
|
||||
// Ensure that sites without a background show with a fallback, only when iframe has loaded
|
||||
background-color: var(--w-preview-background-color);
|
||||
// Sites that do not have a background but have color-scheme will have the
|
||||
// colors (background, text, etc.) automatically styled by the browser.
|
||||
// If the color-scheme matches Wagtail's current color-scheme, the browser
|
||||
// will give the iframe a transparent background. If we only set the
|
||||
// white background-color above, the white background will be used
|
||||
// while the rest of the content follows the color-scheme of the site,
|
||||
// which might result in white text on a white background.
|
||||
// Since we cannot know the actual value of the content's color-scheme,
|
||||
// we set the color-scheme to normal to ensure the iframe stays opaque.
|
||||
color-scheme: var(--w-preview-color-scheme);
|
||||
}
|
||||
|
||||
[dir='rtl'] & {
|
||||
|
@ -72,11 +59,6 @@
|
|||
gap: 0.75rem;
|
||||
padding-bottom: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
@include more-contrast() {
|
||||
border-color: theme('colors.border-furniture-more-contrast');
|
||||
}
|
||||
}
|
||||
|
||||
&__size-button {
|
||||
|
@ -91,12 +73,7 @@
|
|||
place-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&--selected,
|
||||
&--selected:hover {
|
||||
@apply w-bg-surface-menus w-text-text-button w-transform-none w-border w-border-transparent;
|
||||
}
|
||||
|
||||
&:focus-within:has(:focus-visible) {
|
||||
&:focus-within {
|
||||
@include focus-outline;
|
||||
}
|
||||
|
||||
|
@ -112,25 +89,25 @@
|
|||
@include svg-icon(0.9rem);
|
||||
}
|
||||
}
|
||||
|
||||
input[type='radio'] {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__refresh-button.button--icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
padding: 0;
|
||||
top: 1.25rem;
|
||||
inset-inline-end: 1.5rem;
|
||||
|
||||
// Use element and class selectors to beat .button-longrunning specificity
|
||||
svg.icon,
|
||||
svg.icon-spinner {
|
||||
margin-inline-end: 0;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
.icon {
|
||||
@include svg-icon(0.9rem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,6 +117,12 @@
|
|||
inset-inline-end: 1.5rem;
|
||||
}
|
||||
|
||||
&--mobile &__size-button--mobile,
|
||||
&--tablet &__size-button--tablet,
|
||||
&--desktop &__size-button--desktop {
|
||||
@apply w-bg-surface-menus w-text-text-button w-transform-none w-border w-border-transparent;
|
||||
}
|
||||
|
||||
&__controls {
|
||||
@apply w-border-t w-border-transparent w-duration-500 w-ease-in-out;
|
||||
transition-property: border-color, margin-top, padding-top;
|
||||
|
@ -148,7 +131,7 @@
|
|||
|
||||
// Show the border only if there's an error,
|
||||
// but always show it if there are multiple preview modes
|
||||
.w-preview--has-errors &:not(&--multiple),
|
||||
.preview-panel--has-errors &:not(&--multiple),
|
||||
&--multiple {
|
||||
@apply w-border-border-furniture w-border-t;
|
||||
padding-top: 1rem;
|
||||
|
@ -201,22 +184,4 @@
|
|||
&__mode-select {
|
||||
@apply w-outline-offset-inside;
|
||||
}
|
||||
|
||||
// A hidden element that is only rendered for functionality purposes,
|
||||
// but is not visible to the user. Used by radio inputs for preview sizes and
|
||||
// the iframe while it's loading. We nest the selector rather than suffixing
|
||||
// the parent selector to beat the specificity of input[type="radio"] styles
|
||||
.w-preview__proxy {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
|
||||
// Remove mask-image from radio inputs to avoid loading the default icon,
|
||||
// use extra specificity to beat the default styles
|
||||
&:is(input[type='radio'])::before {
|
||||
content: none;
|
||||
mask-image: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.progress {
|
||||
border-radius: 1.2em;
|
||||
background-color: theme('colors.surface-button-hover');
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@use 'sass:color';
|
||||
@use '../settings' as *;
|
||||
|
||||
.w-status {
|
||||
border-radius: 2px;
|
||||
|
@ -20,6 +19,7 @@
|
|||
|
||||
&.w-status--primary {
|
||||
color: theme('colors.text-meta');
|
||||
border: 1px solid theme('colors.text-meta');
|
||||
background: theme('colors.surface-page');
|
||||
}
|
||||
|
||||
|
@ -57,10 +57,8 @@ button.w-status:hover {
|
|||
color: theme('colors.text-button-outline-hover');
|
||||
}
|
||||
|
||||
// Special case for text-transform: uppercase.
|
||||
.page-status-tag {
|
||||
@apply w-inline-flex w-items-center w-justify-center w-whitespace-nowrap w-px-1 w-ml-3 w-text-11 w-rounded-sm w-bg-transparent w-text-text-meta w-border w-border-border-furniture w-no-underline w-font-semibold hover:w-border-surface-menus hover:w-text-text-label w-transition more-contrast:w-border more-contrast:w-border-border-interactive-more-contrast hover:more-contrast:w-border-border-interactive-more-contrast-hover;
|
||||
|
||||
// Special case for text-transform: uppercase.
|
||||
// stylelint-disable-next-line property-disallowed-list
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
|
|
@ -1,34 +1,69 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.w-summary {
|
||||
// set up responsive font size for icon and number as local custom property
|
||||
--w-summary-item-font-size: clamp(
|
||||
theme('fontSize.30') * 1.5,
|
||||
6.5vw,
|
||||
calc(theme('fontSize.30') * 3)
|
||||
);
|
||||
|
||||
color: theme('colors.text-link-default');
|
||||
margin-bottom: theme('spacing.3');
|
||||
padding-top: theme('spacing.1');
|
||||
margin-bottom: theme('spacing.8');
|
||||
padding-top: theme('spacing.8');
|
||||
|
||||
.w-summary__list {
|
||||
@include unlist();
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: theme('spacing.8');
|
||||
justify-content: space-evenly;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Summary item */
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
flex-wrap: nowrap;
|
||||
gap: theme('spacing.[2.5]');
|
||||
margin-bottom: theme('spacing.6');
|
||||
}
|
||||
|
||||
/* Summary icon */
|
||||
.icon {
|
||||
@include svg-icon(1.375rem);
|
||||
color: theme('colors.icon-primary');
|
||||
font-size: var(--w-summary-item-font-size);
|
||||
height: 1em;
|
||||
margin-inline-end: 0.15em;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
/* Summary label (a link, use parent colours ) */
|
||||
a {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
color: inherit;
|
||||
text-align: start;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
gap: theme('spacing.[1.5]');
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
font-size: theme('fontSize.18');
|
||||
}
|
||||
|
||||
/* Summary big number */
|
||||
> span {
|
||||
display: block;
|
||||
font-size: calc(var(--w-summary-item-font-size) * 0.6);
|
||||
font-weight: theme('fontWeight.bold');
|
||||
line-height: 0.9em; // label underneath to come in tight against the number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Media for Windows High Contrast Mode
|
||||
@media (forced-colors: active) {
|
||||
.w-summary {
|
||||
.icon {
|
||||
color: LinkText;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
@use 'sass:map';
|
||||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
// free tagging tags from taggit
|
||||
.tag {
|
||||
border-radius: 2px;
|
||||
|
@ -40,16 +37,16 @@ a.tag:hover {
|
|||
|
||||
.tagfilter {
|
||||
legend {
|
||||
@include media-breakpoint-up(sm) {
|
||||
@include column(2);
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
font-weight: 700;
|
||||
color: theme('colors.text-context');
|
||||
font-size: 1.1em;
|
||||
display: block;
|
||||
padding: 0 0 0.8em;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
@include column(2);
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
@use 'sass:map';
|
||||
@use 'sass:math';
|
||||
@use 'sass:string';
|
||||
@use '../tools' as *;
|
||||
|
||||
// =============================================================================
|
||||
// Variables
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.workflow-timeline {
|
||||
@apply w-label-3;
|
||||
padding: 0;
|
||||
|
@ -43,14 +41,13 @@
|
|||
position: relative;
|
||||
flex-shrink: 0;
|
||||
background: theme('colors.surface-page');
|
||||
@media (forced-colors: active) {
|
||||
background: Canvas;
|
||||
}
|
||||
margin-inline-end: theme('spacing.[2.5]');
|
||||
width: theme('spacing.5');
|
||||
height: theme('spacing.5');
|
||||
z-index: theme('zIndex.10');
|
||||
|
||||
@media (forced-colors: active) {
|
||||
background: Canvas;
|
||||
}
|
||||
}
|
||||
|
||||
&__line {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
.browsermessage {
|
||||
margin: 0 0 0 -150px;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../../settings' as *;
|
||||
|
||||
// file drop zones
|
||||
.drop-zone {
|
||||
border-radius: 5px;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@use 'sass:map';
|
||||
@use '../../settings' as *;
|
||||
|
||||
.error-message {
|
||||
border: 1px solid transparent; // ensure visible separation in Windows High Contrast mode
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@use '../../tools' as *;
|
||||
|
||||
// Comments
|
||||
$icon-size: theme('spacing.4');
|
||||
$button-padding: theme('spacing.2');
|
||||
|
||||
|
@ -54,6 +53,14 @@ $button-padding: theme('spacing.2');
|
|||
transform: translateY(0);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.w-field--date_field &,
|
||||
.w-field--date_time_field &,
|
||||
.w-field--time_field & {
|
||||
position: relative;
|
||||
transform: translateY(0);
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.w-field__comment-button--add {
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
@use '../../tools' as *;
|
||||
|
||||
.w-field-row {
|
||||
@include max-form-width();
|
||||
// Ensure there is enough room for a comment button within the gap.
|
||||
gap: theme('spacing.7');
|
||||
gap: theme('spacing.5');
|
||||
// For mobile viewports, we attempt to display all items in the row side by side even if not at the desired size.
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
@use 'sass:map';
|
||||
@use '../../settings' as *;
|
||||
@use './input-base' as *;
|
||||
|
||||
/**
|
||||
* A container for rendering human-readable field values in forms in a way
|
||||
|
@ -8,7 +6,9 @@
|
|||
*/
|
||||
|
||||
.w-field__textoutput {
|
||||
@include input-base();
|
||||
@apply w-body-text-large;
|
||||
background-color: theme('colors.surface-field-inactive');
|
||||
width: 100%;
|
||||
padding: theme('spacing.[1.5]') theme('spacing.5');
|
||||
min-height: $text-input-height;
|
||||
|
@ -16,13 +16,6 @@
|
|||
overflow: hidden;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
@include input-base();
|
||||
|
||||
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
|
||||
& {
|
||||
background-color: theme('colors.surface-field-inactive');
|
||||
}
|
||||
|
||||
&,
|
||||
&:hover {
|
||||
border-color: theme('colors.border-field-inactive');
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
@use 'sass:map';
|
||||
@use '../../tools' as *;
|
||||
@use '../../settings' as *;
|
||||
|
||||
/**
|
||||
* The field component handles form fields’ layout and ancillary elements such as error messages and help text.
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
@use '../../tools' as *;
|
||||
@use '../../settings' as *;
|
||||
|
||||
.w-form-width {
|
||||
@include max-form-width();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../../tools' as *;
|
||||
|
||||
/**
|
||||
* Field styles reusable across **all** fields, including:
|
||||
* Text input, textarea, checkbox, radio, select, etc.
|
||||
|
@ -11,8 +9,6 @@
|
|||
background-color: theme('colors.surface-field');
|
||||
border: 1px solid theme('colors.border-field-default');
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
&:hover {
|
||||
border-color: theme('colors.border-field-hover');
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
@use '../../settings' as *;
|
||||
@use './input-base' as *;
|
||||
|
||||
// All HTML5 input types, with irrelevant ones commented out.
|
||||
// input[type="button"],
|
||||
// input[type="checkbox"],
|
||||
|
@ -25,12 +22,11 @@ input[type="time"],
|
|||
input[type="url"],
|
||||
input[type="week"],
|
||||
textarea {
|
||||
@include input-base();
|
||||
@apply w-body-text-large;
|
||||
width: 100%;
|
||||
padding: theme('spacing.[1.5]') theme('spacing.5');
|
||||
min-height: $text-input-height;
|
||||
|
||||
@include input-base();
|
||||
}
|
||||
|
||||
// Multiline text fields have larger top-bottom padding.
|
||||
|
@ -43,15 +39,11 @@ textarea {
|
|||
resize: none;
|
||||
}
|
||||
|
||||
// Make non-text field types with custom widgets have a smaller width.
|
||||
.w-field--date_field,
|
||||
.w-field--date_time_field,
|
||||
.w-field--time_field {
|
||||
// Make sure comment buttons are as close as possible.
|
||||
display: inline-block;
|
||||
|
||||
// Make non-text field types with custom widgets have a smaller width.
|
||||
input {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
@use '../../tools' as *;
|
||||
@use '../../settings' as *;
|
||||
|
||||
$header-icon-size: theme('spacing.4');
|
||||
$icon-center-offset: 2px;
|
||||
$guide-line-bottom-margin: calc($form-field-spacing / 3);
|
||||
|
@ -21,11 +18,11 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
|
|||
}
|
||||
|
||||
.w-panel__content {
|
||||
@include guide-line-vertical();
|
||||
// Center the vertical line.
|
||||
margin-inline-start: calc(-1 * var(--nesting-indent));
|
||||
padding-inline-start: var(--nesting-indent);
|
||||
margin-bottom: $guide-line-bottom-margin;
|
||||
@include guide-line-vertical();
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
// Extra pixels for better alignment with center of icon.
|
||||
|
@ -57,11 +54,10 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
|
|||
|
||||
// Styles for nested panels excluding the top level.
|
||||
.w-panel--nested .w-panel {
|
||||
@include guide-line-nested();
|
||||
margin-inline-start: var(--nesting-indent);
|
||||
margin-bottom: 0;
|
||||
|
||||
@include guide-line-nested();
|
||||
|
||||
.w-panel__content {
|
||||
margin-inline-start: calc(
|
||||
-1 * (var(--nesting-indent) + $icon-center-offset - var(--header-gap) / 2)
|
||||
|
@ -84,10 +80,9 @@ $guide-line-bottom-margin: calc($form-field-spacing / 3);
|
|||
}
|
||||
|
||||
.w-panel__divider {
|
||||
@include guide-line-horizontal();
|
||||
// Slightly nicer text alignment.
|
||||
margin-top: 1px;
|
||||
|
||||
@include guide-line-horizontal();
|
||||
}
|
||||
|
||||
.w-panel__heading--label {
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
.w-field--checkbox_select_multiple_with_disabled_options,
|
||||
.w-field--boolean_radio_select,
|
||||
.w-field--radio_select {
|
||||
// Make sure comment buttons are as close as possible.
|
||||
display: inline-block;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
@use 'sass:math';
|
||||
@use '../../settings' as *;
|
||||
@use './input-base' as *;
|
||||
|
||||
// 24px input widget size.
|
||||
$size: 1.5rem;
|
||||
|
@ -11,6 +9,7 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
|
|||
|
||||
// Both input types are very similar in appearance and layout.
|
||||
@mixin radio-checkbox-base() {
|
||||
@include input-base();
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
height: $size;
|
||||
|
@ -20,8 +19,6 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
|
|||
// Prevent the checkbox or radio button from shrinking when the label is long.
|
||||
flex-shrink: 0;
|
||||
|
||||
@include input-base();
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
|
@ -42,11 +39,8 @@ $radio-checkbox-label-gap: theme('spacing.[2.5]');
|
|||
|
||||
input[type='radio'] {
|
||||
@include radio-checkbox-base();
|
||||
|
||||
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
|
||||
& {
|
||||
border-radius: theme('borderRadius.full');
|
||||
}
|
||||
display: inline-block;
|
||||
border-radius: theme('borderRadius.full');
|
||||
|
||||
&:checked::before {
|
||||
mask-image: url('#{$images-root}icons/radio-full.svg');
|
||||
|
@ -55,13 +49,9 @@ input[type='radio'] {
|
|||
|
||||
input[type='checkbox'] {
|
||||
@include radio-checkbox-base();
|
||||
|
||||
// stylelint-disable-next-line no-duplicate-selectors, scss/selector-no-redundant-nesting-selector
|
||||
& {
|
||||
border-radius: theme('borderRadius.sm');
|
||||
// Legacy alignment for checkboxes, particularly within listings.
|
||||
vertical-align: bottom;
|
||||
}
|
||||
border-radius: theme('borderRadius.sm');
|
||||
// Legacy alignment for checkboxes, particularly within listings.
|
||||
vertical-align: bottom;
|
||||
|
||||
&:checked::before {
|
||||
mask-image: url('#{$images-root}icons/check.svg');
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../../tools' as *;
|
||||
|
||||
.w-required-mark {
|
||||
color: theme('colors.text-error');
|
||||
margin-inline-start: 0.25ch;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
@use 'sass:map';
|
||||
@use 'sass:math';
|
||||
@use '../../settings' as *;
|
||||
@use './input-base' as *;
|
||||
|
||||
$select-size: $text-input-height;
|
||||
$chevron-size: 0.375rem;
|
||||
|
@ -38,6 +36,7 @@ $chevron-offset: math.div($select-size - $chevron-size, 2);
|
|||
}
|
||||
|
||||
select {
|
||||
@include input-base();
|
||||
@include select-arrow();
|
||||
@apply w-body-text-large;
|
||||
// Firefox workaround – Set a large line height (but smaller than min height) so the field’s text has enough top padding.
|
||||
|
@ -48,8 +47,6 @@ select {
|
|||
// Prevent the element from overflowing the container.
|
||||
max-width: 100%;
|
||||
|
||||
@include input-base();
|
||||
|
||||
@media (forced-colors: active) {
|
||||
appearance: auto;
|
||||
}
|
||||
|
@ -64,8 +61,3 @@ select[multiple] {
|
|||
padding: 0 theme('spacing.5');
|
||||
}
|
||||
}
|
||||
|
||||
.w-field--select {
|
||||
// Make sure comment buttons are as close as possible.
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,12 @@ $switch-border-radius: math.div(($switch-height + $switch-border * 2), 2);
|
|||
outline: theme('colors.focus') solid $switch-outline;
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
[type='checkbox']:focus + &__toggle {
|
||||
outline: theme('colors.focus') solid $switch-outline;
|
||||
}
|
||||
}
|
||||
|
||||
[type='checkbox'] {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use './input-base' as *;
|
||||
|
||||
.tagit {
|
||||
@include input-base();
|
||||
|
||||
|
|
|
@ -33,22 +33,22 @@ BEM: https://getbem.com/
|
|||
/* Legacy vendor styles. Do not add new styles here. */
|
||||
@use 'generic/normalize';
|
||||
@use 'vendor/jquery-ui-1.10.3.verdant';
|
||||
@use 'vendor/jquery.tagit' as jquery-tagit;
|
||||
@use 'vendor/jquery.Jcrop.min' as jquery-jcrop;
|
||||
@use 'vendor/jquery.tagit' as tagit;
|
||||
@use 'vendor/jquery.Jcrop.min' as jcrop;
|
||||
|
||||
/* SETTINGS
|
||||
These are variables, maps, and fonts.
|
||||
* No CSS should be produced by these files
|
||||
*/
|
||||
|
||||
@use 'settings';
|
||||
@import 'settings';
|
||||
|
||||
/* TOOLS
|
||||
These are functions and mixins.
|
||||
* No CSS should be produced by these files.
|
||||
*/
|
||||
|
||||
@use 'tools';
|
||||
@import 'tools';
|
||||
|
||||
/* GENERIC
|
||||
This is for resets and other rules that affect large collections of bare elements.
|
||||
|
@ -60,9 +60,14 @@ These are base styles for bare HTML elements.
|
|||
* Changes to them should be very rare.
|
||||
*/
|
||||
|
||||
@use 'elements/elements';
|
||||
@use 'elements/typography';
|
||||
@use 'elements/forms';
|
||||
// These inject Tailwind's base, component and utility styles and any styles registered by plugins of each layer.
|
||||
// Unused styles created within tailwinds layers won't be compiled into the compiled stylesheet
|
||||
// https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@import 'elements/elements';
|
||||
@import 'elements/typography';
|
||||
@import 'elements/forms';
|
||||
|
||||
/* COMPONENTS
|
||||
These are classes for components.
|
||||
|
@ -71,87 +76,81 @@ These are classes for components.
|
|||
which is the preferred pattern over housing them in the scss folder.
|
||||
*/
|
||||
|
||||
@use '../src/components/Transition/Transition';
|
||||
@use '../src/components/LoadingSpinner/LoadingSpinner';
|
||||
@use '../src/components/PublicationStatus/PublicationStatus';
|
||||
@use '../src/components/ComboBox/ComboBox';
|
||||
@use '../src/components/ComboBoxPreview/ComboBoxPreview';
|
||||
@use '../src/components/PageExplorer/PageExplorer';
|
||||
@use '../src/components/CommentApp/main';
|
||||
@import '../src/components/Transition/Transition';
|
||||
@import '../src/components/LoadingSpinner/LoadingSpinner';
|
||||
@import '../src/components/PublicationStatus/PublicationStatus';
|
||||
@import '../src/components/ComboBox/ComboBox';
|
||||
@import '../src/components/PageExplorer/PageExplorer';
|
||||
@import '../src/components/CommentApp/main';
|
||||
|
||||
@use 'components/avatar';
|
||||
@use 'components/icons';
|
||||
@use 'components/forms/input-base';
|
||||
@use 'components/forms/input-text';
|
||||
@use 'components/forms/radio-checkbox';
|
||||
@use 'components/forms/select';
|
||||
@use 'components/forms/tagit';
|
||||
@use 'components/forms/radio-checkbox-multiple';
|
||||
@use 'components/forms/error-message';
|
||||
@use 'components/forms/required-mark';
|
||||
@use 'components/forms/help';
|
||||
@use 'components/forms/drop-zone';
|
||||
@use 'components/forms/daterange';
|
||||
@use 'components/forms/file';
|
||||
@use 'components/forms/publishing';
|
||||
@use 'components/forms/switch';
|
||||
@use 'components/forms/title';
|
||||
@use 'components/forms/field';
|
||||
@use 'components/forms/field-row';
|
||||
@use 'components/forms/field-comment-control';
|
||||
@use 'components/forms/field-textoutput';
|
||||
@use 'components/forms/form-width';
|
||||
@use 'components/forms/nested-panel';
|
||||
@use 'components/tabs';
|
||||
@use 'components/panel';
|
||||
@use 'components/dialog';
|
||||
@use 'components/dismissible';
|
||||
@use 'components/drilldown';
|
||||
@use 'components/dropdown';
|
||||
@use 'components/dropdown-button';
|
||||
@use 'components/help-block';
|
||||
@use 'components/button';
|
||||
@use 'components/keyboard-shortcuts';
|
||||
@use 'components/modals';
|
||||
@use 'components/chooser';
|
||||
@use 'components/tag';
|
||||
@use 'components/listing';
|
||||
@use 'components/filters';
|
||||
@use 'components/messages';
|
||||
@use 'components/messages.capability' as messages-capability;
|
||||
@use 'components/messages.status' as messages-status;
|
||||
@use 'components/header';
|
||||
@use 'components/progressbar';
|
||||
@use 'components/summary';
|
||||
@use 'components/whats-new';
|
||||
@use 'components/grid.legacy';
|
||||
@use 'components/footer';
|
||||
@use 'components/loading-mask';
|
||||
@use 'components/human-readable-date';
|
||||
@use 'components/link.legacy';
|
||||
@use 'components/indicator';
|
||||
@use 'components/status-tag';
|
||||
@use 'components/skiplink';
|
||||
@use 'components/workflow-tasks';
|
||||
@use 'components/workflow-timeline';
|
||||
@use 'components/bulk_actions';
|
||||
@use 'components/preview-panel';
|
||||
@use 'components/preview-error';
|
||||
@use 'components/form-side';
|
||||
@use 'components/a11y-result';
|
||||
@use 'components/userbar';
|
||||
@use 'components/breadcrumbs';
|
||||
@use 'components/pill';
|
||||
@use 'components/ping';
|
||||
@use 'components/editing-sessions';
|
||||
@import 'components/avatar';
|
||||
@import 'components/icons';
|
||||
@import 'components/forms/input-base';
|
||||
@import 'components/forms/input-text';
|
||||
@import 'components/forms/radio-checkbox';
|
||||
@import 'components/forms/select';
|
||||
@import 'components/forms/tagit';
|
||||
@import 'components/forms/radio-checkbox-multiple';
|
||||
@import 'components/forms/error-message';
|
||||
@import 'components/forms/required-mark';
|
||||
@import 'components/forms/help';
|
||||
@import 'components/forms/drop-zone';
|
||||
@import 'components/forms/daterange';
|
||||
@import 'components/forms/file';
|
||||
@import 'components/forms/publishing';
|
||||
@import 'components/forms/switch';
|
||||
@import 'components/forms/title';
|
||||
@import 'components/forms/field';
|
||||
@import 'components/forms/field-row';
|
||||
@import 'components/forms/field-comment-control';
|
||||
@import 'components/forms/field-textoutput';
|
||||
@import 'components/forms/form-width';
|
||||
@import 'components/forms/nested-panel';
|
||||
@import 'components/tabs';
|
||||
@import 'components/panel';
|
||||
@import 'components/dialog';
|
||||
@import 'components/dismissible';
|
||||
@import 'components/drilldown';
|
||||
@import 'components/dropdown';
|
||||
@import 'components/dropdown-button';
|
||||
@import 'components/help-block';
|
||||
@import 'components/button';
|
||||
@import 'components/keyboard-shortcuts';
|
||||
@import 'components/modals';
|
||||
@import 'components/chooser';
|
||||
@import 'components/tag';
|
||||
@import 'components/listing';
|
||||
@import 'components/filters';
|
||||
@import 'components/messages';
|
||||
@import 'components/messages.capability';
|
||||
@import 'components/messages.status';
|
||||
@import 'components/header';
|
||||
@import 'components/progressbar';
|
||||
@import 'components/summary';
|
||||
@import 'components/whats-new';
|
||||
@import 'components/grid.legacy';
|
||||
@import 'components/footer';
|
||||
@import 'components/loading-mask';
|
||||
@import 'components/human-readable-date';
|
||||
@import 'components/link.legacy';
|
||||
@import 'components/indicator';
|
||||
@import 'components/status-tag';
|
||||
@import 'components/skiplink';
|
||||
@import 'components/workflow-tasks';
|
||||
@import 'components/workflow-timeline';
|
||||
@import 'components/bulk_actions';
|
||||
@import 'components/preview-panel';
|
||||
@import 'components/preview-error';
|
||||
@import 'components/form-side';
|
||||
@import 'components/a11y-result';
|
||||
@import 'components/userbar';
|
||||
@import 'components/breadcrumbs';
|
||||
@import 'components/pill';
|
||||
@import 'components/ping';
|
||||
@import 'components/editing-sessions';
|
||||
|
||||
@use '../src/components/Sidebar/Sidebar';
|
||||
@use '../src/components/Sidebar/SidebarPanel';
|
||||
@use '../src/components/Sidebar/menu/MenuItem';
|
||||
@use '../src/components/Sidebar/menu/SubMenuItem';
|
||||
@use '../src/components/Sidebar/modules/MainMenu';
|
||||
@use '../src/components/Sidebar/modules/WagtailBranding';
|
||||
@use '../src/components/Minimap/Minimap';
|
||||
@import '../src/components/Sidebar/Sidebar';
|
||||
@import '../src/components/Minimap/Minimap';
|
||||
|
||||
/* OVERRIDES
|
||||
These are classes that provide overrides.
|
||||
|
@ -159,28 +158,30 @@ These are classes that provide overrides.
|
|||
*/
|
||||
|
||||
// VENDOR: overrides of vendor styles.
|
||||
@use 'overrides/vendor.datetimepicker' as vendor-datetimepicker;
|
||||
@use 'overrides/vendor.handsontable' as vendor-handsontable;
|
||||
@use 'overrides/vendor.tagit' as vendor-tagit;
|
||||
@use 'overrides/vendor.tippy' as vendor-tippy;
|
||||
@import 'overrides/vendor.datetimepicker';
|
||||
@import 'overrides/vendor.handsontable';
|
||||
@import 'overrides/vendor.tagit';
|
||||
@import 'overrides/vendor.tippy';
|
||||
|
||||
// UTILITIES: classes that do one simple thing.
|
||||
@use 'overrides/utilities.focus' as utilities-focus;
|
||||
@import 'overrides/utilities.focus';
|
||||
|
||||
// Legacy utilities
|
||||
@use 'overrides/utilities.legacy' as utilities-legacy;
|
||||
@import 'overrides/utilities.legacy';
|
||||
|
||||
// TAILWIND: This is at the bottom so it can take precedence over other css classes
|
||||
@use 'overrides/utilities.tailwind' as utilities-tailwind;
|
||||
@tailwind utilities;
|
||||
|
||||
/* Legacy layout-specific styles. Do not add new styles here. */
|
||||
|
||||
@use 'layouts/404' as layout-404;
|
||||
@use 'layouts/compare-revisions';
|
||||
@use 'layouts/login';
|
||||
@use 'layouts/account';
|
||||
@use 'layouts/workflow-progress';
|
||||
@use 'layouts/report';
|
||||
@use 'layouts/add-multiple';
|
||||
@use 'layouts/chooser-duplicate-upload';
|
||||
@use 'layouts/focal-point-chooser';
|
||||
@use 'layouts/redirects';
|
||||
@import 'layouts/404';
|
||||
@import 'layouts/compare-revisions';
|
||||
@import 'layouts/home';
|
||||
@import 'layouts/login';
|
||||
@import 'layouts/account';
|
||||
@import 'layouts/workflow-progress';
|
||||
@import 'layouts/report';
|
||||
@import 'layouts/add-multiple';
|
||||
@import 'layouts/chooser-duplicate-upload';
|
||||
@import 'layouts/focal-point-chooser';
|
||||
@import 'layouts/redirects';
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
// These inject Tailwind's base and component styles and any styles registered by plugins of each layer.
|
||||
// Unused styles created within tailwinds layers won't be compiled into the compiled stylesheet
|
||||
// https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@use 'sass:map';
|
||||
@use '../tools' as *;
|
||||
// Legacy form reset styles. Avoid adding any new styles here.
|
||||
form {
|
||||
// Historically, Wagtail forms rendered all fields as list items.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.page404__bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
$color-addition-dark: var(--color-addition-dark);
|
||||
$color-addition-light: var(--color-addition-light);
|
||||
$color-deletion-dark: var(--color-deletion-dark);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.focal-point-chooser {
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
.homepage {
|
||||
.listing tbody {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.task .icon {
|
||||
// pull out the icon so it aligns with no-icon text
|
||||
margin-inline-start: -1.75em;
|
||||
}
|
||||
}
|
|
@ -1,19 +1,30 @@
|
|||
@use '../tools' as *;
|
||||
@mixin login-fullscreen-background() {
|
||||
@at-root {
|
||||
:root {
|
||||
--w-login-fullscreen-background: radial-gradient(
|
||||
100% 300.28% at 100% 0%,
|
||||
theme('colors.primary.DEFAULT') 0%,
|
||||
theme('colors.primary.DEFAULT') 32.94%,
|
||||
theme('colors.primary.DEFAULT') 49.9%,
|
||||
theme('colors.primary.DEFAULT') 50.2%,
|
||||
theme('colors.secondary.DEFAULT') 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--w-login-fullscreen-background: radial-gradient(
|
||||
100% 300.28% at 100% 0%,
|
||||
theme('colors.primary.DEFAULT') 0%,
|
||||
theme('colors.primary.DEFAULT') 32.94%,
|
||||
theme('colors.primary.DEFAULT') 49.9%,
|
||||
theme('colors.primary.DEFAULT') 50.2%,
|
||||
theme('colors.secondary.DEFAULT') 100%
|
||||
// support older browsers that do not support radial gradient 'at' usage
|
||||
background: theme('colors.surface-menus');
|
||||
/* stylelint-disable-next-line declaration-block-no-duplicate-properties */
|
||||
background: var(
|
||||
--w-login-fullscreen-background,
|
||||
theme('colors.primary.DEFAULT')
|
||||
);
|
||||
}
|
||||
|
||||
.login {
|
||||
@include login-fullscreen-background;
|
||||
|
||||
color: theme('colors.text-label');
|
||||
background: var(--w-login-fullscreen-background);
|
||||
|
||||
.wrapper {
|
||||
align-items: center;
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
@use '../tools' as *;
|
||||
|
||||
.report {
|
||||
@include nice-margin();
|
||||
display: grid;
|
||||
grid-column-gap: theme('spacing.12');
|
||||
|
||||
@include nice-margin();
|
||||
|
||||
&__results {
|
||||
&--text {
|
||||
margin: 0 theme('spacing.[1.5]') theme('spacing.[1.5]') 0;
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
@use '../settings' as *;
|
||||
|
||||
// stylelint-disable declaration-no-important
|
||||
// Set global focus outline styles so they are consistent across the UI,
|
||||
// without individual components having to explicitly define focus styles.
|
||||
// Using !important because we want to enforce only one style is used across the UI.
|
||||
// Remove :focus selectors once we stop supporting Safari 15.4.
|
||||
*:focus {
|
||||
outline: $focus-outline-width solid theme('colors.focus') !important;
|
||||
}
|
||||
|
||||
*:focus:not(:focus-visible) {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
*:focus-visible {
|
||||
outline: $focus-outline-width solid theme('colors.focus') !important;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
@use '../tools' as *;
|
||||
@use '../settings' as *;
|
||||
|
||||
.nice-padding {
|
||||
padding-inline-start: $mobile-nice-padding;
|
||||
padding-inline-end: $mobile-nice-padding;
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
@tailwind utilities;
|
|
@ -1,6 +1,5 @@
|
|||
// stylelint-disable selector-max-combinators, max-nesting-depth
|
||||
@use 'sass:map';
|
||||
@use '../settings' as *;
|
||||
|
||||
.xdsoft_datetimepicker {
|
||||
box-shadow: 0 5px 10px -5px theme('colors.black-35');
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@use 'sass:map';
|
||||
@use '../settings' as *;
|
||||
|
||||
// taggit tagging
|
||||
.tagit {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// stylelint-disable selector-attribute-name-disallowed-list
|
||||
@use '../../../node_modules/tippy.js/dist/tippy';
|
||||
@import '../../../node_modules/tippy.js/dist/tippy';
|
||||
|
||||
.tippy-box {
|
||||
// Special font size 12px for tooltips
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@use 'sass:list';
|
||||
@use 'sass:map';
|
||||
@use '../settings' as *;
|
||||
// Based upon the fine work and thoughts from Bootstrap v4.
|
||||
// Copyright 2011-2018 The Bootstrap Authors
|
||||
// Copyright 2011-2018 Twitter, Inc.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@use 'functions.breakpoints' as *;
|
||||
|
||||
// Based upon the fine work and thoughts from Bootstrap v4.
|
||||
// Copyright 2011-2018 The Bootstrap Authors
|
||||
// Copyright 2011-2018 Twitter, Inc.
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
// Please note that the mixins partial shouldn't include any classes. This is so
|
||||
// it can be included in any file without accidentally producing output
|
||||
|
||||
@use '../settings' as *;
|
||||
|
||||
// Turns on font-smoothing when used. Use sparingly.
|
||||
@mixin font-smoothing {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
@ -95,21 +93,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply styles for enhanced contrast theming.
|
||||
*/
|
||||
@mixin more-contrast() {
|
||||
.w-contrast-more & {
|
||||
@content;
|
||||
}
|
||||
|
||||
@media (prefers-contrast: more) {
|
||||
.w-contrast-system & {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply styles for the light theme only.
|
||||
*/
|
||||
|
@ -124,52 +107,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply styles for the dark theme with increased contrast.
|
||||
*/
|
||||
@mixin dark-theme-more-contrast() {
|
||||
.w-theme-dark.w-contrast-more & {
|
||||
@content;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.w-theme-system.w-contrast-more & {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-contrast: more) {
|
||||
.w-theme-dark.w-contrast-system & {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) and (prefers-contrast: more) {
|
||||
.w-theme-system.w-contrast-system & {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increased contrast theme styles for interactive components
|
||||
*/
|
||||
@mixin more-contrast-interactive() {
|
||||
@include more-contrast() {
|
||||
border: 1px solid theme('colors.border-interactive-more-contrast');
|
||||
|
||||
&:hover {
|
||||
border-color: theme('colors.border-interactive-more-contrast-hover');
|
||||
}
|
||||
|
||||
&[disabled],
|
||||
&[disabled]:hover {
|
||||
border-style: dashed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin focus-outline {
|
||||
outline: $focus-outline-width solid theme('colors.focus');
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
@use 'sass:math';
|
||||
@use '../settings' as *;
|
||||
@use '../tools/mixins.breakpoints' as *;
|
||||
@use '../tools/mixins.general' as *;
|
||||
|
||||
// grid settings
|
||||
$grid-columns: 12;
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import { WAGTAIL_CONFIG } from '../config/wagtailConfig';
|
||||
import { ADMIN_API } from '../config/wagtailConfig';
|
||||
import { getPageChildren, getPage } from './admin';
|
||||
import client from './client';
|
||||
|
||||
const { ADMIN_API } = WAGTAIL_CONFIG;
|
||||
|
||||
jest.mock('./client', () => {
|
||||
const stubResult = {
|
||||
__types: {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import client from './client';
|
||||
|
||||
import { WAGTAIL_CONFIG } from '../config/wagtailConfig';
|
||||
|
||||
const { ADMIN_API } = WAGTAIL_CONFIG;
|
||||
import { ADMIN_API } from '../config/wagtailConfig';
|
||||
|
||||
export interface WagtailPageAPI {
|
||||
id: number;
|
||||
|
|
|
@ -14,11 +14,8 @@ const checkStatus = (response) => {
|
|||
|
||||
const parseJSON = (response) => response.json();
|
||||
|
||||
/**
|
||||
* Response timeout cancelling the promise (not the request).
|
||||
*
|
||||
* @see https://github.com/github/fetch/issues/175#issuecomment-216791333.
|
||||
*/
|
||||
// Response timeout cancelling the promise (not the request).
|
||||
// See https://github.com/github/fetch/issues/175#issuecomment-216791333.
|
||||
const timeout = (ms, promise) => {
|
||||
const race = new Promise((resolve, reject) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
|
@ -41,7 +38,7 @@ const timeout = (ms, promise) => {
|
|||
};
|
||||
|
||||
/**
|
||||
* Wrapper around fetch with sane defaults for behavior in the face of
|
||||
* Wrapper around fetch with sane defaults for behaviour in the face of
|
||||
* errors.
|
||||
*/
|
||||
const request = (method, url) => {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/* global DocumentChooserModal */
|
||||
|
||||
import { Chooser, ChooserFactory } from '.';
|
||||
|
||||
export class DocumentChooser extends Chooser {
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = DocumentChooserModal;
|
||||
}
|
||||
window.DocumentChooser = DocumentChooser;
|
||||
|
||||
export class DocumentChooserFactory extends ChooserFactory {
|
||||
widgetClass = DocumentChooser;
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = DocumentChooserModal;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/* global ImageChooserModal */
|
||||
|
||||
import { Chooser, ChooserFactory } from '.';
|
||||
|
||||
export class ImageChooser extends Chooser {
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = ImageChooserModal;
|
||||
|
||||
initHTMLElements(id) {
|
||||
|
@ -12,21 +11,12 @@ export class ImageChooser extends Chooser {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the initial state of the chooser from the rendered (static) HTML.
|
||||
* The state is either null (no image chosen) or an object containing the image details.
|
||||
*
|
||||
* @returns {Object|null} The initial state of the chooser. If an image is chosen,
|
||||
* the state object contains the following properties:
|
||||
* - id: {number} The ID of the chosen image.
|
||||
* - edit_url: {string} The URL to edit the chosen image.
|
||||
* - title: {string} The title of the chosen image.
|
||||
* - preview: {Object} An object containing the preview details of the chosen image:
|
||||
* - url: {string} The URL of the preview image.
|
||||
* - width: {string} The width of the preview image.
|
||||
* - height: {string} The height of the preview image.
|
||||
*/
|
||||
getStateFromHTML() {
|
||||
/*
|
||||
Construct initial state of the chooser from the rendered (static) HTML.
|
||||
State is either null (= no image chosen) or a dict of id, edit_url, title
|
||||
and preview (= a dict of url, width, height).
|
||||
*/
|
||||
const state = super.getStateFromHTML();
|
||||
if (state) {
|
||||
state.preview = {
|
||||
|
@ -34,9 +24,6 @@ export class ImageChooser extends Chooser {
|
|||
width: this.previewImage.getAttribute('width'),
|
||||
height: this.previewImage.getAttribute('height'),
|
||||
};
|
||||
state.default_alt_text = this.previewImage.getAttribute(
|
||||
'data-default-alt-text',
|
||||
);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -45,14 +32,11 @@ export class ImageChooser extends Chooser {
|
|||
super.renderState(newState);
|
||||
this.previewImage.setAttribute('src', newState.preview.url);
|
||||
this.previewImage.setAttribute('width', newState.preview.width);
|
||||
this.previewImage.setAttribute(
|
||||
'data-default-alt-text',
|
||||
newState.default_alt_text,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class ImageChooserFactory extends ChooserFactory {
|
||||
widgetClass = ImageChooser;
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = ImageChooserModal;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/* global PageChooserModal */
|
||||
|
||||
import { Chooser, ChooserFactory } from '.';
|
||||
|
||||
export class PageChooser extends Chooser {
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = PageChooserModal;
|
||||
|
||||
titleStateKey = 'adminTitle';
|
||||
|
@ -45,6 +44,7 @@ export class PageChooser extends Chooser {
|
|||
|
||||
export class PageChooserFactory extends ChooserFactory {
|
||||
widgetClass = PageChooser;
|
||||
// eslint-disable-next-line no-undef
|
||||
chooserModalClass = PageChooserModal;
|
||||
|
||||
getModalOptions() {
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import { ChooserModal } from '../../includes/chooserModal';
|
||||
import { Chooser, ChooserFactory } from '.';
|
||||
import { WAGTAIL_CONFIG } from '../../config/wagtailConfig';
|
||||
|
||||
/* global wagtailConfig */
|
||||
|
||||
class SnippetChooserModal extends ChooserModal {
|
||||
getURLParams(opts) {
|
||||
const params = super.getURLParams(opts);
|
||||
if (WAGTAIL_CONFIG.ACTIVE_CONTENT_LOCALE) {
|
||||
if (wagtailConfig.ACTIVE_CONTENT_LOCALE) {
|
||||
// The user is editing a piece of translated content.
|
||||
// Pass the locale along as a request parameter. If this
|
||||
// snippet is also translatable, the results will be
|
||||
// pre-filtered by this locale.
|
||||
params.locale = WAGTAIL_CONFIG.ACTIVE_CONTENT_LOCALE;
|
||||
params.locale = wagtailConfig.ACTIVE_CONTENT_LOCALE;
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import EventEmitter from 'events';
|
||||
import { ChooserModal } from '../../includes/chooserModal';
|
||||
|
||||
export class Chooser extends EventEmitter {
|
||||
export class Chooser {
|
||||
chooserModalClass = ChooserModal;
|
||||
titleStateKey = 'title'; // key used in the 'state' dictionary to hold the human-readable title
|
||||
editUrlStateKey = 'edit_url'; // key used in the 'state' dictionary to hold the URL of the edit page
|
||||
|
||||
constructor(id, opts = {}) {
|
||||
super();
|
||||
this.opts = opts;
|
||||
this.initHTMLElements(id);
|
||||
this.state = this.getStateFromHTML();
|
||||
|
@ -85,7 +83,6 @@ export class Chooser extends EventEmitter {
|
|||
|
||||
setStateFromModalData(data) {
|
||||
this.setState(data);
|
||||
this.emit('chosen', data);
|
||||
}
|
||||
|
||||
clear() {
|
||||
|
@ -213,10 +210,8 @@ export class ChooserFactory {
|
|||
this.modal.open(options, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve the widget object corresponding to the given HTML ID
|
||||
*/
|
||||
getById(id) {
|
||||
/* retrieve the widget object corresponding to the given HTML ID */
|
||||
return document.getElementById(`${id}-chooser`).widget;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,70 +1,24 @@
|
|||
@use '../../../scss/tools' as *;
|
||||
|
||||
// Ensure consistent spacing across the whole component.
|
||||
// With the scrolling and show/hide of the field, correct spacing is critical.
|
||||
$spacing: theme('spacing.[2.5]');
|
||||
$spacing-sm: theme('spacing.4');
|
||||
$width: clamp(300px, 75vw, 1000px);
|
||||
|
||||
.w-combobox-container {
|
||||
background: theme('colors.surface-page');
|
||||
color: theme('colors.text-context');
|
||||
border-radius: theme('borderRadius.DEFAULT');
|
||||
box-shadow: theme('boxShadow.md');
|
||||
outline: 10px solid transparent;
|
||||
|
||||
// Use a single column grid on smaller screens,
|
||||
// and two columns on larger screens.
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
// Case 1: base case
|
||||
// Use max-content width to minimize shifting due to content wrapping,
|
||||
// constraining width to 75% of viewport for devices above 400px width.
|
||||
width: max-content;
|
||||
max-width: max(300px, 75vw);
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
grid-template-columns: min(400px, 80vw) 1fr;
|
||||
}
|
||||
@include media-breakpoint-up(lg) {
|
||||
grid-template-columns: min(512px, 80vw) 1fr;
|
||||
}
|
||||
|
||||
// Case 2: there's a previewable block, but the preview may or may not be active
|
||||
// On smaller screens, the preview will be shown below. We don't want the
|
||||
// combobox to change width when the preview is shown or hidden (e.g. due to
|
||||
// a long description), so set a fixed width. It's OK that this will take up
|
||||
// more than the necessary width for the combobox, as we know it's not going
|
||||
// to be wider than 75% of the small screen anyway.
|
||||
&:has(.w-combobox__option-preview) {
|
||||
width: $width;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
// On medium-up screens, the preview will be shown to the right. Revert
|
||||
// the width back to max-content so it doesn't take up the whole `$width`
|
||||
// when the preview is not active.
|
||||
width: max-content;
|
||||
}
|
||||
}
|
||||
|
||||
// Case 3: the preview is currently active
|
||||
&:has(.w-combobox-preview) {
|
||||
@include media-breakpoint-up(md) {
|
||||
// On larger screens, use the fixed `$width` so the width doesn't change
|
||||
// for different blocks, which may have different description lengths.
|
||||
width: $width;
|
||||
}
|
||||
}
|
||||
$spacing-sm: theme('spacing.5');
|
||||
|
||||
.w-combobox {
|
||||
width: min(400px, 80vw);
|
||||
@include dark-theme() {
|
||||
background-color: theme('colors.surface-tooltip');
|
||||
}
|
||||
background: theme('colors.surface-page');
|
||||
color: theme('colors.text-context');
|
||||
border-radius: theme('borderRadius.DEFAULT');
|
||||
font-size: theme('fontSize.18');
|
||||
box-shadow: theme('boxShadow.md');
|
||||
outline: 10px solid transparent;
|
||||
}
|
||||
|
||||
.w-combobox__field {
|
||||
padding: $spacing;
|
||||
padding-bottom: 0;
|
||||
font-size: theme('fontSize.18');
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding: $spacing-sm;
|
||||
|
@ -89,13 +43,12 @@ $width: clamp(300px, 75vw, 1000px);
|
|||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-auto-flow: column;
|
||||
gap: theme('spacing.1');
|
||||
gap: theme('spacing.[0.5]');
|
||||
padding: $spacing;
|
||||
padding-top: 0;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
width: 100%;
|
||||
column-gap: theme('spacing.5');
|
||||
width: 400px;
|
||||
padding: $spacing-sm;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
@ -117,63 +70,21 @@ $width: clamp(300px, 75vw, 1000px);
|
|||
}
|
||||
}
|
||||
|
||||
.w-combobox__option-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr theme('spacing.6');
|
||||
}
|
||||
|
||||
.w-combobox__option-preview {
|
||||
@include show-focus-outline-inside();
|
||||
color: theme('colors.icon-secondary');
|
||||
background: none;
|
||||
border: 1px solid transparent;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
|
||||
@include more-contrast-interactive();
|
||||
|
||||
.icon {
|
||||
width: theme('spacing.3');
|
||||
height: theme('spacing.3');
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: theme('colors.icon-secondary-hover');
|
||||
}
|
||||
|
||||
&[aria-expanded='true'] {
|
||||
color: theme('colors.text-link-default');
|
||||
|
||||
@media (forced-colors: active) {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox__option-row--col1 {
|
||||
grid-column: 1 / span 1;
|
||||
}
|
||||
|
||||
.w-combobox__option-row--col2 {
|
||||
grid-column: 2 / span 1;
|
||||
}
|
||||
|
||||
.w-combobox__option {
|
||||
display: grid;
|
||||
grid-template-columns: theme('spacing.8') 1fr;
|
||||
align-items: center;
|
||||
padding: theme('spacing.[2.5]');
|
||||
border: 1px dotted theme('colors.border-button-small-outline-default');
|
||||
padding: theme('spacing.2');
|
||||
border: 1px solid transparent;
|
||||
font-size: 0.875rem;
|
||||
line-height: theme('lineHeight.tight');
|
||||
border-radius: theme('borderRadius.sm');
|
||||
cursor: pointer;
|
||||
|
||||
&[aria-selected='true'] {
|
||||
border-color: theme('colors.border-button-outline-default');
|
||||
color: theme('colors.text-link-default');
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
@media (forced-colors: active) {
|
||||
background: Highlight;
|
||||
|
@ -182,6 +93,14 @@ $width: clamp(300px, 75vw, 1000px);
|
|||
}
|
||||
}
|
||||
|
||||
.w-combobox__option--col1 {
|
||||
grid-column: 1 / span 1;
|
||||
}
|
||||
|
||||
.w-combobox__option--col2 {
|
||||
grid-column: 2 / span 1;
|
||||
}
|
||||
|
||||
.w-combobox__option-icon {
|
||||
color: theme('colors.icon-secondary');
|
||||
height: theme('spacing.4');
|
||||
|
|
|
@ -40,13 +40,12 @@ describe('ComboBox', () => {
|
|||
{
|
||||
type: 'paragraph',
|
||||
description: 'Paragraph',
|
||||
icon: <span className="my-icon">P</span>,
|
||||
icon: <span className="custom-icon">P</span>,
|
||||
},
|
||||
{
|
||||
type: 'heading-one',
|
||||
label: 'H1',
|
||||
description: 'Heading 1',
|
||||
icon: ['M 83.625 ', 'L 232.535156 '],
|
||||
},
|
||||
{
|
||||
type: 'heading-two',
|
||||
|
@ -71,10 +70,6 @@ describe('ComboBox', () => {
|
|||
wrapper = shallow(<ComboBox {...testProps} items={items} />);
|
||||
});
|
||||
|
||||
it('matches the snapshot', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('shows items', () => {
|
||||
const options = wrapper.find('.w-combobox__option-text');
|
||||
expect(options).toHaveLength(
|
||||
|
@ -87,24 +82,8 @@ describe('ComboBox', () => {
|
|||
expect(wrapper.find(Icon).at(0).prop('name')).toBe('blockquote');
|
||||
});
|
||||
|
||||
it('supports custom icons (as provided React component)', () => {
|
||||
const paragraphOption = wrapper.findWhere(
|
||||
(el) => el.key() === 'paragraph',
|
||||
);
|
||||
const icon = paragraphOption.find('.w-combobox__option-icon').render();
|
||||
|
||||
expect(icon.find('.my-icon')).toHaveLength(1);
|
||||
expect(icon.text()).toBe('P');
|
||||
});
|
||||
|
||||
it('supports custom icons (as provided path)', () => {
|
||||
const paragraphOption = wrapper.findWhere(
|
||||
(el) => el.key() === 'heading-one',
|
||||
);
|
||||
const icon = paragraphOption.find('.w-combobox__option-icon').render();
|
||||
|
||||
expect(icon.find('svg').hasClass('icon-custom')).toBe(true);
|
||||
expect(icon.find('.icon-custom').html()).toContain('M 83.625');
|
||||
it('supports custom icons', () => {
|
||||
expect(wrapper.find('.custom-icon').text()).toBe('P');
|
||||
});
|
||||
|
||||
it('supports label as icon', () => {
|
||||
|
@ -113,8 +92,8 @@ describe('ComboBox', () => {
|
|||
|
||||
it('combines two categories into one, with two columns', () => {
|
||||
expect(wrapper.find('.w-combobox__optgroup-label')).toHaveLength(1);
|
||||
expect(wrapper.find('.w-combobox__option-row--col1')).toHaveLength(3);
|
||||
expect(wrapper.find('.w-combobox__option-row--col2')).toHaveLength(2);
|
||||
expect(wrapper.find('.w-combobox__option--col1')).toHaveLength(3);
|
||||
expect(wrapper.find('.w-combobox__option--col2')).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react';
|
|||
import { useCombobox, UseComboboxStateChange } from 'downshift';
|
||||
|
||||
import { gettext } from '../../utils/gettext';
|
||||
import ComboBoxPreview from '../ComboBoxPreview/ComboBoxPreview';
|
||||
import Icon from '../Icon/Icon';
|
||||
|
||||
import findMatches from './findMatches';
|
||||
|
@ -10,7 +9,6 @@ import findMatches from './findMatches';
|
|||
export const comboBoxTriggerLabel = gettext('Insert a block');
|
||||
export const comboBoxLabel = gettext('Search options…');
|
||||
export const comboBoxNoResults = gettext('No results');
|
||||
const comboBoxPreviewLabel = gettext('Preview');
|
||||
|
||||
export interface ComboBoxCategory<ItemType> {
|
||||
type: string;
|
||||
|
@ -23,8 +21,6 @@ export interface ComboBoxItem {
|
|||
label?: string | null;
|
||||
description?: string | null;
|
||||
icon?: string | JSX.Element | null;
|
||||
blockDefId?: string;
|
||||
isPreviewable?: boolean;
|
||||
category?: string;
|
||||
render?: (props: { option: ComboBoxItem }) => JSX.Element | string;
|
||||
}
|
||||
|
@ -68,7 +64,6 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
(category) => category.items || [],
|
||||
);
|
||||
const [inputItems, setInputItems] = useState<ComboBoxOption[]>(flatItems);
|
||||
const [previewedIndex, setPreviewedIndex] = useState<number>(-1);
|
||||
// Re-create the categories so the two-column layout flows as expected.
|
||||
const categories = items.reduce<ComboBoxCategory<ComboBoxOption>[]>(
|
||||
(cats, cat, index) => {
|
||||
|
@ -119,10 +114,8 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* For not re-setting and not removing focus from combobox when pressing `Alt+Tab`
|
||||
* to switch windows.
|
||||
*/
|
||||
// For not re-setting and not removing focus from combobox when pressing `Alt+Tab`
|
||||
// to switch windows.
|
||||
stateReducer: (state, actionAndChanges) => {
|
||||
const { type, changes } = actionAndChanges;
|
||||
switch (type) {
|
||||
|
@ -139,9 +132,6 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
},
|
||||
|
||||
onInputValueChange: (changes) => {
|
||||
// Hide any preview when the user types or clears the search input.
|
||||
setPreviewedIndex(-1);
|
||||
|
||||
const { inputValue: val } = changes;
|
||||
if (!val) {
|
||||
setInputItems(flatItems);
|
||||
|
@ -178,129 +168,86 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
}
|
||||
}, [inputValue]);
|
||||
|
||||
const previewedBlock =
|
||||
previewedIndex >= 0 ? inputItems[previewedIndex] : null;
|
||||
|
||||
return (
|
||||
<div className="w-combobox-container">
|
||||
<div className="w-combobox">
|
||||
{/* downshift does the label-field association itself. */}
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label {...getLabelProps()} className="w-sr-only">
|
||||
{label}
|
||||
</label>
|
||||
<div className="w-combobox__field">
|
||||
<input
|
||||
{...getInputProps()}
|
||||
type="text"
|
||||
// Prevent the field from receiving focus if it’s not visible.
|
||||
disabled={inlineCombobox}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</div>
|
||||
{noResults ? (
|
||||
<div className="w-combobox__status">{noResultsText}</div>
|
||||
) : null}
|
||||
<div {...getMenuProps()} className="w-combobox__menu">
|
||||
{categories.map((category) => {
|
||||
const categoryItems = (category.items || []).filter((item) =>
|
||||
inputItems.find((i) => i.type === item.type),
|
||||
);
|
||||
const itemColumns = Math.ceil(categoryItems.length / 2);
|
||||
|
||||
if (categoryItems.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-combobox__optgroup" key={category.type}>
|
||||
{category.label ? (
|
||||
<div className="w-combobox__optgroup-label">
|
||||
{category.label}
|
||||
</div>
|
||||
) : null}
|
||||
{categoryItems.map((item, index) => {
|
||||
const itemLabel = getItemLabel(item.type, item);
|
||||
const description = getItemDescription(item);
|
||||
const itemIndex = inputItems.findIndex(
|
||||
(i) => i.type === item.type,
|
||||
);
|
||||
const itemColumn = index + 1 <= itemColumns ? 1 : 2;
|
||||
const hasIcon =
|
||||
typeof item.icon !== 'undefined' && item.icon !== null;
|
||||
let icon: JSX.Element | null | undefined = null;
|
||||
|
||||
if (hasIcon) {
|
||||
if (Array.isArray(item.icon)) {
|
||||
icon = (
|
||||
<Icon name="custom" viewBox="0 0 1024 1024">
|
||||
{item.icon.map((pathData: string) => (
|
||||
<path key={pathData} d={pathData} />
|
||||
))}
|
||||
</Icon>
|
||||
);
|
||||
} else {
|
||||
icon =
|
||||
typeof item.icon === 'string' ? (
|
||||
<Icon name={item.icon} />
|
||||
) : (
|
||||
item.icon
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.type}
|
||||
className={`w-combobox__option-row w-combobox__option-row--col${itemColumn}`}
|
||||
>
|
||||
<div
|
||||
{...getItemProps({ item, index: itemIndex })}
|
||||
className="w-combobox__option"
|
||||
>
|
||||
<div className="w-combobox__option-icon">
|
||||
{icon}
|
||||
{/* Support for rich text options using text as an icon (for example "B" for bold). */}
|
||||
{itemLabel && !hasIcon ? (
|
||||
<span>{itemLabel}</span>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="w-combobox__option-text">
|
||||
{item.render
|
||||
? item.render({ option: item })
|
||||
: description}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{item.isPreviewable ? (
|
||||
<button
|
||||
className="w-combobox__option-preview"
|
||||
aria-label={comboBoxPreviewLabel}
|
||||
aria-expanded={previewedIndex === itemIndex}
|
||||
type="button"
|
||||
onClick={() =>
|
||||
setPreviewedIndex(
|
||||
previewedIndex === itemIndex ? -1 : itemIndex,
|
||||
)
|
||||
}
|
||||
>
|
||||
<Icon name="view" />
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{previewedBlock?.isPreviewable ? (
|
||||
<ComboBoxPreview
|
||||
item={previewedBlock}
|
||||
previewLabel={comboBoxPreviewLabel}
|
||||
<div className="w-combobox">
|
||||
{/* downshift does the label-field association itself. */}
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label {...getLabelProps()} className="w-sr-only">
|
||||
{label}
|
||||
</label>
|
||||
<div className="w-combobox__field">
|
||||
<input
|
||||
{...getInputProps()}
|
||||
type="text"
|
||||
// Prevent the field from receiving focus if it’s not visible.
|
||||
disabled={inlineCombobox}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</div>
|
||||
{noResults ? (
|
||||
<div className="w-combobox__status">{noResultsText}</div>
|
||||
) : null}
|
||||
<div {...getMenuProps()} className="w-combobox__menu">
|
||||
{categories.map((category) => {
|
||||
const categoryItems = (category.items || []).filter((item) =>
|
||||
inputItems.find((i) => i.type === item.type),
|
||||
);
|
||||
const itemColumns = Math.ceil(categoryItems.length / 2);
|
||||
|
||||
if (categoryItems.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-combobox__optgroup" key={category.type}>
|
||||
{category.label ? (
|
||||
<div className="w-combobox__optgroup-label">
|
||||
{category.label}
|
||||
</div>
|
||||
) : null}
|
||||
{categoryItems.map((item, index) => {
|
||||
const itemLabel = getItemLabel(item.type, item);
|
||||
const description = getItemDescription(item);
|
||||
const itemIndex = inputItems.findIndex(
|
||||
(i) => i.type === item.type,
|
||||
);
|
||||
const itemColumn = index + 1 <= itemColumns ? 1 : 2;
|
||||
const hasIcon =
|
||||
typeof item.icon !== 'undefined' && item.icon !== null;
|
||||
let icon: JSX.Element | null | undefined = null;
|
||||
|
||||
if (hasIcon) {
|
||||
icon =
|
||||
typeof item.icon === 'string' ? (
|
||||
<Icon name={item.icon} />
|
||||
) : (
|
||||
item.icon
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.type}
|
||||
{...getItemProps({ item, index: itemIndex })}
|
||||
className={`w-combobox__option w-combobox__option--col${itemColumn}`}
|
||||
>
|
||||
<div className="w-combobox__option-icon">
|
||||
{icon}
|
||||
{/* Support for rich text options using text as an icon (for example "B" for bold). */}
|
||||
{itemLabel && !hasIcon ? <span>{itemLabel}</span> : null}
|
||||
</div>
|
||||
<div className="w-combobox__option-text">
|
||||
{item.render
|
||||
? item.render({ option: item })
|
||||
: description}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ComboBox rendering matches the snapshot 1`] = `
|
||||
<div
|
||||
className="w-combobox-container"
|
||||
>
|
||||
<div
|
||||
className="w-combobox"
|
||||
>
|
||||
<label
|
||||
className="w-sr-only"
|
||||
htmlFor="downshift-1-input"
|
||||
id="downshift-1-label"
|
||||
>
|
||||
Search options…
|
||||
</label>
|
||||
<div
|
||||
className="w-combobox__field"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant=""
|
||||
aria-autocomplete="list"
|
||||
aria-controls="downshift-1-menu"
|
||||
aria-expanded={false}
|
||||
aria-labelledby="downshift-1-label"
|
||||
autoComplete="off"
|
||||
disabled={false}
|
||||
id="downshift-1-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
placeholder="Search options…"
|
||||
role="combobox"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-labelledby="downshift-1-label"
|
||||
className="w-combobox__menu"
|
||||
id="downshift-1-menu"
|
||||
onMouseLeave={[Function]}
|
||||
role="listbox"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__optgroup"
|
||||
key="blockTypes"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__optgroup-label"
|
||||
>
|
||||
Blocks
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col1"
|
||||
key="blockquote"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-0"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<Icon
|
||||
name="blockquote"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Blockquote
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col1"
|
||||
key="paragraph"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-1"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span
|
||||
className="my-icon"
|
||||
>
|
||||
P
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Paragraph
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col1"
|
||||
key="heading-one"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-2"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<Icon
|
||||
name="custom"
|
||||
viewBox="0 0 1024 1024"
|
||||
>
|
||||
<path
|
||||
d="M 83.625 "
|
||||
key="M 83.625 "
|
||||
/>
|
||||
<path
|
||||
d="L 232.535156 "
|
||||
key="L 232.535156 "
|
||||
/>
|
||||
</Icon>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Heading 1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col2"
|
||||
key="heading-two"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-3"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span>
|
||||
H2
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
<span
|
||||
className="custom-text"
|
||||
>
|
||||
H2
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-row w-combobox__option-row--col2"
|
||||
key="link"
|
||||
>
|
||||
<div
|
||||
aria-disabled={false}
|
||||
aria-selected={false}
|
||||
className="w-combobox__option"
|
||||
id="downshift-1-item-4"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span>
|
||||
🔗
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Link
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -1,59 +0,0 @@
|
|||
@use '../../../scss/tools' as *;
|
||||
|
||||
.w-combobox-preview {
|
||||
padding: theme('spacing.5');
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: theme('spacing.5');
|
||||
// Set a min-height to ensure it's big enough to be useful
|
||||
min-height: 400px;
|
||||
background-color: theme('colors.surface-header');
|
||||
border-block-start: 1px solid theme('colors.border-furniture');
|
||||
border-end-end-radius: inherit;
|
||||
border-end-start-radius: inherit;
|
||||
@include media-breakpoint-up(md) {
|
||||
border-block-start: 0;
|
||||
border-start-end-radius: inherit;
|
||||
border-end-start-radius: 0;
|
||||
border-inline-start: 1px solid theme('colors.border-furniture');
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox-preview__iframe {
|
||||
// Take up remaining space
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
border: 1px solid theme('colors.border-furniture');
|
||||
border-radius: theme('borderRadius.sm');
|
||||
|
||||
// Ensure iframe is always opaque
|
||||
color-scheme: normal;
|
||||
background-color: Canvas;
|
||||
|
||||
@include more-contrast() {
|
||||
border-color: theme('colors.border-furniture-more-contrast');
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox-preview__details {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// Use 65:35 ratio between the iframe and the details, but allow the details
|
||||
// to grow to a minimum of 100px in case the container is very small
|
||||
// (i.e. when there are only a few blocks)
|
||||
min-height: max(35%, 100px);
|
||||
}
|
||||
|
||||
.w-combobox-preview__label {
|
||||
@apply w-label-1;
|
||||
}
|
||||
|
||||
.w-combobox-preview__description {
|
||||
@apply w-help-text;
|
||||
margin-top: theme('spacing.3');
|
||||
margin-bottom: 0;
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue