Skip to content

Commit e302391

Browse files
committed
Add Bootstrap 5 support for Jetstream resources.
1 parent 26d4ac7 commit e302391

File tree

108 files changed

+5210
-249
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+5210
-249
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<input type="checkbox" {!! $attributes->merge(['class' => 'custom-control-input']) !!}>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
@props(['id' => null, 'maxWidth' => null])
2+
3+
<x-jet-modal :id="$id" :maxWidth="$maxWidth" {{ $attributes }}>
4+
<div class="modal-content">
5+
<div class="modal-body">
6+
<div class="d-flex justify-content-start">
7+
<div class="mr-3">
8+
<div class="bg-warning p-2 rounded-circle">
9+
<svg stroke="currentColor" fill="none" viewBox="0 0 24 24" width="24">
10+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
11+
</svg>
12+
</div>
13+
</div>
14+
<div>
15+
<h5 class="font-weight-bold">{{ $title }}</h5>
16+
{{ $content }}
17+
</div>
18+
</div>
19+
</div>
20+
<div class="modal-footer bg-light">
21+
{{ $footer }}
22+
</div>
23+
</div>
24+
</x-jet-modal>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@props(['title' => __('Confirm Password'), 'content' => __('For your security, please confirm your password to continue.'), 'button' => __('Confirm')])
2+
3+
@php
4+
$confirmableId = md5($attributes->wire('then'));
5+
@endphp
6+
7+
<span
8+
{{ $attributes->wire('then') }}
9+
x-data
10+
x-ref="span"
11+
x-on:click="$wire.startConfirmingPassword('{{ $confirmableId }}')"
12+
x-on:password-confirmed.window="setTimeout(() => $event.detail.id === '{{ $confirmableId }}' && $refs.span.dispatchEvent(new CustomEvent('then', { bubbles: false })), 250);"
13+
>
14+
{{ $slot }}
15+
</span>
16+
17+
@once
18+
<x-jet-dialog-modal wire:model="confirmingPassword">
19+
<x-slot name="title">
20+
{{ $title }}
21+
</x-slot>
22+
23+
<x-slot name="content">
24+
{{ $content }}
25+
26+
<div class="mt-4" x-data="{}" x-on:confirming-password.window="setTimeout(() => $refs.confirmable_password.focus(), 250)">
27+
<x-jet-input type="password" class="{{ $errors->has('confirmable_password') ? 'is-invalid' : '' }}" placeholder="{{ __('Password') }}"
28+
x-ref="confirmable_password"
29+
wire:model.defer="confirmablePassword"
30+
wire:keydown.enter="confirmPassword" />
31+
32+
<x-jet-input-error for="confirmable_password" />
33+
</div>
34+
</x-slot>
35+
36+
<x-slot name="footer">
37+
<x-jet-secondary-button wire:click="stopConfirmingPassword" wire:loading.attr="disabled">
38+
{{ __('Cancel') }}
39+
</x-jet-secondary-button>
40+
41+
<x-jet-button class="ml-2" wire:click="confirmPassword" wire:loading.attr="disabled">
42+
{{ $button }}
43+
</x-jet-button>
44+
</x-slot>
45+
</x-jet-dialog-modal>
46+
@endonce
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
@props(['id' => null, 'maxWidth' => null])
2+
3+
<x-jet-modal :id="$id" :maxWidth="$maxWidth" {{ $attributes }}>
4+
<div class="modal-content">
5+
<div class="modal-header">
6+
<h5 class="modal-title">{{ $title }}</h5>
7+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
8+
<span aria-hidden="true">&times;</span>
9+
</button>
10+
</div>
11+
<div class="modal-body">
12+
{{ $content }}
13+
</div>
14+
<div class="modal-footer bg-light">
15+
{{ $footer }}
16+
</div>
17+
</div>
18+
</x-jet-modal>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
@props(['id' => 'navbarDropdown'])
2+
3+
<li class="nav-item dropdown">
4+
<a id="{{ $id }}" {!! $attributes->merge(['class' => 'nav-link']) !!} role="button" data-toggle="dropdown" aria-expanded="false">
5+
{{ $trigger }}
6+
</a>
7+
8+
<div class="dropdown-menu dropdown-menu-right animate slideIn" aria-labelledby="{{ $id }}">
9+
{{ $content }}
10+
</div>
11+
</li>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
@props(['id', 'maxWidth', 'modal' => false])
2+
3+
@php
4+
$id = $id ?? md5($attributes->wire('model'));
5+
6+
$maxWidth = [
7+
'sm' => ' modal-sm',
8+
'md' => '',
9+
'lg' => ' modal-lg',
10+
'xl' => ' modal-xl',
11+
][$maxWidth ?? 'md'];
12+
@endphp
13+
14+
<!-- Modal -->
15+
<div
16+
x-data="{
17+
show: @entangle($attributes->wire('model')).defer,
18+
focusables() {
19+
// All focusable element types...
20+
let selector = 'a, button, input, textarea, select, details, [tabindex]:not([tabindex=\'-1\'])'
21+
return [...$el.querySelectorAll(selector)]
22+
// All non-disabled elements...
23+
.filter(el => ! el.hasAttribute('disabled'))
24+
},
25+
firstFocusable() { return this.focusables()[0] },
26+
lastFocusable() { return this.focusables().slice(-1)[0] },
27+
nextFocusable() { return this.focusables()[this.nextFocusableIndex()] || this.firstFocusable() },
28+
prevFocusable() { return this.focusables()[this.prevFocusableIndex()] || this.lastFocusable() },
29+
nextFocusableIndex() { return (this.focusables().indexOf(document.activeElement) + 1) % (this.focusables().length + 1) },
30+
prevFocusableIndex() { return Math.max(0, this.focusables().indexOf(document.activeElement)) -1 },
31+
}"
32+
x-init="() => {
33+
let modal = $('#{{ $id }}');
34+
$watch('show', value => {
35+
if (value) {
36+
modal.modal('show')
37+
setTimeout(() => (focusables()[0]).focus(), 250);
38+
} else {
39+
modal.modal('hide')
40+
}
41+
});
42+
43+
modal.on('hide.bs.modal', function () {
44+
show = false
45+
})
46+
47+
modal.click(function(e) {
48+
if (e.target == this) {
49+
show = false;
50+
}
51+
});
52+
}"
53+
x-on:keydown.escape.window="show = false"
54+
x-on:keydown.tab.prevent="$event.shiftKey || nextFocusable().focus()"
55+
x-on:keydown.shift.tab.prevent="prevFocusable().focus()"
56+
wire:ignore.self
57+
class="modal fade"
58+
id="{{ $id }}"
59+
aria-labelledby="{{ $id }}"
60+
aria-hidden="true"
61+
x-ref="{{ $id }}"
62+
>
63+
<div class="modal-dialog{{ $maxWidth }}">
64+
{{ $slot }}
65+
</div>
66+
</div>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@props(['team', 'component' => 'jet-dropdown-link'])
2+
3+
<x-dynamic-component :component="$component" href="#" onclick="event.preventDefault();
4+
document.getElementById('switch-team-form-{{ $team->id }}').submit();">
5+
<div class="d-flex align-content-center">
6+
@if (Auth::user()->isCurrentTeam($team))
7+
<svg class="mr-1 text-success" width="20" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor" viewBox="0 0 24 24"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
8+
@endif
9+
10+
<div class="text-truncate" style="width: 12rem;">{{ $team->name }}</div>
11+
</div>
12+
13+
<form method="POST" action="{{ route('current-team.update') }}" id="switch-team-form-{{ $team->id }}">
14+
@method('PUT')
15+
@csrf
16+
17+
<!-- Hidden Team ID -->
18+
<input type="hidden" name="team_id" value="{{ $team->id }}">
19+
</form>
20+
</x-dynamic-component>
21+
22+
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<div class="row justify-content-center my-5">
2+
<div class="col-md-12">
3+
<div class="card shadow bg-light">
4+
<div class="card-body bg-white px-5 py-3 border-bottom rounded-top">
5+
<div class="mx-3 my-3">
6+
<div>
7+
<x-jet-application-logo style="width: 317px;" />
8+
</div>
9+
10+
<h3 class="h3 my-4">
11+
Welcome to your Jetstream application!
12+
</h3>
13+
14+
<div class="text-muted">
15+
Laravel Jetstream provides a beautiful, robust starting point for your next Laravel application. Laravel is designed
16+
to help you build your application using a development environment that is simple, powerful, and enjoyable. We believe
17+
you should love expressing your creativity through programming, so we have spent time carefully crafting the Laravel
18+
ecosystem to be a breath of fresh air. We hope you love it.
19+
</div>
20+
</div>
21+
</div>
22+
<div class="row g-0">
23+
<div class="col-md-6 pr-0">
24+
<div class="card-body border-right border-bottom p-3 h-100">
25+
<div class="d-flex flex-row bd-highlight mb-3">
26+
<div>
27+
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="text-muted" width="32"><path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path></svg>
28+
</div>
29+
<div class="pl-3">
30+
<div class="mb-2">
31+
<a href="https://laravel.com/docs" class="h5 font-weight-bolder text-decoration-none text-dark">Documentation</a>
32+
</div>
33+
<p class="text-muted">
34+
Laravel has wonderful documentation covering every aspect of the framework. Whether you're new to the framework or have previous experience, we recommend reading all of the documentation from beginning to end.
35+
</p>
36+
<a href="https://laravel.com/docs" class="text-decoration-none">
37+
<div class="mt-3 d-flex align-content-center font-weight-bold text-primary">
38+
<div>Explore the documentation</div>
39+
40+
<div class="ml-1 text-primary">
41+
<svg viewBox="0 0 20 20" fill="currentColor" width="16" class="arrow-right w-4 h-4"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
42+
</div>
43+
</div>
44+
</a>
45+
</div>
46+
</div>
47+
</div>
48+
</div>
49+
50+
<div class="col-md-6 pl-0">
51+
<div class="card-body border-bottom p-3 h-100">
52+
<div class="d-flex flex-row bd-highlight mb-3">
53+
<div>
54+
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="text-muted" width="32"><path d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"></path><path d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
55+
</div>
56+
<div class="pl-3">
57+
<div class="mb-2">
58+
<a href="https://laracasts.com" class="h5 font-weight-bolder text-decoration-none text-dark">Laracasts</a>
59+
</div>
60+
<p class="text-muted">
61+
Laracasts offers thousands of video tutorials on Laravel, PHP, and JavaScript development. Check them out, see for yourself, and massively level up your development skills in the process.
62+
</p>
63+
<a href="https://laravel.com/docs" class="text-decoration-none">
64+
<div class="mt-3 d-flex align-content-center font-weight-bold text-primary">
65+
<div>Start watching Laracasts</div>
66+
67+
<div class="ml-1 text-primary">
68+
<svg viewBox="0 0 20 20" fill="currentColor" width="16" class="arrow-right w-4 h-4"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
69+
</div>
70+
</div>
71+
</a>
72+
</div>
73+
</div>
74+
</div>
75+
</div>
76+
77+
<div class="col-md-6 pr-0">
78+
<div class="card-body border-right p-3 h-100">
79+
<div class="d-flex flex-row bd-highlight mb-3">
80+
<div>
81+
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="text-muted" width="32"><path d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
82+
</div>
83+
<div class="pl-3">
84+
<div class="mb-2">
85+
<a href="https://getbootstrap.com/" class="h5 font-weight-bolder text-decoration-none text-dark">Bootstrap</a>
86+
</div>
87+
<p class="text-muted">
88+
Quickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.
89+
</p>
90+
</div>
91+
</div>
92+
</div>
93+
</div>
94+
95+
<div class="col-md-6 pl-0">
96+
<div class="card-body p-3 h-100">
97+
<div class="d-flex flex-row bd-highlight mb-3">
98+
<div>
99+
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="text-muted" width="32"><path d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path></svg>
100+
</div>
101+
<div class="pl-3">
102+
<div class="mb-2">
103+
<span class="h5 font-weight-bolder text-decoration-none text-dark">Authentication</span>
104+
</div>
105+
<p class="text-muted">
106+
Authentication and registration views are included with Laravel Jetstream, as well as support for user email verification and resetting forgotten passwords. So, you're free to get started what matters most: building your application.
107+
</p>
108+
</div>
109+
</div>
110+
</div>
111+
</div>
112+
</div>
113+
</div>
114+
</div>
115+
</div>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<template>
2+
<input type="checkbox" :value="value" v-model="proxyChecked"
3+
class="custom-control-input">
4+
</template>
5+
6+
<script>
7+
import { defineComponent } from 'vue'
8+
9+
export default defineComponent({
10+
emits: ['update:checked'],
11+
12+
props: {
13+
checked: {
14+
type: [Array, Boolean],
15+
default: false,
16+
},
17+
value: {
18+
default: null,
19+
},
20+
},
21+
22+
computed: {
23+
proxyChecked: {
24+
get() {
25+
return this.checked;
26+
},
27+
28+
set(val) {
29+
this.$emit("update:checked", val);
30+
},
31+
},
32+
},
33+
})
34+
</script>
35+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<template>
2+
<modal :id="id" :max-width="maxWidth">
3+
<div class="modal-content">
4+
<div class="modal-body">
5+
<div class="d-flex justify-content-start">
6+
<div class="mr-3">
7+
<div class="bg-warning p-2 rounded-circle">
8+
<svg stroke="currentColor" fill="none" viewBox="0 0 24 24" width="24">
9+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
10+
</svg>
11+
</div>
12+
</div>
13+
<div>
14+
<h5 class="font-weight-bold">
15+
<slot name="title">
16+
</slot>
17+
</h5>
18+
<slot name="content">
19+
</slot>
20+
</div>
21+
</div>
22+
</div>
23+
<div class="modal-footer bg-light">
24+
<slot name="footer">
25+
</slot>
26+
</div>
27+
</div>
28+
</modal>
29+
</template>
30+
31+
<script>
32+
import { defineComponent } from 'vue'
33+
import Modal from './Modal.vue'
34+
35+
export default defineComponent({
36+
components: {
37+
Modal,
38+
},
39+
40+
props: {
41+
id: {
42+
type: String,
43+
required: true
44+
},
45+
maxWidth: {
46+
default: '2xl'
47+
}
48+
}
49+
})
50+
</script>

0 commit comments

Comments
 (0)