first commit

This commit is contained in:
Sampanna Rimal
2024-08-27 17:48:06 +05:45
commit 53c0140f58
10839 changed files with 1125847 additions and 0 deletions

337
vendor/spatie/laravel-html/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,337 @@
# Changelog
All notable changes to `laravel-html` will be documented in this file.
## 3.6.0 - 2024-03-08
### What's Changed
* Laravel 11.x Compatibility by @laravel-shift in https://github.com/spatie/laravel-html/pull/214
**Full Changelog**: https://github.com/spatie/laravel-html/compare/3.5.0...3.6.0
## 3.4.0 - 2024-01-05
### What's Changed
* Fix docblock to solve phpstan errors when passing an array to html()->div() by @SanderMuller in https://github.com/spatie/laravel-html/pull/210
* Documentation on how to extend the package by @azamtav in https://github.com/spatie/laravel-html/pull/204
### New Contributors
* @SanderMuller made their first contribution in https://github.com/spatie/laravel-html/pull/210
* @azamtav made their first contribution in https://github.com/spatie/laravel-html/pull/204
**Full Changelog**: https://github.com/spatie/laravel-html/compare/3.3.0...3.4.0
## 3.3.0 - 2023-10-24
### What's Changed
- Add documentation for new FormElement::route() method by @miken32 in https://github.com/spatie/laravel-html/pull/190
- Update `.gitattributes` by @totoprayogo1916 in https://github.com/spatie/laravel-html/pull/194
- Correction to docs re: readonly vs isReadonly by @sgilberg in https://github.com/spatie/laravel-html/pull/195
- Get value from model with casts php native enum by @bskl in https://github.com/spatie/laravel-html/pull/203
### New Contributors
- @totoprayogo1916 made their first contribution in https://github.com/spatie/laravel-html/pull/194
- @sgilberg made their first contribution in https://github.com/spatie/laravel-html/pull/195
- @bskl made their first contribution in https://github.com/spatie/laravel-html/pull/203
**Full Changelog**: https://github.com/spatie/laravel-html/compare/3.2.2...3.3.0
## 3.2.2 - 2023-07-20
### What's Changed
- Allow setting a form action to a route by @miken32 in https://github.com/spatie/laravel-html/pull/189
### New Contributors
- @miken32 made their first contribution in https://github.com/spatie/laravel-html/pull/189
**Full Changelog**: https://github.com/spatie/laravel-html/compare/3.2.1...3.2.2
## 3.2.1 - 2023-01-24
### What's Changed
- Convert all tests to Pest by @alexmanase in https://github.com/spatie/laravel-html/pull/183
- Laravel 10.x Compatibility by @laravel-shift in https://github.com/spatie/laravel-html/pull/184
### New Contributors
- @alexmanase made their first contribution in https://github.com/spatie/laravel-html/pull/183
- @laravel-shift made their first contribution in https://github.com/spatie/laravel-html/pull/184
**Full Changelog**: https://github.com/spatie/laravel-html/compare/3.2.0...3.2.1
## 3.2.0 - 2022-12-27
- Add `P` class to render paragraphs
## 3.1.0 - 2022-01-14
- Allow Laravel 9
## 3.0.0 - 2021-11-17
- Add compatiblity with PHP 8.1. The only breaking change with v2 is that `readonly` has been renamed to `isReadonly`.
## 2.30.0 - 2022-07-09
- Better support for numeric values in attributes
## 2.29.0 - 2021-02-09
- Add `target` attribute method to links and button
## 2.28.1 - 2020-11-30
- add support for PHP 8
## 2.28.0 - 2020-09-30
- add the disabled method to all elements that support the attribute (#165)
## 2.27.0 - 2020-09-09
- Add support for Laravel 8
## 2.26.0 - 2020-04-20
- Internal refactor to normalize availabel attribute methods
## 2.25.0 - 2020-03-02
- add Laravel 7 support
## 2.24.0 - 2019-09-04
- Added number input
## 2.23.0 - 2019-09-04
- Laravel 6 support
- Better handling for `0` values in inputs
- Add `range` for range inputs
- Format date and time values
## 2.22.1 - 2019-07-16
- Prevent password fields to be filled
## 2.22.0 - 2019-04-26
- Changed the `value` parameter in `data` to an optional parameter
## 2.21.0 - 2019-02-27
- Added Laravel 5.8 support
- Dropped PHP 7.0 support
- Dropped Laravel 5.4 support
- Dropped PHPUnit 6 support
## 2.20.1 - 2019-02-01
- use `Arr::` and `Str::` functions
## 2.20.0 - 2019-01-18
- Added `unless` method and magic `__call` handler (e.g. `$input->valueUnless(false, 5)`)
- Added `size` attribute method to `Input`
- Added `name` attribute method to `Button`
- Fixed checkbox value repopulation after request
## 2.19.9 - 2019-01-10
- Improve default of `tel` link
## 2.19.8 - 2018-09-04
- Add support for Laravel 5.7
## 2.19.7 - 2018-04-30
- Allow radio input check "0" value
## 2.19.6 - 2018-04-30
- Correctly prefill form array attributes from the model
## 2.19.5 - 2018-04-04
- Allow `null` children
## 2.19.4 - 2018-03-28
- Revert comparison function change in `2.19.2`
## 2.19.2 - 2018-03-26
- Fixed comparison function for selected options in `Select`
## 2.19.1 - 2018-03-23
- Fixed `Html::radio` auto-generated id's & checked behaviour
## 2.19.0 - 2018-03-09
- Changed `Input::require` to accept a boolean value
## 2.18.0 - 2018-03-02
- Added `I` element class and `Html::i` factory method
## 2.17.0 - 2018-02-28
- Added `Html::value` function that's a public method for `old`
## 2.16.0 - 2018-02-26
- Added `Img` element class and `Html::img` factory method
## 2.15.1 - 2018-02-26
- Removed `id` from CSRF fields
## 2.15.0 - 2018-02-23
- Added `Input::date` and `Input::time`
## 2.14.0 - 2018-02-22
- Added `Input::disabled`
## 2.13.1 - 2018-02-20
- Added `Form::novalidate`
## 2.12.1 - 2018-02-08
- Fixed Laravel 5.6 compatibility
## 2.12.0 - 2018-02-08
- Added Laravel 5.6 compatibility
- Fixed an issue with checkbox values
## 2.11.0 - 2018-02-02
- Add `readonly` method to input
## 2.10.3 - 2018-01-09
- Fix `__call` when using macros
## 2.10.2 - 2017-12-28
- `Htmlable` elements can now be used in the `html()` method
- Array notation is now implicitly converted to dot notation in `old` (e.g. `foo[1] -> foo.1`)
## 2.10.1 - 2017-12-18
- Fixed old values containing `0`
## 2.10.0 - 2017-11-08
- Added `required` method to `Select`
## 2.9.0 - 2017-10-20
- Added `required` method to `Textarea`
## 2.8.2 - 2017-10-13
- Fixed a bug with values that are a `"0"` string
## 2.8.1 - 2017-10-12
- Fixed a bug with values that are a `"0"` string
## 2.8.0 - 2017-10-12
- Added a magic `__call` method that responds to methods ending with `If`, so any method can be called with a condition as it's first argument. The method will only be applied if the condition is truthy.
## 2.7.0 - 2017-10-11
- Added `BaseElement::data` for data attributes
## 2.6.0 - 2017-10-11
- Added `BaseElement::setChildren` to replace all children
- Fixed a bug that didn't select options in optgroups when applying a value
## 2.5.0 - 2017-10-11
- Added `BaseElement::style` for setting the style attribute (with a string or an associative array)
- Added `Html::reset` for form reset buttons
## 2.4.1 - 2017-09-07
- Nothing changed, but `2.2.0` was accidentally tagged as `2.4.0`. This release contains the actual latest version at the time of writing.
## 2.3.0 - 2017-09-04
- Added `checked` and `unchecked` methods to `Input`
## 2.2.0 - 2017-08-29
- Added `Optgroup` element
- Added the ability to create optgroups in `Options` by passing an array of groups with options
## 2.1.0 - 2017-08-24
- Added `Html::file` and a `File` element for file inputs
## 2.0.2 - 2017-07-14
- Fixed an issue that stripped square brackets from element attributes
## 2.0.1 - 2017-06-28
- Fixed the `Html` facade
## 2.0.0 - 2017-06-13
- Minimum requirements have been reduced to PHP 7.0
- Added a `html()` helper function that returns an instance of `Html`
- Added `Macroable` to all elements and `Html`
- Loosened type hints in method signatures for flexibility
- Added `Html::multiselect` method
- Added `Select::multiple` method
## 1.5.0 - 2017-05-19
- Added `class` method to `Html`
## 1.4.0 - 2017-05-16
- Added a `placeholder` method to `Textarea`
## 1.3.1 - 2017-05-09
- Added an empty `value` to `Select::placeholder`
## 1.3.0 - 2017-05-08
- Added a `placeholder` method to `Select` for default empty values
## 1.2.0 - 2017-04-28
- Added a `Html` facade
## 1.1.1 - 2017-04-27
- Fixed an issue where html was escaped when you didn't want it to do that, like in buttons and links
## 1.1.0 - 2017-04-19
- Added `Html::radio`
- Fixed an issue that set the wrong `value` for a checkbox created with `Html::checkbox`
- Fixed a case sensitivity issue with the `Textarea` class
## 1.0.0 - 2017-03-31
- Initial release

21
vendor/spatie/laravel-html/LICENSE.md vendored Normal file
View File

@@ -0,0 +1,21 @@
# The MIT License (MIT)
Copyright (c) Spatie bvba <info@spatie.be>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.

114
vendor/spatie/laravel-html/README.md vendored Normal file
View File

@@ -0,0 +1,114 @@
# Painless HTML generation
[![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/laravel-html.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-html)
[![MIT Licensed](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
[![Total Downloads](https://img.shields.io/packagist/dt/spatie/laravel-html.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-html)
This package helps you generate HTML using a clean, simple and easy to read API. All elements can be dynamically generated and put together. The HTML builder helps you generate dynamically assigned form elements based on your selected model, the session or a default value.
## Support us
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/laravel-html.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/laravel-html)
We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).
We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).
## Postcardware
You're free to use this package (it's [MIT-licensed](LICENSE.md)), but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.
Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium.
All postcards are published [on our website](https://spatie.be/en/opensource/postcards).
## Installation
You can install the package via composer:
``` bash
composer require spatie/laravel-html
```
And optionally register an alias for the facade.
```php
// config/app.php
'aliases' => [
...
'Html' => Spatie\Html\Facades\Html::class,
];
```
## Usage
### Concepts
Elements—classes under the `Spatie\Html\Elements` namespace—are generally created via a `Spatie\Html\Html` builder instance.
```php
html()->span()->text('Hello world!');
```
Element attributes and contents are modified via with fluent methods which return a new instance. This means element instances are immutable.
```php
$icon = html()->span()->class('fa');
$icon->class('fa-eye'); // '<span class="fa fa-eye"></span>'
$icon->class('fa-eye-slash'); // '<span class="fa fa-eye-slash"></span>'
```
Element classes don't have any knowledge of the outside world. Any coupling to other concepts, like requests and sessions, should happen in the builder class, not on the element classes.
By convention, we assume that builder methods will modify values to our advantage (like pulling old values from the session on a failed form request), and element methods will be deterministic.
```php
// This will try to resolve an initial value, and fall back to 'hello@example.com'
$email = html()->email('email', 'hello@example.com');
// This will always have 'hello@example.com' as it's value
$email = html()->email('email')->value('hello@example.com');
```
## Upgrading
### From v1 to v2
Version 2 was created because the typehints in version 1 was holding the package back in some cases (like multiple select which requires an array of values instead of a string which was assumed).
Luckily, bumping the version number in `composer.json` and running `composer update` should be non-breaking. Here are some caveats to look out for:
- The package now ships with a `html()` function by default, which returns an instance of the `Html` builder class. If you've defined your own method, you'll need to remove it.
- Various type hints have been removed throughout the package, if you've extended a class to override its methods, you'll need to update them accordingly (everything still behaves the same!)
## Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
## Testing
```bash
$ composer test
```
## Contributing
Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.
## Security
If you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker.
## Credits
- [Sebastian De Deyne](https://github.com/sebastiandedeyne)
- [Freek Van der Herten](https://github.com/freekmurze)
- [All Contributors](../../contributors)
## About Spatie
Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource).
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

View File

@@ -0,0 +1,68 @@
{
"name": "spatie/laravel-html",
"description": "A fluent html builder",
"keywords": [
"spatie",
"html"
],
"homepage": "https://github.com/spatie/laravel-html",
"license": "MIT",
"authors": [
{
"name": "Sebastian De Deyne",
"email": "sebastian@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
},
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"require": {
"php": "^8.2",
"illuminate/http": "^10.0|^11.0",
"illuminate/support": "^10.0|^11.0"
},
"require-dev": {
"mockery/mockery": "^1.3",
"orchestra/testbench": "^8.0|^9.0",
"pestphp/pest": "^2.34"
},
"autoload": {
"psr-4": {
"Spatie\\Html\\": "src"
},
"files": [
"src/helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"Spatie\\Html\\Test\\": "tests"
}
},
"scripts": {
"test": "vendor/bin/pest"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
"extra": {
"laravel": {
"providers": [
"Spatie\\Html\\HtmlServiceProvider"
],
"aliases": {
"Html": "Spatie\\Html\\Facades\\Html"
}
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@@ -0,0 +1,160 @@
<?php
namespace Spatie\Html;
use Spatie\Html\Helpers\Arr;
class Attributes
{
/** @var array */
protected $attributes = [];
/** @var array */
protected $classes = [];
/**
* @param iterable $attributes
*
* @return $this
*/
public function setAttributes($attributes)
{
foreach ($attributes as $attribute => $value) {
if ($attribute === 'class') {
$this->addClass($value);
continue;
}
if (is_int($attribute)) {
$attribute = $value;
$value = '';
}
$this->setAttribute($attribute, (string) $value);
}
return $this;
}
/**
* @param string $attribute
* @param string|null $value
*
* @return $this
*/
public function setAttribute($attribute, $value = null)
{
if ($attribute === 'class') {
$this->addClass($value);
return $this;
}
$this->attributes[$attribute] = $value;
return $this;
}
/**
* @param string $attribute
*
* @return $this
*/
public function forgetAttribute($attribute)
{
if ($attribute === 'class') {
$this->classes = [];
return $this;
}
if (isset($this->attributes[$attribute])) {
unset($this->attributes[$attribute]);
}
return $this;
}
/**
* @param string $attribute
* @param mixed $fallback
*
* @return mixed
*/
public function getAttribute($attribute, $fallback = null)
{
if ($attribute === 'class') {
return implode(' ', $this->classes);
}
return $this->attributes[$attribute] ?? $fallback;
}
public function hasAttribute(string $attribute): bool
{
return array_key_exists($attribute, $this->attributes);
}
/**
* @param string|iterable $class
*/
public function addClass($class)
{
if (is_string($class)) {
$class = explode(' ', $class);
}
$class = Arr::getToggledValues($class);
$this->classes = array_unique(
array_merge($this->classes, $class)
);
}
/**
* @return bool
*/
public function isEmpty()
{
return empty($this->attributes) && empty($this->classes);
}
/**
* @return array
*/
public function toArray()
{
if (empty($this->classes)) {
return $this->attributes;
}
return array_merge(['class' => implode(' ', $this->classes)], $this->attributes);
}
/**
* @return string
*/
public function render()
{
if ($this->isEmpty()) {
return '';
}
$attributeStrings = [];
foreach ($this->toArray() as $attribute => $value) {
if ($value === '') {
$attributeStrings[] = $attribute;
continue;
}
$value = htmlentities($value, ENT_QUOTES, 'UTF-8', false);
$attributeStrings[] = "{$attribute}=\"{$value}\"";
}
return implode(' ', $attributeStrings);
}
}

View File

@@ -0,0 +1,491 @@
<?php
namespace Spatie\Html;
use BadMethodCallException;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\Collection;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
use Spatie\Html\Exceptions\InvalidChild;
use Spatie\Html\Exceptions\InvalidHtml;
use Spatie\Html\Exceptions\MissingTag;
abstract class BaseElement implements Htmlable, HtmlElement
{
use Macroable {
__call as __macro_call;
}
/** @var string */
protected $tag;
/** @var \Spatie\Html\Attributes */
protected $attributes;
/** @var \Illuminate\Support\Collection */
protected $children;
public function __construct()
{
if (empty($this->tag)) {
throw MissingTag::onClass(static::class);
}
$this->attributes = new Attributes();
$this->children = new Collection();
}
public static function create()
{
return new static();
}
/**
* @param string $attribute
* @param string|null $value
*
* @return static
*/
public function attribute($attribute, $value = null)
{
$element = clone $this;
$element->attributes->setAttribute($attribute, (string) $value);
return $element;
}
/**
* @param iterable $attributes
*
* @return static
*/
public function attributes($attributes)
{
$element = clone $this;
$element->attributes->setAttributes($attributes);
return $element;
}
/**
* @param string $attribute
*
* @return static
*/
public function forgetAttribute($attribute)
{
$element = clone $this;
$element->attributes->forgetAttribute($attribute);
return $element;
}
/**
* @param string $attribute
* @param mixed $fallback
*
* @return mixed
*/
public function getAttribute($attribute, $fallback = null)
{
return $this->attributes->getAttribute($attribute, $fallback);
}
/**
* @param string $attribute
*
* @return bool
*/
public function hasAttribute($attribute)
{
return $this->attributes->hasAttribute($attribute);
}
/**
* @param iterable|string $class
*
* @return static
*/
public function class($class)
{
return $this->addClass($class);
}
/**
* Alias for `class`.
*
* @param iterable|string $class
*
* @return static
*/
public function addClass($class)
{
$element = clone $this;
$element->attributes->addClass($class);
return $element;
}
/**
* @param string $id
*
* @return static
*/
public function id($id)
{
return $this->attribute('id', $id);
}
/**
* @param array|string|null $style
*
* @return static
*/
public function style($style)
{
if (is_array($style)) {
$style = implode('; ', array_map(function ($value, $attribute) {
return "{$attribute}: {$value}";
}, $style, array_keys($style)));
}
return $this->attribute('style', $style);
}
/**
* @param string $name
* @param string $value
*
* @return static
*/
public function data($name, $value = null)
{
return $this->attribute("data-{$name}", $value);
}
/**
* @param \Spatie\Html\HtmlElement|string|iterable|int|float|null $children
* @param callable|null $mapper
*
* @return static
*/
public function addChildren($children, $mapper = null)
{
if (is_null($children)) {
return $this;
}
$children = $this->parseChildren($children, $mapper);
$element = clone $this;
$element->children = $element->children->merge($children);
return $element;
}
/**
* Alias for `addChildren`.
*
* @param \Spatie\Html\HtmlElement|string|iterable|int|float|null $children
* @param callable|null $mapper
*
* @return static
*/
public function addChild($child, $mapper = null)
{
return $this->addChildren($child, $mapper);
}
/**
* Alias for `addChildren`.
*
* @param \Spatie\Html\HtmlElement|string|iterable|int|float|null $children
* @param callable|null $mapper
*
* @return static
*/
public function child($child, $mapper = null)
{
return $this->addChildren($child, $mapper);
}
/**
* Alias for `addChildren`.
*
* @param \Spatie\Html\HtmlElement|string|iterable|int|float|null $children
* @param callable|null $mapper
*
* @return static
*/
public function children($children, $mapper = null)
{
return $this->addChildren($children, $mapper);
}
/**
* Replace all children with an array of elements.
*
* @param \Spatie\Html\HtmlElement[] $children
* @param callable|null $mapper
*
* @return static
*/
public function setChildren($children, $mapper = null)
{
$element = clone $this;
$element->children = new Collection();
return $element->addChildren($children, $mapper);
}
/**
* @param \Spatie\Html\HtmlElement|string|iterable|int|float|null $children
* @param callable|null $mapper
*
* @return static
*/
public function prependChildren($children, $mapper = null)
{
$children = $this->parseChildren($children, $mapper);
$element = clone $this;
$element->children = $children->merge($element->children);
return $element;
}
/**
* Alias for `prependChildren`.
*
* @param \Spatie\Html\HtmlElement|string|iterable|int|float|null $children
* @param callable|null $mapper
*
* @return static
*/
public function prependChild($children, $mapper = null)
{
return $this->prependChildren($children, $mapper);
}
/**
* @param string|null $text
*
* @return static
*/
public function text($text)
{
return $this->html(htmlentities($text, ENT_QUOTES, 'UTF-8', false));
}
/**
* @param string|null $html
*
* @return static
*/
public function html($html)
{
if ($this->isVoidElement()) {
throw new InvalidHtml("Can't set inner contents on `{$this->tag}` because it's a void element");
}
return $this->setChildren($html);
}
/**
* Conditionally transform the element. Note that since elements are
* immutable, you'll need to return a new instance from the callback.
*
* @param bool $condition
* @param \Closure $callback
*
* @return mixed
*/
public function if(bool $condition, \Closure $callback)
{
return $condition ? $callback($this) : $this;
}
/**
* Conditionally transform the element. Note that since elements are
* immutable, you'll need to return a new instance from the callback.
*
* @param bool $condition
* @param \Closure $callback
*
* @return mixed
*/
public function unless(bool $condition, \Closure $callback)
{
return $this->if(! $condition, $callback);
}
/**
* Conditionally transform the element. Note that since elements are
* immutable, you'll need to return a new instance from the callback.
*
* @param mixed $value
* @param \Closure $callback
*
* @return mixed
*/
public function ifNotNull($value, \Closure $callback)
{
return ! is_null($value) ? $callback($this) : $this;
}
/**
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function open()
{
$tag = $this->attributes->isEmpty()
? '<' . $this->tag . '>'
: "<{$this->tag} {$this->attributes->render()}>";
$children = $this->children->map(function ($child): string {
if ($child instanceof HtmlElement) {
return $child->render();
}
if (is_null($child)) {
return '';
}
if (is_string($child) || is_numeric($child)) {
return $child;
}
throw InvalidChild::childMustBeAnHtmlElementOrAString();
})->implode('');
return new HtmlString($tag . $children);
}
/**
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function close()
{
return new HtmlString(
$this->isVoidElement()
? ''
: "</{$this->tag}>"
);
}
/**
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function render()
{
return new HtmlString(
$this->open() . $this->close()
);
}
public function isVoidElement(): bool
{
return in_array($this->tag, [
'area', 'base', 'br', 'col', 'embed', 'hr',
'img', 'input', 'keygen', 'link', 'menuitem',
'meta', 'param', 'source', 'track', 'wbr',
]);
}
/**
* Dynamically handle calls to the class.
* Check for methods finishing by If or fallback to Macroable.
*
* @param string $name
* @param array $arguments
* @return mixed
*
* @throws BadMethodCallException
*/
public function __call($name, $arguments)
{
if (Str::endsWith($name, $conditions = ['If', 'Unless', 'IfNotNull'])) {
foreach ($conditions as $condition) {
if (! method_exists($this, $method = str_replace($condition, '', $name))) {
continue;
}
return $this->callConditionalMethod($condition, $method, $arguments);
}
}
return $this->__macro_call($name, $arguments);
}
protected function callConditionalMethod($type, $method, array $arguments)
{
$value = array_shift($arguments);
$callback = function () use ($method, $arguments) {
return $this->{$method}(...$arguments);
};
switch ($type) {
case 'If':
return $this->if((bool) $value, $callback);
case 'Unless':
return $this->unless((bool) $value, $callback);
case 'IfNotNull':
return $this->ifNotNull($value, $callback);
default:
return $this;
}
}
public function __clone()
{
$this->attributes = clone $this->attributes;
$this->children = clone $this->children;
}
public function __toString(): string
{
return $this->render();
}
public function toHtml(): string
{
return $this->render();
}
protected function parseChildren($children, $mapper = null): Collection
{
if ($children instanceof HtmlElement) {
$children = [$children];
}
$children = Collection::make($children);
if ($mapper) {
$children = $children->map($mapper);
}
$this->guardAgainstInvalidChildren($children);
return $children;
}
protected function guardAgainstInvalidChildren(Collection $children)
{
foreach ($children as $child) {
if ($child instanceof HtmlElement || is_null($child) || is_string($child) || is_numeric($child)) {
continue;
}
throw InvalidChild::childMustBeAnHtmlElementOrAString();
}
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Target;
class A extends BaseElement
{
use Target;
protected $tag = 'a';
/**
* @param string|null $href
*
* @return static
*/
public function href($href)
{
return $this->attribute('href', $href);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Autocomplete
{
/**
* @param bool|string $autocomplete
*
* @return static
*/
public function autocomplete($autocomplete = true)
{
$value = 'on';
if ($autocomplete === false) {
$value = 'off';
}
if (is_string($autocomplete)) {
$value = $autocomplete;
}
return $this->attribute('autocomplete', $value);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Autofocus
{
/**
* @param bool $autofocus
*
* @return static
*/
public function autofocus($autofocus = true)
{
return $autofocus
? $this->attribute('autofocus')
: $this->forgetAttribute('autofocus');
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Disabled
{
/**
* @param bool $disabled
*
* @return static
*/
public function disabled($disabled = true)
{
return $disabled
? $this->attribute('disabled', 'disabled')
: $this->forgetAttribute('disabled');
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait MinMaxLength
{
/**
* @param int $minlength
*
* @return static
*/
public function minlength(int $minlength)
{
return $this->attribute('minlength', $minlength);
}
/**
* @param int $maxlength
*
* @return static
*/
public function maxlength(int $maxlength)
{
return $this->attribute('maxlength', $maxlength);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Name
{
/**
* @param string $name
*
* @return static
*/
public function name($name)
{
return $this->attribute('name', $name);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Placeholder
{
/**
* @param string|null $placeholder
*
* @return static
*/
public function placeholder($placeholder)
{
return $this->attribute('placeholder', $placeholder);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait ReadonlyTrait
{
/**
* @param bool $readonly
*
* @return static
*/
public function isReadonly($readonly = true)
{
return $readonly
? $this->attribute('readonly')
: $this->forgetAttribute('readonly');
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Required
{
/**
* @param bool $required
*
* @return static
*/
public function required($required = true)
{
return $required
? $this->attribute('required')
: $this->forgetAttribute('required');
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Target
{
/**
* @param string $target
*
* @return static
*/
public function target($target)
{
return $this->attribute('target', $target);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Type
{
/**
* @param string|null $type
*
* @return static
*/
public function type($type)
{
return $this->attribute('type', $type);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Spatie\Html\Elements\Attributes;
trait Value
{
/**
* @param string|null $value
*
* @return static
*/
public function value($value)
{
return $this->attribute('value', $value);
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Disabled;
use Spatie\Html\Elements\Attributes\Name;
use Spatie\Html\Elements\Attributes\Type;
use Spatie\Html\Elements\Attributes\Value;
class Button extends BaseElement
{
use Disabled;
use Value;
use Name;
use Type;
protected $tag = 'button';
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
class Div extends BaseElement
{
protected $tag = 'div';
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Spatie\Html\Elements;
use Illuminate\Support\Collection;
use ReflectionClass;
use Spatie\Html\Attributes;
use Spatie\Html\BaseElement;
class Element extends BaseElement
{
/**
* @param string $tag
*
* @return static
*/
public static function withTag($tag)
{
$element = (new ReflectionClass(static::class))->newInstanceWithoutConstructor();
$element->tag = $tag;
$element->attributes = new Attributes();
$element->children = new Collection();
return $element;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Disabled;
class Fieldset extends BaseElement
{
use Disabled;
protected $tag = 'fieldset';
/**
* @param \Spatie\Html\HtmlElement|string $text
*
* @return static
*/
public function legend($contents)
{
return $this->prependChild(
Legend::create()->text($contents)
);
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Autofocus;
use Spatie\Html\Elements\Attributes\Name;
use Spatie\Html\Elements\Attributes\Required;
class File extends BaseElement
{
use Autofocus;
use Name;
use Required;
protected $tag = 'input';
public const ACCEPT_AUDIO = 'audio/*';
public const ACCEPT_VIDEO = 'video/*';
public const ACCEPT_IMAGE = 'image/*';
public function __construct()
{
parent::__construct();
$this->attributes->setAttribute('type', 'file');
}
/**
* @param string|null $name
*
* @return static
*/
public function accept($type)
{
return $this->attribute('accept', $type);
}
/**
* @return static
*/
public function acceptAudio()
{
return $this->attribute('accept', self::ACCEPT_AUDIO);
}
/**
* @return static
*/
public function acceptVideo()
{
return $this->attribute('accept', self::ACCEPT_VIDEO);
}
/**
* @return static
*/
public function acceptImage()
{
return $this->attribute('accept', self::ACCEPT_IMAGE);
}
/**
* @return static
*/
public function multiple()
{
return $this->attribute('multiple');
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Target;
class Form extends BaseElement
{
use Target;
protected $tag = 'form';
/**
* @param string|null $action
*
* @return static
*/
public function action($action)
{
return $this->attribute('action', $action);
}
/**
* @param string|null $route
* @param mixed $params
*
* @return static
*/
public function route($route, ...$params)
{
return $this->action(route($route, ...$params));
}
/**
* @param string|null $method
*
* @return static
*/
public function method($method)
{
return $this->attribute('method', $method);
}
/**
* @param bool $novalidate
*
* @return static
*/
public function novalidate($novalidate = true)
{
return $novalidate
? $this->attribute('novalidate')
: $this->forgetAttribute('novalidate');
}
/**
* @return static
*/
public function acceptsFiles()
{
return $this->attribute('enctype', 'multipart/form-data');
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
class I extends BaseElement
{
protected $tag = 'i';
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
class Img extends BaseElement
{
protected $tag = 'img';
/**
* @param string|null $alt
*
* @return static
*/
public function alt($alt)
{
return $this->attribute('alt', $alt);
}
/**
* @param string|null $src
*
* @return static
*/
public function src($src)
{
return $this->attribute('src', $src);
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Autocomplete;
use Spatie\Html\Elements\Attributes\Autofocus;
use Spatie\Html\Elements\Attributes\Disabled;
use Spatie\Html\Elements\Attributes\MinMaxLength;
use Spatie\Html\Elements\Attributes\Name;
use Spatie\Html\Elements\Attributes\Placeholder;
use Spatie\Html\Elements\Attributes\ReadonlyTrait;
use Spatie\Html\Elements\Attributes\Required;
use Spatie\Html\Elements\Attributes\Type;
use Spatie\Html\Elements\Attributes\Value;
class Input extends BaseElement
{
use Autofocus;
use Autocomplete;
use Disabled;
use MinMaxLength;
use Name;
use Placeholder;
use ReadonlyTrait;
use Required;
use Type;
use Value;
protected $tag = 'input';
/**
* @return static
*/
public function unchecked()
{
return $this->checked(false);
}
/**
* @param bool $checked
*
* @return static
*/
public function checked($checked = true)
{
return $checked
? $this->attribute('checked', 'checked')
: $this->forgetAttribute('checked');
}
/**
* @param string|null $size
*
* @return static
*/
public function size($size)
{
return $this->attribute('size', $size);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
class Label extends BaseElement
{
protected $tag = 'label';
/**
* @param string|null $for
*
* @return static
*/
public function for($for)
{
return $this->attribute('for', $for);
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
class Legend extends BaseElement
{
protected $tag = 'legend';
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Disabled;
class Optgroup extends BaseElement
{
use Disabled;
protected $tag = 'optgroup';
/**
* @param string|null $href
*
* @return static
*/
public function label($label)
{
return $this->attribute('label', $label);
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Disabled;
use Spatie\Html\Elements\Attributes\Value;
use Spatie\Html\Selectable;
class Option extends BaseElement implements Selectable
{
use Disabled;
use Value;
/** @var string */
protected $tag = 'option';
/**
* @return static
*/
public function selected()
{
return $this->attribute('selected', 'selected');
}
/**
* @param bool $condition
*
* @return static
*/
public function selectedIf($condition)
{
return $condition ?
$this->selected() :
$this->unselected();
}
/**
* @return static
*/
public function unselected()
{
return $this->forgetAttribute('selected');
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
class P extends BaseElement
{
protected $tag = 'p';
}

View File

@@ -0,0 +1,152 @@
<?php
namespace Spatie\Html\Elements;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Autocomplete;
use Spatie\Html\Elements\Attributes\Autofocus;
use Spatie\Html\Elements\Attributes\Disabled;
use Spatie\Html\Elements\Attributes\Name;
use Spatie\Html\Elements\Attributes\ReadonlyTrait;
use Spatie\Html\Elements\Attributes\Required;
use Spatie\Html\Selectable;
class Select extends BaseElement
{
use Autofocus;
use Autocomplete;
use Disabled;
use Name;
use Required;
use ReadonlyTrait;
/** @var string */
protected $tag = 'select';
/** @var array */
protected $options = [];
/** @var string|iterable */
protected $value = '';
/**
* @return static
*/
public function multiple()
{
$element = clone $this;
$element = $element->attribute('multiple');
$name = $element->getAttribute('name');
if ($name && ! Str::endsWith($name, '[]')) {
$element = $element->name($name.'[]');
}
$element->applyValueToOptions();
return $element;
}
/**
* @param iterable $options
*
* @return static
*/
public function options($options)
{
return $this->addChildren($options, function ($text, $value) {
if (is_array($text) || $text instanceof Collection) {
return $this->optgroup($value, $text);
}
return Option::create()
->value($value)
->text($text)
->selectedIf($value === $this->value);
});
}
/**
* @param string $label
* @param iterable $options
*
* @return static
*/
public function optgroup($label, $options)
{
return Optgroup::create()
->label($label)
->addChildren($options, function ($text, $value) {
return Option::create()
->value($value)
->text($text)
->selectedIf($value === $this->value);
});
}
/**
* @param string|null $text
*
* @return static
*/
public function placeholder($text)
{
return $this->prependChild(
Option::create()
->value(null)
->text($text)
->selectedIf(! $this->hasSelection())
);
}
/**
* @param string|iterable $value
*
* @return static
*/
public function value($value = null)
{
$element = clone $this;
$element->value = $value;
$element->applyValueToOptions();
return $element;
}
protected function hasSelection()
{
return $this->children->contains->hasAttribute('selected');
}
protected function applyValueToOptions()
{
$value = Collection::make($this->value);
if (! $this->hasAttribute('multiple')) {
$value = $value->take(1);
}
$this->children = $this->applyValueToElements($value, $this->children);
}
protected function applyValueToElements($value, Collection $children)
{
return $children->map(function ($child) use ($value) {
if ($child instanceof Optgroup) {
return $child->setChildren($this->applyValueToElements($value, $child->children));
}
if ($child instanceof Selectable) {
return $child->selectedIf($value->contains($child->getAttribute('value')));
}
return $child;
});
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
class Span extends BaseElement
{
protected $tag = 'span';
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Spatie\Html\Elements;
use Spatie\Html\BaseElement;
use Spatie\Html\Elements\Attributes\Autocomplete;
use Spatie\Html\Elements\Attributes\Autofocus;
use Spatie\Html\Elements\Attributes\Disabled;
use Spatie\Html\Elements\Attributes\MinMaxLength;
use Spatie\Html\Elements\Attributes\Name;
use Spatie\Html\Elements\Attributes\Placeholder;
use Spatie\Html\Elements\Attributes\ReadonlyTrait;
use Spatie\Html\Elements\Attributes\Required;
class Textarea extends BaseElement
{
use Autofocus;
use Autocomplete;
use Placeholder;
use Name;
use Required;
use Disabled;
use ReadonlyTrait;
use MinMaxLength;
protected $tag = 'textarea';
/**
* @param string|null $value
*
* @return static
* @throws \Spatie\Html\Exceptions\InvalidHtml
*/
public function value($value)
{
return $this->html($value);
}
/**
* @param int $rows
*
* @return static
*/
public function rows(int $rows)
{
return $this->attribute('rows', $rows);
}
/**
* @param int $cols
*
* @return static
*/
public function cols(int $cols)
{
return $this->attribute('cols', $cols);
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Spatie\Html\Exceptions;
use Exception;
use Spatie\Html\HtmlElement;
class InvalidChild extends Exception
{
public static function childMustBeAnHtmlElementOrAString()
{
return new static('The given child should implement `'.HtmlElement::class.'` or be a string');
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace Spatie\Html\Exceptions;
use Exception;
class InvalidHtml extends Exception
{
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Spatie\Html\Exceptions;
use Exception;
class MissingTag extends Exception
{
public static function onClass($className): self
{
return new self("Class {$className} has nog `\$tag` property");
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Spatie\Html\Facades;
use Illuminate\Support\Facades\Facade;
use Spatie\Html\Html as HtmlBuilder;
class Html extends Facade
{
/**
* Get the registered name of the component.
*
* @see \Spatie\Html\Html
*
* @return string
*/
protected static function getFacadeAccessor()
{
return HtmlBuilder::class;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Spatie\Html\Helpers;
use Illuminate\Support\Collection;
class Arr
{
/**
* Return an array of enabled values. Enabled values are either:
* - Keys that have a truthy value;
* - Values that don't have keys.
*
* Example:
*
* Arr::getToggledValues(['foo' => true, 'bar' => false, 'baz'])
* // => ['foo', 'baz']
*
* @param mixed $map
*
* @return array
*/
public static function getToggledValues($map)
{
return Collection::make($map)->map(function ($condition, $value) {
if (is_numeric($value)) {
return $condition;
}
return $condition ? $value : null;
})->filter()->toArray();
}
}

678
vendor/spatie/laravel-html/src/Html.php vendored Normal file
View File

@@ -0,0 +1,678 @@
<?php
namespace Spatie\Html;
use BackedEnum;
use DateTimeImmutable;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
use Spatie\Html\Elements\A;
use Spatie\Html\Elements\Button;
use Spatie\Html\Elements\Div;
use Spatie\Html\Elements\Element;
use Spatie\Html\Elements\Fieldset;
use Spatie\Html\Elements\File;
use Spatie\Html\Elements\Form;
use Spatie\Html\Elements\I;
use Spatie\Html\Elements\Img;
use Spatie\Html\Elements\Input;
use Spatie\Html\Elements\Label;
use Spatie\Html\Elements\Legend;
use Spatie\Html\Elements\Option;
use Spatie\Html\Elements\P;
use Spatie\Html\Elements\Select;
use Spatie\Html\Elements\Span;
use Spatie\Html\Elements\Textarea;
use UnitEnum;
class Html
{
use Macroable;
public const HTML_DATE_FORMAT = 'Y-m-d';
public const HTML_TIME_FORMAT = 'H:i:s';
/** @var \Illuminate\Http\Request */
protected $request;
/** @var \ArrayAccess|array */
protected $model;
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* @param string|null $href
* @param string|null $text
*
* @return \Spatie\Html\Elements\A
*/
public function a($href = null, $contents = null)
{
return A::create()
->attributeIf($href, 'href', $href)
->html($contents);
}
/**
* @param string|null $href
* @param string|null $text
*
* @return \Spatie\Html\Elements\I
*/
public function i($contents = null)
{
return I::create()
->html($contents);
}
/**
* @param \Spatie\Html\HtmlElement|string|null $contents
*
* @return \Spatie\Html\Elements\P
*/
public function p($contents = null)
{
return P::create()
->html($contents);
}
/**
* @param string|null $type
* @param string|null $text
*
* @return \Spatie\Html\Elements\Button
*/
public function button($contents = null, $type = null, $name = null)
{
return Button::create()
->attributeIf($type, 'type', $type)
->attributeIf($name, 'name', $this->fieldName($name))
->html($contents);
}
/**
* @param \Illuminate\Support\Collection|iterable|string $classes
*
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function class($classes): Htmlable
{
if ($classes instanceof Collection) {
$classes = $classes->toArray();
}
$attributes = new Attributes();
$attributes->addClass($classes);
return new HtmlString(
$attributes->render()
);
}
/**
* @param string|null $name
* @param bool $checked
* @param string|null $value
*
* @return \Spatie\Html\Elements\Input
*/
public function checkbox($name = null, $checked = null, $value = '1')
{
return $this->input('checkbox', $name, $value)
->attributeIf(! is_null($value), 'value', $value)
->attributeIf((bool) $this->old($name, $checked), 'checked');
}
/**
* @param \Spatie\Html\HtmlElement|string|iterable|int|float|null $contents
*
* @return \Spatie\Html\Elements\Div
*/
public function div($contents = null)
{
return Div::create()->children($contents);
}
/**
* @param string|null $name
* @param string|null $value
*
* @return \Spatie\Html\Elements\Input
*/
public function email($name = null, $value = null)
{
return $this->input('email', $name, $value);
}
/**
* @param string|null $name
* @param string|null $value
*
* @return \Spatie\Html\Elements\Input
*/
public function search($name = null, $value = null)
{
return $this->input('search', $name, $value);
}
/**
* @param string|null $name
* @param string|null $value
* @param bool $format
*
* @return \Spatie\Html\Elements\Input
*/
public function date($name = '', $value = null, $format = true)
{
$element = $this->input('date', $name, $value);
if (! $format || empty($element->getAttribute('value'))) {
return $element;
}
return $element->value($this->formatDateTime($element->getAttribute('value'), self::HTML_DATE_FORMAT));
}
/**
* @param string|null $name
* @param string|null $value
* @param bool $format
*
* @return \Spatie\Html\Elements\Input
*/
public function datetime($name = '', $value = null, $format = true)
{
$element = $this->input('datetime-local', $name, $value);
if (! $format || empty($element->getAttribute('value'))) {
return $element;
}
return $element->value($this->formatDateTime(
$element->getAttribute('value'),
self::HTML_DATE_FORMAT.'\T'.self::HTML_TIME_FORMAT
));
}
/**
* @param string|null $name
* @param string|null $value
* @param string|null $min
* @param string|null $max
* @param string|null $step
*
* @return \Spatie\Html\Elements\Input
*/
public function range($name = '', $value = '', $min = null, $max = null, $step = null)
{
return $this->input('range', $name, $value)
->attributeIfNotNull($min, 'min', $min)
->attributeIfNotNull($max, 'max', $max)
->attributeIfNotNull($step, 'step', $step);
}
/**
* @param string|null $name
* @param string|null $value
* @param bool $format
*
* @return \Spatie\Html\Elements\Input
*/
public function time($name = '', $value = null, $format = true)
{
$element = $this->input('time', $name, $value);
if (! $format || empty($element->getAttribute('value'))) {
return $element;
}
return $element->value($this->formatDateTime($element->getAttribute('value'), self::HTML_TIME_FORMAT));
}
/**
* @param string $tag
*
* @return \Spatie\Html\Elements\Element
*/
public function element($tag)
{
return Element::withTag($tag);
}
/**
* @param string|null $type
* @param string|null $name
* @param string|null $value
*
* @return \Spatie\Html\Elements\Input
*/
public function input($type = null, $name = null, $value = null)
{
$hasValue = $name && ($type !== 'password' && ! is_null($this->old($name, $value)) || ! is_null($value));
return Input::create()
->attributeIf($type, 'type', $type)
->attributeIf($name, 'name', $this->fieldName($name))
->attributeIf($name, 'id', $this->fieldName($name))
->attributeIf($hasValue, 'value', $this->old($name, $value));
}
/**
* @param \Spatie\Html\HtmlElement|string|null $legend
*
* @return \Spatie\Html\Elements\Fieldset
*/
public function fieldset($legend = null)
{
return $legend ?
Fieldset::create()->legend($legend) : Fieldset::create();
}
/**
* @param string $method
* @param string|null $action
*
* @return \Spatie\Html\Elements\Form
*/
public function form($method = 'POST', $action = null)
{
$method = strtoupper($method);
$form = Form::create();
// If Laravel needs to spoof the form's method, we'll append a hidden
// field containing the actual method
if (in_array($method, ['DELETE', 'PATCH', 'PUT'])) {
$form = $form->addChild($this->hidden('_method')->value($method));
}
// On any other method that get, the form needs a CSRF token
if ($method !== 'GET') {
$form = $form->addChild($this->token());
}
return $form
->method($method === 'GET' ? 'GET' : 'POST')
->attributeIf($action, 'action', $action);
}
/**
* @param string|null $name
* @param string|null $value
*
* @return \Spatie\Html\Elements\Input
*/
public function hidden($name = null, $value = null)
{
return $this->input('hidden', $name, $value);
}
/**
* @param string|null $src
* @param string|null $alt
*
* @return \Spatie\Html\Elements\Img
*/
public function img($src = null, $alt = null)
{
return Img::create()
->attributeIf($src, 'src', $src)
->attributeIf($alt, 'alt', $alt);
}
/**
* @param \Spatie\Html\HtmlElement|iterable|string|null $contents
* @param string|null $for
*
* @return \Spatie\Html\Elements\Label
*/
public function label($contents = null, $for = null)
{
return Label::create()
->attributeIf($for, 'for', $this->fieldName($for))
->children($contents);
}
/**
* @param \Spatie\Html\HtmlElement|string|null $contents
*
* @return \Spatie\Html\Elements\Legend
*/
public function legend($contents = null)
{
return Legend::create()->html($contents);
}
/**
* @param string $email
* @param string|null $text
*
* @return \Spatie\Html\Elements\A
*/
public function mailto($email, $text = null)
{
return $this->a('mailto:'.$email, $text ?: $email);
}
/**
* @param string|null $name
* @param iterable $options
* @param string|iterable|null $value
*
* @return \Spatie\Html\Elements\Select
*/
public function multiselect($name = null, $options = [], $value = null)
{
return Select::create()
->attributeIf($name, 'name', $this->fieldName($name))
->attributeIf($name, 'id', $this->fieldName($name))
->options($options)
->value($name ? $this->old($name, $value) : $value)
->multiple();
}
/**
* @param string|null $name
* @param string|null $value
* @param string|null $min
* @param string|null $max
* @param string|null $step
*
* @return \Spatie\Html\Elements\Input
*/
public function number($name = null, $value = null, $min = null, $max = null, $step = null)
{
return $this->input('number', $name, $value)
->attributeIfNotNull($min, 'min', $min)
->attributeIfNotNull($max, 'max', $max)
->attributeIfNotNull($step, 'step', $step);
}
/**
* @param string|null $text
* @param string|null $value
* @param bool $selected
*
* @return \Spatie\Html\Elements\Option
*/
public function option($text = null, $value = null, $selected = false)
{
return Option::create()
->text($text)
->value($value)
->selectedIf($selected);
}
/**
* @param string|null $value
*
* @return \Spatie\Html\Elements\Input
*/
public function password($name = null)
{
return $this->input('password', $name);
}
/**
* @param string|null $name
* @param bool $checked
* @param string|null $value
*
* @return \Spatie\Html\Elements\Input
*/
public function radio($name = null, $checked = null, $value = null)
{
return $this->input('radio', $name, $value)
->attributeIf($name, 'id', $value === null ? $name : ($name.'_'.Str::slug($value)))
->attributeIf(! is_null($value), 'value', $value)
->attributeIf((! is_null($value) && $this->old($name) == $value) || $checked, 'checked');
}
/**
* @param string|null $name
* @param iterable $options
* @param string|iterable|null $value
*
* @return \Spatie\Html\Elements\Select
*/
public function select($name = null, $options = [], $value = null)
{
return Select::create()
->attributeIf($name, 'name', $this->fieldName($name))
->attributeIf($name, 'id', $this->fieldName($name))
->options($options)
->value($name ? $this->old($name, $value) : $value);
}
/**
* @param \Spatie\Html\HtmlElement|string|null $contents
*
* @return \Spatie\Html\Elements\Span
*/
public function span($contents = null)
{
return Span::create()->children($contents);
}
/**
* @param string|null $text
*
* @return \Spatie\Html\Elements\Button
*/
public function submit($text = null)
{
return $this->button($text, 'submit');
}
/**
* @param string|null $text
*
* @return \Spatie\Html\Elements\Button
*/
public function reset($text = null)
{
return $this->button($text, 'reset');
}
/**
* @param string $number
* @param string|null $text
*
* @return \Spatie\Html\Elements\A
*/
public function tel($number, $text = null)
{
return $this->a('tel:'.$number, $text ?: $number);
}
/**
* @param string|null $name
* @param string|null $value
*
* @return \Spatie\Html\Elements\Input
*/
public function text($name = null, $value = null)
{
return $this->input('text', $name, $value);
}
/**
* @param string|null $name
*
* @return \Spatie\Html\Elements\File
*/
public function file($name = null)
{
return File::create()
->attributeIf($name, 'name', $this->fieldName($name))
->attributeIf($name, 'id', $this->fieldName($name));
}
/**
* @param string|null $name
* @param string|null $value
*
* @return \Spatie\Html\Elements\Textarea
*/
public function textarea($name = null, $value = null)
{
return Textarea::create()
->attributeIf($name, 'name', $this->fieldName($name))
->attributeIf($name, 'id', $this->fieldName($name))
->value($this->old($name, $value));
}
/**
* @return \Spatie\Html\Elements\Input
*/
public function token()
{
return $this
->hidden()
->name('_token')
->value($this->request->session()->token());
}
/**
* @param \ArrayAccess|array $model
*
* @return $this
*/
public function model($model)
{
$this->model = $model;
return $this;
}
/**
* @param \ArrayAccess|array $model
* @param string|null $method
* @param string|null $action
*
* @return \Spatie\Html\Elements\Form
*/
public function modelForm($model, $method = 'POST', $action = null): Form
{
$this->model($model);
return $this->form($method, $action);
}
/**
* @return $this
*/
public function endModel()
{
$this->model = null;
return $this;
}
/**
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function closeModelForm(): Htmlable
{
$this->endModel();
return $this->form()->close();
}
/**
* @param string $name
* @param mixed $value
*
* @return mixed
*/
protected function old($name, $value = null)
{
if (empty($name)) {
return;
}
// Convert array format (sth[1]) to dot notation (sth.1)
$name = preg_replace('/\[(.+)\]/U', '.$1', $name);
// If there's no default value provided, the html builder currently
// has a model assigned and there aren't old input items,
// try to retrieve a value from the model.
if (is_null($value) && $this->model && empty($this->request->old())) {
$value = ($value = data_get($this->model, $name)) instanceof UnitEnum
? $this->getEnumValue($value)
: $value;
}
return $this->request->old($name, $value);
}
/**
* Retrieve the value from the current session or assigned model. This is
* a public alias for `old`.
*
* @param string $name
* @param mixed $value
*
* @return mixed
*/
public function value($name, $default = null)
{
return $this->old($name, $default);
}
/**
* @param string $name
*
* @return string
*/
protected function fieldName($name)
{
return $name;
}
protected function ensureModelIsAvailable()
{
if (empty($this->model)) {
throw new Exception('Method requires a model to be set on the html builder');
}
}
/**
* @param string $value
* @param string $format DateTime formatting string supported by date_format()
* @return string
*/
protected function formatDateTime($value, $format)
{
if (empty($value)) {
return $value;
}
try {
$date = new DateTimeImmutable($value);
return $date->format($format);
} catch (\Exception $e) {
return $value;
}
}
/**
* Get the value from the given enum.
*
* @param \UnitEnum|\BackedEnum $value
* @return string|int
*/
protected function getEnumValue($value)
{
return $value instanceof BackedEnum
? $value->value
: $value->name;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Spatie\Html;
interface HtmlElement
{
/**
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function render();
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Spatie\Html;
use Illuminate\Support\ServiceProvider;
class HtmlServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(Html::class);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Spatie\Html;
interface Selectable
{
/**
* @return static
*/
public function selected();
/**
* @param bool $condition
* @return static
*/
public function selectedIf($condition);
/**
* @return static
*/
public function unselected();
}

View File

@@ -0,0 +1,13 @@
<?php
use Spatie\Html\Html;
if (! function_exists('html')) {
/**
* @return \Spatie\Html\Html
*/
function html()
{
return app(Html::class);
}
}