├── composer.json
├── config
└── laravel-bootstrap-components.php
├── readme.md
├── resources
└── views
│ └── components
│ ├── alert.blade.php
│ ├── badge.blade.php
│ ├── button.blade.php
│ ├── check-label.blade.php
│ ├── check.blade.php
│ ├── close.blade.php
│ ├── color.blade.php
│ ├── datalist.blade.php
│ ├── desc.blade.php
│ ├── dropdown-item.blade.php
│ ├── dropdown.blade.php
│ ├── error.blade.php
│ ├── form.blade.php
│ ├── help.blade.php
│ ├── icon.blade.php
│ ├── image.blade.php
│ ├── input-addon.blade.php
│ ├── input.blade.php
│ ├── label.blade.php
│ ├── link.blade.php
│ ├── nav-dropdown.blade.php
│ ├── nav-link.blade.php
│ ├── pagination.blade.php
│ ├── progress.blade.php
│ ├── radio.blade.php
│ ├── select.blade.php
│ └── textarea.blade.php
└── src
├── Providers
└── LaravelBootstrapComponentsProvider.php
└── Traits
└── WithModel.php
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bastinald/laravel-bootstrap-components",
3 | "homepage": "https://github.com/bastinald/laravel-bootstrap-components",
4 | "description": "Laravel Bootstrap Blade components.",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Kevin Dion",
9 | "email": "bastinald@icloud.com",
10 | "role": "Developer"
11 | }
12 | ],
13 | "require": {
14 | "laravel/framework": "^8.0"
15 | },
16 | "autoload": {
17 | "psr-4": {
18 | "Bastinald\\LaravelBootstrapComponents\\": "src"
19 | }
20 | },
21 | "extra": {
22 | "laravel": {
23 | "providers": [
24 | "Bastinald\\LaravelBootstrapComponents\\Providers\\LaravelBootstrapComponentsProvider"
25 | ]
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/config/laravel-bootstrap-components.php:
--------------------------------------------------------------------------------
1 | 'solid',
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Use With Model Trait
23 | |--------------------------------------------------------------------------
24 | |
25 | | This value specifies if you are using the WithModel trait for modelled
26 | | form data in your Livewire components. This trait allows you to use a
27 | | single $model property for form data, rather than a ton of separate ones.
28 | |
29 | */
30 |
31 | 'use_with_model_trait' => true,
32 |
33 | ];
34 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Laravel Bootstrap Components
2 |
3 | This package contains a set of useful Bootstrap Laravel Blade components. It promotes DRY principles and allows you to keep your HTML nice and clean. Components include alerts, badges, buttons, form inputs (with automatic error feedback), dropdowns, navs, pagination (responsive), and more. The components come with Laravel Livewire integration built in, so you can use them with or without Livewire.
4 |
5 | ## Documentation
6 |
7 | - [Requirements](#requirements)
8 | - [Installation](#installation)
9 | - [Components](#components)
10 | - [Alert](#alert)
11 | - [Badge](#badge)
12 | - [Button](#button)
13 | - [Check](#check)
14 | - [Close](#close)
15 | - [Color](#color)
16 | - [Datalist](#datalist)
17 | - [Dropdown](#dropdown)
18 | - [Dropdown Item](#dropdown-item)
19 | - [Icon](#icon)
20 | - [Image](#image)
21 | - [Input](#input)
22 | - [Link](#link)
23 | - [Nav Dropdown](#nav-dropdown)
24 | - [Nav Link](#nav-link)
25 | - [Pagination](#pagination)
26 | - [Progress](#progress)
27 | - [Radio](#radio)
28 | - [Select](#select)
29 | - [Textarea](#textarea)
30 | - [Traits](#traits)
31 | - [WithModel](#withmodel)
32 | - [Publishing Assets](#publishing-assets)
33 | - [Custom Views](#custom-views)
34 | - [Custom Icons](#custom-icons)
35 |
36 | ## Requirements
37 |
38 | - Bootstrap 5 must be installed via webpack first
39 | - Font Awesome must be installed to use icons
40 |
41 | ## Installation
42 |
43 | Require the package via composer:
44 |
45 | ```console
46 | composer require bastinald/laravel-bootstrap-components
47 | ```
48 |
49 | ## Components
50 |
51 | ### Alert
52 |
53 | A Bootstrap alert:
54 |
55 | ```html
56 |
61 | ```
62 |
63 | #### Available Props & Slots
64 |
65 | - `icon`: Font Awesome icon to show before label e.g. `cog`, `envelope`
66 | - `label`: label to display, can also be placed in the `slot`
67 | - `color`: Bootstrap color e.g. `primary`, `danger`, `success`
68 | - `dismissible`: set the alert to be dismissible
69 |
70 | ---
71 |
72 | ### Badge
73 |
74 | A Bootstrap badge:
75 |
76 | ```html
77 |
81 | ```
82 |
83 | #### Available Props & Slots
84 |
85 | - `icon`: Font Awesome icon to show before label e.g. `cog`, `envelope`
86 | - `label`: label to display, can also be placed in the `slot`
87 | - `color`: Bootstrap color e.g. `primary`, `danger`, `success`
88 |
89 | ---
90 |
91 | ### Button
92 |
93 | A Bootstrap button:
94 |
95 | ```html
96 |
102 | ```
103 |
104 | #### Available Props & Slots
105 |
106 | - `icon`: Font Awesome icon to show before label e.g. `cog`, `envelope`
107 | - `label`: label to display, can also be placed in the `slot`
108 | - `color`: Bootstrap color e.g. `primary`, `danger`, `success`
109 | - `size`: Bootstrap button size e.g. `sm`, `lg`
110 | - `type`: button type e.g. `button`, `submit`
111 | - `route`: sets the `href` to a route
112 | - `url`: sets the `href` to a url
113 | - `href`: sets the `href`
114 | - `dismiss`: a `data-bs-dismiss` value e.g. `alert`, `modal`
115 | - `toggle`: a `data-bs-toggle` value e.g. `collapse`, `dropdown`
116 | - `click`: Livewire action on click
117 | - `confirm`: prompts the user for confirmation on click
118 |
119 | ---
120 |
121 | ### Check
122 |
123 | A Bootstrap checkbox input:
124 |
125 | ```html
126 |
133 | ```
134 |
135 | #### Available Props & Slots
136 |
137 | - `label`: label to display above the input
138 | - `checkLabel`: label to display beside the input
139 | - `help`: helper label to display under the input
140 | - `switch`: style the input as a switch
141 | - `model`: Livewire model property key
142 | - `lazy`: bind Livewire data on change
143 |
144 | ---
145 |
146 | ### Close
147 |
148 | A Bootstrap close button:
149 |
150 | ```html
151 |
154 | ```
155 |
156 | #### Available Props & Slots
157 |
158 | - `color`: Bootstrap close color e.g. `white`
159 | - `dismiss`: a `data-bs-dismiss` value e.g. `alert`, `modal`
160 |
161 | ---
162 |
163 | ### Color
164 |
165 | A Bootstrap color picker input:
166 |
167 | ```html
168 |
175 | ```
176 |
177 | #### Available Props & Slots
178 |
179 | - `label`: label to display above the input
180 | - `icon`: Font Awesome icon to show before input e.g. `cog`, `envelope`
181 | - `prepend`: addon to display before input, can be used via named slot
182 | - `append`: addon to display after input, can be used via named slot
183 | - `size`: Bootstrap input size e.g. `sm`, `lg`
184 | - `help`: helper label to display under the input
185 | - `model`: Livewire model property key
186 | - `lazy`: bind Livewire data on change
187 |
188 | ---
189 |
190 | ### Datalist
191 |
192 | A Bootstrap datalist input:
193 |
194 | ```html
195 |
203 | ```
204 |
205 | #### Available Props & Slots
206 |
207 | - `label`: label to display above the input
208 | - `options`: array of input options e.g. `['Red', 'Blue']`
209 | - `icon`: Font Awesome icon to show before input e.g. `cog`, `envelope`
210 | - `prepend`: addon to display before input, can be used via named slot
211 | - `append`: addon to display after input, can be used via named slot
212 | - `size`: Bootstrap input size e.g. `sm`, `lg`
213 | - `help`: helper label to display under the input
214 | - `model`: Livewire model property key
215 | - `debounce`: time in ms to bind Livewire data on keyup e.g. `500`
216 | - `lazy`: bind Livewire data on change
217 |
218 | ---
219 |
220 | ### Desc
221 |
222 | A description list:
223 |
224 | ```html
225 |
229 | ```
230 |
231 | #### Available Props & Slots
232 |
233 | - `tern`: the description list term
234 | - `details`: the description list details, can also be placed in the `slot`
235 | - `date`: date to use instead of details (for use with [Laravel Timezone](https://github.com/jamesmills/laravel-timezone))
236 |
237 | ---
238 |
239 | ### Dropdown
240 |
241 | A Bootstrap dropdown:
242 |
243 | ```html
244 |
248 |
252 |
256 |
257 | ```
258 |
259 | #### Available Props & Slots
260 |
261 | - `icon`: Font Awesome icon to show before label e.g. `cog`, `envelope`
262 | - `label`: dropdown label to display, can be used via named slot
263 | - `items`: dropdown items, can also be placed in the `slot`
264 | - `color`: Bootstrap color e.g. `primary`, `danger`, `success`
265 | - `size`: Bootstrap button size e.g. `sm`, `lg`
266 |
267 | ---
268 |
269 | ### Dropdown Item
270 |
271 | A Bootstrap dropdown menu item:
272 |
273 | ```html
274 |
278 | ```
279 |
280 | #### Available Props & Slots
281 |
282 | - `icon`: Font Awesome icon to show before label e.g. `cog`, `envelope`
283 | - `label`: label to display, can also be placed in the `slot`
284 | - `route`: sets the `href` to a route
285 | - `url`: sets the `href` to a url
286 | - `href`: sets the `href`
287 |
288 | ---
289 |
290 | ### Form
291 |
292 | A Bootstrap form:
293 |
294 | ```html
295 |
296 |
297 |
298 |
299 |
300 | ```
301 |
302 | #### Available Props & Slots
303 |
304 | - `submit`: Livewire action on submit
305 |
306 | ### Icon
307 |
308 | A Font Awesome icon:
309 |
310 | ```html
311 |
314 | ```
315 |
316 | #### Available Props & Slots
317 |
318 | - `name`: Font Awesome icon name e.g. `cog`, `rocket`
319 | - `style`: Font Awesome icon style e.g. `solid`, `regular`, `brands`
320 | - `size`: Font Awesome icon size e.g. `sm`, `lg`, `3x`, `5x`
321 | - `color`: Bootstrap color e.g. `primary`, `danger`, `success`
322 | - `spin`: sets the icon to use a spin animation
323 | - `pulse`: sets the icon to use a pulse animation
324 |
325 | ---
326 |
327 | ### Image
328 |
329 | An image:
330 |
331 | ```html
332 |
337 | ```
338 |
339 | #### Available Props & Slots
340 |
341 | - `asset`: sets the `src` to an asset
342 | - `src`: sets the `src`
343 | - `fluid`: sets the image to be fluid width
344 | - `thumbnail`: sets the image to use thumbnail styling
345 | - `rounded`: sets the image to have rounded corners
346 |
347 | ---
348 |
349 | ### Input
350 |
351 | A Bootstrap text input:
352 |
353 | ```html
354 |
360 |
361 |
362 |
363 |
364 | ```
365 |
366 | #### Available Props & Slots
367 |
368 | - `label`: label to display above the input
369 | - `type`: input type e.g. `text`, `email`
370 | - `icon`: Font Awesome icon to show before input e.g. `cog`, `envelope`
371 | - `prepend`: addon to display before input, can be used via named slot
372 | - `append`: addon to display after input, can be used via named slot
373 | - `size`: Bootstrap input size e.g. `sm`, `lg`
374 | - `help`: helper label to display under the input
375 | - `model`: Livewire model property key
376 | - `debounce`: time in ms to bind Livewire data on keyup e.g. `500`
377 | - `lazy`: bind Livewire data on change
378 |
379 | ---
380 |
381 | ### Link
382 |
383 | A hyperlink:
384 |
385 | ```html
386 |
390 | ```
391 |
392 | #### Available Props & Slots
393 |
394 | - `icon`: Font Awesome icon to show before label e.g. `cog`, `envelope`
395 | - `label`: label to display, can also be placed in the `slot`
396 | - `route`: sets the `href` to a route
397 | - `url`: sets the `href` to a url
398 | - `href`: sets the `href`
399 |
400 | ---
401 |
402 | ### Nav Dropdown
403 |
404 | A Bootstrap nav dropdown:
405 |
406 | ```html
407 |
410 |
414 |
418 |
419 | ```
420 |
421 | #### Available Props & Slots
422 |
423 | - `icon`: Font Awesome icon to show before label e.g. `cog`, `envelope`
424 | - `label`: dropdown label to display, can be used via named slot
425 | - `items`: dropdown items, can also be placed in the `slot`
426 |
427 | ---
428 |
429 | ### Nav Link
430 |
431 | A Bootstrap nav link:
432 |
433 | ```html
434 |
438 | ```
439 |
440 | #### Available Props & Slots
441 |
442 | - `icon`: Font Awesome icon to show before label e.g. `cog`, `envelope`
443 | - `label`: label to display, can also be placed in the `slot`
444 | - `route`: sets the `href` to a route
445 | - `url`: sets the `href` to a url
446 | - `href`: sets the `href`
447 |
448 | ---
449 |
450 | ### Pagination
451 |
452 | Responsive Bootstrap pagination links:
453 |
454 | ```html
455 |
459 | ```
460 |
461 | #### Available Props & Slots
462 |
463 | - `links`: paginated Laravel models
464 | - `justify`: Bootstrap justification e.g. `start`, `end`
465 |
466 | ---
467 |
468 | ### Progress
469 |
470 | A Bootstrap progress bar:
471 |
472 | ```html
473 |
481 | ```
482 |
483 | #### Available Props & Slots
484 |
485 | - `label`: label to display inside the progress bar
486 | - `percent`: percentage of the progress bar
487 | - `color`: Bootstrap color e.g. `primary`, `danger`, `success`
488 | - `height`: height of the progress bar in pixels
489 | - `animated`: animate the progress bar
490 | - `striped`: use striped styling for the progress bar
491 |
492 | ---
493 |
494 | ### Radio
495 |
496 | A Bootstrap radio input:
497 |
498 | ```html
499 |
506 | ```
507 |
508 | #### Available Props & Slots
509 |
510 | - `label`: label to display above the input
511 | - `options`: array of input options e.g. `['Red', 'Blue']`
512 | - `help`: helper label to display under the input
513 | - `switch`: sets the input to use a switch style
514 | - `model`: Livewire model property key
515 | - `lazy`: bind Livewire data on change
516 |
517 | ---
518 |
519 | ### Select
520 |
521 | A Bootstrap select input:
522 |
523 | ```html
524 |
533 | ```
534 |
535 | #### Available Props & Slots
536 |
537 | - `label`: label to display above the input
538 | - `placeholder`: placeholder to use for the empty first option
539 | - `options`: array of input options e.g. `['Red', 'Blue']`
540 | - `icon`: Font Awesome icon to show before input e.g. `cog`, `envelope`
541 | - `prepend`: addon to display before input, can be used via named slot
542 | - `append`: addon to display after input, can be used via named slot
543 | - `size`: Bootstrap input size e.g. `sm`, `lg`
544 | - `help`: helper label to display under the input
545 | - `model`: Livewire model property key
546 | - `lazy`: bind Livewire data on change
547 |
548 | ---
549 |
550 | ### Textarea
551 |
552 | A Bootstrap textarea input:
553 |
554 | ```html
555 |
561 | ```
562 |
563 | #### Available Props & Slots
564 |
565 | - `label`: label to display above the input
566 | - `icon`: Font Awesome icon to show before input e.g. `cog`, `envelope`
567 | - `prepend`: addon to display before input, can be used via named slot
568 | - `append`: addon to display after input, can be used via named slot
569 | - `size`: Bootstrap input size e.g. `sm`, `lg`
570 | - `help`: helper label to display under the input
571 | - `model`: Livewire model property key
572 | - `debounce`: time in ms to bind Livewire data on keyup e.g. `500`
573 | - `lazy`: bind Livewire data on change
574 |
575 | ## Traits
576 |
577 | ### WithModel
578 |
579 | This trait makes form data model manipulation a breeze. No more having to create a Livewire component property for every single form input. All form data will be placed inside the `$model` property array.
580 |
581 | #### Getting Model Data
582 |
583 | Get the model data as a collection:
584 |
585 | ```php
586 | $collection = $this->model();
587 | ```
588 |
589 | #### Setting Model Data
590 |
591 | Set a single value:
592 |
593 | ```php
594 | $this->setModel('name', 'Kevin');
595 | ```
596 |
597 | Set values using Eloquent model data:
598 |
599 | ```php
600 | $this->setModel(User::first());
601 | ```
602 |
603 | Set values using an array:
604 |
605 | ```php
606 | $this->setModel([
607 | 'name' => 'Kevin',
608 | 'email' => 'kevin@example.com',
609 | ]);
610 | ```
611 |
612 | #### Working With Arrays
613 |
614 | Add an empty array item:
615 |
616 | ```php
617 | $this->addModelItem('locations');
618 | ```
619 |
620 | Remove an array item by its key:
621 |
622 | ```php
623 | $this->removeModelItem('locations', 3);
624 | ```
625 |
626 | Order an array item by its key & direction:
627 |
628 | ```php
629 | $this->orderModelItem('locations', 3, 'up');
630 | ```
631 |
632 | The direction should be `up` or `down`.
633 |
634 | #### Binding Model Data
635 |
636 | Package components work with this trait via the `model` attribute:
637 |
638 | ```html
639 |
640 |
641 | ```
642 |
643 | #### Validating Model Data
644 |
645 | Use the `validateModel` method to validate model data:
646 |
647 | ```php
648 | $this->validateModel([
649 | 'name' => ['required'],
650 | 'email' => ['required', 'email'],
651 | ]);
652 | ```
653 |
654 | This method works just like the Livewire `validate` method, so you can specify your rules in a separate `rules` method if you prefer.
655 |
656 | ## Publishing Assets
657 |
658 | ### Custom Views
659 |
660 | Use your own component views by publishing the package views:
661 |
662 | ```console
663 | php artisan vendor:publish --tag=laravel-bootstrap-components:views
664 | ```
665 |
666 | Now edit the files inside `resources/views/vendor/bs`. The package will use these files to render the components.
667 |
668 | ### Custom Icons
669 |
670 | Use your own font icons by publishing the package config:
671 |
672 | ```console
673 | php artisan vendor:publish --tag=laravel-bootstrap-components:config
674 | ```
675 |
676 | Now edit the `icon_class_prefix` value inside `config/laravel-bootstrap-components.php`. The package will use this class to render the icons.
677 |
--------------------------------------------------------------------------------
/resources/views/components/alert.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | 'color' => 'success',
5 | 'dismissible' => false,
6 | ])
7 |
8 | @php
9 | $attributes = $attributes->class([
10 | 'alert alert-' . $color . ' fade show mb-0',
11 | 'alert-dismissible' => $dismissible,
12 | ])->merge([
13 | //
14 | ]);
15 | @endphp
16 |
17 |
18 |
19 |
20 | {{ $label ?? $slot }}
21 |
22 | @if($dismissible)
23 |
24 | @endif
25 |
26 |
--------------------------------------------------------------------------------
/resources/views/components/badge.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | 'color' => 'primary',
5 | ])
6 |
7 | @php
8 | $attributes = $attributes->class([
9 | 'badge bg-' . $color,
10 | ])->merge([
11 | //
12 | ]);
13 | @endphp
14 |
15 |
16 |
17 |
18 | {{ $label ?? $slot }}
19 |
20 |
--------------------------------------------------------------------------------
/resources/views/components/button.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | 'color' => 'primary',
5 | 'size' => null,
6 | 'type' => 'button',
7 | 'route' => null,
8 | 'url' => null,
9 | 'href' => null,
10 | 'dismiss' => null,
11 | 'toggle' => null,
12 | 'click' => null,
13 | 'confirm' => false,
14 | ])
15 |
16 | @php
17 | if ($route) $href = route($route);
18 | else if ($url) $href = url($url);
19 |
20 | $attributes = $attributes->class([
21 | 'btn btn-' . $color,
22 | 'btn-' . $size => $size,
23 | ])->merge([
24 | 'type' => !$href ? $type : null,
25 | 'href' => $href,
26 | 'data-bs-dismiss' => $dismiss,
27 | 'data-bs-toggle' => $toggle,
28 | 'wire:click' => $click,
29 | 'onclick' => $confirm ? 'confirm(\'' . __('Are you sure?') . '\') || event.stopImmediatePropagation()' : null,
30 | ]);
31 | @endphp
32 |
33 | <{{ $href ? 'a' : 'button' }} {{ $attributes }}>
34 |
35 |
36 | {{ $label ?? $slot }}
37 | {{ $href ? 'a' : 'button' }}>
38 |
--------------------------------------------------------------------------------
/resources/views/components/check-label.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | ])
4 |
5 | @php
6 | $attributes = $attributes->class([
7 | 'form-check-label',
8 | ])->merge([
9 | //
10 | ]);
11 | @endphp
12 |
13 | @if($label || !$slot->isEmpty())
14 |
17 | @endif
18 |
--------------------------------------------------------------------------------
/resources/views/components/check.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | 'checkLabel' => null,
4 | 'help' => null,
5 | 'switch' => false,
6 | 'model' => null,
7 | 'lazy' => false,
8 | ])
9 |
10 | @php
11 | if ($lazy) $bind = 'lazy';
12 | else $bind = 'defer';
13 |
14 | $wireModel = $attributes->whereStartsWith('wire:model')->first();
15 | $key = $attributes->get('name', $model ?? $wireModel);
16 | $id = $attributes->get('id', $model ?? $wireModel);
17 | $prefix = config('laravel-bootstrap-components.use_with_model_trait') ? 'model.' : null;
18 |
19 | $attributes = $attributes->class([
20 | 'form-check-input',
21 | 'is-invalid' => $errors->has($key),
22 | ])->merge([
23 | 'type' => 'checkbox',
24 | 'id' => $id,
25 | 'wire:model.' . $bind => $model ? $prefix . $model : null,
26 | ]);
27 | @endphp
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/resources/views/components/close.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'color' => null,
3 | 'dismiss' => null,
4 | ])
5 |
6 | @php
7 | $attributes = $attributes->class([
8 | 'btn-close',
9 | 'btn-close-' . $color => $color,
10 | ])->merge([
11 | 'type' => 'button',
12 | 'data-bs-dismiss' => $dismiss,
13 | ]);
14 | @endphp
15 |
16 |
17 |
--------------------------------------------------------------------------------
/resources/views/components/color.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | 'icon' => null,
4 | 'prepend' => null,
5 | 'append' => null,
6 | 'size' => null,
7 | 'help' => null,
8 | 'model' => null,
9 | 'lazy' => false,
10 | ])
11 |
12 | @php
13 | if ($lazy) $bind = 'lazy';
14 | else $bind = 'defer';
15 |
16 | $wireModel = $attributes->whereStartsWith('wire:model')->first();
17 | $key = $attributes->get('name', $model ?? $wireModel);
18 | $id = $attributes->get('id', $model ?? $wireModel);
19 | $prefix = config('laravel-bootstrap-components.use_with_model_trait') ? 'model.' : null;
20 |
21 | $attributes = $attributes->class([
22 | 'form-control form-control-color',
23 | 'form-control-' . $size => $size,
24 | 'rounded-end' => !$append,
25 | 'is-invalid' => $errors->has($key),
26 | ])->merge([
27 | 'type' => 'color',
28 | 'id' => $id,
29 | 'wire:model.' . $bind => $model ? $prefix . $model : null,
30 | ]);
31 | @endphp
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/resources/views/components/datalist.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | 'options' => [],
4 | 'icon' => null,
5 | 'prepend' => null,
6 | 'append' => null,
7 | 'size' => null,
8 | 'help' => null,
9 | 'model' => null,
10 | 'debounce' => null,
11 | 'lazy' => false,
12 | ])
13 |
14 | @php
15 | if ($debounce) $bind = 'debounce.' . (ctype_digit($debounce) ? $debounce : 150) . 'ms';
16 | else if ($lazy) $bind = 'lazy';
17 | else $bind = 'defer';
18 |
19 | $wireModel = $attributes->whereStartsWith('wire:model')->first();
20 | $key = $attributes->get('name', $model ?? $wireModel);
21 | $id = $attributes->get('id', $model ?? $wireModel);
22 | $prefix = config('laravel-bootstrap-components.use_with_model_trait') ? 'model.' : null;
23 | $list = $attributes->get('list', $key . '_list');
24 |
25 | $attributes = $attributes->class([
26 | 'form-control',
27 | 'form-control-' . $size => $size,
28 | 'rounded-end' => !$append,
29 | 'is-invalid' => $errors->has($key),
30 | ])->merge([
31 | 'list' => $list,
32 | 'id' => $id,
33 | 'wire:model.' . $bind => $model ? $prefix . $model : null,
34 | ]);
35 | @endphp
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/resources/views/components/desc.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'term' => null,
3 | 'details' => null,
4 | 'date' => null,
5 | ])
6 |
7 | @php
8 | $attributes = $attributes->class([
9 | 'mb-0',
10 | ])->merge([
11 | //
12 | ]);
13 | @endphp
14 |
15 |
16 | - {{ $term }}
17 |
18 | -
19 | @if($details || !$slot->isEmpty())
20 | {{ $details ?? $slot }}
21 | @elseif($date)
22 | @displayDate($date)
23 | @else
24 | {{ __('N/A') }}
25 | @endif
26 |
27 |
28 |
--------------------------------------------------------------------------------
/resources/views/components/dropdown-item.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | 'route' => null,
5 | 'url' => null,
6 | 'href' => null,
7 | 'click' => null,
8 | ])
9 |
10 | @php
11 | if ($route) $href = route($route);
12 | else if ($url) $href = url($url);
13 |
14 | $attributes = $attributes->class([
15 | 'dropdown-item',
16 | 'active' => $href == Request::url(),
17 | ])->merge([
18 | 'type' => !$href ? 'button' : null,
19 | 'href' => $href,
20 | 'wire:click' => $click,
21 | ]);
22 | @endphp
23 |
24 | <{{ $href ? 'a' : 'button' }} {{ $attributes }}>
25 |
26 |
27 | {{ $label ?? $slot }}
28 | {{ $href ? 'a' : 'button' }}>
29 |
--------------------------------------------------------------------------------
/resources/views/components/dropdown.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | 'items' => null,
5 | 'color' => 'primary',
6 | 'size' => null,
7 | ])
8 |
9 | @php
10 | $attributes = $attributes->class([
11 | 'btn btn-' . $color,
12 | 'btn-' . $size => $size,
13 | 'dropdown-toggle',
14 | 'border-0 p-0' => $color == 'link',
15 | ])->merge([
16 | 'type' => 'button',
17 | 'data-bs-toggle' => 'dropdown',
18 | ]);
19 | @endphp
20 |
21 |
22 |
27 |
28 |
31 |
32 |
--------------------------------------------------------------------------------
/resources/views/components/error.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'key' => null,
3 | ])
4 |
5 | @php
6 | $attributes = $attributes->class([
7 | 'invalid-feedback',
8 | ])->merge([
9 | //
10 | ]);
11 | @endphp
12 |
13 | @error($key)
14 |
15 | {{ $message }}
16 |
17 | @enderror
18 |
--------------------------------------------------------------------------------
/resources/views/components/form.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'submit' => null,
3 | ])
4 |
5 | @php
6 | $attributes = $attributes->class([
7 | //
8 | ])->merge([
9 | 'wire:submit.prevent' => $submit
10 | ]);
11 | @endphp
12 |
13 |
16 |
--------------------------------------------------------------------------------
/resources/views/components/help.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | ])
4 |
5 | @php
6 | $attributes = $attributes->class([
7 | 'form-text',
8 | ])->merge([
9 | //
10 | ]);
11 | @endphp
12 |
13 | @if($label || !$slot->isEmpty())
14 |
15 | {{ $label ?? $slot }}
16 |
17 | @endif
18 |
--------------------------------------------------------------------------------
/resources/views/components/icon.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'name' => null,
3 | 'style' => config('laravel-bootstrap-components.font_awesome_style'),
4 | 'size' => null,
5 | 'color' => null,
6 | 'spin' => false,
7 | 'pulse' => false,
8 | ])
9 |
10 | @php
11 | $attributes = $attributes->class([
12 | 'fa' . Str::limit($style, 1, null) . ' fa-fw fa-' . $name,
13 | 'fa-' . $size => $size,
14 | 'text-' . $color => $color,
15 | 'fa-spin' => $spin,
16 | 'fa-pulse' => $pulse,
17 | ])->merge([
18 | //
19 | ]);
20 | @endphp
21 |
22 | @if($name)
23 |
24 | @endif
25 |
--------------------------------------------------------------------------------
/resources/views/components/image.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'asset' => null,
3 | 'mix' => null,
4 | 'src' => null,
5 | 'fluid' => false,
6 | 'thumbnail' => false,
7 | 'rounded' => false,
8 | ])
9 |
10 | @php
11 | if ($asset) $src = asset($asset);
12 | else if ($mix) $src = mix($mix);
13 |
14 | $attributes = $attributes->class([
15 | 'img-fluid' => $fluid,
16 | 'img-thumbnail' => $thumbnail,
17 | 'rounded' => $rounded,
18 | ])->merge([
19 | 'src' => $src,
20 | ]);
21 | @endphp
22 |
23 |
24 |
--------------------------------------------------------------------------------
/resources/views/components/input-addon.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | ])
5 |
6 | @php
7 | $attributes = $attributes->class([
8 | 'input-group-text',
9 | ])->merge([
10 | //
11 | ]);
12 | @endphp
13 |
14 | @if($icon || $label || !$slot->isEmpty())
15 |
16 |
17 |
18 | {{ $label ?? $slot }}
19 |
20 | @endif
21 |
--------------------------------------------------------------------------------
/resources/views/components/input.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | 'type' => 'text',
4 | 'icon' => null,
5 | 'prepend' => null,
6 | 'append' => null,
7 | 'size' => null,
8 | 'help' => null,
9 | 'model' => null,
10 | 'debounce' => false,
11 | 'lazy' => false,
12 | ])
13 |
14 | @php
15 | if ($type == 'number') $inputmode = 'decimal';
16 | else if (in_array($type, ['tel', 'search', 'email', 'url'])) $inputmode = $type;
17 | else $inputmode = 'text';
18 |
19 | if ($debounce) $bind = 'debounce.' . (ctype_digit($debounce) ? $debounce : 150) . 'ms';
20 | else if ($lazy) $bind = 'lazy';
21 | else $bind = 'defer';
22 |
23 | $wireModel = $attributes->whereStartsWith('wire:model')->first();
24 | $key = $attributes->get('name', $model ?? $wireModel);
25 | $id = $attributes->get('id', $model ?? $wireModel);
26 | $prefix = config('laravel-bootstrap-components.use_with_model_trait') ? 'model.' : null;
27 |
28 | $attributes = $attributes->class([
29 | 'form-control',
30 | 'form-control-' . $size => $size,
31 | 'rounded-end' => !$append,
32 | 'is-invalid' => $errors->has($key),
33 | ])->merge([
34 | 'type' => $type,
35 | 'inputmode' => $inputmode,
36 | 'id' => $id,
37 | 'wire:model.' . $bind => $model ? $prefix . $model : null,
38 | ]);
39 | @endphp
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/resources/views/components/label.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | ])
4 |
5 | @php
6 | $attributes = $attributes->class([
7 | 'form-label',
8 | ])->merge([
9 | //
10 | ]);
11 | @endphp
12 |
13 | @if($label || !$slot->isEmpty())
14 |
17 | @endif
18 |
--------------------------------------------------------------------------------
/resources/views/components/link.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | 'color' => null,
5 | 'route' => null,
6 | 'url' => null,
7 | 'href' => '#',
8 | 'click' => null,
9 | ])
10 |
11 | @php
12 | if ($route) $href = route($route);
13 | else if ($url) $href = url($url);
14 |
15 | $attributes = $attributes->class([
16 | 'text-' . $color => $color,
17 | ])->merge([
18 | 'href' => $href,
19 | 'wire:click.prevent' => $click,
20 | ]);
21 | @endphp
22 |
23 |
24 |
25 |
26 | {{ $label ?? $slot }}
27 |
28 |
--------------------------------------------------------------------------------
/resources/views/components/nav-dropdown.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | 'items' => null,
5 | ])
6 |
7 | @php
8 | $attributes = $attributes->class([
9 | 'nav-link',
10 | 'dropdown-toggle',
11 | ])->merge([
12 | 'href' => '#',
13 | 'data-bs-toggle' => 'dropdown',
14 | ]);
15 | @endphp
16 |
17 |
28 |
--------------------------------------------------------------------------------
/resources/views/components/nav-link.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'icon' => null,
3 | 'label' => null,
4 | 'route' => null,
5 | 'url' => null,
6 | 'href' => null,
7 | 'click' => null,
8 | ])
9 |
10 | @php
11 | if ($route) $href = route($route);
12 | else if ($url) $href = url($url);
13 |
14 | $attributes = $attributes->class([
15 | 'nav-link',
16 | 'active' => $href == Request::url(),
17 | ])->merge([
18 | 'href' => $href,
19 | 'wire:click.prevent' => $click,
20 | ]);
21 | @endphp
22 |
23 |
24 |
25 |
26 | {{ $label ?? $slot }}
27 |
28 |
--------------------------------------------------------------------------------
/resources/views/components/pagination.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'links' => null,
3 | 'justify' => 'center',
4 | ])
5 |
6 | @php
7 | $attributes = $attributes->class([
8 | 'd-flex',
9 | 'justify-content-' . $justify => $justify,
10 | ])->merge([
11 | //
12 | ]);
13 | @endphp
14 |
15 | @if($links->hasPages())
16 |
17 | @if(isset($this) && method_exists($this, 'initializeWithPagination'))
18 |
19 | {{ $links->links('livewire::simple-bootstrap') }}
20 |
21 |
22 |
23 | {{ $links->links('livewire::bootstrap') }}
24 |
25 | @else
26 |
27 | {{ $links->links('pagination::simple-bootstrap-4') }}
28 |
29 |
30 |
31 | {{ $links->links('pagination::bootstrap-4') }}
32 |
33 | @endif
34 |
35 | @endif
36 |
--------------------------------------------------------------------------------
/resources/views/components/progress.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | 'percent' => 0,
4 | 'color' => 'primary',
5 | 'height' => null,
6 | 'animated' => false,
7 | 'striped' => false,
8 | ])
9 |
10 | @php
11 | $attributes = $attributes->class([
12 | 'progress-bar',
13 | 'progress-bar-animated' => $animated,
14 | 'progress-bar-striped' => $striped,
15 | 'bg-' . $color => $color,
16 | ])->merge([
17 | 'style' => 'width: ' . $percent . '%',
18 | ]);
19 | @endphp
20 |
21 |
22 |
23 | {{ $label ?? $slot }}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/resources/views/components/radio.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | 'options' => [],
4 | 'help' => null,
5 | 'switch' => false,
6 | 'model' => null,
7 | 'lazy' => false,
8 | ])
9 |
10 | @php
11 | if ($lazy) $bind = 'lazy';
12 | else $bind = 'defer';
13 |
14 | $wireModel = $attributes->whereStartsWith('wire:model')->first();
15 | $key = $attributes->get('name', $model ?? $wireModel);
16 | $id = $attributes->get('id', $model ?? $wireModel);
17 | $prefix = config('laravel-bootstrap-components.use_with_model_trait') ? 'model.' : null;
18 | $options = Arr::isAssoc($options) ? $options : array_combine($options, $options);
19 |
20 | $attributes = $attributes->class([
21 | 'form-check-input',
22 | 'is-invalid' => $errors->has($key),
23 | ])->merge([
24 | 'type' => 'radio',
25 | 'name' => $key,
26 | 'wire:model.' . $bind => $model ? $prefix . $model : null,
27 | ]);
28 | @endphp
29 |
30 |
31 |
32 |
33 | @foreach($options as $optionValue => $optionLabel)
34 |
35 | @php($optionId = $id . '_' . $loop->index)
36 |
37 | merge(['id' => $optionId, 'value' => $optionValue]) }}>
38 |
39 |
40 |
41 | @if($loop->last)
42 |
43 |
44 |
45 | @endif
46 |
47 | @endforeach
48 |
49 |
--------------------------------------------------------------------------------
/resources/views/components/select.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | 'placeholder' => null,
4 | 'options' => [],
5 | 'icon' => null,
6 | 'prepend' => null,
7 | 'append' => null,
8 | 'size' => null,
9 | 'help' => null,
10 | 'model' => null,
11 | 'lazy' => false,
12 | ])
13 |
14 | @php
15 | if ($lazy) $bind = 'lazy';
16 | else $bind = 'defer';
17 |
18 | $wireModel = $attributes->whereStartsWith('wire:model')->first();
19 | $key = $attributes->get('name', $model ?? $wireModel);
20 | $id = $attributes->get('id', $model ?? $wireModel);
21 | $prefix = config('laravel-bootstrap-components.use_with_model_trait') ? 'model.' : null;
22 | $options = Arr::isAssoc($options) ? $options : array_combine($options, $options);
23 |
24 | $attributes = $attributes->class([
25 | 'form-select',
26 | 'form-select-' . $size => $size,
27 | 'rounded-end' => !$append,
28 | 'is-invalid' => $errors->has($key),
29 | ])->merge([
30 | 'id' => $id,
31 | 'wire:model.' . $bind => $model ? $prefix . $model : null,
32 | ]);
33 | @endphp
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/resources/views/components/textarea.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'label' => null,
3 | 'icon' => null,
4 | 'prepend' => null,
5 | 'append' => null,
6 | 'rows' => 3,
7 | 'size' => null,
8 | 'help' => null,
9 | 'model' => null,
10 | 'debounce' => false,
11 | 'lazy' => false,
12 | ])
13 |
14 | @php
15 | if ($debounce) $bind = 'debounce.' . (ctype_digit($debounce) ? $debounce : 150) . 'ms';
16 | else if ($lazy) $bind = 'lazy';
17 | else $bind = 'defer';
18 |
19 | $wireModel = $attributes->whereStartsWith('wire:model')->first();
20 | $key = $attributes->get('name', $model ?? $wireModel);
21 | $id = $attributes->get('id', $model ?? $wireModel);
22 | $prefix = config('laravel-bootstrap-components.use_with_model_trait') ? 'model.' : null;
23 |
24 | $attributes = $attributes->class([
25 | 'form-control',
26 | 'form-control-' . $size => $size,
27 | 'rounded-end' => !$append,
28 | 'is-invalid' => $errors->has($key),
29 | ])->merge([
30 | 'id' => $id,
31 | 'rows' => $rows,
32 | 'wire:model.' . $bind => $model ? $prefix . $model : null,
33 | ]);
34 | @endphp
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/Providers/LaravelBootstrapComponentsProvider.php:
--------------------------------------------------------------------------------
1 | loadViewsFrom(__DIR__ . '/../../resources/views', 'bs');
12 |
13 | $this->publishes(
14 | [__DIR__ . '/../../config/laravel-bootstrap-components.php' => config_path('laravel-bootstrap-components.php')],
15 | ['laravel-bootstrap-components', 'laravel-bootstrap-components:config']
16 | );
17 |
18 | $this->publishes(
19 | [__DIR__ . '/../../resources/views' => resource_path('views/vendor/bs')],
20 | ['laravel-bootstrap-components', 'laravel-bootstrap-components:views']
21 | );
22 | }
23 |
24 | public function register()
25 | {
26 | $this->mergeConfigFrom(__DIR__ . '/../../config/laravel-bootstrap-components.php', 'laravel-bootstrap-components');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Traits/WithModel.php:
--------------------------------------------------------------------------------
1 | modelCollection) {
17 | $this->modelCollection = collect($this->model);
18 | }
19 |
20 | return $this->modelCollection;
21 | }
22 |
23 | public function setModel($key, $value = null)
24 | {
25 | if ($key instanceof Model) {
26 | $key = $key->toArray();
27 | }
28 |
29 | if (is_array($key)) {
30 | foreach ($key as $arrayKey => $arrayValue) {
31 | Arr::set($this->model, $arrayKey, $arrayValue);
32 | }
33 | } else {
34 | Arr::set($this->model, $key, $value);
35 | }
36 | }
37 |
38 | public function addModelItem($key)
39 | {
40 | $array = $this->getModel($key);
41 | $arrayKey = $array ? max(array_keys($array)) + 1 : 0;
42 |
43 | Arr::set($this->model, $key . '.' . $arrayKey, null);
44 |
45 | $this->rekeyModelItems($key);
46 | }
47 |
48 | public function removeModelItem($key, $arrayKey)
49 | {
50 | Arr::forget($this->model, $key . '.' . $arrayKey);
51 |
52 | $this->rekeyModelItems($key);
53 | }
54 |
55 | public function rekeyModelItems($key)
56 | {
57 | $this->setModel($key, array_values($this->getModel($key)));
58 | }
59 |
60 | public function orderModelItem($key, $arrayKey, $direction)
61 | {
62 | $arrayValue = $this->getModel($key . '.' . $arrayKey);
63 | $swapKey = strtolower($direction) == 'up' ? $arrayKey - 1 : $arrayKey + 1;
64 |
65 | if ($swapValue = $this->getModel($key . '.' . $swapKey)) {
66 | $this->setModel($key . '.' . $arrayKey, $swapValue);
67 | $this->setModel($key . '.' . $swapKey, $arrayValue);
68 | }
69 | }
70 |
71 | public function validateModel($rules = null)
72 | {
73 | $validator = Validator::make($this->model, $rules ?? $this->getRules());
74 | $validatedModel = $validator->validate();
75 |
76 | $this->resetErrorBag();
77 |
78 | return $validatedModel;
79 | }
80 |
81 | public function updatingModelSearch()
82 | {
83 | if (method_exists($this, 'resetPage')) {
84 | $this->resetPage();
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------