first commit

This commit is contained in:
2026-01-25 18:18:09 +08:00
commit 509312e604
8136 changed files with 2349298 additions and 0 deletions

104
vendor/yiisoft/extensions.php vendored Normal file
View File

@ -0,0 +1,104 @@
<?php
$vendorDir = dirname(__DIR__);
return array (
'yidas/yii2-composer-bower-skip' =>
array (
'name' => 'yidas/yii2-composer-bower-skip',
'version' => '2.0.13.0',
),
'omnilight/yii2-scheduling' =>
array (
'name' => 'omnilight/yii2-scheduling',
'version' => '1.1.5.0',
'alias' =>
array (
'@omnilight/scheduling' => $vendorDir . '/omnilight/yii2-scheduling/src',
),
'bootstrap' => 'omnilight\\scheduling\\Bootstrap',
),
'yidas/yii2-bower-asset' =>
array (
'name' => 'yidas/yii2-bower-asset',
'version' => '2.0.13.1',
'alias' =>
array (
'@yidas/yii2BowerAsset' => $vendorDir . '/yidas/yii2-bower-asset',
),
),
'yiisoft/yii2-bootstrap5' =>
array (
'name' => 'yiisoft/yii2-bootstrap5',
'version' => '2.0.51.0',
'alias' =>
array (
'@yii/bootstrap5' => $vendorDir . '/yiisoft/yii2-bootstrap5/src',
),
'bootstrap' => 'yii\\bootstrap5\\i18n\\TranslationBootstrap',
),
'yiisoft/yii2-debug' =>
array (
'name' => 'yiisoft/yii2-debug',
'version' => '2.1.27.0',
'alias' =>
array (
'@yii/debug' => $vendorDir . '/yiisoft/yii2-debug/src',
),
),
'yiisoft/yii2-faker' =>
array (
'name' => 'yiisoft/yii2-faker',
'version' => '2.0.5.0',
'alias' =>
array (
'@yii/faker' => $vendorDir . '/yiisoft/yii2-faker/src',
),
),
'yiisoft/yii2-gii' =>
array (
'name' => 'yiisoft/yii2-gii',
'version' => '2.2.7.0',
'alias' =>
array (
'@yii/gii' => $vendorDir . '/yiisoft/yii2-gii/src',
),
),
'yiisoft/yii2-symfonymailer' =>
array (
'name' => 'yiisoft/yii2-symfonymailer',
'version' => '2.0.4.0',
'alias' =>
array (
'@yii/symfonymailer' => $vendorDir . '/yiisoft/yii2-symfonymailer/src',
),
),
'yiisoft/yii2-queue' =>
array (
'name' => 'yiisoft/yii2-queue',
'version' => '2.3.8.0',
'alias' =>
array (
'@yii/queue' => $vendorDir . '/yiisoft/yii2-queue/src',
'@yii/queue/db' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/db',
'@yii/queue/sqs' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/sqs',
'@yii/queue/amqp' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/amqp',
'@yii/queue/file' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/file',
'@yii/queue/sync' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/sync',
'@yii/queue/redis' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/redis',
'@yii/queue/stomp' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/stomp',
'@yii/queue/gearman' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/gearman',
'@yii/queue/beanstalk' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/beanstalk',
'@yii/queue/amqp_interop' => $vendorDir . '/yiisoft/yii2-queue/src/drivers/amqp_interop',
),
),
'yiisoft/yii2-redis' =>
array (
'name' => 'yiisoft/yii2-redis',
'version' => '2.1.0.0',
'alias' =>
array (
'@yii/redis' => $vendorDir . '/yiisoft/yii2-redis/src',
),
),
);

View File

@ -0,0 +1,14 @@
# editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false

View File

@ -0,0 +1,2 @@
# Added ecs
949c26fa4398c95fc7a7cb8c2dbc4cb5b92423db

View File

@ -0,0 +1,7 @@
Contributing to Yii2
====================
- [Report an issue](https://github.com/yiisoft/yii2/blob/master/docs/internals/report-an-issue.md)
- [Translate documentation or messages](https://github.com/yiisoft/yii2/blob/master/docs/internals/translation-workflow.md)
- [Give us feedback or start a design discussion](https://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/)
- [Contribute to the core code or fix bugs](https://github.com/yiisoft/yii2/blob/master/docs/internals/git-workflow.md)

View File

@ -0,0 +1,5 @@
# These are supported funding model platforms
open_collective: yiisoft
github: [yiisoft]
tidelift: "packagist/yiisoft/yii2-bootstrap5"

View File

@ -0,0 +1,19 @@
<!--
Please use this issue tracker for bugs and feature requests only. In case you need support please use one of
Yii communities listed at https://github.com/yiisoft/yii2/wiki/communities
-->
### What steps will reproduce the problem?
### What is the expected result?
### What do you get instead?
### Additional info
| Q | A
| ---------------- | ---
| Yii vesion |
| PHP version |
| Operating system |

View File

@ -0,0 +1,6 @@
| Q | A
| ------------- | ---
| Is bugfix? | ✔️/❌
| New feature? | ✔️/❌
| Breaks BC? | ✔️/❌
| Fixed issues | <!-- comma-separated list of tickets # fixed by the PR, if any -->

View File

@ -0,0 +1,6 @@
# Security Policy
Please use the [security issue form](https://www.yiiframework.com/security) to report to us any security issue you find in Yii.
DO NOT use the issue tracker or discuss it in the public forum as it will cause more damage than help.
Please note that as a non-commercial OpenSource project we are not able to pay bounties at the moment.

View File

@ -0,0 +1,49 @@
name: build
on: [ push, pull_request ]
env:
DEFAULT_COMPOSER_FLAGS: "--prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi --ignore-platform-req=php"
jobs:
phpunit:
name: PHP ${{ matrix.php }}-${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
php: [ "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4" ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- name: Determine composer cache directory
id: composer-cache
run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
- name: Cache dependencies composer installed with composer
uses: actions/cache@v4
with:
path: ${{ env.COMPOSER_CACHE_DIR }}
key: php${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
restore-keys: php${{ matrix.php }}-composer-
- name: Update composer
run: composer self-update
- name: Install dependencies with composer
run: composer update $DEFAULT_COMPOSER_FLAGS
- name: Run unit tests with coverage
run: vendor/bin/phpunit --verbose --coverage-clover=coverage.clover --colors=always
if: matrix.php == '7.4'
- name: Run unit tests without coverage
run: vendor/bin/phpunit --verbose --colors=always
if: matrix.php != '7.4'
- name: Upload code coverage
run: |
wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover coverage.clover
if: matrix.php == '7.4'
continue-on-error: true # if is fork

View File

@ -0,0 +1,39 @@
name: ecs
on: [ push, pull_request ]
env:
DEFAULT_COMPOSER_FLAGS: "--prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi --ignore-platform-req=php"
jobs:
easy-coding-standard:
name: PHP ${{ matrix.php }}-${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
php: [ "8.0", "8.1", "8.2", "8.3", "8.4" ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- name: Determine composer cache directory
id: composer-cache
run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
- name: Cache dependencies composer installed with composer
uses: actions/cache@v4
with:
path: ${{ env.COMPOSER_CACHE_DIR }}
key: php${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
restore-keys: php${{ matrix.php }}-composer-
- name: Update composer
run: composer self-update
- name: Install dependencies with composer
run: composer update $DEFAULT_COMPOSER_FLAGS
- name: Run easy-coding-standard
run: vendor/bin/ecs check src tests --ansi

View File

@ -0,0 +1,37 @@
# phpstorm project files
.idea
# netbeans project files
nbproject
# zend studio for eclipse project files
.buildpath
.project
.settings
# windows thumbnail cache
Thumbs.db
# composer
composer.phar
/vendor
/composer.lock
# Mac DS_Store Files
.DS_Store
# phpunit itself is not needed
phpunit.phar
# local phpunit config
/phpunit.xml
/tests/bootstrap.local.php
/tests/runtime
/tests/data/config.local.php
/tests/docker
/tests/dockerids
# nodejs
/node_modules
/package-lock.json
.phpunit.result.cache

View File

@ -0,0 +1,71 @@
Yii Framework 2 bootstrap5 extension Change Log
==============================================
2.0.52 under development
------------------------
2.0.51 December 03, 2025
------------------------
- Enh #87: Added view option to render a view with Yii inside tab content
- Bug #83: Removed bower asset and replaced with twbs/bootstrap package (simialbi)
- Bug #88: Fix ButtonDropdown JS error (stevekr, simialbi)
- Bug #103: Fix `LinkPager::getPageRange` when `maxButtons` is 2 (mspirkov)
2.0.50 April 10, 2025
---------------------
- Bug #84: Checkbox labels in inline forms are no longer hidden (BBoom)
- Bug #80: Prevent publishing of whole bootstrap directory (rmenor)
- Bug #92: Explicit nullable parameter (OneMorePenguin, simialbi)
- Enh #78: Navbar has new attribute `brandImageOptions` (EvilKarter)
- Bug #74: Bootstrap5 Button is not registering clientEvents (simialbi)
- Bug #72: Nav::isItemActive(): Return value must be of type bool, int returned (hirenbhut93)
- Bug #62: Navbar can now accept `collapseOptions` to be `false` (theblindfrog)
2.0.4 November 30, 2022
-----------------------
- Bug #58: Dropdown clientEvents did not fire because they need to be bound on parent (simialbi)
- Bug #43: Accordion widget does not set "collapsed" class on toggle button (simialbi)
- Enh #39: Add inline mode to `BaseHtml::checkboxList()` and `BaseHtml::radioList()` (WinterSilence)
- Enh #40: Breadcrumbs refactoring (WinterSilence)
- Bug #46: Fix data-attribute usage for Dropdown toggle (machour)
- Enh #48: Update `BootstrapWidgetTrait` to initialize JS plugins without jQuery (WinterSilence)
2.0.3 April 22, 2022
--------------------
- Enh #36: `BootstrapWidgetTrait::$clientOptions = false` disables registerJs in `BootstrapWidgetTrait` (julianrutten)
- Enh #33: Updated russian translations (WinterSilence)
- Enh #28: Added translations (simialbi)
- Enh #24: Accept `Breadcrumbs::$homeLink = false` to omit "Home" link (fetus-hina)
- Enh #27: Changed all data- and aria- attributes to short syntax (simialbi)
- Enh #26: Add Bootstrap icon asset (Krakozaber)
- Enh #18: Add rangeInput(), colorInput() and switch mode to checkbox() in class ActiveField (WinterSilence)
- Bug #19: Fix value of attribute "aria-current" in LinkPager::renderPageButton() (WinterSilence)
- Bug #23: Fix class attribute in listBox() and dropDownList() of class ActiveField (WinterSilence)
- Bug #133: Fix default `homeUrl` in `Breadcrumbs` widget (luke-)
2.0.2 October 21, 2021
----------------------
- Bug #5: BootstrapWidgetTrait::registerPlugin do nothing if no clientOptions is provided (dicrtarasov)
- Bug #6: yii\bootstrap5\BaseHtml::staticControl(): Argument #1 ($value) must be of type string, int given (dicrtarasov)
- Bug #9: fixed default ActiveField::hintOptions (dicrtarasov)
- Bug #15: Fixed inline rendering of checkboxLists and radioLists (simialbi)
- Enh #11: Brought back close button api (simialbi)
2.0.1 August 11, 2021
---------------------
- no changes in this release.
1.0.0
-----------------------
- Initial release

View File

@ -0,0 +1,29 @@
Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Yii Software LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,55 @@
<p align="center">
<a href="https://getbootstrap.com/" target="_blank" rel="external">
<img src="https://getbootstrap.com/docs/5.0/assets/brand/bootstrap-logo.svg" height="80px">
</a>
<h1 align="center">Twitter Bootstrap 5 Extension for Yii 2</h1>
<br>
</p>
This is the Twitter Bootstrap extension for [Yii framework 2.0](https://www.yiiframework.com). It encapsulates [Bootstrap 5](https://getbootstrap.com/) components
and plugins in terms of Yii widgets, and thus makes using Bootstrap components/plugins
in Yii applications extremely easy.
For license information check the [LICENSE](LICENSE.md)-file.
Documentation is at [docs/guide/README.md](docs/guide/README.md).
[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2-bootstrap5/v/stable.png)](https://packagist.org/packages/yiisoft/yii2-bootstrap5)
[![Total Downloads](https://poser.pugx.org/yiisoft/yii2-bootstrap5/downloads.png)](https://packagist.org/packages/yiisoft/yii2-bootstrap5)
[![Build Status](https://github.com/yiisoft/yii2-bootstrap5/workflows/build/badge.svg)](https://github.com/yiisoft/yii2-bootstrap5/actions/workflows/build.yml)
[![ECS Status](https://github.com/yiisoft/yii2-bootstrap5/workflows/ecs/badge.svg)](https://github.com/yiisoft/yii2-bootstrap5/actions/workflows/ecs.yml)
Installation
------------
The preferred way to install this extension is through [composer](https://getcomposer.org/download/).
Either run
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
or add
```
"yiisoft/yii2-bootstrap5": "*"
```
to the require section of your `composer.json` file.
Translations
----
The i18n configuration will be automatically added to your application configuration via bootstrapping process.
Usage
----
For example, the following
single line of code in a view file would render a Bootstrap Progress plugin:
```php
<?= yii\bootstrap5\Progress::widget(['percent' => 60, 'label' => 'test']) ?>
```

View File

@ -0,0 +1,68 @@
{
"name": "yiisoft/yii2-bootstrap5",
"description": "The Twitter Bootstrap v5 extension for the Yii framework",
"keywords": [
"yii2",
"bootstrap",
"bootstrap5"
],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
"source": "https://github.com/yiisoft/yii2-bootstrap5"
},
"authors": [
{
"name": "Sergey Zhukovskiy",
"email": "mylistryx@gmail.com",
"homepage": "https://net23.ru/"
},
{
"name": "Simon Karlen",
"email": "simi.albi@outlook.com"
}
],
"minimum-stability": "stable",
"require": {
"php": ">=7.3",
"ext-json": "*",
"yiisoft/yii2": "^2.0.42",
"twbs/bootstrap": "^5.2.3"
},
"require-dev": {
"yiisoft/yii2-coding-standards": "~2.0",
"phpunit/phpunit": "^9.6",
"symplify/easy-coding-standard": "^12.1",
"twbs/bootstrap-icons": "^1.7.2"
},
"suggest": {
"twbs/bootstrap-icons": "Add this package to the `require` section of your `composer.json` if you'd like to use the bootstrap icon asset."
},
"config": {
"allow-plugins": {
"yiisoft/yii2-composer": true
}
},
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
],
"autoload": {
"psr-4": {
"yii\\bootstrap5\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"yiiunit\\extensions\\bootstrap5\\": "tests"
}
},
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
},
"bootstrap": "yii\\bootstrap5\\i18n\\TranslationBootstrap"
}
}

View File

@ -0,0 +1,30 @@
Twitter Bootstrap Erweiterung für Yii 2
=======================================
Diese Erweiterung enthält Unterstützung für das [Bootstrap 5 Framework](https://getbootstrap.com/) (auch bekannt als "Twitter Bootstrap")
Markup und dessen Komponenten. Bootstrap ist eine exzellentes, reponsives Framework welches den clientseitigen
Entwicklungsprozess vehement zu verkürzen vermag.
Die Basis von Bootstrap ist unterteilt in folgende 2 Bereiche:
- CSS Basics: Grid Layout System, Typography, Helper-Klassen, Responsive Funktionen.
- "Ready to use"-Komponenten: Formulare, Menus, Paginationen, Modals, Tabs etc.
Loslegen
--------
* [Installation](installation.md)
* [Assets Setup](assets-setup.md)
* [Basic Usage](basic-usage.md)
Verwendung
----------
* [Yii widgets](usage-widgets.md)
* [Html helper](helper-html.md)
* [Asset Bundles](asset-bundles.md)
Weitere Themen
--------------
* [Using the .sass files of Bootstrap directly](topics-sass.md)
* [Migration von yii2-bootstrap](migrating-yii2-bootstrap.md)

View File

@ -0,0 +1,18 @@
Asset Bundles
=============
Bootstrap ist eine komplexe Front-End-Lösung, welche CSS, Javascript, Schriften usw. beinhaltet.
Um Ihnen die flexibelste Kontrolle über die einzelnen Komponenten zu ermöglichen, enthält diese Erweiterung verschiedene Asset Bundles.
Das sind:
- [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] - enthält nur das hauptsächliche CSS.
- [[yii\bootstrap5\BootstrapPluginAsset|BootstrapPluginAsset]] - enthält das Javascript. Abhängig von [[yii\bootstrap5\BootstrapAsset]].
- [[yii\bootstrap5\BootstrapIconAsset|BootstrapIconAsset]] - enthält die Bootstrap Icons.
Verschiedene Anwendungsanforderungen erfordern verschiedene Bundles (bzw. Kombinationen).
Falls Sie nur auf das CSS angewiesen sind, reicht es wenn Sie [[yii\bootstrap5\BootstrapAsset]] laden.
Wenn Sie das Javascript verwenden möchten, müssen Sie [[yii\bootstrap5\BootstrapPluginAsset]] auch laden.
Falls Sie die Icons von Bootstrap 5 verwenden möchten, fügen Sie `twbs/bootstrap-icons` zu ihrem `composer.json` in die
`require` Sektion ein und registrieren Sie [[yii\bootstrap5\BootstrapIconAsset]] in Ihrer Applikation
> Tipp: Die meisten Widgets laden [[yii\bootstrap5\BootstrapPluginAsset]] automatisch.

View File

@ -0,0 +1,170 @@
Asset-Konfiguration
===================
Diese Erweiterung beruht auf [Bower](https://bower.io/) und/oder [NPM](https://www.npmjs.org/) Packages für die Asset Installation.
Bevor Sie diese Erweiterung einsetzen, sollten Sie entscheiden, auf welche Weise Sie diese Packages installieren möchten.
## Verwendung des asset-packagist Repository
Sie können [asset-packagist.or](https://asset-packagist.org) als Package-Quelle für die Bootstrap-Assets angeben.
Fügen Sie dazu folgende Zeilen zur `composer.json`-Datei ihres Projekts hinzu:
```json
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
]
```
Passen Sie `@npm` und `@bower` in der Konfiguration ihrer Applikation wie folgt an:
```php
return [
//...
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
//...
];
```
## Verwendung des composer asset Plugins
Installieren Sie das [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/) global durch das Ausführen folgendes Befehls:
```
composer global require "fxp/composer-asset-plugin:^1.4.0"
```
Fügen Sie folgende Zeilen zur `composer.json`-Datei ihres Projekts hinzu um das Verzeichnis der Installation von Assets anzupassen
falls Sie möchten, das Yii sie verwaltet:
```json
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
```
Daraufhin können Sie den composer install bzw. update Befehl ausführen um die Boostrap Assets zu installieren.
> Warnung: Das Plugin `fxp/composer-asset-plugin` verlangsamt den `composer update` Befehl signifikant verglichen zur
"asset-packagist"-Methode.
## Direkte Verwendung des Bower/NPM Clients
Sie kännen die Bootstrap Assets direkt via Bower oder NPM Client installieren.
Fügen Sie dafür folgende Zeilen zur `package.json`-Datei Ihres Projekts hinzu:
```json
{
...
"dependencies": {
"bootstrap": "5.1",
...
}
...
}
```
Fügen Sie zur `composer.json`-Datei Ihres Projekts folgende Zeilen hinzu zum Verhindern von redundanten Bootstrap-Installationen:
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
## Verwendung des CDN
Sie können die Bootstrap Assets vom [offiziellen CDN](https://www.bootstrapcdn.com) laden.
Fügen Sie zur `composer.json`-Datei Ihres Projekts folgende Zeilen hinzu zum Verhindern von redundanten Bootstrap-Installationen:
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
Konfigurieren Sie die 'assetManager'-Komponente wie folgt (überschreibt die Bootstrap Asset mit den CDN Links):
```php
return [
'components' => [
'assetManager' => [
// override bundles to use CDN :
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'sourcePath' => null,
'baseUrl' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.1/dist/',
'css' => [
'css/bootstrap.min.css'
],
],
'yii\bootstrap5\BootstrapPluginAsset' => [
'sourcePath' => null,
'baseUrl' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.1/dist/',
'js' => [
'js/bootstrap.bundle.min.js'
],
],
],
],
// ...
],
// ...
];
```
## Kompilieren von den .sass Dateien
Falls Sie den Bootstrap Quelltext direkt anpassen möchten, können Sie das CSS direkt von den Quell *.sass-Dateien kompilieren.
In diesem Fall macht die Installation der Bootstrap Assets via composer bzw. Bower/NPM kein Sinn, da Sie keine Dateien innerhalb
des 'vendor'-Verzeichnisses bearbeiten können.
Sie müssen die Bootstrap-Assets manuell herunterladen und sie irgendwo in Ihrem Projekt platzieren (z.B. 'assets/source/bootstrap').
Fügen Sie zur `composer.json`-Datei Ihres Projekts folgende Zeilen hinzu zum Verhindern von redundanten Bootstrap-Installationen:
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
Konfigurieren Sie die 'assetManager'-Komponente wie folgt (überschreibt die Bootstrap Assets):
```php
return [
'components' => [
'assetManager' => [
// override bundles to use local project files :
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'sourcePath' => '@app/assets/source/bootstrap/dist',
'css' => [
YII_ENV_DEV ? 'css/bootstrap.css' : 'css/bootstrap.min.css',
],
],
'yii\bootstrap5\BootstrapPluginAsset' => [
'sourcePath' => '@app/assets/source/bootstrap/dist',
'js' => [
YII_ENV_DEV ? 'js/bootstrap.js' : 'js/bootstrap.min.js',
]
],
],
],
// ...
],
// ...
];
```
Nach dem Verändern des Bootstrap Quellcodes, stellen Sie sicher, dass sie neu [kompiliert werden](https://getbootstrap.com/docs/5.1/getting-started/contribute/#using-npm-scripts), z.B. mittels `npm run dist`.

View File

@ -0,0 +1,17 @@
Grundlegende Verwendung
=======================
Yii verpackt die Bootstrap Basics nicht in PHP Code, da dass HTML selbst sehr einfach aufgebaut ist. Sie finden mehr
Informationen zur Verwendung der Basics unter [bootstrap documentation website](https://getbootstrap.com/docs/). Yii bietet
aber eine einfache Methode zur Einbindung der Bootstrap Assets in Ihre Seite durch das Hinzufügen einer Zeile zu `AppAsset.ph`
im `@app/assets` Verzeichnis:
```php
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset', // Diese Zeile
];
```
Die Verwendung von Bootstrap mittels des Yii Asset Manager erlaubt die Komprimierung und Kombinierung der Bootstrapressourcen
mit den Applikationsressourcen (falls nötig).

View File

@ -0,0 +1,30 @@
HTML helper
===========
Bootstrap führt viele konsistente HTML Strukturen ein, welche es erlauben, verschiedene visuelle Effekte einfach zu verwenden.
Ausschliesslich die komplexesten von ihnen sind mittels Widgets in dieser Erweiterung umgesetzt worden. Der Rest kann manuell
mittels HTML zusammengestellt werden.
Einige spezielle Bootstrap Markups sind implementiert im [[\yii\bootstrap5\Html]]-Helper.
Die [[\yii\bootstrap5\Html]]-Klasse ist eine Erweiterung der regulären [[\yii\helpers\Html]]-Klasse mit Anpassungen zur
Verwendung mit Bootstrap. Sie bietet verschiedene nützliche Methoden wie z.B.
- `staticControl()` - erlaubt das erstellen von "[statischen Feldern](https://getbootstrap.com/docs/5.1/forms/form-control/#readonly-plain-text)"
Die [[\yii\bootstrap5\Html]]-Klasse erbt von der [[\yii\helpers\Html]]-Klasse und ersetzt diese dadurch vollumfänglich.
Sie benötigen folglich **nicht** beide in Ihren Views.
Beispiel:
```php
<?php
use yii\bootstrap5\Button;
use yii\bootstrap5\Html;
?>
<?= Button::widget([
'label' => Html::tag('i', ['class' => 'fas fa-check']) . Html::encode('Save & apply'),
'encodeLabel' => false,
'options' => ['class' => 'btn-primary'],
]); ?>
```
> Vorsicht: Verwechseln Sie [[\yii\bootstrap5\Html]] und [[\yii\helpers\Html]] Klassen nicht und bedenken Sie jeweils
welche Sie in Ihren Views verwenden.

View File

@ -0,0 +1,20 @@
Installation
============
## Mittels Composer Package
Der empfohlene Weg zur Installation dieser Erweiterung ist mittels [composer](https://getcomposer.org/download/).
Führen Sie entweder folgenden Befehlt aus
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
oder fügen Sie folgendes
```
"yiisoft/yii2-bootstrap5": "~1.0.0"
```
zur `require`-Sektion Ihrer `composer.json`-Datei hinzu.

View File

@ -0,0 +1,48 @@
Migration von yii2-bootstrap4
=============================
yii2-bootstrap4 ist eine komplette Überarbeitung des Projekts (siehe den Bootstrap 4 von Bootstrap 3 Migrationsguide).
Die größten Änderungen finden Sie hier zusammengefasst:
## Allgemein
* Der Namespace ist nun `yii\bootstrap5` anstatt `yii\bootstrap4`
* Die PHP Kompatibilität **ist beschränkt auf** `>=7.0`
* Der "Schließen"-Button von Widgets wie [[yii\bootstrap5\Alert|Alert]] oder [[yii\bootstrap5|Modal|Modal]] wird neu
via CSS dargestellt und hat keinen Inhalt mehr. Es ist daher beim Überschreiben sicherzustellen, dass die `btn-close`
Klasse entfernt wird und die benötigten Stile manuell gesetzt werden.
## Widgets / Klassen
### BaseHtml
### ActiveField
### ActiveForm
Es gibt eine neue Konstante [[yii\bootstrap5\ActiveForm::LAYOUT_FLOATING]]. Sie repräsentiert ein
[neues Formular-Layout](https://getbootstrap.com/docs/5.1/forms/floating-labels/) in Bootstrap 5.
### Breadcrumbs
### ButtonDropdown
### ButtonToolbar
### Carousel
### LinkPager
### Modal
### Nav
### NavBar
Es gibt nun die Möglichkeit der Erstellung einer [Offcanvas Navbar](https://getbootstrap.com/docs/5.1/components/navbar/#offcanvas).
Dies ist zu erreichen, indem man die Eigenschaft `$collapseOptions` des Widgets [[yii\bootstrap5\NavBar|Navbar]] auf `false`
und die Eigenschaft `$offcanvasOptions` auf ein array setzt (auch wenn leer).
### Tabs
### ToggleButtonGroup

View File

@ -0,0 +1,17 @@
Direkte Verwendung der .sass Dateien von Bootstrap
==================================================
Falls Sie das [Bootstrap CSS direkt in Ihre SASS-Dateien integerieren](https://getbootstrap.com/docs/4.1/getting-started/theming/#sass)
möchten, müssen Sie unter Umständen das Laden der Orginal Bootstrap-CSS-Dateien verhindern.
Dies können Sie durch das Leeren des `css`-Property in der [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]]-Datei bewerkstelligen.
Konfigurieren Sie dazu die `assetManager`-[Komponente](https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-application-components.md) wie folgt:
```php
'assetManager' => [
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'css' => [],
]
]
]
```

View File

@ -0,0 +1,97 @@
Yii widgets
===========
Die komplexesten Bootstrap Komponenten sind umgesetzt mittels Yii-Widget zur vereinfachten Verwendung und Integration
von Framework-Funktionen. Alle Widgets gehören zum `\yii\bootstrap5` Namespace:
- [[yii\bootstrap5\Accordion|Accordion]]
- [[yii\bootstrap5\ActiveField|ActiveField]]
- [[yii\bootstrap5\ActiveForm|ActiveForm]]
- [[yii\bootstrap5\Alert|Alert]]
- [[yii\bootstrap5\Breadcrumbs|Breadcrumbs]]
- [[yii\bootstrap5\Button|Button]]
- [[yii\bootstrap5\ButtonDropdown|ButtonDropdown]]
- [[yii\bootstrap5\ButtonGroup|ButtonGroup]]
- [[yii\bootstrap5\ButtonToolbar|ButtonToolbar]]
- [[yii\bootstrap5\Carousel|Carousel]]
- [[yii\bootstrap5\Dropdown|Dropdown]]
- [[yii\bootstrap5\Modal|Modal]]
- [[yii\bootstrap5\Nav|Nav]]
- [[yii\bootstrap5\NavBar|NavBar]]
- [[yii\bootstrap5\Offcanvas|Offcanvas]]
- [[yii\bootstrap5\Progress|Progress]]
- [[yii\bootstrap5\Tabs|Tabs]]
- [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]]
## ActiveField: Weitere Input-Typen <span id="additional-fields"></span>
- [Range](https://getbootstrap.com/docs/5.1/forms/range/): `$form->rangeInput(['min' => 0, 'max' => 100, 'step' => 1])`
- [Color picker](https://getbootstrap.com/docs/5.1/forms/form-control/#color): `$form->colorInput()`
- [Switch](https://getbootstrap.com/docs/5.1/forms/checks-radios/#switches): `$form->checkbox(['switch' => true])`
## Anpassen der Widget CSS-Klassen <span id="customizing-css-classes"></span>
Die Widgets erlauben die schnelle Erstellung von HTML-Markup der Bootstrap Komponenten.
Die Standard-CSS-Klassen einer bestimmten Komponente wird automatisch vom Widget hinzugefügt. Alle weiteren (optionalen)
Klassen können Sie mittels der Attribute des Widgets anpassen.
Verwenden Sie z.B. [[yii\bootstrap5\Button::options]] zur Anpassung des Aussehens des Buttons. Die Klasse `btn`, welche
benötigt vom Button Widget benötigt wird, wird automatisch hinzugefügt. Sie müssen lediglich die besondere Button-Klasse
hinzufügen:
```php
echo Button::widget([
'label' => 'Action',
'options' => ['class' => 'btn-primary'], // produces class "btn btn-primary"
]);
```
Manchmal möchte man aber die Standard-Klasse ersetzen.
Das [[yii\bootstrap5\ButtonGroup]]-Widget beispielsweise verwendet standardmässig die 'btn-group' Klasse für den Container,
es müsste aber 'btn-group-vertical' erhalten zur vertikalen Ausrichtung.
Würden Sie wie oben nur die 'class'-Option verwenden, würde die 'btn-group-vertical'-Klasse zur 'btn-group'-Klasse hinzugefügt.
Zum Überschreiben der Standard-Klassen eines Widgets, müssen Sie die 'class'-Option unter dem Array-Schlüssel 'widget' angeben:
```php
echo ButtonGroup::widget([
'options' => [
'class' => ['widget' => 'btn-group-vertical'] // replaces 'btn-group' with 'btn-group-vertical'
],
'buttons' => [
['label' => 'A'],
['label' => 'B'],
]
]);
```
## Navbar widget <span id="navbar-widget"></span>
Das Navbar Widget hat so seine Eigenheiten. Bei der Verwendung des Widgets sollten Sie darauf achten, dass der Breakpoint,
ab welchem die Navigation zugeklappt wird (Mobile Navigation) sowie das Farbschema definiert sind.
Diese Definition geschieht über CSS Klassen. Die Standartwerte lauten `navbar-light bg-light` fürs Farbschema und
`navbar-expand-lg` für den brakpoint. Für weitere Informationen, konsultieren Sie die [Bootstrap Dokumentation](https://getbootstrap.com/docs/5.1/components/navbar/):
```php
Navbar::begin([
'options' => [
'class' => ['navbar-dark', 'bg-dark', 'navbar-expand-md']
]
]);
[...]
Navbar::end();
```
Falls Sie die Reihenfolge des Logos und des "Toggle Buttons" ändern möchten, können Sie dies wie folgt tun:
```php
Navbar::begin([
'brandOptions' => [
'class' => ['order-1']
],
'togglerOptions' => [
'class' => ['order-0']
]
]);
[...]
Navbar::end();
```

View File

@ -0,0 +1,29 @@
Extensión Twitter Bootstrap para Yii 2
======================================
La extensión incluye soporte para el marcado de [Bootstrap 5](https://getbootstrap.com/) y los componentes del framework
(también conocido como "Twitter Bootstrap"). Bootstrap es un excelente framework responsivo que puede acelerar
enormemente el proceso de desarrollo del lado del cliente.
El núcleo de Boostrap está representado por dos partes:
- Bases de CSS, tales como un sistema de cuadriculas, tipografía, clases de ayuda, y utilidades responsivas.
- Componentes listos para usar, tales como formularios, menús, paginación, cajas modales, tabs, etc.
Pasos Iniciales
---------------
* [Instalación](installation.md)
* [Uso Básico](basic-usage.md)
Uso
---
* [Yii widgets](usage-widgets.md)
* [Html helper](helper-html.md)
* [Asset Bundles](asset-bundles.md)
Temas Adicionales
-----------------
* [Usando directamente los ficheros .sass de Bootstrap](topics-sass.md)

View File

@ -0,0 +1,16 @@
Asset Bundles
=============
Bootstrap es una completa solución front-end, que incluye CSS, JavaScript, fuentes y mucho más.
Con el fin de permitir un control más flexible sobre los componentes de Bootstrap, esta extensión proporciona
varios asset bundles.
Ellos son:
- [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] - contiene unicamente los ficheros CSS principales.
- [[yii\bootstrap5\BootstrapPluginAsset|BootstrapPluginAsset]] - depende de [[yii\bootstrap5\BootstrapAsset]], contiene ficheros javascript.
Particularmente las aplicaciones pueden necesitar requerir diferentes usos de bundle (o combinación de bundle).
Si necesitas unicamente estilos CSS, [[yii\bootstrap5\BootstrapAsset]] será suficiente para ti. Sin embargo, si
quieres usar el JavaScript de Bootstrap, necesitas registrar [[yii\bootstrap5\BootstrapPluginAsset]].
> Consejo: la mayoría de los widgets registran automaticamente [[yii\bootstrap5\BootstrapPluginAsset]].

View File

@ -0,0 +1,16 @@
Uso Básico
==========
Yii no se ajusta a los conceptos básicos de bootstrap dentro del código PHP, desde el HTML es muy simple en si mismo
en este caso. Puedes encontrar los detalles sobre el uso de los conceptos básicos en la [web de bootstrap](https://getbootstrap.com/docs/). Yii proporciona una manera de incluir los assets de bootstrap en tus páginas añadiendo una única linea a `AppAsset.php` localizado en tu
directorio `@app/assets`:
```php
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset', // esta linea
];
```
Usando bootstrap a través de Yii asset manager permite que minimices los recursos y combinarlos con tus propios recursos
cuando lo necesites.

View File

@ -0,0 +1,28 @@
Html helper
===========
Bootstrap introduce muchas construcciones y esqueletos consistentes de HTML, que permiten crear diferentes efectos visuales.
Unicamente lo más complejo está cubierto por los widgets proporcionados en esta extensión. El resto debería ser
compuesto manualmente usando HTML directamente.
Sin embargo, algunas marcas especiales de Bootstrap son cubiertas por el helper [[\yii\bootstrap5\Html]].
[[\yii\bootstrap5\Html]] es una versión mejorada de la regular [[\yii\helpers\Html]] dedicada a las necesidades de Bootstrap.
Proporciona varios métodos útiles:
- `staticControl()` - permite renderizar formularios "[static controls](https://getbootstrap.com/docs/5.1/forms/form-control/#readonly-plain-text)"
[[\yii\bootstrap5\Html]] hereda todas las funcionalidades disponibles en [[\yii\helpers\Html]] y puede usarse como sustituto,
así que no es necesario incluir ambos dentro de los archivos de tus vistas.
Por ejemplo:
```php
<?php
use yii\bootstrap5\Html;
?>
<?= Button::widget([
'label' => Html::encode('Save & apply'),
'encodeLabel' => false,
'options' => ['class' => 'btn-primary'],
]); ?>
```
> Atención: no confundas [[\yii\bootstrap5\Html]] con [[\yii\helpers\Html]], ten cuidado que clases estás usando dentro de tus vistas.

View File

@ -0,0 +1,20 @@
Instalación
===========
## Obteniendo el Paquete de Composer
La mejor manera para instalar esta extensión es a través de [composer](https://getcomposer.org/download/).
Ejecuta
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
o añade
```
"yiisoft/yii2-bootstrap": "~1.0.0"
```
en la sección require de tu fichero `composer.json`.

View File

@ -0,0 +1,17 @@
Usando directamente los ficheros .sass de Bootstrap
===================================================
Si deseas incluir el [css de Bootstrap directamente en tus ficheros sass](https://getbootstrap.com/getting-started/#customizing) puedes necesitar deshabilitar los ficheros css de bootstrap originales para ser cargados.
Puedes hacer esto mediante la configuración de la propiedad css de [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] asignando
un array vacio.
Para esto necesitas configurar el `assetManager` [componente de aplicación](https://github.com/yiisoft/yii2/blob/master/docs/guide-es/structure-application-components.md) como se muestra a continuación:
```php
'assetManager' => [
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'css' => [],
]
]
]
```

View File

@ -0,0 +1,66 @@
Yii widgets
===========
La mayoría de los componentes de bootstrap están encapsulados dentro de Yii widgets lo que permite una sintaxis
más robusta y poder integrarse con las características del framework. Todos los widgets pertenecen
al namespace `\yii\bootstrap5`:
- [[yii\bootstrap5\Accordion|Accordion]]
- [[yii\bootstrap5\ActiveField|ActiveField]]
- [[yii\bootstrap5\ActiveForm|ActiveForm]]
- [[yii\bootstrap5\Alert|Alert]]
- [[yii\bootstrap5\Breadcrumbs|Breadcrumbs]]
- [[yii\bootstrap5\Button|Button]]
- [[yii\bootstrap5\ButtonDropdown|ButtonDropdown]]
- [[yii\bootstrap5\ButtonGroup|ButtonGroup]]
- [[yii\bootstrap5\ButtonToolbar|ButtonToolbar]]
- [[yii\bootstrap5\Carousel|Carousel]]
- [[yii\bootstrap5\Dropdown|Dropdown]]
- [[yii\bootstrap5\LinkPager|LinkPager]]
- [[yii\bootstrap5\Modal|Modal]]
- [[yii\bootstrap5\Nav|Nav]]
- [[yii\bootstrap5\NavBar|NavBar]]
- [[yii\bootstrap5\Offcanvas|Offcanvas]]
- [[yii\bootstrap5\Popover|Popover]]
- [[yii\bootstrap5\Progress|Progress]]
- [[yii\bootstrap5\Tabs|Tabs]]
- [[yii\bootstrap5\Toast|Toast]]
- [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]]
## Personalización de las clases css para los widget <span id="customizing-css-classes"></span>
Los widgets permiten una rápida composición del HTML para los componentes de bootstrap que requieren las clases
CSS de bootstrap.
Las clases por defecto para un componente en particular serán añadidas automáticamente por los widgets, y las clases
opcionales que quieres personalizar son frecuentemente soportadas a través de las propiedades de los widgets.
Por ejemplo, puedas usar [[yii\bootstrap5\Button::options]] para personalizar la apariencia de un botón.
La clase 'btn' que se requiere para un botón será añadida automáticamente, por lo que no necesitas preocuparte
por ello.
Todo lo que necesitas es especificar una clase de botón en particular:
```php
echo Button::widget([
'label' => 'Action',
'options' => ['class' => 'btn-primary'], // produce la clase "btn btn-primary"
]);
```
Sin embargo, a veces puede que tengas que remplazar las clases por defecto por las alternativas.
Por ejemplo, el widget [[yii\bootstrap5\ButtonGroup]] utiliza por defecto la clase 'btn-group' para el contenido del div, pero necesitas usar 'btn-group-vertical' en lugar de alinear los botones verticalmente.
El uso directo de la opción 'class' simplemente añade 'btn-group-vertical' a 'btn-group, el cual producirá un resultado incorrecto.
Con el fin de sobrescribir las clases por defecto de un widget, necesitas especificar la opción 'class' como un
array que contiene la definición de la clase personalizada bajo la clave 'widget':
```php
echo ButtonGroup::widget([
'options' => [
'class' => ['widget' => 'btn-group-vertical'] // remplaza 'btn-group' con 'btn-group-vertical'
],
'buttons' => [
['label' => 'A'],
['label' => 'B'],
]
]);
```

View File

@ -0,0 +1,31 @@
Yii 2 Twitter Bootstrap エクステンション
========================================
このエクステンションは、マークアップとコンポーネントのフレームワーク [Bootstrap 5](https://getbootstrap.com/) ("Twitter Bootstrap" としても知られています)
に対するサポートを提供します。
Bootstrap は優れた、レスポンシブなフレームワークであり、クライアント・サイドの開発プロセスを大いにスピードアップすることが出来るものです。
Bootstrap のコアは二つの部分によって表されます。
- CSS の基礎。例えば、グリッド・レイアウト・システム、タイポグラフィ、ヘルパ・クラス、レスポンシブ・ユーティリティなど。
- そのまま使えるコンポーネント。フォーム、メニュー、ページネーション、モーダル・ボックス、タブなど。
始めよう
--------
* [インストール](installation.md)
* [アセットのセットアップ](assets-setup.md)
* [基本的な使用方法](basic-usage.md)
使用方法
--------
* [Yii ウィジェット](usage-widgets.md)
* [Html ヘルパ](helper-html.md)
* [アセット・バンドル](asset-bundles.md)
追加のトピック
--------------
* [Bootstrap の .sass ファイルを直接に使う](topics-sass.md)
* [yii2-bootstrap からの移行](migrating-yii2-bootstrap.md)

View File

@ -0,0 +1,16 @@
アセット・バンドル
==================
Bootstrap は、CSS、JavaScript、フォントなどを含む複雑なフロントエンド・ソリューションです。
Bootstrap コンポーネントに対する最大限の柔軟な制御を可能にするために、このエクステンションは複数のアセット・バンドルを提供しています。
すなわち、
- [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] - メインの CSS ファイルのみを含みます。
- [[yii\bootstrap5\BootstrapPluginAsset|BootstrapPluginAsset]] - [[yii\bootstrap5\BootstrapAsset]] に依存し、javascript ファイルを含みます。
個々のアプリケーションは、その要求に応じて、異なるバンドル (またはバンドルの組み合わせ) を必要とするでしょう。
CSS のスタイルだけが必要なのであれば、[[yii\bootstrap5\BootstrapAsset]] だけで十分です。
しかし、Bootstrap の JavaScript を必要とする場合は、[[yii\bootstrap5\BootstrapPluginAsset]]
をも登録しなければなりません。
> Tip: ほとんどのウィジェットは [[yii\bootstrap5\BootstrapPluginAsset]] を自動的に登録します。

View File

@ -0,0 +1,176 @@
アセットのセットアップ
======================
Bootstrap エクステンションは、アセットのインストールについて、[Bower](https://bower.io/) および/または [NPM](https://www.npmjs.org/) のパッケージに依存しています。
Bootstrap パッケージを使う前に、これらのパッケージをあなたのプロジェクトにインストールする方法を決定しなければなりません。
## asset-packagist レポジトリを使う
[asset-packagist.org](https://asset-packagist.org) を Bootstrap アセットのソース・パッケージとしてセットアップすることが出来ます。
あなたのプロジェクトの `composer.json` に下記の行を追加して下さい。
```json
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
]
```
そして、アプリケーション構成で `@npm``@bower` を設定します。
```php
return [
//...
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
//...
];
```
## composer アセット・プラグインを使う
次のコマンドを使って [composer アセット・プラグイン](https://github.com/francoispluchino/composer-asset-plugin/) をグローバルにインストールします。
```
composer global require "fxp/composer-asset-plugin:^1.4.0"
```
Yii を使ってアセットを発行したい場合は、あなたのプロジェクトの `composer.json` に下記の行を追加して、
インストールされるパッケージが置かれるディレクトリを設定します。
```json
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
```
これで、`composer install/update` コマンドを実行すると、Bootstrap のアセットを取得することが可能になります。
> Note: `fxp/composer-asset-plugin` は asset-packagist に比べると、`composer update`
コマンドを著しく遅くさせます。
## Bower/NPM クライアントを直接に使う
Bower または NPM のクライアントを直接に使って Bootstrap のアセットをインストールすることが出来ます。
あなたのプロジェクトの `package.json` に次の行を追加して下さい。
```json
{
...
"dependencies": {
"bootstrap": "4.2.1",
...
}
...
}
```
あなたのプロジェクトの `package.json` に次の行を追加して、Bootstrap アセットの冗長なインストールを防止します。
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
## CDN を使う
[公式 CDN](https://www.bootstrapcdn.com) から Bootstrap アセットを使うことが出来ます。.
あなたのプロジェクトの `package.json` に次の行を追加して、Bootstrap アセットの冗長なインストールを防止します。
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
'assetManager' アプリケーション・コンポーネントを構成して、Bootstrap アセット・バンドルを CDN のリンクでオーバーライドします。
```php
return [
'components' => [
'assetManager' => [
// CDN を使うようにバンドルをオーバーライド
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'sourcePath' => null,
'baseUrl' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.1/dist/',
'css' => [
'css/bootstrap.min.css'
],
],
'yii\bootstrap5\BootstrapPluginAsset' => [
'sourcePath' => null,
'baseUrl' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.1/dist/',
'js' => [
'js/bootstrap.bundle.min.js'
],
],
],
],
// ...
],
// ...
];
```
## .sass ファイルからコンパイルする
Bootstrap CSS ソースを直接にカスタマイズしたい場合、ソースの *.sass ファイルから CSS をコンパイルしたいと思うことがあるでしょう。
そのような場合は、Bootstrap アセットを Composer や Bower/NPM からインストールしても意味がありません。
なぜなら、`vendor` ディレクトリ内のファイルは変更できないからです。
Bootstrap アセットを手作業でダウンロードし、プロジェクト・ソース・コード内のどこか、
例えば `assets/source/bootstrap` フォルダに置かなければなりません。
あなたのプロジェクトの `package.json` に次の行を追加して、Bootstrap アセットの冗長なインストールを防止します。
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
'assetManager' アプリケーション・コンポーネントを構成して、Bootstrap アセット・バンドルをオーバーライドします。
```php
return [
'components' => [
'assetManager' => [
// バンドルをオーバーライドし、ローカル・プロジェクト・ファイルを使う
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'sourcePath' => '@app/assets/source/bootstrap/dist',
'css' => [
YII_ENV_DEV ? 'css/bootstrap.css' : 'css/bootstrap.min.css',
],
],
'yii\bootstrap5\BootstrapPluginAsset' => [
'sourcePath' => '@app/assets/source/bootstrap/dist',
'js' => [
YII_ENV_DEV ? 'js/bootstrap.js' : 'js/bootstrap.min.js',
]
],
],
],
// ...
],
// ...
];
```
Bootsrap のソース・ファイルを変更した後は、例えば `npm run dist` を使って、必ず[コンパイル](https://getbootstrap.com/docs/5.1/getting-started/contribute/#using-npm-scripts)して下さい。

View File

@ -0,0 +1,17 @@
基本的な使用方法
================
Yii は bootstrap の基礎を PHP コードでラップすることをしていません。なぜなら、この場合の HTML コードがそれ自体として非常にシンプルだからです。
bootstrap の基礎を使用することに関する詳細は、[bootstrap ドキュメント・ウェブ・サイト](https://getbootstrap.com/docs/) で見ることが出来ます。
それでも、Yii はあなたのページに bootstrap のアセットをインクルードするための便利な方法を提供しています。
`@app/assets` ディレクトリに配置されている `AppAsset.php` に一行を加えるだけで大丈夫です。
```php
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset', // この行です
];
```
Yii のアセットマネージャによって bootstrap を使うと、必要に応じて、bootstrap のリソースを最小化したり、
あなた自身のリソースと結合したりすることが出来ます。

View File

@ -0,0 +1,30 @@
Html ヘルパ
===========
Bootstrap は、一貫性の高い多数の HTML 構文ないしはスケルトンを導入して、さまざまな視覚的効果の生成を可能にしています。
このエクステンションによって提供されるウィジェットがカバーしているのは、その中の最も複雑なものだけです。
残りのものは、直接に HTML 構文を使って、手作業で構築しなければなりません。
ただし、いくつかの特別な Bootstrap マークアップについては、[[\yii\bootstrap5\Html]] によってカバーされています。
[[\yii\bootstrap5\Html]] は通常の [[\yii\helpers\Html]] の拡張版であり、Bootstrap の要求に特化して、
いくつかの便利なメソッドを提供するものです。例えば、
- `staticControl()` - フォームの "[static controls](https://getbootstrap.com/docs/5.1/forms/form-control/#readonly-plain-text)" のレンダリングを可能にする
[[\yii\bootstrap5\Html]] は [[\yii\helpers\Html]] を継承しており、
その代替物として使うことが出来ますので、ビュー・ファイルの中で両方を使う必要はありません。
例えば、
```php
<?php
use yii\bootstrap5\Html;
?>
<?= Button::widget([
'label' => Html::encode('Save & apply'),
'encodeLabel' => false,
'options' => ['class' => 'btn-primary'],
]); ?>
```
> 注意: [[\yii\bootstrap5\Html]] と [[\yii\helpers\Html]] を混同してはいけません。
ビューの中でどちらのクラスを使っているのかに注意してください。

View File

@ -0,0 +1,19 @@
インストール
============
## Composer パッケージを取得する
このエクステンションをインストールするのに推奨される方法は [composer](https://getcomposer.org/download/) によるものです。
下記のコマンドを実行してください。
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
または、あなたの `composer.json` ファイルの `require` セクションに、
```
"yiisoft/yii2-bootstrap": "~1.0.0"
```
を追加してください。

View File

@ -0,0 +1,39 @@
yii2-bootstrap4 からの移行
=========================
yii2-bootstrap5 は、Bootstrap 4 から Bootstrap 5 への移行ガイドに従って、yii-bootstrap4 プロジェクト全体を大きく書き換えたものです。
最も注目すべき変更点を要約すると以下の通りです。
## 一般
* 名前空間は `yii\bootstrap4` から `yii\bootstrap5` に変更
## ウィジェット / クラス
### BaseHtml
### ActiveField
### ActiveForm
新しい定数[[yii\bootstrap5\ActiveForm::LAYOUT_FLOATING]]があります。 Bootstrap5で導入された[新しいフォームレイアウト](https://getbootstrap.com/docs/5.1/forms/floating-labels/)です。
### Breadcrumbs
### ButtonDropdown
### ButtonToolbar
### Carousel
### LinkPager
### Modal
### Nav
### NavBar
### Tabs
### ToggleButtonGroup

View File

@ -0,0 +1,17 @@
Bootstrap の .sass ファイルを直接に使う
=======================================
あなたが [Bootstrap CSS をあなたの sass ファイルに直接含める](https://getbootstrap.com/getting-started/#customizing) ことを望む場合は、
オリジナルの CSS ファイルがロードされないように無効化する必要があります。
[[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] の `css` プロパティを空に設定することによって、そうすることが出来ます。
そのためには、`assetManager` [アプリケーション・コンポーネント](https://github.com/yiisoft/yii2/blob/master/docs/guide-ja/structure-application-components.md) を以下のように構成します。
```php
'assetManager' => [
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'css' => [],
]
]
]
```

View File

@ -0,0 +1,95 @@
Yii ウィジェット
================
複雑な bootstrap コンポーネントのほとんどは Yii ウィジェットでラップされて、より堅牢な構文を与えられ、フレームワークの諸機能と統合されています。
全てのウィジェットは `\yii\bootstrap5` 名前空間に属します。
- [[yii\bootstrap5\Accordion|Accordion]]
- [[yii\bootstrap5\ActiveField|ActiveField]]
- [[yii\bootstrap5\ActiveForm|ActiveForm]]
- [[yii\bootstrap5\Alert|Alert]]
- [[yii\bootstrap5\Breadcrumbs|Breadcrumbs]]
- [[yii\bootstrap5\Button|Button]]
- [[yii\bootstrap5\ButtonDropdown|ButtonDropdown]]
- [[yii\bootstrap5\ButtonGroup|ButtonGroup]]
- [[yii\bootstrap5\ButtonToolbar|ButtonToolbar]]
- [[yii\bootstrap5\Carousel|Carousel]]
- [[yii\bootstrap5\Dropdown|Dropdown]]
- [[yii\bootstrap5\LinkPager|LinkPager]]
- [[yii\bootstrap5\Modal|Modal]]
- [[yii\bootstrap5\Nav|Nav]]
- [[yii\bootstrap5\NavBar|NavBar]]
- [[yii\bootstrap5\Offcanvas|Offcanvas]]
- [[yii\bootstrap5\Popover|Popover]]
- [[yii\bootstrap5\Progress|Progress]]
- [[yii\bootstrap5\Tabs|Tabs]]
- [[yii\bootstrap5\Toast|Toast]]
- [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]]
## ウィジェットの CSS クラスをカスタマイズする <span id="customizing-css-classes"></span>
これらのウィジェットを使うと、bootstrap CSS クラスの使用を要求する bootstrap コンポーネントのための HTML を素速く構成することが出来ます。特定のコンポーネントのデフォルトの CSS クラスはウィジェットによって自動的に追加されます。
そして、あなたがカスタマイズしたいであろうオプションの CSS クラスは、通常は、ウィジェットのプロパティによってサポートされています。
例えば、[[yii\bootstrap5\Button::options]] を使って、ボタンの外見をカスタマイズすることが出来ます。
このとき、ボタンに要求される 'btn' クラスは自動的に追加されますので、あなたが心配をする必要はありません。
特定のボタン・クラスを指定するだけで十分です。
```php
echo Button::widget([
'label' => 'Action',
'options' => ['class' => 'btn-primary'], // "btn btn-primary" というクラスを生成
]);
```
しかしながら、時として、デフォルトのクラスを別のクラスで置き換える必要がある場合があります。
例えば、[[yii\bootstrap5\ButtonGroup]] は、コンテナの div に 'btn-group' をデフォルトで使用しますが、
ボタンを垂直に並べるために 'btn-group-vertical' を代りに使いたいことがあるでしょう。
単純に 'class' オプションを使うと、'btn-group-vertical' が 'btn-group' に追加されるだけで、正しくない結果が生成されることになります。
ウィジェットのデフォルトのクラスをオーバーライドするためには、'class' オプションに配列形式を使用して、'widget' キーの下にカスタマイズしたクラスの定義を指定しなければなりません。
```php
echo ButtonGroup::widget([
'options' => [
'class' => ['widget' => 'btn-group-vertical'] // 'btn-group' を 'btn-group-vertical' で置き換え
],
'buttons' => [
['label' => 'A'],
['label' => 'B'],
]
]);
```
## Navbar ウィジェット <span id="navbar-widget"></span>
Navbar ウィジェットには独特の癖があります。あなたは Navbar が折り畳まれるブレークポイントと
Navbar の全体的なスタイル (カラー・スキーム) を指定しなければなりません。
カラー・スキームと折り畳みのブレークポイントは CSS のクラスで変更することが出来ます。指定されない場合は、カラー・スキームは `navbar-light bg-light`
ブレークポイントは`navbar-expand-lg` がデフォルトとして採用されます。詳細な情報は、[Bootstrap documentation](https://getbootstrap.com/docs/5.1/components/navbar/) を参照して下さい。
```php
Navbar::begin([
'options' => [
'class' => ['navbar-dark', 'bg-dark', 'navbar-expand-md']
]
]);
[...]
Navbar::end();
```
モバイル向けナビゲーションでブランド (アイコン) とトグル・ボタンの位置を入れ替えたい場合は、次のようにすることが出来ます。
```php
Navbar::begin([
'brandOptions' => [
'class' => ['order-1']
],
'togglerOptions' => [
'class' => ['order-0']
]
]);
[...]
Navbar::end();
```

View File

@ -0,0 +1,29 @@
Extenção Twitter Bootstrap para Yii 2
=====================================
A extensão inclui suporte para marcação e componentes ao framework [Bootstrap 5](https://getbootstrap.com/)
(também conhecido como "Bootstrap Twitter"). Bootstrap é um excelente framework ágil, que pode acelerar bastante o
do lado do cliente do seu processo de desenvolvimento.
O núcleo do bootstrap é representado por duas partes:
- Noções básicas de estilo CSS, tais como um sistema de rede layout, tipografia, classes auxiliares, e os utilitários de resposta.
- Componentes prontos para usar, tais como formulários, menus, paginação, caixas de modais, guias, etc.
Iniciando
---------------
* [Instalação](installation.md)
* [uso Básico](basic-usage.md)
Uso
-----
* [Yii widgets](usage-widgets.md)
* [Html helper](helper-html.md)
* [Asset Bundles](asset-bundles.md)
Tópicos Adicionais
-----------------
* [Usando arquivos .sass do Bootstrap diretamente](topics-sass.md)

View File

@ -0,0 +1,14 @@
Asset Bundles
=============
Bootstrap é uma solução complexa para front-end, o qual inclue CSS, JavaScript, fontes e assim por diante.
A fim de permitir que você tenha controle mais flexível sobre componentes Bootstrap , esta extensão fornece vários asset bundles. Eles são:
- [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] - Contém apenas arquivos CSS.
- [[yii\bootstrap5\BootstrapPluginAsset|BootstrapPluginAsset]] - Depende de [[yii\bootstrap5\BootstrapAsset]], contem os arquivos JavaScript.
Necessidades de aplicações específicas podem exigir utilização de pacotes diferentes ( ou a combinação bundle).
Se você precisa apenas de estilos CSS, [[yii\bootstrap5\BootstrapAsset]] será o suficiente para você. No entanto , se
você quiser usar Bootstrap JavaScript, você precisa se registrar [[yii\bootstrap5\BootstrapPluginAsset]].
> Tip: a maioria dos widgets [[yii\bootstrap5\BootstrapPluginAsset]] registram automaticamente.

View File

@ -0,0 +1,17 @@
Uso Básico
===========
O Yii Não registra os componentes básicos do bootstrap em código PHP visto que esse HTML é muito simples, por si só.
Você pode encontrar detalhes sobre como usar o básico no [site documentação do Bootstrap] (https://getbootstrap.com/docs/). O Yii ainda fornece uma
forma conveniente para incluir assets de bootstrap em suas páginas com uma única linha adicionado ao arquivo `AppAsset.php` localizado no seu
diretório `@app/assets`:
```php
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset', // this line
];
```
Usando bootstrap através Yii assets lhe permite minimizar os seus recursos/fontes e combinar com seus próprios recursos/fontes quando
necessário.

View File

@ -0,0 +1,17 @@
Bootstrap introduz construções HTML mais consistentes e esqueletos, que permitem a criação de diferentes efeitos visuais. Apenas o mais complexos deles são cobertos por os widgets fornecidos com esta extensão . O restante deverá ser escrito manualmente usando escrita HTML direta. No entanto, vários casos especiais de marcação Bootstrap são cobertos pelo helper [[\yii\bootstrap5\Html]]. [[\yii\bootstrap5\Html]] é uma versão melhorada de [[\yii\helpers\Html]] dedicada à quem precisa do Bootstrap. Ele fornece vários métodos úteis :
- staticControl() - allows rendering of form "[static controls](https://getbootstrap.com/docs/5.1/forms/form-control/#readonly-plain-text)"
[[\yii\bootstrap5\Html]] herda toda funcionalidade disponível em [[\yii\helpers\Html]] e pode ser usado como um substituto , para que você não precisa de ambos dentro de seus arquivos de views . Por exemplo:
<?php
use yii\bootstrap5\Html;
?>
<?= Button::widget([
'label' => Html::encode('Save & apply'),
'encodeLabel' => false,
'options' => ['class' => 'btn-primary'],
]); ?>
Atenção: Não confunda [[\yii\bootstrap5\Html]] e [[\yii\helpers\Html]], tenha o cuidado de que classe você está usando dentro de seus arquivos de views.

View File

@ -0,0 +1,20 @@
Instalação
============
## Instalando através do composer
A maneira recomendada para instalar esta extensão é através do [composer](https://getcomposer.org/download/).
Então rode
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
Ou Adicione
```
"yiisoft/yii2-bootstrap": "~1.0.0"
```
na sessão de requirimentos do seu arquivo `composer.json`.

View File

@ -0,0 +1,18 @@
Usando arquivos .sass diretamente do Bootstrap
===========================================
Se você quiser incluir o [css do Bootstrap diretamente em seus arquivos sass] (https://getbootstrap.com/getting-started/#customizing)
talvez você precise desativar os arquivos css do Bootstrap originais que são carregados.
Você pode fazer isso definindo a propriedade css do [[yii \ inicialização \ BootstrapAsset | BootstrapAsset]] e deixe estar vazio.
Para isso, você precisa configurar o `assetManager` [application component](https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-application-components.md)
do seguinte modo:
```php
'assetManager' => [
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'css' => [],
]
]
]
```

View File

@ -0,0 +1,27 @@
Yii widgets
===========
A maioria dos componentes complexos do bootstrap são envolvidos em widgets Yii para permitir uma sintaxe mais robusta e integrar-se com
características estruturais do framework. Todos widgets pertencem ao namespace `\yii\bootstrap5`:
- [[yii\bootstrap5\Accordion|Accordion]]
- [[yii\bootstrap5\ActiveField|ActiveField]]
- [[yii\bootstrap5\ActiveForm|ActiveForm]]
- [[yii\bootstrap5\Alert|Alert]]
- [[yii\bootstrap5\Breadcrumbs|Breadcrumbs]]
- [[yii\bootstrap5\Button|Button]]
- [[yii\bootstrap5\ButtonDropdown|ButtonDropdown]]
- [[yii\bootstrap5\ButtonGroup|ButtonGroup]]
- [[yii\bootstrap5\ButtonToolbar|ButtonToolbar]]
- [[yii\bootstrap5\Carousel|Carousel]]
- [[yii\bootstrap5\Dropdown|Dropdown]]
- [[yii\bootstrap5\LinkPager|LinkPager]]
- [[yii\bootstrap5\Modal|Modal]]
- [[yii\bootstrap5\Nav|Nav]]
- [[yii\bootstrap5\NavBar|NavBar]]
- [[yii\bootstrap5\Offcanvas|Offcanvas]]
- [[yii\bootstrap5\Popover|Popover]]
- [[yii\bootstrap5\Progress|Progress]]
- [[yii\bootstrap5\Tabs|Tabs]]
- [[yii\bootstrap5\Toast|Toast]]
- [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]]

View File

@ -0,0 +1,28 @@
Расширение Twitter Bootstrap для Yii 2
======================================
Расширение включает поддержку разметки и компонентов фреймворка [Bootstrap 5](https://getbootstrap.com/) (также известного как "Twitter Bootstrap"). Bootstrap является прекрасным, отзывчивым фреймворком, который может значительно ускорить процесс разработки на стороне клиента.
Ядро Bootstrap представлено двумя частями:
- CSS основа, такая как система разметки, типографика, вспомогательные классы, и утилиты адаптивности.
- Готовые к использованию компоненты, такие как формы, меню, нумерация страниц, модальные окна, вкладки и т.д.
Как начать
----------
* [Установка](installation.md)
* [Основы использования](basic-usage.md)
Использование
------------
* [Виджеты Yii](usage-widgets.md)
* [Класс-помощник Html](helper-html.md)
* [Asset Bundles](asset-bundles.md)
Дополнительно
-------------
* [Использование .sass файлов Bootstrap напрямую](topics-sass.md)
* [Миграция с yii2-bootstrap4](migrating-yii2-bootstrap.md)

View File

@ -0,0 +1,12 @@
Asset Bundles
=============
Bootstrap - это комплексное front-end решение, включающее CSS, JavaScript, шрифты и т.д. Для того чтобы обеспечить гибкий контроль над компонентами Bootstrap, расширение предоставляет несколько Asset Bundles. Вот они:
- [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] - содержит CSS файлы.
- [[yii\bootstrap5\BootstrapPluginAsset|BootstrapPluginAsset]] - зависит от [[yii\bootstrap5\BootstrapAsset]], содержащий javascript файлы.
- [[yii\bootstrap5\BootstrapIconAsset|BootstrapIconAsset]] - содержит иконки.
Конкретные приложения могут потребовать различного использования. Если вам нужны только CSS-стили, то пакета [[yii\bootstrap5\BootstrapAsset]] будет достаточно. Тем не менее, если вы хотите использовать Bootstrap JavaScript, вам необходимо зарегистрировать [[yii\bootstrap5\BootstrapPluginAsset]], если вы хотите использовать Bootstrap Icons, вам необходимо зарегистрировать [[yii\bootstrap5\BootstrapIconAsset|BootstrapIconAsset]].
> Tip: большинство виджетов регистрируются с помощью [[yii\bootstrap5\BootstrapPluginAsset]] автоматически.

View File

@ -0,0 +1,13 @@
Базовое использование
===========
Yii не оборачивает базовый Bootstrap в PHP код, поскольку HTML, в этом случае, прост сам по себе. Вы можете найти подробную информацию о возможностях Bootstrap в [официальной документации](https://getbootstrap.com/docs/). Тем не менее, Yii обеспечивает удобный способ включения Bootstrap assets на страницах вашего приложения добавлением одной строки в файл `AppAsset.php`, расположенный в директории `@app/assets`:
```php
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset', // подключение Bootstrap
];
```
Использование загрузки Bootstrap через Yii Asset Manager позволяет минимизировать ресурсы и объединить с вашими собственными ресурсами, когда это будет необходимо.

View File

@ -0,0 +1,21 @@
Класс-помощник Html
===================
Bootstrap предоставляет множество последовательных HTML конструкции и каркасов, которые позволяют создавать различные визуальные эффекты. Только самые сложные из них передставлены виджетами, поставляемые с данным расширением. Остальные должны быть собраны вручную, используя HTML напрямую. Тем не менее, несколько специальных Bootstrap разметок предоставляются в помощнике [[\yii\bootstrap5\Html]]. [[\yii\bootstrap5\Html]] является расширенной версией [[\yii\helpers\Html]], удовлетворяющей потребности Bootstrap. Он предоставляет несколько полезных методов:
- `staticControl()` - позволяет отображать "[статические элементы управления](https://getbootstrap.com/docs/5.1/forms/form-control/#readonly-plain-text)" формы
[[\yii\bootstrap5\Html]] наследует все функциональные возможности, доступные в [[\yii\helpers\Html]], и может быть использован в качестве замены в ваших представлениях. Например:
```php
<?php
use yii\bootstrap5\Html;
?>
<?= Button::widget([
'label' => Html::encode('Save & apply'),
'encodeLabel' => false,
'options' => ['class' => 'btn-primary'],
]); ?>
```
> Attention: не путайте [[\yii\bootstrap5\Html]] и [[\yii\helpers\Html]]! Следите за тем какой класс вы используете в своих представлениях.

View File

@ -0,0 +1,20 @@
Установка
=========
## Получение расширения через Composer
Предпочтительный способ установки расширения - через [Composer](https://getcomposer.org/download/).
Для этого запустите команду
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
или добавьте
```
"yiisoft/yii2-bootstrap5": "~2.0.0"
```
в секцию **require** вашего `composer.json`.

View File

@ -0,0 +1,50 @@
Миграция с yii2-bootstrap4
==============================
yii2-bootstrap5 является серьезной переработкой всего проекта (в соответствии с руководством по миграции с Bootstrap4 на Bootstrap5).
Наиболее заметные изменения кратко изложены ниже:
## General
* Изменение namespace с `yii\bootstrap4` на `yii\bootstrap5`
* Минимальная совместимая версия php **ограничена** `>=7.0`
* Кнопки закрытия виджетов, таких как [[yii\bootstrap5\Alert|Alert]] или [[yii\bootstrap5\Modal|Modal]], теперь отображаются
с помощью CSS и больше не содержат содержимого. Поэтому обязательно удалите класс "btn-close" и самостоятельно установите соответствующие стили, если вы его переопределяли.
## Widgets / Classes
### BaseHtml
### ActiveField
### ActiveForm
Новая константа [[yii\bootstrap5\ActiveForm::LAYOUT_FLOATING]]. Это
[new form layout](https://getbootstrap.com/docs/5.1/forms/floating-labels/) введен в Bootstrap 5.
### Breadcrumbs
### ButtonDropdown
### ButtonToolbar
### Carousel
### LinkPager
### Modal
Заменить `data-target` и `data-toggle` на `data-bs-target` и `data-bs-toggle`
### Nav
### NavBar
Теперь есть возможность создать [offcanvas navbar](https://getbootstrap.com/docs/5.1/components/navbar/#offcanvas).
Вы можете добиться этого, установив для параметра `$collapseOptions` значение `false` в виджете [[yii\bootstrap5\NavBar|Navbar]] и
`$offcanvasOptions`, значение пустого массива.
### Tabs
### ToggleButtonGroup

View File

@ -0,0 +1,14 @@
Использование .sass файлов Bootstrap напрямую
=============================================
Если вы хотите включить [Bootstrap CSS непосредственно в ваши sass-файлы](https://getbootstrap.com/getting-started/#customizing), вам может понадобиться исключить исходные css-файлы Bootstrap из загрузки. Вы можете сделать это, установив пустым свойство `css` пакета [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]]. Для этого вам необходимо настроить [компонент приложения](https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-application-components.md) `assetManager` следующим образом:
```php
'assetManager' => [
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'css' => [], // исключение исходных css-файлов из загрузки
]
]
]
```

View File

@ -0,0 +1,92 @@
Виджеты Yii
===========
Большинство сложных Bootstrap компонентов обернуты в виджеты Yii, чтобы обеспечить более надежный синтаксис и интеграцию с особенностями фреймворка. Все виджеты относятся к пространству имен `\yii\bootstrap5`:
- [[yii\bootstrap5\Accordion|Accordion]]
- [[yii\bootstrap5\ActiveField|ActiveField]]
- [[yii\bootstrap5\ActiveForm|ActiveForm]]
- [[yii\bootstrap5\Alert|Alert]]
- [[yii\bootstrap5\Breadcrumbs|Breadcrumbs]]
- [[yii\bootstrap5\Button|Button]]
- [[yii\bootstrap5\ButtonDropdown|ButtonDropdown]]
- [[yii\bootstrap5\ButtonGroup|ButtonGroup]]
- [[yii\bootstrap5\ButtonToolbar|ButtonToolbar]]
- [[yii\bootstrap5\Carousel|Carousel]]
- [[yii\bootstrap5\Dropdown|Dropdown]]
- [[yii\bootstrap5\LinkPager|LinkPager]]
- [[yii\bootstrap5\Modal|Modal]]
- [[yii\bootstrap5\Nav|Nav]]
- [[yii\bootstrap5\NavBar|NavBar]]
- [[yii\bootstrap5\Offcanvas|Offcanvas]]
- [[yii\bootstrap5\Popover|Popover]]
- [[yii\bootstrap5\Progress|Progress]]
- [[yii\bootstrap5\Tabs|Tabs]]
- [[yii\bootstrap5\Toast|Toast]]
- [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]]
## ActiveField: дополнительные поля <span id="additional-fields"></span>
- [Диапазон](https://getbootstrap.com/docs/5.1/forms/range/): `$form->rangeInput(['min' => 0, 'max' => 100, 'step' => 1])`
- [Выбор цвета](https://getbootstrap.com/docs/5.1/forms/form-control/#color): `$form->colorInput()`
- [Переключатель](https://getbootstrap.com/docs/5.1/forms/checks-radios/#switches): `$form->checkbox(['switch' => true])`
## Настройка CSS классов виджетов <span id="customizing-css-classes"></span>
Виджеты позволяют быстро создавать HTML Bootstrap компоненты, которые требуют CSS классы Bootstrap. Классы по умолчанию, для конкретного компонента, будут добавлены автоматически виджетом, и необязательные классы, которые вы можете настроить, как правило, поддерживаются через свойства виджета.
Например, вы можете использовать [[yii\bootstrap5\Button::options]] чтобы настроить внешний вид кнопки. Класс `btn`, который требуется для кнопки, будет добавлен автоматически. Все, что вам нужно, это указать конкретный класс кнопки:
```php
echo Button::widget([
'label' => 'Action',
'options' => ['class' => 'btn-primary'], // устанавливает класс "btn btn-primary"
]);
```
Тем не менее, иногда вам может понадобиться заменить классы по умолчанию альтернативными. Например, виджет [[yii\bootstrap5\ButtonGroup]] использует класс `btn-group` для контейнера `div` по умолчанию, но вам, возможно, придётся использовать `btn-group-vertical` чтобы выровнять кнопки по вертикали. Добавление `btn-group-vertical` в параметр `class` приведет к неправильному результату. Для того, чтобы переопределить классы виджета по умолчанию, необходимо указать параметр `class` как массив, содержащий определение класса, настроенное в ключе `widget`:
```php
echo ButtonGroup::widget([
'options' => [
'class' => ['widget' => 'btn-group-vertical'] // заменяет класс 'btn-group' на 'btn-group-vertical'
],
'buttons' => [
['label' => 'A'],
['label' => 'B'],
]
]);
```
## Виджет навигационной панели <span id="navbar-widget"></span>
Виджет навигационной панели имеет свои особенности. Вы должны задать точку останова (разрешение при котором панель отображается в свернутом виде)
и основной стиль отображения (цветовая схема) для панели.
Вы можете изменить цветовую схему и точку останова с помощью CSS классов. По умолчанию, используется цветовая схема
`navbar-light bg-light` и точка останова `navbar-expand-lg`. Для получения доп. информации, смотрите [документацию Bootstrap](https://getbootstrap.com/docs/5.1/components/navbar/):
```php
Navbar::begin([
'options' => [
'class' => ['navbar-dark', 'bg-dark', 'navbar-expand-md']
]
]);
[...]
Navbar::end();
```
Если Вы хотите повернуть бренд (значок) и переключить положение кнопок в мобильной навигации, то можете сделать это следующим образом:
```php
Navbar::begin([
'brandOptions' => [
'class' => ['order-1']
],
'togglerOptions' => [
'class' => ['order-0']
]
]);
[...]
Navbar::end();
```

View File

@ -0,0 +1,27 @@
Розширення Twitter Bootstrap для Yii 2
======================================
З коробки Yii включає підтримку розмітки [Bootstrap 5](https://getbootstrap.com/) та компонентів фреймворку
(також відомий як "Twitter Bootstrap"). Bootstrap є чудовим, адаптивним фреймворком, який може значно прискорити
процес розробки клієнтської частини сайту.
Ядро Bootstrap представлене двома частинами:
- Основи CSS, такі як система макету сітки, типографія, допоміжні класи і адаптивні утиліти.
- Готові до використання компоненти, такі як форми, меню, нумерація сторінок (pagination), модальні вікна, вкладки (tabs) і т.д.
Початок роботи
--------------
* [Встановлення](installation.md)
* [Основи використання](basic-usage.md)
Використання
------------
* [Віджети Yii](usage-widgets.md)
Додаткові теми
--------------
* [Використання .sass файлів в Bootstrap](topics-sass.md)

View File

@ -0,0 +1,16 @@
Основи використання
===================
Yii не загортає основи bootstrap в код PHP, оскільки в цьому випадку, сам по собі HTML є дуже простим.
Ви можете знайти детальну інформацію щодо використання основ на [сайті документації bootstrap](https://getbootstrap.com/docs/).
Проте Yii забезпечує зручний спосіб підключення ресурсів bootstrap до ваших сторінок за допомогою додання всього одного рядка до файлу
`AppAsset.php`, розташованого в каталозі `@app/assets`:
```php
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset', // цей рядок
];
```
Використання bootstrap через менеджер ресурсів Yii дозволяє мінімізувати свої ресурси і обʼєднати із вашими власними ресурсами коли це необхідно.

View File

@ -0,0 +1,20 @@
Встановлення
============
## Отримання пакету Composer
Кращим способом для встановлення даного розширення є встановлення через [composer](https://getcomposer.org/download/).
Запустіть
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
або додайте
```
"yiisoft/yii2-bootstrap": "~1.0.0"
```
до потрібного розділу вашого файлу `composer.json`.

View File

@ -0,0 +1,18 @@
Використання .sass файлів в Bootstrap
=====================================
Якщо ви хочете включити [CSS Bootstrap напряму до ваших sass файлів](https://getbootstrap.com/getting-started/#customizing)
вам необхідно відключити завантаження оригінальних css файлів bootstrap.
Ви можете зробити це, встановивши CSS властивість [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] порожньою.
Для цього вам необхідно налаштувати [компонент додатка](https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-application-components.md)
`assetManager` наступним чином:
```php
'assetManager' => [
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'css' => [],
]
]
]
```

View File

@ -0,0 +1,27 @@
Віджети Yii
===========
Найбільш складні компоненти bootstrap загорнуті в віджети Yii, щоб забезпечити більш надійний синтаксис
та інтегрувати його з можливостями фреймворку. Всі віджети належать до простору імен `\yii\bootstrap5`:
- [[yii\bootstrap5\Accordion|Accordion]]
- [[yii\bootstrap5\ActiveField|ActiveField]]
- [[yii\bootstrap5\ActiveForm|ActiveForm]]
- [[yii\bootstrap5\Alert|Alert]]
- [[yii\bootstrap5\Breadcrumbs|Breadcrumbs]]
- [[yii\bootstrap5\Button|Button]]
- [[yii\bootstrap5\ButtonDropdown|ButtonDropdown]]
- [[yii\bootstrap5\ButtonGroup|ButtonGroup]]
- [[yii\bootstrap5\ButtonToolbar|ButtonToolbar]]
- [[yii\bootstrap5\Carousel|Carousel]]
- [[yii\bootstrap5\Dropdown|Dropdown]]
- [[yii\bootstrap5\LinkPager|LinkPager]]
- [[yii\bootstrap5\Modal|Modal]]
- [[yii\bootstrap5\Nav|Nav]]
- [[yii\bootstrap5\NavBar|NavBar]]
- [[yii\bootstrap5\Offcanvas|Offcanvas]]
- [[yii\bootstrap5\Popover|Popover]]
- [[yii\bootstrap5\Progress|Progress]]
- [[yii\bootstrap5\Tabs|Tabs]]
- [[yii\bootstrap5\Toast|Toast]]
- [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]]

View File

@ -0,0 +1,29 @@
基于Yii 2 的 Twitter Bootstrap 扩展
=====================================
扩展包括对 [Bootstrap 5](https://getbootstrap.com/) 标记和组件框架的支持
也称为“Twitter Bootstrap”。 Bootstrap是一个优秀的响应式框架可以大大加快
客户端的开发过程。
Bootstrap的核心由两部分组成
- 基础CSS样式如栅格化布局排版帮助类和响应式工具。
- 开箱即用的组件,如表单,菜单,分页,模态框,标签等。
起步
---------------
* [安装](installation.md)
* [基本用法](basic-usage.md)
使用
-----
* [Yii 小部件](usage-widgets.md)
* [Html 助手](helper-html.md)
* [Asset Bundles资源包](asset-bundles.md)
其他
-----------------
* [直接使用Bootstrap的.sass文件](topics-sass.md)

View File

@ -0,0 +1,14 @@
资源包
=============
Bootstrap是一个复杂的前端解决方案其中包括 CSS JavaScript ,字体等。
为了灵活的控制 Bootstrap 组件,此扩展提供了多个资源包。
如下:
- [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] - 只包含主要的 CSS 文件.
- [[yii\bootstrap5\BootstrapPluginAsset|BootstrapPluginAsset]] - 包含 javascript 文件, 依赖于 [[yii\bootstrap5\BootstrapAsset]] .
特定的应用可能需要加载不同的资源包,(或者资源包组合).
如果只需要 CSS 文件, 引入 [[yii\bootstrap5\BootstrapAsset]] 即可. 但是, 如果需要使用 Bootstrap 的 JavaScript, 则需要引入 [[yii\bootstrap5\BootstrapPluginAsset]].
> 提示:大多数小部件会自动注册到 [[yii\bootstrap5\BootstrapPluginAsset]] 。

View File

@ -0,0 +1,13 @@
使用
===========
Yii不会将 bootstrap 合并到PHP代码中因为HTML本身是非常简单的。猛击 [bootstrap 文档页](https://getbootstrap.com/docs/) 查看如何使用 bootstrap. 但是 Yii 还是提供了在框架中更为方便的管理和使用 bootstrap的方式`@app/assets` 路径下的 `AppAsset.php` 文件中,添加如下代码即可:
```php
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset', // this line
];
```
通过 Yii 的资源管理器asset manager引入 bootstrap ,可最小化的引入 bootstrap 并在需要时合并自定义资源文件一起使用。

View File

@ -0,0 +1,26 @@
Html 助手
===========
Bootstrap 引入了许多一致的 HTML 结构和骨架,允许创建不同的视觉效果。
只有最复杂的部分由此扩展提供的小部件覆盖。 其余应使用直接 HTML 手动组合。
但是, 有些特殊的 Bootstrap 标签被 [[\yii\bootstrap5\Html]] 重载.
[[\yii\bootstrap5\Html]] 是基于 Bootstrap 的 [[\yii\helpers\Html]] 增强版.
它提供了很多实用的方法,例如:
- `staticControl()` - 生成表单静态组件 "[static controls](https://getbootstrap.com/docs/5.1/forms/form-control/#readonly-plain-text)"
[[\yii\bootstrap5\Html]] 继承了 [[\yii\helpers\Html]] 的所有功能,所以不需要在视图文件中同时引入这两个文件,如果需要,仅使用 [[\yii\bootstrap5\Html]] 即可.
例如:
```php
<?php
use yii\bootstrap5\Html;
?>
<?= Button::widget([
'label' => Html::encode('Save & apply'),
'encodeLabel' => false,
'options' => ['class' => 'btn-primary'],
]); ?>
```
> 注意: 不要混淆 [[\yii\bootstrap5\Html]] 和 [[\yii\helpers\Html]], 一定注意你在视图中引入和使用的类.

View File

@ -0,0 +1,18 @@
安装
============
## 获取 Composer 包
安装此扩展的首选方式是通过 [composer](https://getcomposer.org/download/).
直接运行
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
或者在项目目录的 `composer.json` 文件中添加如下代码
```
"yiisoft/yii2-bootstrap": "~1.0.0"
```

View File

@ -0,0 +1,17 @@
直接使用Bootstrap的.sass文件
=======================================
如果引入 [直接使用Bootstrap的.sass文件](https://getbootstrap.com/getting-started/#customizing)
则需要禁用原始加载的 css 文件.
通过设置 [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] 的 css 属性为空即可.
为此,需要配置 `assetManager` [应用组件](https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-application-components.md) 为如下:
```php
'assetManager' => [
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'css' => [],
]
]
]
```

View File

@ -0,0 +1,58 @@
Yii 小部件
===========
大多数复杂的 bootstrap 组件被包装到 Yii 小部件中,以允许更强大的语法并与框架特性集成。 所有小部件都在命名空间 `\yii\bootstrap5` 下:
- [[yii\bootstrap5\Accordion|Accordion]]
- [[yii\bootstrap5\ActiveField|ActiveField]]
- [[yii\bootstrap5\ActiveForm|ActiveForm]]
- [[yii\bootstrap5\Alert|Alert]]
- [[yii\bootstrap5\Breadcrumbs|Breadcrumbs]]
- [[yii\bootstrap5\Button|Button]]
- [[yii\bootstrap5\ButtonDropdown|ButtonDropdown]]
- [[yii\bootstrap5\ButtonGroup|ButtonGroup]]
- [[yii\bootstrap5\ButtonToolbar|ButtonToolbar]]
- [[yii\bootstrap5\Carousel|Carousel]]
- [[yii\bootstrap5\Dropdown|Dropdown]]
- [[yii\bootstrap5\LinkPager|LinkPager]]
- [[yii\bootstrap5\Modal|Modal]]
- [[yii\bootstrap5\Nav|Nav]]
- [[yii\bootstrap5\NavBar|NavBar]]
- [[yii\bootstrap5\Offcanvas|Offcanvas]]
- [[yii\bootstrap5\Popover|Popover]]
- [[yii\bootstrap5\Progress|Progress]]
- [[yii\bootstrap5\Tabs|Tabs]]
- [[yii\bootstrap5\Toast|Toast]]
- [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]]
## 自定义小部件CSS类 <span id="customizing-css-classes"></span>
这些小部件可以快速构建基于 bootstrap CSS 样式的 bootstrap 组件,并直接生成 HTML 代码。
特定组件的默认样式是自动添加的,也可以通过修改部件属性添加自定义样式类。
例如, 使用 [[yii\bootstrap5\Button::options]] 创建按钮。
按钮中的 `btn` 样式将会被自动添加。只要再添加自己所需的按钮样式即可:
```php
echo Button::widget([
'label' => 'Action',
'options' => ['class' => 'btn-primary'], // produces class "btn btn-primary"
]);
```
但是,有的时候需要将默认样式替换为自定义样式。
例如, 小部件 [[yii\bootstrap5\ButtonGroup]] 默认使用 'btn-group' 类作为 div 容器的默认样式,但是我们希望使用 'btn-group-vertical' 作为默认样式以实现按钮组的垂直居中。
直接在 'class' 选项中添加 'btn-group-vertical' 是替换不了 'btn-group' 的。
为了重载组件的默认样式,需要在 'class' 选项中的 'widget' 选项中定义即可:
```php
echo ButtonGroup::widget([
'options' => [
'class' => ['widget' => 'btn-group-vertical'] // replaces 'btn-group' with 'btn-group-vertical'
],
'buttons' => [
['label' => 'A'],
['label' => 'B'],
]
]);
```

View File

@ -0,0 +1,31 @@
Twitter Bootstrap Extension for Yii 2
=====================================
The extension includes support for the [Bootstrap 5](https://getbootstrap.com/) markup and components framework
(also known as "Twitter Bootstrap"). Bootstrap is an excellent, responsive framework that can greatly speed up the
client-side of your development process.
The core of Bootstrap is represented by two parts:
- CSS basics, such as a grid layout system, typography, helper classes, and responsive utilities.
- Ready to use components, such as forms, menus, pagination, modal boxes, tabs etc.
Getting Started
---------------
* [Installation](installation.md)
* [Assets Setup](assets-setup.md)
* [Basic Usage](basic-usage.md)
Usage
-----
* [Yii widgets](usage-widgets.md)
* [Html helper](helper-html.md)
* [Asset Bundles](asset-bundles.md)
Additional topics
-----------------
* [Using the .sass files of Bootstrap directly](topics-sass.md)
* [Migrating from yii2-bootstrap](migrating-yii2-bootstrap.md)

View File

@ -0,0 +1,18 @@
Asset Bundles
=============
Bootstrap is a complex front-end solution, which includes CSS, JavaScript, fonts and so on.
In order to allow you the most flexible control over Bootstrap components, this extension provides several asset bundles.
They are:
- [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] - contains only the main CSS files.
- [[yii\bootstrap5\BootstrapPluginAsset|BootstrapPluginAsset]] - depends on [[yii\bootstrap5\BootstrapAsset]], contains the javascript files.
- [[yii\bootstrap5\BootstrapIconAsset|BootstrapIconAsset]] - contains Bootstrap icons.
Particular application needs may require different bundle (or bundle combination) usage.
If you only need CSS styles, [[yii\bootstrap5\BootstrapAsset]] will be enough for you. However, if
you intend to use Bootstrap JavaScript, you will need to register [[yii\bootstrap5\BootstrapPluginAsset]]
as well. If you'd like to use the Bootstrap icons, you'll need to add `twbs/bootstrap-icons` package to your
`composer.json` and register [[yii\bootstrap5\BootstrapIconAsset]] in your application.
> Tip: most of the widgets register [[yii\bootstrap5\BootstrapPluginAsset]] automatically.

View File

@ -0,0 +1,176 @@
Assets Setup
============
This extensions relies on [Bower](https://bower.io/) and/or [NPM](https://www.npmjs.org/) packages for the asset installation.
Before using this package you should decide in which way you will install those packages in your project.
## Using asset-packagist repository
You can setup [asset-packagist.org](https://asset-packagist.org) as package source for the Bootstrap assets.
In the `composer.json` of your project, add the following lines:
```json
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
]
```
Adjust `@npm` and `@bower` in you application configuration:
```php
return [
//...
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
//...
];
```
## Using composer asset plugin
Install [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/) globally, using following command:
```
composer global require "fxp/composer-asset-plugin:^1.4.0"
```
Add the following lines to `composer.json` of your project to adjust directories where the installed packages
will be placed, if you want to publish them using Yii:
```json
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
```
Then you can run composer install/update command to pick up Bootstrap assets.
> Note: `fxp/composer-asset-plugin` significantly slows down the `composer update` command in comparison
to asset-packagist.
## Using Bower/NPM client directly
You can install Bootstrap assets directly via Bower or NPM client.
In the `package.json` of your project, add the following lines:
```json
{
...
"dependencies": {
"bootstrap": "5.1",
...
}
...
}
```
In the `composer.json` of your project, add the following lines in order to prevent redundant Bootstrap asset installation:
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
## Using CDN
You may use Bootstrap assets from [official CDN](https://www.bootstrapcdn.com).
In the `composer.json` of your project, add the following lines in order to prevent redundant Bootstrap asset installation:
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
Configure 'assetManager' application component, overriding Bootstrap asset bundles with CDN links:
```php
return [
'components' => [
'assetManager' => [
// override bundles to use CDN :
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'sourcePath' => null,
'baseUrl' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.1/dist/',
'css' => [
'css/bootstrap.min.css'
],
],
'yii\bootstrap5\BootstrapPluginAsset' => [
'sourcePath' => null,
'baseUrl' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.1/dist/',
'js' => [
'js/bootstrap.bundle.min.js'
],
],
],
],
// ...
],
// ...
];
```
## Compiling from the .sass files
If you want to customize the Bootstrap CSS source directly, you may want to compile it from source *.sass files.
In such case installing Bootstrap assets from Composer or Bower/NPM makes no sense, since you can not modify files
inside 'vendor' directory.
You'll have to download Bootstrap assets manually and place them somewhere inside your project source code,
for example in the 'assets/source/bootstrap' folder.
In the `composer.json` of your project, add the following lines in order to prevent redundant Bootstrap asset installation:
```json
"replace": {
"npm-asset/bootstrap": ">=5.1"
},
```
Configure 'assetManager' application component, overriding Bootstrap asset bundles:
```php
return [
'components' => [
'assetManager' => [
// override bundles to use local project files :
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'sourcePath' => '@app/assets/source/bootstrap/dist',
'css' => [
YII_ENV_DEV ? 'css/bootstrap.css' : 'css/bootstrap.min.css',
],
],
'yii\bootstrap5\BootstrapPluginAsset' => [
'sourcePath' => '@app/assets/source/bootstrap/dist',
'js' => [
YII_ENV_DEV ? 'js/bootstrap.js' : 'js/bootstrap.min.js',
]
],
],
],
// ...
],
// ...
];
```
After you make changes to Bootstrap's source files, make sure to [compile them](https://getbootstrap.com/docs/5.1/getting-started/contribute/#using-npm-scripts), eg. using `npm run dist`.

View File

@ -0,0 +1,18 @@
Basic Usage
===========
Yii doesn't wrap the Bootstrap basics into PHP code since HTML is very simple by itself in this case. You can find details
about using the basics at [Bootstrap documentation](https://getbootstrap.com/docs/). Still Yii provides a convenient
way to include Bootstrap assets in your pages with a line(s) added to `@app/assets/AppAsset.php`(basic application):
```php
public $depends = [
<...>
yii\bootstrap5\BootstrapAsset::class,
// optional, Bootstrap icons
// yii\bootstrap5\BootstrapIconAsset::class
];
```
Using Bootstrap through Yii asset manager allows you to minimize its resources and combine with your own resources when
needed.

View File

@ -0,0 +1,30 @@
Html helper
===========
Bootstrap introduces many consistent HTML constructions and skeletons, which allow creating different visual effects.
Only the most complex of them are covered by the widgets provided with this extension. The rest should be composed manually
using direct HTML composition.
However, several special Bootstrap markup cases are covered by the [[\yii\bootstrap5\Html]] helper.
[[\yii\bootstrap5\Html]] is an enhanced version of the regular [[\yii\helpers\Html]] dedicated to the Bootstrap needs.
It provides some useful methods like:
- `staticControl()` - allows rendering of form "[static controls](https://getbootstrap.com/docs/5.1/forms/form-control/#readonly-plain-text)"
As [[\yii\bootstrap5\Html]] extends [[\yii\helpers\Html]], it can be used as a substitute, so you don't need them both
inside your view files.
For example:
```php
<?php
use yii\bootstrap5\Html;
?>
<?= Button::widget([
'label' => Html::encode('Save & apply'),
'encodeLabel' => false,
'options' => ['class' => 'btn-primary'],
]); ?>
```
> Attention: do not confuse [[\yii\bootstrap5\Html]] and [[\yii\helpers\Html]], be careful of which class
you are using inside your views.

View File

@ -0,0 +1,20 @@
Installation
============
## Getting Composer package
The preferred way to install this extension is through [composer](https://getcomposer.org/download/).
Either run
```
php composer.phar require --prefer-dist yiisoft/yii2-bootstrap5
```
or add
```
"yiisoft/yii2-bootstrap5": "~1.0.0"
```
to the require section of your `composer.json` file.

View File

@ -0,0 +1,50 @@
Migrating from yii2-bootstrap4
==============================
yii2-bootstrap5 is a major rewrite of the entire project (according Bootstrap 5 to Bootstrap 4 migration guide).
The most notable changes are summarized below:
## General
* The namespace is `yii\bootstrap5` instead of `yii\bootstrap4`
* The php compatibility **is limited to** `>=7.0`
* The close buttons of widgets like [[yii\bootstrap5\Alert|Alert]] or [[yii\bootstrap5|Modal|Modal]] now gets rendered
via CSS and does not have any content anymore. So be sure to remove `btn-close` class and set appropriate styles yourself
if you override it.
## Widgets / Classes
### BaseHtml
### ActiveField
### ActiveForm
There is a new constant [[yii\bootstrap5\ActiveForm::LAYOUT_FLOATING]]. It's a
[new form layout](https://getbootstrap.com/docs/5.1/forms/floating-labels/) introduced in Bootstrap 5.
### Breadcrumbs
### ButtonDropdown
### ButtonToolbar
### Carousel
### LinkPager
### Modal
Change `data-target` and `data-toggle` to `data-bs-target` and `data-bs-toggle`
### Nav
### NavBar
There is now the possibility to create an [offcanvas navbar](https://getbootstrap.com/docs/5.1/components/navbar/#offcanvas).
You can achieve this by setting the `$collapseOptions` to `false` in [[yii\bootstrap5\NavBar|Navbar]] widget and the
`$offcanvasOptions` to at least an empty array.
### Tabs
### ToggleButtonGroup

View File

@ -0,0 +1,17 @@
Using the .sass files of Bootstrap directly
===========================================
If you want to include the [Bootstrap css directly in your sass files](https://getbootstrap.com/getting-started/#customizing)
you may need to disable the bootstrap css files loaded by this extension.
You can do this by setting the css property of [[yii\bootstrap5\BootstrapAsset|BootstrapAsset]] to be empty.
For this, you need to configure the `assetManager` [application component](https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-application-components.md) as follows:
```php
'assetManager' => [
'bundles' => [
'yii\bootstrap5\BootstrapAsset' => [
'css' => [],
]
]
]
```

View File

@ -0,0 +1,100 @@
Yii widgets
===========
Most complex bootstrap components are wrapped into Yii widgets to allow more robust syntax and integrate with
framework features. All widgets belong to `\yii\bootstrap5` namespace:
- [[yii\bootstrap5\Accordion|Accordion]]
- [[yii\bootstrap5\ActiveField|ActiveField]]
- [[yii\bootstrap5\ActiveForm|ActiveForm]]
- [[yii\bootstrap5\Alert|Alert]]
- [[yii\bootstrap5\Breadcrumbs|Breadcrumbs]]
- [[yii\bootstrap5\Button|Button]]
- [[yii\bootstrap5\ButtonDropdown|ButtonDropdown]]
- [[yii\bootstrap5\ButtonGroup|ButtonGroup]]
- [[yii\bootstrap5\ButtonToolbar|ButtonToolbar]]
- [[yii\bootstrap5\Carousel|Carousel]]
- [[yii\bootstrap5\Dropdown|Dropdown]]
- [[yii\bootstrap5\LinkPager|LinkPager]]
- [[yii\bootstrap5\Modal|Modal]]
- [[yii\bootstrap5\Nav|Nav]]
- [[yii\bootstrap5\NavBar|NavBar]]
- [[yii\bootstrap5\Offcanvas|Offcanvas]]
- [[yii\bootstrap5\Popover|Popover]]
- [[yii\bootstrap5\Progress|Progress]]
- [[yii\bootstrap5\Tabs|Tabs]]
- [[yii\bootstrap5\Toast|Toast]]
- [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]]
## ActiveField: additional fields <span id="additional-fields"></span>
- [Range](https://getbootstrap.com/docs/5.1/forms/range/): `$form->rangeInput(['min' => 0, 'max' => 100, 'step' => 1])`
- [Color picker](https://getbootstrap.com/docs/5.1/forms/form-control/#color): `$form->colorInput()`
- [Switch](https://getbootstrap.com/docs/5.1/forms/checks-radios/#switches): `$form->checkbox(['switch' => true])`
## Customizing widget CSS classes <span id="customizing-css-classes"></span>
The widgets allow quick composition of the HTML for the bootstrap components that require the bootstrap CSS classes.
The default classes for a particular component will be added automatically by the widget, and the optional classes that you may want to customize are usually supported through the properties of the widget.
For example, you may use [[yii\bootstrap5\Button::options]] to customize the appearance of a button.
The class 'btn' which is required for a button will be added automatically, so you don't need to worry about it.
All you need is specify a particular button class:
```php
echo Button::widget([
'label' => 'Action',
'options' => ['class' => 'btn-primary'], // produces class "btn btn-primary"
]);
```
However, sometimes you may need to replace the default classes with the alternative ones.
For example, the widget [[yii\bootstrap5\ButtonGroup]] uses 'btn-group' class for the container div by default,
but you may need to use 'btn-group-vertical' instead to align the buttons vertically.
Using a plain 'class' option simply adds 'btn-group-vertical' to 'btn-group', which will produce an incorrect result.
In order to override the default classes of a widget, you need to specify the 'class' option as an array that contains the customized class definition under the 'widget' key:
```php
echo ButtonGroup::widget([
'options' => [
'class' => ['widget' => 'btn-group-vertical'] // replaces 'btn-group' with 'btn-group-vertical'
],
'buttons' => [
['label' => 'A'],
['label' => 'B'],
]
]);
```
## Navbar widget <span id="navbar-widget"></span>
The navbar widget has its peculiarities. You should define at which breakpoint the navbar collapses and the generic
style of navbar (color scheme).
You can change the color scheme and the collapse breakpoint with css classes. If not defined, the scheme defaults to
`navbar-light bg-light` and the breakpoint to `navbar-expand-lg`. For more information, see [Bootstrap documentation](https://getbootstrap.com/docs/5.1/components/navbar/):
```php
Navbar::begin([
'options' => [
'class' => ['navbar-dark', 'bg-dark', 'navbar-expand-md']
]
]);
[...]
Navbar::end();
```
If you'd like to flip the brand (icon) and toggle button positions in mobile navigation, you can do this like this:
```php
Navbar::begin([
'brandOptions' => [
'class' => ['order-1']
],
'togglerOptions' => [
'class' => ['order-0']
]
]);
[...]
Navbar::end();
```

40
vendor/yiisoft/yii2-bootstrap5/ecs.php vendored Normal file
View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
use PhpCsFixer\Fixer\ClassNotation\ClassDefinitionFixer;
use PhpCsFixer\Fixer\ClassNotation\OrderedTraitsFixer;
use PhpCsFixer\Fixer\Import\NoUnusedImportsFixer;
use Symplify\EasyCodingStandard\Config\ECSConfig;
return ECSConfig::configure()
->withConfiguredRule(
ClassDefinitionFixer::class,
[
'space_before_parenthesis' => true,
],
)
->withFileExtensions(['php'])
->withPaths(
[
__DIR__ . '/src',
__DIR__ . '/tests',
]
)
->withPhpCsFixerSets(false, false, false, false, false, true)
->withPreparedSets(
true,
false,
false,
false,
true,
true,
true,
false,
true,
false,
false,
true,
true
)
->withRules([NoUnusedImportsFixer::class, OrderedTraitsFixer::class]);

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit bootstrap="./tests/bootstrap.php"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnFailure="false">
<testsuites>
<testsuite name="Test Suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@ -0,0 +1,286 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Exception;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
/**
* Accordion renders an accordion bootstrap javascript component.
*
* For example:
*
* ```php
* echo Accordion::widget([
* 'items' => [
* // equivalent to the above
* [
* 'label' => 'Collapsible Group Item #1',
* 'content' => 'Anim pariatur cliche...',
* // open its content by default
* 'contentOptions' => ['class' => 'in']
* ],
* // another group item
* [
* 'label' => 'Collapsible Group Item #1',
* 'content' => 'Anim pariatur cliche...',
* 'contentOptions' => [...],
* 'options' => [...],
* 'expand' => true,
* ],
* // if you want to swap out .card-block with .list-group, you may use the following
* [
* 'label' => 'Collapsible Group Item #1',
* 'content' => [
* 'Anim pariatur cliche...',
* 'Anim pariatur cliche...'
* ],
* 'contentOptions' => [...],
* 'options' => [...],
* 'footer' => 'Footer' // the footer label in list-group
* ],
* ]
* ]);
* ```
*
* @see https://getbootstrap.com/docs/5.1/components/collapse/#accordion-example
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class Accordion extends Widget
{
/**
* @var array list of groups in the collapse widget. Each array element represents a single
* group with the following structure:
*
* - label: string, required, the group header label.
* - encode: bool, optional, whether this label should be HTML-encoded. This param will override
* global `$this->encodeLabels` param.
* - content: array|string|object, required, the content (HTML) of the group
* - options: array, optional, the HTML attributes of the group
* - contentOptions: optional, the HTML attributes of the group's content
*
* Since version 2.0.7 you may also specify this property as key-value pairs, where the key refers to the
* `label` and the value refers to `content`. If value is a string it is interpreted as label. If it is
* an array, it is interpreted as explained above.
*
* For example:
*
* ```php
* echo Accordion::widget([
* 'items' => [
* 'Introduction' => 'This is the first collapsable menu',
* 'Second panel' => [
* 'content' => 'This is the second collapsable menu',
* ],
* [
* 'label' => 'Third panel',
* 'content' => 'This is the third collapsable menu',
* ],
* ]
* ])
* ```
*/
public $items = [];
/**
* @var bool whether the labels for header items should be HTML-encoded.
*/
public $encodeLabels = true;
/**
* @var bool whether to close other items if an item is opened. Defaults to `true` which causes an
* accordion effect. Set this to `false` to allow keeping multiple items open at once.
*/
public $autoCloseItems = true;
/**
* @var array the HTML options for the item toggle tag. Key 'tag' might be used here for the tag name specification.
* For example:
*
* ```php
* [
* 'tag' => 'div',
* 'class' => 'custom-toggle',
* ]
* ```
*/
public $itemToggleOptions = [];
/**
* @throws InvalidConfigException
*/
public function run(): string
{
$this->registerPlugin('collapse');
Html::addCssClass($this->options, [
'widget' => 'accordion',
]);
return implode("\n", [
Html::beginTag('div', $this->options),
$this->renderItems(),
Html::endTag('div'),
]) . "\n";
}
/**
* Renders collapsible items as specified on [[items]].
* @throws InvalidConfigException if label isn't specified
* @return string the rendering result
*/
public function renderItems(): string
{
$items = [];
$index = 0;
$expanded = in_array(true, ArrayHelper::getColumn(ArrayHelper::toArray($this->items), 'expand', true), true);
foreach ($this->items as $key => $item) {
if (!is_array($item)) {
$item = [
'content' => $item,
];
}
// BC compatibility: expand first item if none is expanded
if ($expanded === false && $index === 0) {
$item['expand'] = true;
}
if (!array_key_exists('label', $item)) {
if (is_int($key)) {
throw new InvalidConfigException("The 'label' option is required.");
} else {
$item['label'] = $key;
}
}
$header = ArrayHelper::remove($item, 'label');
$options = ArrayHelper::getValue($item, 'options', []);
Html::addCssClass($options, [
'panel' => 'accordion-item',
]);
$items[] = Html::tag('div', $this->renderItem($header, $item, $index++), $options);
}
return implode("\n", $items);
}
/**
* Renders a single collapsible item group
*
* @param string $header a label of the item group [[items]]
* @param array $item a single item from [[items]]
* @param int $index the item index as each item group content must have an id
*
* @return string the rendering result
* @throws InvalidConfigException|Exception|\Throwable
*/
public function renderItem(string $header, array $item, int $index): string
{
if (array_key_exists('content', $item)) {
$id = $this->options['id'] . '-collapse' . $index;
$expand = ArrayHelper::remove($item, 'expand', false);
$options = ArrayHelper::getValue($item, 'contentOptions', []);
$options['id'] = $id;
Html::addCssClass($options, [
'widget' => 'collapse',
]);
// check if accordion expanded, if true add show class
if ($expand) {
Html::addCssClass($options, [
'visibility' => 'show',
]);
}
if (!isset($options['aria']['label'], $options['aria']['labelledby'])) {
$options['aria']['labelledby'] = $options['id'] . '-heading';
}
$encodeLabel = $item['encode'] ?? $this->encodeLabels;
if ($encodeLabel) {
$header = Html::encode($header);
}
$itemToggleOptions = array_merge([
'tag' => 'button',
'type' => 'button',
'data' => [
'bs-toggle' => 'collapse',
'bs-target' => '#' . $options['id'],
],
'aria' => [
'expanded' => $expand ? 'true' : 'false',
'controls' => $options['id'],
],
], $this->itemToggleOptions);
$itemToggleTag = ArrayHelper::remove($itemToggleOptions, 'tag', 'button');
if ($itemToggleTag === 'a') {
ArrayHelper::remove($itemToggleOptions, 'data.bs-target');
$headerToggle = Html::a($header, '#' . $id, $itemToggleOptions) . "\n";
} else {
if (!$expand) {
Html::addCssClass($itemToggleOptions, [
'widget' => 'accordion-button collapsed',
]);
} else {
Html::addCssClass($itemToggleOptions, [
'widget' => 'accordion-button',
]);
}
$headerToggle = Button::widget([
'label' => $header,
'encodeLabel' => false,
'options' => $itemToggleOptions,
]) . "\n";
}
$header = Html::tag('h5', $headerToggle, [
'class' => 'mb-0',
]);
if (is_string($item['content']) || is_numeric($item['content']) || is_object($item['content'])) {
$content = Html::tag('div', $item['content'], [
'class' => 'accordion-body',
]) . "\n";
} elseif (is_array($item['content'])) {
$content = Html::ul($item['content'], [
'class' => 'list-group',
'itemOptions' => [
'class' => 'list-group-item',
],
'encode' => false,
]) . "\n";
} else {
throw new InvalidConfigException('The "content" option should be a string, array or object.');
}
} else {
throw new InvalidConfigException('The "content" option is required.');
}
$group = [];
if ($this->autoCloseItems) {
$options['data']['bs-parent'] = '#' . $this->options['id'];
}
$group[] = Html::tag('div', $header, [
'class' => 'accordion-header',
'id' => $options['id'] . '-heading',
]);
$group[] = Html::beginTag('div', $options);
$group[] = $content;
if (isset($item['footer'])) {
$group[] = Html::tag('div', $item['footer'], [
'class' => 'accordion-footer',
]);
}
$group[] = Html::endTag('div');
return implode("\n", $group);
}
}

View File

@ -0,0 +1,659 @@
<?php
declare(strict_types=1);
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
namespace yii\bootstrap5;
use yii\helpers\ArrayHelper;
/**
* A Bootstrap 5 enhanced version of [[\yii\widgets\ActiveField]].
*
* This class adds some useful features to [[\yii\widgets\ActiveField|ActiveField]] to render all
* sorts of Bootstrap 5 form fields in different form layouts:
*
* - [[inputTemplate]] is an optional template to render complex inputs, for example input groups
* - [[horizontalCssClasses]] defines the CSS grid classes to add to label, wrapper, error and hint
* in horizontal forms
* - [[inline]]/[[inline()]] is used to render inline [[checkboxList()]] and [[radioList()]]
* - [[enableError]] can be set to `false` to disable to the error
* - [[enableLabel]] can be set to `false` to disable to the label
* - [[label()]] can be used with a `bool` argument to enable/disable the label
*
* There are also some new placeholders that you can use in the [[template]] configuration:
*
* - `{beginLabel}`: the opening label tag
* - `{labelTitle}`: the label title for use with `{beginLabel}`/`{endLabel}`
* - `{endLabel}`: the closing label tag
* - `{beginWrapper}`: the opening wrapper tag
* - `{endWrapper}`: the closing wrapper tag
*
* The wrapper tag is only used for some layouts and form elements.
*
* Note that some elements use slightly different defaults for [[template]] and other options.
* You may want to override those predefined templates for checkboxes, radio buttons, checkboxLists
* and radioLists in the [[\yii\widgets\ActiveForm::fieldConfig|fieldConfig]] of the
* [[\yii\widgets\ActiveForm]]:
*
* - [[checkTemplate]] the default template for checkboxes and radios
* - [[radioTemplate]] the template for radio buttons in default layout
* - [[checkHorizontalTemplate]] the template for checkboxes in horizontal layout
* - [[radioHorizontalTemplate]] the template for radio buttons in horizontal layout
* - [[checkEnclosedTemplate]] the template for checkboxes and radios enclosed by label
*
* Example:
*
* ```php
* use yii\bootstrap5\ActiveForm;
*
* $form = ActiveForm::begin(['layout' => 'horizontal']);
*
* // Form field without label
* echo $form->field($model, 'demo', [
* 'inputOptions' => [
* 'placeholder' => $model->getAttributeLabel('demo'),
* ],
* ])->label(false);
*
* // Inline radio list
* echo $form->field($model, 'demo')->inline()->radioList($items);
*
* // Control sizing in horizontal mode
* echo $form->field($model, 'demo', [
* 'horizontalCssClasses' => [
* 'wrapper' => 'col-sm-2',
* ]
* ]);
*
* // With 'default' layout you would use 'template' to size a specific field:
* echo $form->field($model, 'demo', [
* 'template' => '{label} <div class="row"><div class="col-sm-4">{input}{error}{hint}</div></div>'
* ]);
*
* // Input group
* echo $form->field($model, 'demo', [
* 'inputTemplate' => '<div class="input-group"><div class="input-group-prepend">
* <span class="input-group-text">@</span>
* </div>{input}</div>',
* ]);
*
* ActiveForm::end();
* ```
*
* @see ActiveForm
* @see https://getbootstrap.com/docs/5.1/components/forms/
*
* @author Michael Härtl <haertl.mike@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class ActiveField extends \yii\widgets\ActiveField
{
/**
* @var bool whether to render [[checkboxList()]] and [[radioList()]] inline.
*/
public $inline = false;
/**
* @var string|null optional template to render the `{input}` placeholder content
*/
public $inputTemplate = null;
/**
* @var array options for the wrapper tag, used in the `{beginWrapper}` placeholder
*/
public $wrapperOptions = [];
public $options = [
'class' => [
'widget' => 'mb-3',
],
];
public $inputOptions = [
'class' => [
'widget' => 'form-control',
],
];
/**
* @var array the default options for the input checkboxes. The parameter passed to individual
* input methods (e.g. [[checkbox()]]) will be merged with this property when rendering the input tag.
*
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
*
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
* @since 2.0.7
*/
public $checkOptions = [
'class' => [
'widget' => 'form-check-input',
],
'labelOptions' => [
'class' => [
'widget' => 'form-check-label',
],
],
];
/**
* @var array the default options for the input radios. The parameter passed to individual
* input methods (e.g. [[radio()]]) will be merged with this property when rendering the input tag.
*
* If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
*
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
* @since 2.0.7
*/
public $radioOptions = [
'class' => [
'widget' => 'form-check-input',
],
'labelOptions' => [
'class' => [
'widget' => 'form-check-label',
],
],
];
public $errorOptions = [
'class' => 'invalid-feedback',
];
public $labelOptions = [
'class' => [
'widget' => 'form-label',
],
];
public $hintOptions = [
'class' => [
'widget' => 'form-text',
'text-muted',
],
'tag' => 'div',
];
/**
* @var null|array CSS grid classes for horizontal layout. This must be an array with these keys:
* - 'offset' the offset grid class to append to the wrapper if no label is rendered
* - 'label' the label grid class
* - 'wrapper' the wrapper grid class
* - 'error' the error grid class
* - 'hint' the hint grid class
*/
public $horizontalCssClasses = [];
/**
* @var string the template for checkboxes in default layout
*/
public $checkTemplate = "<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>";
/**
* @var string the template forswitches (custom checkboxes) in default layout
*/
public $switchTemplate = "<div class=\"form-check form-switch\">\n{input}\n{label}\n{error}\n{hint}\n</div>";
/**
* @var string the template for radios in default layout
* @since 2.0.5
*/
public $radioTemplate = "<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>";
/**
* @var string the template for checkboxes and radios in horizontal layout
*/
public $checkHorizontalTemplate = "{beginWrapper}\n<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}";
/**
* @var string the template for switches (custom checkboxes) in horizontal layout
*/
public $switchHorizontalTemplate = "{beginWrapper}\n<div class=\"form-check form-switch\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}";
/**
* @var string the template for checkboxes and radios in horizontal layout
* @since 2.0.5
*/
public $radioHorizontalTemplate = "{beginWrapper}\n<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}";
/**
* @var string the `enclosed by label` template for checkboxes and radios in default layout
*/
public $checkEnclosedTemplate = "<div class=\"form-check\">\n{beginLabel}\n{input}\n{labelTitle}\n{endLabel}\n{error}\n{hint}\n</div>";
/**
* @var string tthe `enclosed by label` template for switches(custom checkboxes) in default layout
*/
public $switchEnclosedTemplate = "<div class=\"form-check form-switch\">\n{beginLabel}\n{input}\n{labelTitle}\n{endLabel}\n{error}\n{hint}\n</div>";
/**
* @var bool whether to render the error. Default is `true` except for layout `inline`.
*/
public $enableError = true;
/**
* @var bool whether to render the label. Default is `true`.
*/
public $enableLabel = true;
public function __construct($config = [])
{
$layoutConfig = $this->createLayoutConfig($config);
$config = ArrayHelper::merge($layoutConfig, $config);
parent::__construct($config);
}
public function render($content = null): string
{
if ($content === null) {
if (!isset($this->parts['{beginWrapper}'])) {
$options = $this->wrapperOptions;
$tag = ArrayHelper::remove($options, 'tag', 'div');
$this->parts['{beginWrapper}'] = Html::beginTag($tag, $options);
$this->parts['{endWrapper}'] = Html::endTag($tag);
}
if ($this->enableLabel === false) {
$this->parts['{label}'] = '';
$this->parts['{beginLabel}'] = '';
$this->parts['{labelTitle}'] = '';
$this->parts['{endLabel}'] = '';
} elseif (!isset($this->parts['{beginLabel}'])) {
$this->renderLabelParts();
}
if ($this->enableError === false) {
$this->parts['{error}'] = '';
}
if ($this->inputTemplate) {
$options = $this->inputOptions;
if ($this->form->validationStateOn === ActiveForm::VALIDATION_STATE_ON_INPUT) {
$this->addErrorClassIfNeeded($options);
}
$this->addAriaAttributes($options);
$input = $this->parts['{input}'] ?? Html::activeTextInput($this->model, $this->attribute, $options);
$this->parts['{input}'] = strtr($this->inputTemplate, [
'{input}' => $input,
]);
}
}
return parent::render($content);
}
/**
* {@inheritdoc}
* Enable option `switch` to render as toggle switch.
* @see https://getbootstrap.com/docs/5.1/forms/checks-radios/#switches
*/
public function checkbox($options = [], $enclosedByLabel = false): self
{
$checkOptions = $this->checkOptions;
$options = ArrayHelper::merge($checkOptions, $options);
$labelOptions = ArrayHelper::remove($options, 'labelOptions', []);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', []);
Html::removeCssClass($options, 'form-control');
$this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions);
$this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions);
$switch = isset($options['switch']) && $options['switch'];
if ($switch) {
$this->addRoleAttributes($options, 'switch');
}
if (!isset($options['template'])) {
if ($switch) {
$this->template = $enclosedByLabel ? $this->switchEnclosedTemplate : $this->switchTemplate;
} else {
$this->template = $enclosedByLabel ? $this->checkEnclosedTemplate : $this->checkTemplate;
}
} else {
$this->template = $options['template'];
}
if ($this->form->layout === ActiveForm::LAYOUT_HORIZONTAL) {
if (!isset($options['template'])) {
$this->template = ($switch)
? $this->switchHorizontalTemplate
: $this->checkHorizontalTemplate;
}
Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']);
Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']);
}
if ($this->form->layout === ActiveForm::LAYOUT_INLINE) {
Html::removeCssClass($this->labelOptions, 'visually-hidden');
}
Html::removeCssClass($this->labelOptions, 'form-label');
unset($options['template'], $options['switch']);
if ($enclosedByLabel) {
if (isset($options['label'])) {
$this->parts['{labelTitle}'] = $options['label'];
}
}
parent::checkbox($options, false);
return $this;
}
public function radio($options = [], $enclosedByLabel = false): self
{
$checkOptions = $this->radioOptions;
$options = ArrayHelper::merge($checkOptions, $options);
$labelOptions = ArrayHelper::remove($options, 'labelOptions', []);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', []);
Html::removeCssClass($options, 'form-control');
$this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions);
$this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions);
if (!isset($options['template'])) {
$this->template = $enclosedByLabel ? $this->checkEnclosedTemplate : $this->radioTemplate;
} else {
$this->template = $options['template'];
}
if ($this->form->layout === ActiveForm::LAYOUT_HORIZONTAL) {
if (!isset($options['template'])) {
$this->template = $this->radioHorizontalTemplate;
}
Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']);
Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']);
}
Html::removeCssClass($this->labelOptions, 'form-label');
unset($options['template']);
if ($enclosedByLabel && isset($options['label'])) {
$this->parts['{labelTitle}'] = $options['label'];
}
parent::radio($options, false);
return $this;
}
public function checkboxList($items, $options = []): self
{
if (!isset($options['item'])) {
$this->template = str_replace("\n{error}", '', $this->template);
$itemOptions = $options['itemOptions'] ?? [];
$encode = ArrayHelper::getValue($options, 'encode', true);
$itemCount = count($items) - 1;
$error = $this->error()->parts['{error}'];
$options['item'] = function ($i, $label, $name, $checked, $value) use ($itemOptions, $encode, $itemCount, $error): string {
$options = array_merge($this->checkOptions, [
'label' => $encode ? Html::encode($label) : $label,
'value' => $value,
], $itemOptions);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', [
'class' => [
'widget' => 'form-check',
],
]);
if ($this->inline) {
Html::addCssClass($wrapperOptions, [
'inline' => 'form-check-inline',
]);
}
$html = Html::beginTag('div', $wrapperOptions) . "\n" .
Html::checkbox($name, $checked, $options) . "\n";
if ($itemCount === $i) {
$html .= $error . "\n";
}
$html .= Html::endTag('div') . "\n";
return $html;
};
}
parent::checkboxList($items, $options);
return $this;
}
public function radioList($items, $options = []): self
{
if (!isset($options['item'])) {
$this->template = str_replace("\n{error}", '', $this->template);
$itemOptions = $options['itemOptions'] ?? [];
$encode = ArrayHelper::getValue($options, 'encode', true);
$itemCount = count($items) - 1;
$error = $this->error()->parts['{error}'];
$options['item'] = function ($i, $label, $name, $checked, $value) use ($itemOptions, $encode, $itemCount, $error): string {
$options = array_merge($this->radioOptions, [
'label' => $encode ? Html::encode($label) : $label,
'value' => $value,
], $itemOptions);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', [
'class' => [
'widget' => 'form-check',
],
]);
if ($this->inline) {
Html::addCssClass($wrapperOptions, [
'inline' => 'form-check-inline',
]);
}
$html = Html::beginTag('div', $wrapperOptions) . "\n" .
Html::radio($name, $checked, $options) . "\n";
if ($itemCount === $i) {
$html .= $error . "\n";
}
$html .= Html::endTag('div') . "\n";
return $html;
};
}
parent::radioList($items, $options);
return $this;
}
public function listBox($items, $options = []): self
{
if ($this->form->layout === ActiveForm::LAYOUT_INLINE) {
Html::removeCssClass($this->labelOptions, 'visually-hidden');
}
Html::addCssClass($options, [
'widget' => 'form-select',
]);
parent::listBox($items, $options);
return $this;
}
public function dropDownList($items, $options = []): self
{
if ($this->form->layout === ActiveForm::LAYOUT_INLINE) {
Html::removeCssClass($this->labelOptions, 'visually-hidden');
}
Html::addCssClass($options, [
'widget' => 'form-select',
]);
parent::dropDownList($items, $options);
return $this;
}
/**
* Renders Bootstrap static form control.
*
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. There are also a special options:
*
* - encode: bool, whether value should be HTML-encoded or not.
*
* @return $this the field object itself
* @see https://getbootstrap.com/docs/5.1/components/forms/#readonly-plain-text
*/
public function staticControl(array $options = []): self
{
$this->adjustLabelFor($options);
$this->parts['{input}'] = Html::activeStaticControl($this->model, $this->attribute, $options);
return $this;
}
public function label($label = null, $options = []): self
{
if (is_bool($label)) {
$this->enableLabel = $label;
if ($label === false && $this->form->layout === ActiveForm::LAYOUT_HORIZONTAL) {
Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']);
}
} else {
$this->enableLabel = true;
$this->renderLabelParts($label, $options);
parent::label($label, $options);
}
return $this;
}
/**
* Set inline to true or false
*
* @param bool $value whether to render a inline list
*
* @return $this the field object itself
* Make sure you call this method before [[checkboxList()]] or [[radioList()]] to have any effect.
*/
public function inline(bool $value = true): self
{
$this->inline = $value;
return $this;
}
public function fileInput($options = []): self
{
Html::addCssClass($options, [
'widget' => 'form-control',
]);
parent::fileInput($options);
return $this;
}
/**
* Renders a range (custom input).
*
* @param array $options the tag options in terms of name-value pairs:
*
* - 'min': min. value
* - 'max': max. value
* - 'step': range step, by default, 1
*
* @return $this
* @see https://getbootstrap.com/docs/5.1/forms/range/
*/
public function rangeInput(array $options = []): self
{
Html::addCssClass($options, [
'widget' => 'form-range',
]);
$this->input('range', $options);
return $this;
}
/**
* Renders a color picker (custom input).
*
* @param array $options the tag options in terms of name-value pairs
*
* @return $this
* @see https://getbootstrap.com/docs/5.1/forms/form-control/#color
*/
public function colorInput(array $options = []): self
{
Html::removeCssClass($options, 'form-control');
Html::addCssClass($options, [
'widget' => 'form-control form-control-color',
]);
return $this->input('color', $options);
}
/**
* @param array $instanceConfig the configuration passed to this instance's constructor
*
* @return array the layout specific default configuration for this instance
*/
protected function createLayoutConfig(array $instanceConfig): array
{
$config = [
'hintOptions' => [
'tag' => 'div',
'class' => ['form-text', 'text-muted'],
],
'errorOptions' => [
'tag' => 'div',
'class' => 'invalid-feedback',
],
'inputOptions' => [
'class' => 'form-control',
],
'labelOptions' => [
'class' => ['form-label'],
],
];
$layout = $instanceConfig['form']->layout;
if ($layout === ActiveForm::LAYOUT_HORIZONTAL) {
$config['template'] = "{label}\n{beginWrapper}\n{input}\n{error}\n{hint}\n{endWrapper}";
$config['wrapperOptions'] = [];
$config['labelOptions'] = [];
$config['options'] = [];
$cssClasses = [
'offset' => ['col-sm-10', 'offset-sm-2'],
'label' => ['col-sm-2', 'col-form-label'],
'wrapper' => 'col-sm-10',
'error' => '',
'hint' => '',
'field' => 'mb-3 row',
];
if (isset($instanceConfig['horizontalCssClasses'])) {
$cssClasses = ArrayHelper::merge($cssClasses, $instanceConfig['horizontalCssClasses']);
}
$config['horizontalCssClasses'] = $cssClasses;
Html::addCssClass($config['wrapperOptions'], $cssClasses['wrapper']);
Html::addCssClass($config['labelOptions'], $cssClasses['label']);
Html::addCssClass($config['errorOptions'], $cssClasses['error']);
Html::addCssClass($config['hintOptions'], $cssClasses['hint']);
Html::addCssClass($config['options'], $cssClasses['field']);
} elseif ($layout === ActiveForm::LAYOUT_INLINE) {
$config['inputOptions']['placeholder'] = true;
$config['enableError'] = false;
Html::addCssClass($config['labelOptions'], [
'screenreader' => 'visually-hidden',
]);
} elseif ($layout === ActiveForm::LAYOUT_FLOATING) {
$config['inputOptions']['placeholder'] = true;
$config['template'] = "{input}\n{label}\n{error}\n{hint}";
Html::addCssClass($config['options'], [
'layout' => 'form-floating mt-3',
]);
}
return $config;
}
/**
* @param string|null $label the label or null to use model label
* @param array $options the tag options
*/
protected function renderLabelParts(?string $label = null, array $options = []): void
{
$options = array_merge($this->labelOptions, $options);
if ($label === null) {
if (isset($options['label'])) {
$label = $options['label'];
unset($options['label']);
} else {
$attribute = Html::getAttributeName($this->attribute);
$label = Html::encode($this->model->getAttributeLabel($attribute));
}
}
if (!isset($options['for'])) {
$options['for'] = Html::getInputId($this->model, $this->attribute);
}
$this->parts['{beginLabel}'] = Html::beginTag('label', $options);
$this->parts['{endLabel}'] = Html::endTag('label');
if (!isset($this->parts['{labelTitle}'])) {
$this->parts['{labelTitle}'] = $label;
}
}
}

View File

@ -0,0 +1,136 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use yii\base\InvalidConfigException;
/**
* A Bootstrap 5 enhanced version of [[\yii\widgets\ActiveForm]].
*
* This class mainly adds the [[layout]] property to choose a Bootstrap 5 form layout.
* So for example to render a horizontal form you would:
*
* ```php
* use yii\bootstrap5\ActiveForm;
*
* $form = ActiveForm::begin(['layout' => 'horizontal'])
* ```
*
* This will set default values for the [[ActiveField]]
* to render horizontal form fields. In particular the [[ActiveField::template|template]]
* is set to `{label} {beginWrapper} {input} {error} {endWrapper} {hint}` and the
* [[ActiveField::horizontalCssClasses|horizontalCssClasses]] are set to:
*
* ```php
* [
* 'offset' => 'offset-sm-3',
* 'label' => 'col-sm-3',
* 'wrapper' => 'col-sm-6',
* 'error' => '',
* 'hint' => 'col-sm-3',
* ]
* ```
*
* To get a different column layout in horizontal mode you can modify those options
* through [[fieldConfig]]:
*
* ```php
* $form = ActiveForm::begin([
* 'layout' => 'horizontal',
* 'fieldConfig' => [
* 'template' => "{label}\n{beginWrapper}\n{input}\n{hint}\n{error}\n{endWrapper}",
* 'horizontalCssClasses' => [
* 'label' => 'col-sm-4',
* 'offset' => 'offset-sm-4',
* 'wrapper' => 'col-sm-8',
* 'error' => '',
* 'hint' => '',
* ],
* ],
* ]);
* ```
*
* @see ActiveField for details on the [[fieldConfig]] options
* @see https://getbootstrap.com/docs/5.1/components/forms/
*
* @author Michael Härtl <haertl.mike@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class ActiveForm extends \yii\widgets\ActiveForm
{
/**
* Default form layout
*/
public const LAYOUT_DEFAULT = 'default';
/**
* Horizontal form layout
*/
public const LAYOUT_HORIZONTAL = 'horizontal';
/**
* Inline form layout
*/
public const LAYOUT_INLINE = 'inline';
/**
* Floating labels form layout
*/
public const LAYOUT_FLOATING = 'floating';
/**
* @var string the default field class name when calling [[field()]] to create a new field.
* @see fieldConfig
*/
public $fieldClass = ActiveField::class;
/**
* @var array HTML attributes for the form tag. Default is `[]`.
*/
public $options = [];
/**
* @var string the form layout. Either [[LAYOUT_DEFAULT]], [[LAYOUT_HORIZONTAL]] or [[LAYOUT_INLINE]].
* By choosing a layout, an appropriate default field configuration is applied. This will
* render the form fields with slightly different markup for each layout. You can
* override these defaults through [[fieldConfig]].
* @see ActiveField for details on Bootstrap 5 field configuration
*/
public $layout = self::LAYOUT_DEFAULT;
/**
* @var string the CSS class that is added to a field container when the associated attribute has validation error.
*/
public $errorCssClass = 'is-invalid';
public $successCssClass = 'is-valid';
public $errorSummaryCssClass = 'alert alert-danger';
public $validationStateOn = self::VALIDATION_STATE_ON_INPUT;
/**
* @throws InvalidConfigException
*/
public function init(): void
{
if (!in_array($this->layout, [self::LAYOUT_DEFAULT, self::LAYOUT_HORIZONTAL, self::LAYOUT_INLINE, self::LAYOUT_FLOATING], true)) {
throw new InvalidConfigException('Invalid layout type: ' . $this->layout);
}
if ($this->layout === self::LAYOUT_INLINE) {
Html::addCssClass($this->options, [
'widget' => 'form-inline',
]);
}
parent::init();
}
/**
* @return ActiveField|\yii\widgets\ActiveField
*/
public function field($model, $attribute, $options = []): ActiveField
{
return parent::field($model, $attribute, $options);
}
}

View File

@ -0,0 +1,153 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Yii;
use yii\helpers\ArrayHelper;
/**
* Alert renders an alert bootstrap component.
*
* For example,
*
* ```php
* echo Alert::widget([
* 'options' => [
* 'class' => 'alert-info',
* ],
* 'body' => 'Say hello...',
* ]);
* ```
*
* The following example will show the content enclosed between the [[begin()]]
* and [[end()]] calls within the alert box:
*
* ```php
* Alert::begin([
* 'options' => [
* 'class' => 'alert-warning',
* ],
* ]);
*
* echo 'Say hello...';
*
* Alert::end();
* ```
*
* @see https://getbootstrap.com/docs/5.1/components/alerts/
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class Alert extends Widget
{
/**
* @var string the body content in the alert component. Note that anything between
* the [[begin()]] and [[end()]] calls of the Alert widget will also be treated
* as the body content, and will be rendered before this.
*/
public $body;
/**
* @var array|false the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking
* on the button will hide the modal window. If this is false, no close button will be rendered.
*
* The following special options are supported:
*
* - tag: string, the tag name of the button. Defaults to 'button'.
*
* The rest of the options will be rendered as the HTML attributes of the button tag.
* Please refer to the [Alert documentation](https://getbootstrap.com/docs/5.1/components/alerts/)
* for the supported HTML attributes.
*/
public $closeButton = [];
public function init(): void
{
parent::init();
$this->initOptions();
ob_start();
echo Html::beginTag('div', $this->options) . "\n";
}
public function run(): string
{
$content = ob_get_clean();
$content .= "\n" . $this->renderBodyEnd();
$content .= "\n" . Html::endTag('div');
$this->registerPlugin('alert');
return $content;
}
/**
* Renders the alert body and the close button (if any).
* @return string the rendering result
*/
protected function renderBodyEnd(): string
{
return $this->body . "\n" . $this->renderCloseButton() . "\n";
}
/**
* Renders the close button.
* @return string|null the rendering result
*/
protected function renderCloseButton(): ?string
{
if (($closeButton = $this->closeButton) !== false) {
$tag = ArrayHelper::remove($closeButton, 'tag', 'button');
$label = ArrayHelper::remove($closeButton, 'label', '');
if ($tag === 'button' && !isset($closeButton['type'])) {
$closeButton['type'] = 'button';
}
return Html::tag($tag, $label, $closeButton);
} else {
return null;
}
}
/**
* Initializes the widget options.
* This method sets the default values for various options.
*/
protected function initOptions(): void
{
Html::addCssClass($this->options, [
'widget' => 'alert',
]);
if ($this->closeButton !== false) {
$this->closeButton = array_merge([
'class' => [
'widget' => 'btn-close',
],
'data' => [
'bs-dismiss' => 'alert',
],
'aria' => [
'label' => Yii::t('yii/bootstrap5', 'Close'),
],
], $this->closeButton);
Html::addCssClass($this->options, [
'toggle' => 'alert-dismissible',
]);
}
if (!isset($this->options['role'])) {
$this->options['role'] = 'alert';
}
}
}

View File

@ -0,0 +1,213 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use yii\base\Model;
use yii\helpers\ArrayHelper;
/**
* BaseHtml provides concrete implementation for [[Html]].
*/
abstract class BaseHtml extends \yii\helpers\Html
{
/**
* @var int a counter used to generate [[id]] for widgets.
* @internal
*/
public static $counter = 0;
/**
* @var string the prefix to the automatically generated widget IDs.
* @see getId()
*/
public static $autoIdPrefix = 'i';
public static $normalizeClassAttribute = true;
/**
* Renders Bootstrap static form control.
*
* @param string $value static control value.
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. There are also a special options:
*
* @return string generated HTML
* @see https://getbootstrap.com/docs/5.1/components/forms/#readonly-plain-text
*/
public static function staticControl(string $value, array $options = []): string
{
static::addCssClass($options, 'form-control-plaintext');
$options['readonly'] = true;
return static::input('text', null, $value, $options);
}
/**
* Generates a Bootstrap static form control for the given model attribute.
*
* @param Model $model the model object.
* @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
* about attribute expression.
* @param array $options the tag options in terms of name-value pairs. See [[staticControl()]] for details.
* @return string generated HTML
* @see staticControl()
*/
public static function activeStaticControl(Model $model, string $attribute, array $options = []): string
{
if (isset($options['value'])) {
$value = $options['value'];
unset($options['value']);
} else {
$value = static::getAttributeValue($model, $attribute);
}
return static::staticControl((string) $value, $options);
}
/**
* {@inheritdoc}
* Pass `true` in `$options['inline']` to generate [inline list](https://getbootstrap.com/docs/5.1/forms/checks-radios/#inline).
*/
public static function radioList($name, $selection = null, $items = [], $options = []): string
{
$inline = ArrayHelper::remove($options, 'inline', false);
if (!isset($options['item'])) {
$itemOptions = ArrayHelper::remove($options, 'itemOptions', []);
static::addCssClass($itemOptions, [
'bootstrap' => 'form-check-input',
]);
if (!isset($itemOptions['labelOptions'])) {
$itemOptions['labelOptions'] = [
'class' => 'form-check-label',
];
} else {
static::addCssClass($itemOptions['labelOptions'], [
'bootstrap' => 'form-check-label',
]);
}
$wrapperOptions = $inline ? [
'class' => 'form-check form-check-inline',
] : [
'class' => 'form-check',
];
$encode = ArrayHelper::getValue($options, 'encode', true);
$options['item'] = function ($index, $label, $name, $checked, $value) use ($itemOptions, $wrapperOptions, $encode) {
$itemOptions['value'] = $value;
if (!isset($itemOptions['label'])) {
$itemOptions['label'] = $encode ? static::encode($label) : $label;
}
return static::tag('div', static::radio($name, $checked, $itemOptions), $wrapperOptions);
};
}
return parent::radioList($name, $selection, $items, $options);
}
/**
* {@inheritdoc}
* Pass `true` in `$options['inline']` to generate [inline list](https://getbootstrap.com/docs/5.1/forms/checks-radios/#inline).
*/
public static function checkboxList($name, $selection = null, $items = [], $options = []): string
{
$inline = ArrayHelper::remove($options, 'inline', false);
if (!isset($options['item'])) {
$itemOptions = ArrayHelper::remove($options, 'itemOptions', []);
static::addCssClass($itemOptions, 'form-check-input');
if (!isset($itemOptions['labelOptions'])) {
$itemOptions['labelOptions'] = [
'class' => 'form-check-label',
];
} else {
static::addCssClass($itemOptions['labelOptions'], 'form-check-label');
}
$wrapperOptions = $inline ? [
'class' => 'form-check form-check-inline',
] : [
'class' => 'form-check',
];
$encode = ArrayHelper::getValue($options, 'encode', true);
$options['item'] = function ($index, $label, $name, $checked, $value) use ($itemOptions, $wrapperOptions, $encode) {
$itemOptions['value'] = $value;
if (!isset($itemOptions['label'])) {
$itemOptions['label'] = $encode ? static::encode($label) : $label;
}
return static::tag('div', static::checkbox($name, $checked, $itemOptions), $wrapperOptions);
};
}
return parent::checkboxList($name, $selection, $items, $options);
}
public static function error($model, $attribute, $options = []): string
{
if (!array_key_exists('class', $options)) {
$options['class'] = ['invalid-feedback'];
}
return parent::error($model, $attribute, $options);
}
protected static function booleanInput($type, $name, $checked = false, $options = []): string
{
$options['checked'] = (bool) $checked;
$value = array_key_exists('value', $options) ? $options['value'] : '1';
if (isset($options['uncheck'])) {
// add a hidden field so that if the checkbox is not selected, it still submits a value
$hiddenOptions = [];
if (isset($options['form'])) {
$hiddenOptions['form'] = $options['form'];
}
$hidden = static::hiddenInput($name, $options['uncheck'], $hiddenOptions);
unset($options['uncheck']);
} else {
$hidden = '';
}
if (isset($options['label'])) {
$label = $options['label'];
$labelOptions = $options['labelOptions'] ?? [];
unset($options['label'], $options['labelOptions']);
if (!isset($options['id'])) {
$options['id'] = static::getId();
}
$input = static::input($type, $name, $value, $options);
if (isset($labelOptions['wrapInput']) && $labelOptions['wrapInput']) {
unset($labelOptions['wrapInput']);
$content = static::label($input . $label, $options['id'], $labelOptions);
} else {
$content = $input . "\n" . static::label($label, $options['id'], $labelOptions);
}
return $hidden . $content;
}
return $hidden . static::input($type, $name, $value, $options);
}
/**
* Returns an autogenerated ID
* @return string Autogenerated ID
*/
protected static function getId(): string
{
return static::$autoIdPrefix . static::$counter++;
}
}

View File

@ -0,0 +1,25 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use yii\web\AssetBundle;
/**
* Twitter Bootstrap 5 CSS bundle.
*/
class BootstrapAsset extends AssetBundle
{
public $sourcePath = '@vendor/twbs/bootstrap/dist/css';
public $css = [
'bootstrap.css',
];
}

View File

@ -0,0 +1,25 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use yii\web\AssetBundle;
/**
* Twitter Bootstrap 5 icon bundle
*/
class BootstrapIconAsset extends AssetBundle
{
public $sourcePath = '@vendor/twbs/bootstrap-icons/font';
public $css = [
'bootstrap-icons.css',
];
}

View File

@ -0,0 +1,29 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use yii\web\AssetBundle;
/**
* Twitter Bootstrap 5 JavaScript bundle.
*/
class BootstrapPluginAsset extends AssetBundle
{
public $sourcePath = '@vendor/twbs/bootstrap/dist/js';
public $js = [
'bootstrap.bundle.js',
];
public $depends = [
'yii\bootstrap5\BootstrapAsset',
];
}

View File

@ -0,0 +1,122 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use yii\base\InvalidConfigException;
use yii\helpers\Json;
/**
* BootstrapWidgetTrait is the trait, which provides basic for all Bootstrap widgets features.
*
* Note: class, which uses this trait must declare public field named `options` with the array default value:
*
* ```php
* class MyWidget extends \yii\base\Widget
* {
* use BootstrapWidgetTrait;
*
* public $options = [];
* }
* ```
*
* This field is not present in the trait in order to avoid possible PHP Fatal error on definition conflict.
*
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Paul Klimov <klimov.paul@gmail.com>
*/
trait BootstrapWidgetTrait
{
/**
* @var array|false the options for the underlying Bootstrap JS plugin/component.
* Please refer to the corresponding Bootstrap plugin/component Web page for possible options.
* For example, [this page](https://getbootstrap.com/docs/5.1/components/modal/#options) shows
* how to use the "Modal" component and the supported options (e.g. "backdrop").
* If this property is false, `registerJs()` will not be called on the view to initialize the module.
*/
public $clientOptions = [];
/**
* @var array the event handlers for the underlying Bootstrap JS plugin.
* Please refer to the corresponding Bootstrap plugin Web page for possible events.
* For example, [this page](https://getbootstrap.com/docs/5.1/components/modal/#events) shows
* how to use the "Modal" plugin and the supported events (e.g. "shown.bs.modal").
*/
public $clientEvents = [];
/**
* Initializes the widget.
* This method will register the bootstrap asset bundle. If you override this method,
* make sure you call the parent implementation first.
* @throws InvalidConfigException
*/
public function init(): void
{
parent::init();
if (!isset($this->options['id'])) {
$this->options['id'] = $this->getId();
}
}
/**
* Registers a specific Bootstrap plugin/component and the related events.
*
* @param string $name the name of the Bootstrap plugin
*/
protected function registerPlugin(string $name): void
{
/**
* @see https://github.com/twbs/bootstrap/blob/v5.2.0/js/index.esm.js
*/
$jsPlugins = [
'alert',
'button',
'carousel',
'collapse',
'dropdown',
'modal',
'offcanvas',
'popover',
'scrollspy',
'tab',
'toast',
'tooltip',
];
if (in_array($name, $jsPlugins, true)) {
$view = $this->getView();
BootstrapPluginAsset::register($view);
// 'popover', 'toast' and 'tooltip' plugins not activates via data attributes
if ($this->clientOptions !== false || in_array($name, ['popover', 'toast', 'tooltip'], true)) {
$name = ucfirst($name);
$id = $this->options['id'];
$options = empty($this->clientOptions) ? '{}' : Json::htmlEncode($this->clientOptions);
$view->registerJs("(new bootstrap.$name('#$id', $options));");
}
$this->registerClientEvents($name);
}
}
/**
* Registers JS event handlers that are listed in [[clientEvents]].
*/
protected function registerClientEvents(?string $name = null): void
{
if (!empty($this->clientEvents)) {
$id = $this->options['id'];
$js = [];
$appendix = ($name === 'dropdown') ? '.parentElement' : '';
foreach ($this->clientEvents as $event => $handler) {
$js[] = "document.getElementById('$id')$appendix.addEventListener('$event', $handler);";
}
$this->getView()->registerJs(implode("\n", $js));
}
}
}

View File

@ -0,0 +1,218 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
/**
* This widget represents a Bootstrap 5 component "Breadcrumb". It displays a list of links indicating the
* position of the current page in the whole site hierarchy.
*
* ```php
* echo Breadcrumbs::widget([
* 'links' => [
* [
* 'label' => 'the item label', // required
* 'url' => 'the item URL', // optional, will be processed by `Url::to()`
* 'template' => 'own template of the item', // optional
* ],
* ['label' => 'the label of the active item']
* ],
* 'options' => [...],
* ]);
* ```
* or
* ```php
* echo Breadcrumbs::widget([
* 'links' => [
* 'the item URL' => 'the item label',
* 0 => 'the label of the active item',
* ],
* 'options' => [...],
* ]);
* ```
*
* @see https://getbootstrap.com/docs/5.1/components/breadcrumb/
* @author Alexandr Kozhevnikov <onmotion1@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class Breadcrumbs extends \yii\widgets\Breadcrumbs
{
use BootstrapWidgetTrait;
public $tag = 'ol';
/**
* @var array|false the first hyperlink in the breadcrumbs (called home link).
* Please refer to [[links]] on the format of the link.
* If this property is not set, it will default to a link pointing to [[\yii\web\Application::homeUrl]]
* with the label 'Home'. If this property is false, the home link will not be rendered.
*/
public $homeLink = [];
public $itemTemplate = "<li class=\"breadcrumb-item\">{link}</li>\n";
public $activeItemTemplate = "<li class=\"breadcrumb-item active\" aria-current=\"page\">{link}</li>\n";
/**
* @var array the HTML attributes for the widgets nav container tag.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $navOptions = [
'aria' => [
'label' => 'breadcrumb',
],
];
public function run(): string
{
if (empty($this->links)) {
return '';
}
// Normalize links
$links = [];
foreach ($this->links as $key => $value) {
if (is_array($value)) {
$links[] = $value;
} else {
$links[] = [
'label' => $value,
'url' => is_string($key) ? $key : null,
];
}
}
$this->links = $links;
unset($links);
if ($this->homeLink === []) {
$this->homeLink = null;
}
if (!isset($this->options['id'])) {
$this->options['id'] = "{$this->getId()}-breadcrumb";
}
Html::addCssClass($this->options, [
'widget' => 'breadcrumb',
]);
// parent method not return result
ob_start();
parent::run();
$content = ob_get_clean();
return Html::tag('nav', $content, $this->navOptions);
}
/**
* The template used to render each active item in the breadcrumbs. The token `{link}` will be replaced with the
* actual HTML link for each active item.
*
* @return $this
*/
public function activeItemTemplate(string $value): self
{
$this->activeItemTemplate = $value;
return $this;
}
/**
* Whether to HTML-encode the link labels.
*
* @return $this
*/
public function encodeLabels(bool $value): self
{
$this->encodeLabels = $value;
return $this;
}
/**
* The first hyperlink in the breadcrumbs (called home link).
*
* Please refer to {@see links} on the format of the link.
*
* If this property is not set, it will default to a link pointing with the label 'Home'. If this property is false,
* the home link will not be rendered.
*
* @param array|false $value
*
* @return $this
*/
public function homeLink($value): self
{
$this->homeLink = $value;
return $this;
}
/**
* The template used to render each inactive item in the breadcrumbs. The token `{link}` will be replaced with the
* actual HTML link for each inactive item.
*
* @return $this
*/
public function itemTemplate(string $value): self
{
$this->itemTemplate = $value;
return $this;
}
/**
* List of links to appear in the breadcrumbs. If this property is empty, the widget will not render anything.
* Each array element represents a single item in the breadcrumbs with the following structure.
*
* @return $this
*/
public function links(array $value): self
{
$this->links = $value;
return $this;
}
/**
* The HTML attributes for the widgets nav container tag.
*
* {@see \yii\helpers\Html::renderTagAttributes()} for details on how attributes are being rendered.
*
* @return $this
*/
public function navOptions(array $value): self
{
$this->navOptions = $value;
return $this;
}
/**
* The HTML attributes for the widget container tag. The following special options are recognized.
*
* {@see \yii\helpers\Html::renderTagAttributes()} for details on how attributes are being rendered.
*
* @return $this
*/
public function options(array $value): self
{
$this->options = $value;
return $this;
}
/**
* The name of the breadcrumb container tag.
*
* @return $this
*/
public function tag(string $value): self
{
$this->tag = $value;
return $this;
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use yii\base\InvalidConfigException;
/**
* Button renders a bootstrap button.
*
* For example,
*
* ```php
* echo Button::widget([
* 'label' => 'Action',
* 'options' => ['class' => 'btn-lg'],
* ]);
* ```
* @see https://getbootstrap.com/docs/5.1/components/buttons/
* @author Antonio Ramirez <amigo.cobos@gmail.com>
*/
class Button extends Widget
{
/**
* @var string the tag to use to render the button
*/
public $tagName = 'button';
/**
* @var string the button label
*/
public $label = 'Button';
/**
* @var bool whether the label should be HTML-encoded.
*/
public $encodeLabel = true;
/**
* Initializes the widget.
* If you override this method, make sure you call the parent implementation first.
* @throws InvalidConfigException
*/
public function init(): void
{
parent::init();
Html::addCssClass($this->options, [
'widget' => 'btn',
]);
}
public function run(): string
{
$this->registerPlugin('button');
return Html::tag(
$this->tagName,
$this->encodeLabel ? Html::encode($this->label) : $this->label,
$this->options,
);
}
}

View File

@ -0,0 +1,227 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Throwable;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
/**
* ButtonDropdown renders a group or split button dropdown bootstrap component.
*
* For example,
*
* ```php
* // a button group using Dropdown widget
* echo ButtonDropdown::widget([
* 'label' => 'Action',
* 'dropdown' => [
* 'items' => [
* ['label' => 'DropdownA', 'url' => '/'],
* ['label' => 'DropdownB', 'url' => '#'],
* ],
* ],
* ]);
* ```
* @see https://getbootstrap.com/docs/5.1/components/buttons/
* @see https://getbootstrap.com/docs/5.1/components/dropdowns/
* @author Antonio Ramirez <amigo.cobos@gmail.com>
*/
class ButtonDropdown extends Widget
{
/**
* The css class part of dropdown
*/
public const DIRECTION_DOWN = 'down';
/**
* The css class part of dropleft
*/
public const DIRECTION_LEFT = 'left';
/**
* The css class part of dropright
*/
public const DIRECTION_RIGHT = 'right';
/**
* The css class part of dropup
*/
public const DIRECTION_UP = 'up';
/**
* @var string|null the button label
*/
public $label = null;
/**
* @var array the HTML attributes for the container tag. The following special options are recognized:
*
* - tag: string, defaults to "div", the name of the container tag.
*
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $options = [];
/**
* @var array the HTML attributes of the button.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $buttonOptions = [];
/**
* @var array the configuration array for [[Dropdown]].
*/
public $dropdown = [];
/**
* @var string the drop-direction of the widget
*
* Possible values are 'left', 'right', 'up', or 'down' (default)
*/
public $direction = self::DIRECTION_DOWN;
/**
* @var bool whether to display a group of split-styled button group.
*/
public $split = false;
/**
* @var string the tag to use to render the button
*/
public $tagName = 'button';
/**
* @var bool whether the label should be HTML-encoded.
*/
public $encodeLabel = true;
/**
* @var string name of a class to use for rendering dropdowns withing this widget. Defaults to [[Dropdown]].
*/
public $dropdownClass = Dropdown::class;
/**
* @var bool whether to render the container using the [[options]] as HTML attributes. If set to `false`,
* the container element enclosing the button and dropdown will NOT be rendered.
*/
public $renderContainer = true;
public function init(): void
{
parent::init();
if (!isset($this->buttonOptions['id'])) {
$this->buttonOptions['id'] = $this->options['id'] . '-button';
}
if ($this->label === null) {
$this->label = Yii::t('yii/bootstrap5', 'Button');
}
}
/**
* @throws Throwable
*/
public function run(): string
{
$html = $this->renderButton() . "\n" . $this->renderDropdown();
if ($this->renderContainer) {
Html::addCssClass($this->options, [
'widget' => 'drop' . $this->direction,
'btn-group',
]);
$options = $this->options;
$tag = ArrayHelper::remove($options, 'tag', 'div');
$html = Html::tag($tag, $html, $options);
}
// Set options id to button options id to ensure correct css selector in plugin initialisation
$this->options['id'] = $this->buttonOptions['id'];
$this->registerPlugin('dropdown');
return $html;
}
/**
* Generates the button dropdown.
* @return string the rendering result.
* @throws Throwable
*/
protected function renderButton(): string
{
Html::addCssClass($this->buttonOptions, [
'widget' => 'btn',
]);
$label = $this->label;
if ($this->encodeLabel) {
$label = Html::encode($label);
}
if ($this->split) {
$buttonOptions = $this->buttonOptions;
$this->buttonOptions['data'] = [
'bs-toggle' => 'dropdown',
];
$this->buttonOptions['aria'] = [
'expanded' => 'false',
];
Html::addCssClass($this->buttonOptions, [
'toggle' => 'dropdown-toggle dropdown-toggle-split',
]);
unset($buttonOptions['id']);
$splitButton = Button::widget([
'label' => '<span class="visually-hidden">' . Yii::t('yii/bootstrap5', 'Toggle Dropdown') . '</span>',
'encodeLabel' => false,
'options' => $this->buttonOptions,
'view' => $this->getView(),
]);
} else {
$buttonOptions = $this->buttonOptions;
Html::addCssClass($buttonOptions, [
'toggle' => 'dropdown-toggle',
]);
$buttonOptions['data'] = [
'bs-toggle' => 'dropdown',
];
$buttonOptions['aria'] = [
'expanded' => 'false',
];
$splitButton = '';
}
if (isset($buttonOptions['href'])) {
if (is_array($buttonOptions['href'])) {
$buttonOptions['href'] = Url::to($buttonOptions['href']);
}
} else {
if ($this->tagName === 'a') {
$buttonOptions['href'] = '#';
$buttonOptions['role'] = 'button';
}
}
return Button::widget([
'tagName' => $this->tagName,
'label' => $label,
'options' => $buttonOptions,
'clientOptions' => false,
'encodeLabel' => false,
'view' => $this->getView(),
]) . "\n" . $splitButton;
}
/**
* Generates the dropdown menu.
* @return string the rendering result.
* @throws Throwable
*/
protected function renderDropdown(): string
{
$config = $this->dropdown;
$config['clientOptions'] = [];
$config['view'] = $this->getView();
/** @var Widget $dropdownClass */
$dropdownClass = $this->dropdownClass;
return $dropdownClass::widget($config);
}
}

View File

@ -0,0 +1,116 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Throwable;
use yii\helpers\ArrayHelper;
/**
* ButtonGroup renders a button group bootstrap component.
*
* For example,
*
* ```php
* // a button group with items configuration
* echo ButtonGroup::widget([
* 'buttons' => [
* ['label' => 'A'],
* ['label' => 'B'],
* ['label' => 'C', 'visible' => false],
* ]
* ]);
*
* // button group with an item as a string
* echo ButtonGroup::widget([
* 'buttons' => [
* Button::widget(['label' => 'A']),
* ['label' => 'B'],
* ]
* ]);
* ```
*
* Pressing on the button should be handled via JavaScript. See the following for details:
*
* @see https://getbootstrap.com/docs/5.1/components/buttons/
* @see https://getbootstrap.com/docs/5.1/components/button-group/
*
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class ButtonGroup extends Widget
{
/**
* @var array list of buttons. Each array element represents a single button
* which can be specified as a string or an array of the following structure:
*
* - label: string, required, the button label.
* - options: array, optional, the HTML attributes of the button.
* - visible: bool, optional, whether this button is visible. Defaults to true.
*/
public $buttons = [];
/**
* @var bool whether to HTML-encode the button labels.
*/
public $encodeLabels = true;
public function init(): void
{
parent::init();
Html::addCssClass($this->options, [
'widget' => 'btn-group',
]);
if (!isset($this->options['role'])) {
$this->options['role'] = 'group';
}
}
/**
* @throws Throwable
*/
public function run(): string
{
BootstrapAsset::register($this->getView());
return Html::tag('div', $this->renderButtons(), $this->options);
}
/**
* Generates the buttons that compound the group as specified on [[buttons]].
* @return string the rendering result.
* @throws Throwable
*/
protected function renderButtons(): string
{
$buttons = [];
foreach ($this->buttons as $button) {
if (is_array($button)) {
$visible = ArrayHelper::remove($button, 'visible', true);
if ($visible === false) {
continue;
}
$button['view'] = $this->getView();
if (!isset($button['encodeLabel'])) {
$button['encodeLabel'] = $this->encodeLabels;
}
if (!isset($button['options'], $button['options']['type'])) {
ArrayHelper::setValue($button, 'options.type', 'button');
}
$buttons[] = Button::widget($button);
} else {
$buttons[] = $button;
}
}
return implode("\n", $buttons);
}
}

View File

@ -0,0 +1,116 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Throwable;
/**
* ButtonToolbar Combines sets of button groups into button toolbars for more complex components.
* Use utility classes as needed to space out groups, buttons, and more.
*
* For example,
*
* ```php
* // a button toolbar with items configuration
* echo ButtonToolbar::widget([
* 'buttonGroups' => [
* [
* 'buttons' => [
* ['label' => '1', 'options' => ['class' => ['btn-secondary']]],
* ['label' => '2', 'options' => ['class' => ['btn-secondary']]],
* ['label' => '3', 'options' => ['class' => ['btn-secondary']]],
* ['label' => '4', 'options' => ['class' => ['btn-secondary']]]
* ],
* 'class' => ['mr-2']
* ],
* [
* 'buttons' => [
* ['label' => '5', 'options' => ['class' => ['btn-secondary']]],
* ['label' => '6', 'options' => ['class' => ['btn-secondary']]],
* ['label' => '7', 'options' => ['class' => ['btn-secondary']]]
* ],
* 'class' => ['mr-2']
* ],
* [
* 'buttons' => [
* ['label' => '8', 'options' => ['class' => ['btn-secondary']]]
* ]
* ]
* ]
* ]);
* ```
*
* Pressing on the button should be handled via JavaScript. See the following for details:
*
* @see https://getbootstrap.com/docs/5.1/components/buttons/
* @see https://getbootstrap.com/docs/5.1/components/button-group/#button-toolbar
*
* @author Simon Karlen <simi.albi@outlook.com>
*/
class ButtonToolbar extends Widget
{
/**
* @var array list of buttons groups. Each array element represents a single group
* which can be specified as a string or an array of the following structure:
*
* - buttons: array list of buttons. Either as array or string representation
* - options: array optional, the HTML attributes of the button group.
* - encodeLabels: bool whether to HTML-encode the button labels.
*/
public $buttonGroups = [];
public function init(): void
{
parent::init();
Html::addCssClass($this->options, [
'widget' => 'btn-toolbar',
]);
if (!isset($this->options['role'])) {
$this->options['role'] = 'toolbar';
}
}
/**
* @throws Throwable
*/
public function run(): string
{
BootstrapAsset::register($this->getView());
return Html::tag('div', $this->renderButtonGroups(), $this->options);
}
/**
* Generates the button groups that compound the toolbar as specified on [[buttonGroups]].
* @return string the rendering result.
* @throws Throwable
*/
protected function renderButtonGroups(): string
{
$buttonGroups = [];
foreach ($this->buttonGroups as $group) {
if (is_array($group)) {
$group['view'] = $this->getView();
if (!isset($group['buttons'])) {
continue;
}
$buttonGroups[] = ButtonGroup::widget($group);
} else {
$buttonGroups[] = $group;
}
}
return implode("\n", $buttonGroups);
}
}

View File

@ -0,0 +1,240 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Exception;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
/**
* Carousel renders a carousel bootstrap javascript component.
*
* For example:
*
* ```php
* echo Carousel::widget([
* 'items' => [
* // the item contains only the image
* '<img src="https://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-01.jpg"/>',
* // equivalent to the above
* ['content' => '<img src="https://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-02.jpg"/>'],
* // the item contains both the image and the caption
* [
* 'content' => '<img src="https://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-03.jpg"/>',
* 'caption' => '<h4>This is title</h4><p>This is the caption text</p>',
* 'captionOptions' => ['class' => ['d-none', 'd-md-block']]
* 'options' => [...],
* ],
* ]
* ]);
* ```
*
* @see https://getbootstrap.com/docs/5.1/components/carousel/
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class Carousel extends Widget
{
/**
* @var array|null the labels for the previous and the next control buttons.
* If null, it means the previous and the next control buttons should not be displayed.
*/
public $controls = [
'<span class="carousel-control-prev-icon" aria-hidden="true"></span><span class="visually-hidden">Previous</span>',
'<span class="carousel-control-next-icon" aria-hidden="true"></span><span class="visually-hidden">Next</span>',
];
/**
* @var bool whether carousel indicators (<ol> tag with anchors to items) should be displayed or not.
*/
public $showIndicators = true;
/**
* @var array list of slides in the carousel. Each array element represents a single
* slide with the following structure:
*
* ```php
* [
* // required, slide content (HTML), such as an image tag
* 'content' => '<img src="https://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-01.jpg"/>',
* // optional, the caption (HTML) of the slide
* 'caption' => '<h4>This is title</h4><p>This is the caption text</p>',
* // optional the HTML attributes of the slide container
* 'options' => [],
* ]
* ```
*/
public $items = [];
/**
* @var bool Animate slides with a fade transition instead of a slide. Defaults to `false`
*/
public $crossfade = false;
public $options = [
'data' => [
'bs-ride' => 'carousel',
],
];
/**
* @throws InvalidConfigException
*/
public function init(): void
{
parent::init();
Html::addCssClass($this->options, [
'widget' => 'carousel slide',
]);
if ($this->crossfade) {
Html::addCssClass($this->options, [
'animation' => 'carousel-fade',
]);
}
}
/**
* @throws InvalidConfigException
*/
public function run(): string
{
$this->registerPlugin('carousel');
return implode("\n", [
Html::beginTag('div', $this->options),
$this->renderIndicators(),
$this->renderItems(),
$this->renderControls(),
Html::endTag('div'),
]) . "\n";
}
/**
* Renders carousel indicators.
* @return string the rendering result
*/
public function renderIndicators(): string
{
if ($this->showIndicators === false) {
return '';
}
$indicators = [];
for ($i = 0, $count = count($this->items); $i < $count; $i++) {
$options = [
'data' => [
'bs-target' => '#' . $this->options['id'],
'bs-slide-to' => $i,
],
'type' => 'button',
];
if ($i === 0) {
Html::addCssClass($options, [
'activate' => 'active',
]);
$options['aria']['current'] = 'true';
}
$indicators[] = Html::tag('button', '', $options);
}
return Html::tag('div', implode("\n", $indicators), [
'class' => ['carousel-indicators'],
]);
}
/**
* Renders carousel items as specified on [[items]].
* @return string the rendering result
* @throws InvalidConfigException
*/
public function renderItems(): string
{
$items = [];
for ($i = 0, $count = count($this->items); $i < $count; $i++) {
$items[] = $this->renderItem($this->items[$i], $i);
}
return Html::tag('div', implode("\n", $items), [
'class' => 'carousel-inner',
]);
}
/**
* Renders a single carousel item
* @param string|array $item a single item from [[items]]
* @param int $index the item index as the first item should be set to `active`
* @return string the rendering result
* @throws InvalidConfigException if the item is invalid
* @throws Exception
*/
public function renderItem($item, int $index): string
{
if (is_string($item)) {
$content = $item;
$caption = null;
$options = [];
} elseif (isset($item['content'])) {
$content = $item['content'];
$caption = ArrayHelper::getValue($item, 'caption');
if ($caption !== null) {
$captionOptions = ArrayHelper::remove($item, 'captionOptions', []);
Html::addCssClass($captionOptions, [
'widget' => 'carousel-caption',
]);
$caption = Html::tag('div', $caption, $captionOptions);
}
$options = ArrayHelper::getValue($item, 'options', []);
} else {
throw new InvalidConfigException('The "content" option is required.');
}
Html::addCssClass($options, [
'widget' => 'carousel-item',
]);
if ($index === 0) {
Html::addCssClass($options, [
'activate' => 'active',
]);
}
return Html::tag('div', $content . "\n" . $caption, $options);
}
/**
* Renders previous and next control buttons.
*
* @return string The rendered controls
*
* @throws InvalidConfigException if [[controls]] is invalid.
*/
public function renderControls(): string
{
if (isset($this->controls[0], $this->controls[1])) {
return Html::button($this->controls[0], [
'class' => 'carousel-control-prev',
'data' => [
'bs-target' => '#' . $this->options['id'],
'bs-slide' => 'prev',
],
'type' => 'button',
]) . "\n"
. Html::button($this->controls[1], [
'class' => 'carousel-control-next',
'data' => [
'bs-target' => '#' . $this->options['id'],
'bs-slide' => 'next',
],
'type' => 'button',
]);
} elseif ($this->controls === false) {
return '';
} else {
throw new InvalidConfigException('The "controls" property must be either false or an array of two elements.');
}
}
}

View File

@ -0,0 +1,190 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Exception;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
/**
* Dropdown renders a Bootstrap dropdown menu component.
*
* For example,
*
* ```php
* <div class="dropdown">
* <a href="#" data-bs-toggle="dropdown" class="dropdown-toggle">Label <b class="caret"></b></a>
* <?php
* echo Dropdown::widget([
* 'items' => [
* ['label' => 'DropdownA', 'url' => '/'],
* ['label' => 'DropdownB', 'url' => '#'],
* ],
* ]);
* ?>
* </div>
* ```
* @see https://getbootstrap.com/docs/5.1/components/dropdowns/
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class Dropdown extends Widget
{
/**
* @var array list of menu items in the dropdown. Each array element can be either an HTML string,
* or an array representing a single menu with the following structure:
*
* - label: string, required, the label of the item link.
* - encode: bool, optional, whether to HTML-encode item label.
* - url: string|array, optional, the URL of the item link. This will be processed by [[\yii\helpers\Url::to()]].
* If not set, the item will be treated as a menu header when the item has no sub-menu.
* - visible: bool, optional, whether this menu item is visible. Defaults to true.
* - disabled: bool, optional, whether this menu item is disabled. Defaults to false.
* - linkOptions: array, optional, the HTML attributes of the item link.
* - options: array, optional, the HTML attributes of the item.
* - active: bool, optional, whether the item should be on active state or not.
* - items: array, optional, the submenu items. The structure is the same as this property.
* Note that Bootstrap doesn't support dropdown submenu. You have to add your own CSS styles to support it.
* - submenuOptions: array, optional, the HTML attributes for sub-menu container tag. If specified it will be
* merged with [[submenuOptions]].
*
* To insert divider use `-`.
*/
public $items = [];
/**
* @var bool whether the labels for header items should be HTML-encoded.
*/
public $encodeLabels = true;
/**
* @var array|null the HTML attributes for sub-menu container tags.
*/
public $submenuOptions = [];
public function init(): void
{
parent::init();
Html::addCssClass($this->options, [
'widget' => 'dropdown-menu',
]);
}
/**
* Renders the widget.
* @throws InvalidConfigException
*/
public function run(): string
{
BootstrapPluginAsset::register($this->getView());
$this->registerClientEvents('dropdown');
return $this->renderItems($this->items, $this->options);
}
/**
* Renders menu items.
* @param array $items the menu items to be rendered
* @param array $options the container HTML attributes
* @return string the rendering result.
* @throws InvalidConfigException if the label option is not specified in one of the items.
* @throws Exception
*/
protected function renderItems(array $items, array $options = []): string
{
$lines = [];
foreach ($items as $item) {
if (is_string($item)) {
$lines[] = ($item === '-')
? Html::tag('hr', '', [
'class' => 'dropdown-divider',
])
: $item;
continue;
}
if (isset($item['visible']) && !$item['visible']) {
continue;
}
if (!array_key_exists('label', $item)) {
throw new InvalidConfigException("The 'label' option is required.");
}
$encodeLabel = $item['encode'] ?? $this->encodeLabels;
$label = $encodeLabel ? Html::encode($item['label']) : $item['label'];
$itemOptions = ArrayHelper::getValue($item, 'options', []);
$linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
$active = ArrayHelper::getValue($item, 'active', false);
$disabled = ArrayHelper::getValue($item, 'disabled', false);
Html::addCssClass($linkOptions, [
'widget' => 'dropdown-item',
]);
if ($disabled) {
ArrayHelper::setValue($linkOptions, 'tabindex', '-1');
ArrayHelper::setValue($linkOptions, 'aria.disabled', 'true');
Html::addCssClass($linkOptions, [
'disable' => 'disabled',
]);
} elseif ($active) {
ArrayHelper::setValue($linkOptions, 'aria.current', 'true');
Html::addCssClass($linkOptions, [
'activate' => 'active',
]);
}
$url = array_key_exists('url', $item) ? $item['url'] : null;
if (empty($item['items'])) {
if ($url === null) {
$content = Html::tag('h6', $label, [
'class' => 'dropdown-header',
]);
} else {
$content = Html::a($label, $url, $linkOptions);
}
$lines[] = $content;
} else {
$submenuOptions = $this->submenuOptions;
if (isset($item['submenuOptions'])) {
$submenuOptions = array_merge($submenuOptions, $item['submenuOptions']);
}
Html::addCssClass($submenuOptions, [
'widget' => 'dropdown-submenu dropdown-menu',
]);
Html::addCssClass($linkOptions, [
'toggle' => 'dropdown-toggle',
]);
$lines[] = Html::beginTag('div', array_merge_recursive([
'class' => ['dropdown'],
'aria' => [
'expanded' => 'false',
],
], $itemOptions));
$lines[] = Html::a($label, $url, array_merge_recursive([
'data' => [
'bs-toggle' => 'dropdown',
],
'aria' => [
'expanded' => 'false',
],
'role' => 'button',
], $linkOptions));
$lines[] = static::widget([
'items' => $item['items'],
'options' => $submenuOptions,
'submenuOptions' => $submenuOptions,
'encodeLabels' => $this->encodeLabels,
]);
$lines[] = Html::endTag('div');
}
}
return Html::tag('div', implode("\n", $lines), $options);
}
}

View File

@ -0,0 +1,13 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
class Html extends BaseHtml {}

View File

@ -0,0 +1,16 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
abstract class InputWidget extends \yii\widgets\InputWidget
{
use BootstrapWidgetTrait;
}

View File

@ -0,0 +1,336 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use yii\base\InvalidConfigException;
use yii\data\Pagination;
use yii\helpers\ArrayHelper;
/**
* LinkPager represents a Bootstrap 5 version of [[\yii\widgets\LinkPager]]. It displays a list of hyperlinks
* that lead to different pages of target.
*
* LinkPager works with a [[\yii\widget\Pagination]] object which specifies the total number
* of pages and the current page number.
*
* To apply LinkPager globally e.g. in all GridViews, set in configuration DI:
*
* ```php
* 'container' => [
* 'definitions' => [
* \yii\widgets\LinkPager::class => \yii\bootstrap5\LinkPager::class,
* ],
* ],
* ```
*
* @see https://getbootstrap.com/docs/5.1/components/pagination/
* @author Simon Karlen <simi.albi@outlook.com>
* @since 2.0.2
*
* @property-read array $pageRange
*/
class LinkPager extends Widget
{
/**
* @var Pagination the pagination object that this pager is associated with.
* You must set this property in order to make LinkPager work.
*/
public $pagination;
/**
* @var array HTML attributes for the pager container tag.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $options = [];
/**
* @var array HTML attributes for the pager list tag.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $listOptions = [
'class' => ['pagination'],
];
/**
* @var array HTML attributes which will be applied to all link containers
*/
public $linkContainerOptions = [
'class' => ['page-item'],
];
/**
* @var array HTML attributes for the link in a pager container tag.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $linkOptions = [
'class' => ['page-link'],
];
/**
* @var string the CSS class for the each page button.
*/
public $pageCssClass = 'page-item';
/**
* @var string the CSS class for the "first" page button.
*/
public $firstPageCssClass = 'first';
/**
* @var string the CSS class for the "last" page button.
*/
public $lastPageCssClass = 'last';
/**
* @var string the CSS class for the "previous" page button.
*/
public $prevPageCssClass = 'prev';
/**
* @var string the CSS class for the "next" page button.
*/
public $nextPageCssClass = 'next';
/**
* @var string the CSS class for the active (currently selected) page button.
*/
public $activePageCssClass = 'active';
/**
* @var string the CSS class for the disabled page buttons.
*/
public $disabledPageCssClass = 'disabled';
/**
* @var array the options for the disabled tag to be generated inside the disabled list element.
* In order to customize the html tag, please use the tag key.
*
* ```php
* $disabledListItemSubTagOptions = ['class' => 'disabled-link'];
* ```
*/
public $disabledListItemSubTagOptions = [];
/**
* @var int maximum number of page buttons that can be displayed. Defaults to 10.
*/
public $maxButtonCount = 10;
/**
* @var string|bool the label for the "next" page button. Note that this will NOT be HTML-encoded.
* If this property is false, the "next" page button will not be displayed.
*/
public $nextPageLabel = '<span aria-hidden="true">&raquo;</span>';
/**
* @var string|bool the text label for the "previous" page button. Note that this will NOT be HTML-encoded.
* If this property is false, the "previous" page button will not be displayed.
*/
public $prevPageLabel = '<span aria-hidden="true">&laquo;</span>';
/**
* @var string|bool the text label for the "first" page button. Note that this will NOT be HTML-encoded.
* If it's specified as true, page number will be used as label.
* Default is false that means the "first" page button will not be displayed.
*/
public $firstPageLabel = false;
/**
* @var string|bool the text label for the "last" page button. Note that this will NOT be HTML-encoded.
* If it's specified as true, page number will be used as label.
* Default is false that means the "last" page button will not be displayed.
*/
public $lastPageLabel = false;
/**
* @var bool whether to register link tags in the HTML header for prev, next, first and last page.
* Defaults to `false` to avoid conflicts when multiple pagers are used on one page.
* @see https://www.w3.org/TR/html401/struct/links.html#h-12.1.2
* @see registerLinkTags()
*/
public $registerLinkTags = false;
/**
* @var bool Hide widget when only one page exist.
*/
public $hideOnSinglePage = true;
/**
* @var bool whether to render current page button as disabled.
*/
public $disableCurrentPageButton = false;
/**
* Initializes the pager.
* @throws InvalidConfigException
*/
public function init(): void
{
parent::init();
if ($this->pagination === null) {
throw new InvalidConfigException('The "pagination" property must be set.');
}
}
/**
* Executes the widget.
* This overrides the parent implementation by displaying the generated page buttons.
*/
public function run(): string
{
if ($this->registerLinkTags) {
$this->registerLinkTags();
}
$options = $this->options;
$tag = ArrayHelper::remove($options, 'tag', 'nav');
$html = Html::beginTag($tag, $options);
$html .= $this->renderPageButtons();
$html .= Html::endTag($tag);
return $html;
}
/**
* Registers relational link tags in the html header for prev, next, first and last page.
* These links are generated using [[\yii\data\Pagination::getLinks()]].
* @see https://www.w3.org/TR/html401/struct/links.html#h-12.1.2
*/
protected function registerLinkTags(): void
{
$view = $this->getView();
foreach ($this->pagination->getLinks() as $rel => $href) {
$view->registerLinkTag([
'rel' => $rel,
'href' => $href,
], $rel);
}
}
/**
* Renders the page buttons.
* @return string the rendering result
*/
protected function renderPageButtons(): string
{
$pageCount = $this->pagination->getPageCount();
if ($pageCount < 2 && $this->hideOnSinglePage) {
return '';
}
$buttons = [];
$currentPage = $this->pagination->getPage();
// first page
$firstPageLabel = $this->firstPageLabel === true ? '1' : $this->firstPageLabel;
if ($firstPageLabel !== false) {
$buttons[] = $this->renderPageButton(
$firstPageLabel,
0,
$this->firstPageCssClass,
$currentPage <= 0,
false,
);
}
// prev page
if ($this->prevPageLabel !== false) {
if (($page = $currentPage - 1) < 0) {
$page = 0;
}
$buttons[] = $this->renderPageButton(
$this->prevPageLabel,
$page,
$this->prevPageCssClass,
$currentPage <= 0,
false,
);
}
// internal pages
list($beginPage, $endPage) = $this->getPageRange();
for ($i = $beginPage; $i <= $endPage; ++$i) {
$buttons[] = $this->renderPageButton(
(string) ($i + 1),
$i,
'',
$this->disableCurrentPageButton && $i === $currentPage,
$i === $currentPage,
);
}
// next page
if ($this->nextPageLabel !== false) {
if (($page = $currentPage + 1) >= $pageCount - 1) {
$page = $pageCount - 1;
}
$buttons[] = $this->renderPageButton(
$this->nextPageLabel,
$page,
$this->nextPageCssClass,
$currentPage >= $pageCount - 1,
false,
);
}
// last page
$lastPageLabel = $this->lastPageLabel === true ? $pageCount : $this->lastPageLabel;
if ($lastPageLabel !== false) {
$buttons[] = $this->renderPageButton(
(string) $lastPageLabel,
$pageCount - 1,
$this->lastPageCssClass,
$currentPage >= $pageCount - 1,
false,
);
}
$options = $this->listOptions;
$tag = ArrayHelper::remove($options, 'tag', 'ul');
return Html::tag($tag, implode("\n", $buttons), $options);
}
/**
* Renders a page button.
* You may override this method to customize the generation of page buttons.
* @param string $label the text label for the button
* @param int $page the page number
* @param string $class the CSS class for the page button.
* @param bool $disabled whether this page button is disabled
* @param bool $active whether this page button is active
* @return string the rendering result
*/
protected function renderPageButton(string $label, int $page, string $class, bool $disabled, bool $active): string
{
$options = $this->linkContainerOptions;
$linkWrapTag = ArrayHelper::remove($options, 'tag', 'li');
Html::addCssClass($options, $class ?: $this->pageCssClass);
$linkOptions = $this->linkOptions;
$linkOptions['data']['page'] = $page;
if ($active) {
$options['aria'] = [
'current' => 'page',
];
Html::addCssClass($options, $this->activePageCssClass);
}
if ($disabled) {
Html::addCssClass($options, $this->disabledPageCssClass);
$disabledItemOptions = $this->disabledListItemSubTagOptions;
$linkOptions = ArrayHelper::merge($linkOptions, $disabledItemOptions);
$linkOptions['tabindex'] = '-1';
}
return Html::tag($linkWrapTag, Html::a($label, $this->pagination->createUrl($page), $linkOptions), $options);
}
/**
* @return array the begin and end pages that need to be displayed.
*/
protected function getPageRange(): array
{
$currentPage = $this->pagination->getPage();
$pageCount = $this->pagination->getPageCount();
$beginPageOffset = $this->maxButtonCount > 2 ? (int) ($this->maxButtonCount / 2) : 0;
$beginPage = max(0, $currentPage - $beginPageOffset);
if (($endPage = $beginPage + $this->maxButtonCount - 1) >= $pageCount) {
$endPage = $pageCount - 1;
$beginPage = max(0, $endPage - $this->maxButtonCount + 1);
}
return [$beginPage, $endPage];
}
}

View File

@ -0,0 +1,354 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
/**
* Modal renders a modal window that can be toggled by clicking on a button.
*
* The following example will show the content enclosed between the [[begin()]]
* and [[end()]] calls within the modal window:
*
* ~~~php
* Modal::begin([
* 'title' => 'Hello world',
* 'toggleButton' => ['label' => 'click me'],
* ]);
*
* echo 'Say hello...';
*
* Modal::end();
* ~~~
*
* @see https://getbootstrap.com/docs/5.1/components/modal/
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Simon Karlen <simi.albi@outlook.com>
*/
class Modal extends Widget
{
/**
* The additional css class of extra large modal
* @since 2.0.3
*/
public const SIZE_EXTRA_LARGE = 'modal-xl';
/**
* The additional css class of large modal
*/
public const SIZE_LARGE = 'modal-lg';
/**
* The additional css class of small modal
*/
public const SIZE_SMALL = 'modal-sm';
/**
* The additional css class of default modal
*/
public const SIZE_DEFAULT = '';
/**
* @var string the title content in the modal window.
*/
public $title;
/**
* @var array additional title options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $titleOptions = [];
/**
* @var array additional header options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $headerOptions = [];
/**
* @var array body options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $bodyOptions = [];
/**
* @var string|null the footer content in the modal window.
*/
public $footer;
/**
* @var array additional footer options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $footerOptions = [];
/**
* @var string|null the modal size. Can be [[SIZE_LARGE]] or [[SIZE_SMALL]], or empty for default.
*/
public $size;
/**
* @var array|false the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking
* on the button will hide the modal window. If this is false, no close button will be rendered.
*
* The following special options are supported:
*
* - tag: string, the tag name of the button. Defaults to 'button'.
*
* The rest of the options will be rendered as the HTML attributes of the button tag.
* Please refer to the [Modal plugin help](https://getbootstrap.com/javascript/#modals)
* for the supported HTML attributes.
*/
public $closeButton = [];
/**
* @var array|false the options for rendering the toggle button tag.
* The toggle button is used to toggle the visibility of the modal window.
* If this property is false, no toggle button will be rendered.
*
* The following special options are supported:
*
* - tag: string, the tag name of the button. Defaults to 'button'.
* - label: string, the label of the button. Defaults to 'Show'.
*
* The rest of the options will be rendered as the HTML attributes of the button tag.
* Please refer to the [Modal plugin help](https://getbootstrap.com/javascript/#modals)
* for the supported HTML attributes.
*/
public $toggleButton = false;
/**
* @var boolean whether to center the modal vertically
*
* When true the modal-dialog-centered class will be added to the modal-dialog
* @since 2.0.9
*/
public $centerVertical = false;
/**
* @var boolean whether to make the modal body scrollable
*
* When true the modal-dialog-scrollable class will be added to the modal-dialog
* @since 2.0.9
*/
public $scrollable = false;
/**
* @var array modal dialog options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
* @since 2.0.9
*/
public $dialogOptions = [];
/**
* @throws InvalidConfigException
*/
public function init(): void
{
parent::init();
$this->initOptions();
ob_start();
echo $this->renderToggleButton() . "\n";
echo Html::beginTag('div', $this->options) . "\n";
echo Html::beginTag('div', $this->dialogOptions) . "\n";
echo Html::beginTag('div', [
'class' => 'modal-content',
]) . "\n";
echo $this->renderHeader() . "\n";
echo $this->renderBodyBegin() . "\n";
}
/**
* Renders the widget.
*/
public function run(): string
{
$content = ob_get_clean();
$content .= "\n" . $this->renderBodyEnd();
$content .= "\n" . $this->renderFooter();
$content .= "\n" . Html::endTag('div'); // modal-content
$content .= "\n" . Html::endTag('div'); // modal-dialog
$content .= "\n" . Html::endTag('div');
$this->registerPlugin('modal');
return $content;
}
/**
* Renders the header HTML markup of the modal
* @return string the rendering result
*/
protected function renderHeader(): string
{
$button = $this->renderCloseButton();
if (isset($this->title)) {
Html::addCssClass($this->titleOptions, [
'widget' => 'modal-title',
]);
$header = Html::tag('h5', $this->title, $this->titleOptions);
} else {
$header = '';
}
if ($button !== null) {
$header .= "\n" . $button;
} elseif ($header === '') {
return '';
}
Html::addCssClass($this->headerOptions, [
'widget' => 'modal-header',
]);
return Html::tag('div', "\n" . $header . "\n", $this->headerOptions);
}
/**
* Renders the opening tag of the modal body.
* @return string the rendering result
*/
protected function renderBodyBegin(): string
{
Html::addCssClass($this->bodyOptions, [
'widget' => 'modal-body',
]);
return Html::beginTag('div', $this->bodyOptions);
}
/**
* Renders the closing tag of the modal body.
* @return string the rendering result
*/
protected function renderBodyEnd(): string
{
return Html::endTag('div');
}
/**
* Renders the HTML markup for the footer of the modal
* @return string|null the rendering result
*/
protected function renderFooter(): ?string
{
if (isset($this->footer)) {
Html::addCssClass($this->footerOptions, [
'widget' => 'modal-footer',
]);
return Html::tag('div', "\n" . $this->footer . "\n", $this->footerOptions);
} else {
return null;
}
}
/**
* Renders the toggle button.
* @return string|null the rendering result
*/
protected function renderToggleButton(): ?string
{
if (($toggleButton = $this->toggleButton) !== false) {
$tag = ArrayHelper::remove($toggleButton, 'tag', 'button');
$label = ArrayHelper::remove($toggleButton, 'label', 'Show');
return Html::tag($tag, $label, $toggleButton);
} else {
return null;
}
}
/**
* Renders the close button.
* @return string|null the rendering result
*/
protected function renderCloseButton(): ?string
{
if (($closeButton = $this->closeButton) !== false) {
$tag = ArrayHelper::remove($closeButton, 'tag', 'button');
$label = ArrayHelper::remove($closeButton, 'label', '');
if ($tag === 'button' && !isset($closeButton['type'])) {
$closeButton['type'] = 'button';
}
return Html::tag($tag, $label, $closeButton);
} else {
return null;
}
}
/**
* Initializes the widget options.
* This method sets the default values for various options.
*/
protected function initOptions(): void
{
$this->options = array_merge([
'tabindex' => -1,
'aria-hidden' => 'true',
], $this->options);
Html::addCssClass($this->options, [
'widget' => 'modal fade',
]);
if (!empty($this->clientOptions)) {
$this->clientOptions = array_merge([
'show' => false,
], $this->clientOptions);
}
$this->titleOptions = array_merge([
'id' => $this->options['id'] . '-label',
], $this->titleOptions);
if (!isset($this->options['aria']['label'], $this->options['aria']['labelledby']) && isset($this->title)) {
$this->options['aria']['labelledby'] = $this->titleOptions['id'];
}
if ($this->closeButton !== false) {
$this->closeButton = array_merge([
'class' => [
'widget' => 'btn-close',
],
'data' => [
'bs-dismiss' => 'modal',
],
'aria' => [
'label' => Yii::t('yii/bootstrap5', 'Close'),
],
], $this->closeButton);
}
if ($this->toggleButton !== false) {
$this->toggleButton = array_merge([
'data' => [
'bs-toggle' => 'modal',
],
'type' => 'button',
], $this->toggleButton);
if (!isset($this->toggleButton['data']['bs-target']) && !isset($this->toggleButton['href'])) {
$this->toggleButton['data']['bs-target'] = '#' . $this->options['id'];
}
}
Html::addCssClass($this->dialogOptions, [
'widget' => 'modal-dialog',
]);
if (isset($this->size)) {
Html::addCssClass($this->dialogOptions, [
'size' => $this->size,
]);
}
if ($this->centerVertical) {
Html::addCssClass($this->dialogOptions, [
'align' => 'modal-dialog-centered',
]);
}
if ($this->scrollable) {
Html::addCssClass($this->dialogOptions, [
'scroll' => 'modal-dialog-scrollable',
]);
}
}
}

View File

@ -0,0 +1,318 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Exception;
use Throwable;
use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
/**
* Nav renders a nav HTML component.
*
* For example:
*
* ```php
* echo Nav::widget([
* 'items' => [
* [
* 'label' => 'Home',
* 'url' => ['site/index'],
* 'linkOptions' => [...],
* ],
* [
* 'label' => 'Dropdown',
* 'items' => [
* ['label' => 'Level 1 - Dropdown A', 'url' => '#'],
* '<div class="dropdown-divider"></div>',
* '<div class="dropdown-header">Dropdown Header</div>',
* ['label' => 'Level 1 - Dropdown B', 'url' => '#'],
* ],
* ],
* [
* 'label' => 'Login',
* 'url' => ['site/login'],
* 'visible' => Yii::$app->user->isGuest
* ],
* ],
* 'options' => ['class' =>'nav-pills'], // set this to nav-tabs to get tab-styled navigation
* ]);
* ```
*
* Note: Multilevel dropdowns beyond Level 1 are not supported in Bootstrap 5.
*
* @see https://getbootstrap.com/docs/5.1/components/navs/
* @see https://getbootstrap.com/docs/5.1/components/dropdowns/
*
* @author Antonio Ramirez <amigo.cobos@gmail.com>
*/
class Nav extends Widget
{
/**
* @var array list of items in the nav widget. Each array element represents a single
* menu item which can be either a string or an array with the following structure:
*
* - label: string, required, the nav item label.
* - url: optional, the item's URL. Defaults to "#".
* - visible: bool, optional, whether this menu item is visible. Defaults to true.
* - disabled: bool, optional, whether this menu item is disabled. Defaults to false.
* - linkOptions: array, optional, the HTML attributes of the item's link.
* - options: array, optional, the HTML attributes of the item container (LI).
* - active: bool, optional, whether the item should be on active state or not.
* - dropdownOptions: array, optional, the HTML options that will passed to the [[Dropdown]] widget.
* - items: array|string, optional, the configuration array for creating a [[Dropdown]] widget,
* or a string representing the dropdown menu. Note that Bootstrap does not support sub-dropdown menus.
* - encode: bool, optional, whether the label will be HTML-encoded. If set, supersedes the $encodeLabels option for only this item.
*
* If a menu item is a string, it will be rendered directly without HTML encoding.
*/
public $items = [];
/**
* @var bool whether the nav items labels should be HTML-encoded.
*/
public $encodeLabels = true;
/**
* @var bool whether to automatically activate items according to whether their route setting
* matches the currently requested route.
* @see isItemActive
*/
public $activateItems = true;
/**
* @var bool whether to activate parent menu items when one of the corresponding child menu items is active.
*/
public $activateParents = false;
/**
* @var string|null the route used to determine if a menu item is active or not.
* If not set, it will use the route of the current request.
* @see params
* @see isItemActive
*/
public $route = null;
/**
* @var array|null the parameters used to determine if a menu item is active or not.
* If not set, it will use `$_GET`.
* @see route
* @see isItemActive
*/
public $params = null;
/**
* @var string name of a class to use for rendering dropdowns within this widget. Defaults to [[Dropdown]].
*/
public $dropdownClass = Dropdown::class;
public function init(): void
{
parent::init();
if ($this->route === null && Yii::$app->controller !== null) {
$this->route = Yii::$app->controller->getRoute();
}
if ($this->params === null) {
$this->params = Yii::$app->request->getQueryParams();
}
Html::addCssClass($this->options, [
'widget' => 'nav',
]);
}
/**
* Renders the widget.
* @throws InvalidConfigException|Throwable
*/
public function run(): string
{
BootstrapAsset::register($this->getView());
return $this->renderItems();
}
/**
* Renders widget items.
* @throws InvalidConfigException|Throwable
*/
public function renderItems(): string
{
$items = [];
foreach ($this->items as $item) {
if (isset($item['visible']) && !$item['visible']) {
continue;
}
$items[] = $this->renderItem($item);
}
return Html::tag('ul', implode("\n", $items), $this->options);
}
/**
* Renders a widget's item.
* @param string|array $item the item to render.
* @return string the rendering result.
* @throws InvalidConfigException
* @throws Throwable
*/
public function renderItem($item): string
{
if (is_string($item)) {
return $item;
}
if (!isset($item['label'])) {
throw new InvalidConfigException("The 'label' option is required.");
}
$encodeLabel = $item['encode'] ?? $this->encodeLabels;
$label = $encodeLabel ? Html::encode($item['label']) : $item['label'];
$options = ArrayHelper::getValue($item, 'options', []);
$items = ArrayHelper::getValue($item, 'items');
$url = ArrayHelper::getValue($item, 'url', '#');
$linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
$disabled = ArrayHelper::getValue($item, 'disabled', false);
$active = $this->isItemActive($item);
if (empty($items)) {
$items = '';
Html::addCssClass($options, [
'widget' => 'nav-item',
]);
Html::addCssClass($linkOptions, [
'widget' => 'nav-link',
]);
} else {
$linkOptions['data']['bs-toggle'] = 'dropdown';
$linkOptions['role'] = 'button';
$linkOptions['aria']['expanded'] = 'false';
Html::addCssClass($options, [
'widget' => 'dropdown nav-item',
]);
Html::addCssClass($linkOptions, [
'widget' => 'dropdown-toggle nav-link',
]);
if (is_array($items)) {
$items = $this->isChildActive($items, $active);
$items = $this->renderDropdown($items, $item);
}
}
if ($disabled) {
ArrayHelper::setValue($linkOptions, 'tabindex', '-1');
ArrayHelper::setValue($linkOptions, 'aria.disabled', 'true');
Html::addCssClass($linkOptions, [
'disable' => 'disabled',
]);
} elseif ($this->activateItems && $active) {
Html::addCssClass($linkOptions, [
'activate' => 'active',
]);
}
return Html::tag('li', Html::a($label, $url, $linkOptions) . $items, $options);
}
/**
* Renders the given items as a dropdown.
* This method is called to create sub-menus.
* @param array $items the given items. Please refer to [[Dropdown::items]] for the array structure.
* @param array $parentItem the parent item information. Please refer to [[items]] for the structure of this array.
* @return string the rendering result.
* @throws Throwable
*/
protected function renderDropdown(array $items, array $parentItem): string
{
/** @var Widget $dropdownClass */
$dropdownClass = $this->dropdownClass;
return $dropdownClass::widget([
'options' => ArrayHelper::getValue($parentItem, 'dropdownOptions', []),
'items' => $items,
'encodeLabels' => $this->encodeLabels,
'clientOptions' => [],
'view' => $this->getView(),
]);
}
/**
* Check to see if a child item is active optionally activating the parent.
* @param array $items @see items
* @param bool $active should the parent be active too
* @throws Exception
* @see items
*/
protected function isChildActive(array $items, bool &$active): array
{
foreach ($items as $i => $child) {
if (is_array($child) && !ArrayHelper::getValue($child, 'visible', true)) {
continue;
}
if (is_array($child) && $this->isItemActive($child)) {
ArrayHelper::setValue($items[$i], 'active', true);
if ($this->activateParents) {
$active = true;
}
}
$childItems = ArrayHelper::getValue($child, 'items');
if (is_array($childItems)) {
$activeParent = false;
$items[$i]['items'] = $this->isChildActive($childItems, $activeParent);
if ($activeParent) {
Html::addCssClass($items[$i]['options'], [
'activate' => 'active',
]);
$active = true;
}
}
}
return $items;
}
/**
* Checks whether a menu item is active.
* This is done by checking if [[route]] and [[params]] match that specified in the `url` option of the menu item.
* When the `url` option of a menu item is specified in terms of an array, its first element is treated
* as the route for the item and the rest of the elements are the associated parameters.
* Only when its route and parameters match [[route]] and [[params]], respectively, will a menu item
* be considered active.
* @param array $item the menu item to be checked
* @return bool whether the menu item is active
* @throws Exception
*/
protected function isItemActive(array $item): bool
{
if (!$this->activateItems) {
return false;
}
if (isset($item['active'])) {
return (bool) ArrayHelper::getValue($item, 'active', false);
}
if (isset($item['url']) && is_array($item['url']) && isset($item['url'][0])) {
$route = $item['url'][0];
if ($route[0] !== '/' && Yii::$app->controller) {
$route = Yii::$app->controller->module->getUniqueId() . '/' . $route;
}
if (ltrim($route, '/') !== $this->route) {
return false;
}
unset($item['url']['#']);
if (count($item['url']) > 1) {
$params = $item['url'];
unset($params[0]);
foreach ($params as $name => $value) {
if ($value !== null && (!isset($this->params[$name]) || $this->params[$name] !== $value)) {
return false;
}
}
}
return true;
}
return false;
}
}

View File

@ -0,0 +1,262 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/
declare(strict_types=1);
namespace yii\bootstrap5;
use Yii;
use yii\helpers\ArrayHelper;
/**
* NavBar renders a navbar HTML component.
*
* Any content enclosed between the [[begin()]] and [[end()]] calls of NavBar
* is treated as the content of the navbar. You may use widgets such as [[Nav]]
* or [[\yii\widgets\Menu]] to build up such content. For example,
*
* ```php
* use yii\bootstrap5\NavBar;
* use yii\bootstrap5\Nav;
*
* NavBar::begin(['brandLabel' => 'NavBar Test']);
* echo Nav::widget([
* 'items' => [
* ['label' => 'Home', 'url' => ['/site/index']],
* ['label' => 'About', 'url' => ['/site/about']],
* ],
* 'options' => ['class' => 'navbar-nav'],
* ]);
* NavBar::end();
* ```
*
* @property-write array $containerOptions
*
* @see https://getbootstrap.com/docs/5.1/components/navbar/
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @author Alexander Kochetov <creocoder@gmail.com>
*/
class NavBar extends Widget
{
/**
* @var array the HTML attributes for the widget container tag. The following special options are recognized:
*
* - tag: string, defaults to "nav", the name of the container tag.
*
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $options = [];
/**
* @var array|bool the HTML attributes for the collapse container tag. The following special options are recognized:
*
* - tag: string, defaults to "div", the name of the container tag.
*
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $collapseOptions = [];
/**
* @var array|bool the HTML attributes for the offcanvas container tag.
*
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $offcanvasOptions = false;
/**
* @var string|bool the text of the brand or false if it's not used. Note that this is not HTML-encoded.
* @see https://getbootstrap.com/docs/5.1/components/navbar/
*/
public $brandLabel = false;
/**
* @var string|bool src of the brand image or false if it's not used. Note that this param will override `$this->brandLabel` param.
* @see https://getbootstrap.com/docs/5.1/components/navbar/
* @since 2.0.8
*/
public $brandImage = false;
/**
* @var array the HTML attributes of the brand image.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $brandImageOptions = [];
/**
* @var array|string|bool the URL for the brand's hyperlink tag. This parameter will be processed by [[\yii\helpers\Url::to()]]
* and will be used for the "href" attribute of the brand link. Default value is false that means
* [[\yii\web\Application::homeUrl]] will be used.
* You may set it to `null` if you want to have no link at all.
*/
public $brandUrl = false;
/**
* @var array the HTML attributes of the brand link.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $brandOptions = [];
/**
* @var string text to show for screen readers for the button to toggle the navbar.
*/
public $screenReaderToggleText;
/**
* @var string the toggle button content. Defaults to bootstrap 5 default `<span class="navbar-toggler-icon"></span>`
*/
public $togglerContent = '<span class="navbar-toggler-icon"></span>';
/**
* @var array the HTML attributes of the navbar toggler button.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $togglerOptions = [];
/**
* @var bool whether the navbar content should be included in an inner div container which by default
* adds left and right padding. Set this to false for a 100% width navbar.
*/
public $renderInnerContainer = true;
/**
* @var array the HTML attributes of the inner container.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $innerContainerOptions = [];
public $clientOptions = [];
public function init(): void
{
parent::init();
if (!isset($this->options['class']) || empty($this->options['class'])) {
Html::addCssClass($this->options, [
'widget' => 'navbar',
'toggle' => 'navbar-expand-lg',
'navbar-light',
'bg-light',
]);
} else {
Html::addCssClass($this->options, [
'widget' => 'navbar',
]);
}
$navOptions = $this->options;
$navTag = ArrayHelper::remove($navOptions, 'tag', 'nav');
$brand = '';
if (!isset($this->innerContainerOptions['class'])) {
Html::addCssClass($this->innerContainerOptions, [
'panel' => 'container',
]);
}
if ($this->collapseOptions !== false && !isset($this->collapseOptions['id'])) {
$this->collapseOptions['id'] = "{$this->options['id']}-collapse";
} elseif ($this->offcanvasOptions !== false && !isset($this->offcanvasOptions['id'])) {
$this->offcanvasOptions['id'] = "{$this->options['id']}-offcanvas";
}
if ($this->brandImage !== false) {
$this->brandLabel = Html::img($this->brandImage, $this->brandImageOptions);
}
if ($this->brandLabel !== false) {
Html::addCssClass($this->brandOptions, [
'widget' => 'navbar-brand',
]);
if ($this->brandUrl === null) {
$brand = Html::tag('span', $this->brandLabel, $this->brandOptions);
} else {
$brand = Html::a(
$this->brandLabel,
$this->brandUrl === false ? Yii::$app->homeUrl : $this->brandUrl,
$this->brandOptions,
);
}
}
ob_start();
echo Html::beginTag($navTag, $navOptions) . "\n";
if ($this->renderInnerContainer) {
echo Html::beginTag('div', $this->innerContainerOptions) . "\n";
}
echo $brand . "\n";
echo $this->renderToggleButton() . "\n";
if ($this->collapseOptions !== false) {
Html::addCssClass($this->collapseOptions, [
'collapse' => 'collapse',
'widget' => 'navbar-collapse',
]);
$collapseOptions = $this->collapseOptions;
$collapseTag = ArrayHelper::remove($collapseOptions, 'tag', 'div');
echo Html::beginTag($collapseTag, $collapseOptions) . "\n";
} elseif ($this->offcanvasOptions !== false) {
Offcanvas::begin($this->offcanvasOptions);
}
}
/**
* Renders the widget.
*/
public function run(): string
{
if ($this->collapseOptions !== false) {
$tag = ArrayHelper::remove($this->collapseOptions, 'tag', 'div');
echo Html::endTag($tag) . "\n";
} elseif ($this->offcanvasOptions !== false) {
Offcanvas::end();
}
$content = ob_get_clean();
if ($this->renderInnerContainer) {
$content .= Html::endTag('div') . "\n";
}
$tag = ArrayHelper::remove($this->options, 'tag', 'nav');
$content .= Html::endTag($tag);
BootstrapPluginAsset::register($this->getView());
return $content;
}
/**
* Container options setter for backwards compatibility
* @deprecated
*/
public function setContainerOptions(array $collapseOptions): void
{
$this->collapseOptions = $collapseOptions;
}
/**
* Renders collapsible toggle button.
* @return string the rendering toggle button.
*/
protected function renderToggleButton(): string
{
if ($this->collapseOptions === false && $this->offcanvasOptions === false) {
return '';
}
$options = $this->togglerOptions;
Html::addCssClass($options, [
'widget' => 'navbar-toggler',
]);
if ($this->offcanvasOptions !== false) {
$bsData = [
'bs-toggle' => 'offcanvas',
'bs-target' => '#' . $this->offcanvasOptions['id'],
];
$aria = $this->offcanvasOptions['id'];
} elseif ($this->collapseOptions !== false) {
$bsData = [
'bs-toggle' => 'collapse',
'bs-target' => '#' . $this->collapseOptions['id'],
];
$aria = $this->collapseOptions['id'];
}
return Html::button(
$this->togglerContent,
ArrayHelper::merge($options, [
'type' => 'button',
'data' => $bsData,
'aria' => [
'controls' => $aria,
'expanded' => 'false',
'label' => $this->screenReaderToggleText ?: Yii::t('yii/bootstrap5', 'Toggle navigation'),
],
]),
);
}
}

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