您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

index.blade.php 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. @php
  2. use Filament\Support\Enums\Alignment;
  3. use Filament\Support\Enums\MaxWidth;
  4. @endphp
  5. @props([
  6. 'alignment' => Alignment::Start,
  7. 'ariaLabelledby' => null,
  8. 'closeButton' => \Filament\Support\View\Components\Modal::$hasCloseButton,
  9. 'closeByClickingAway' => \Filament\Support\View\Components\Modal::$isClosedByClickingAway,
  10. 'closeEventName' => 'close-modal',
  11. 'description' => null,
  12. 'displayClasses' => 'inline-block',
  13. 'footer' => null,
  14. 'footerActions' => [],
  15. 'footerActionsAlignment' => Alignment::Start,
  16. 'header' => null,
  17. 'heading' => null,
  18. 'icon' => null,
  19. 'iconAlias' => null,
  20. 'iconColor' => 'primary',
  21. 'id' => null,
  22. 'openEventName' => 'open-modal',
  23. 'slideOver' => false,
  24. 'stickyFooter' => false,
  25. 'stickyHeader' => false,
  26. 'trigger' => null,
  27. 'visible' => true,
  28. 'width' => 'sm',
  29. ])
  30. @php
  31. if (! $alignment instanceof Alignment) {
  32. $alignment = filled($alignment) ? (Alignment::tryFrom($alignment) ?? $alignment) : null;
  33. }
  34. if (! $footerActionsAlignment instanceof Alignment) {
  35. $footerActionsAlignment = filled($footerActionsAlignment) ? (Alignment::tryFrom($footerActionsAlignment) ?? $footerActionsAlignment) : null;
  36. }
  37. if (! $width instanceof MaxWidth) {
  38. $width = filled($width) ? (MaxWidth::tryFrom($width) ?? $width) : null;
  39. }
  40. $closeEventHandler = filled($id) ? '$dispatch(' . \Illuminate\Support\Js::from($closeEventName) . ', { id: ' . \Illuminate\Support\Js::from($id) . ' })' : 'close()';
  41. @endphp
  42. <div
  43. @if ($ariaLabelledby)
  44. aria-labelledby="{{ $ariaLabelledby }}"
  45. @elseif ($heading)
  46. aria-labelledby="{{ "{$id}.heading" }}"
  47. @endif
  48. aria-modal="true"
  49. role="dialog"
  50. x-data="{
  51. isOpen: false,
  52. livewire: null,
  53. close: function () {
  54. this.isOpen = false
  55. this.$refs.modalContainer.dispatchEvent(
  56. new CustomEvent('modal-closed', { id: '{{ $id }}' }),
  57. )
  58. {{-- this.$nextTick(() => {
  59. if (document.getElementsByClassName('fi-modal-open').length) {
  60. return
  61. }
  62. window.clearAllBodyScrollLocks()
  63. }) --}}
  64. },
  65. open: function () {
  66. this.isOpen = true
  67. {{-- window.clearAllBodyScrollLocks()
  68. window.disableBodyScroll(this.$root) --}}
  69. this.$refs.modalContainer.dispatchEvent(
  70. new CustomEvent('modal-opened', { id: '{{ $id }}' }),
  71. )
  72. },
  73. }"
  74. @if ($id)
  75. x-on:{{ $closeEventName }}.window="if ($event.detail.id === '{{ $id }}') close()"
  76. x-on:{{ $openEventName }}.window="if ($event.detail.id === '{{ $id }}') open()"
  77. @endif
  78. x-trap.noscroll="isOpen"
  79. x-bind:class="{
  80. 'fi-modal-open': isOpen,
  81. }"
  82. @class([
  83. 'fi-modal',
  84. 'fi-width-screen' => $width === MaxWidth::Screen,
  85. $displayClasses,
  86. ])
  87. >
  88. @if ($trigger)
  89. <div
  90. x-on:click="open"
  91. {{ $trigger->attributes->class(['fi-modal-trigger flex cursor-pointer']) }}
  92. >
  93. {{ $trigger }}
  94. </div>
  95. @endif
  96. <div
  97. x-cloak
  98. x-show="isOpen"
  99. >
  100. <div
  101. aria-hidden="true"
  102. x-show="isOpen"
  103. x-transition.duration.300ms.opacity
  104. @class([
  105. 'fi-modal-close-overlay fixed inset-0 z-40 bg-gray-950/50 dark:bg-gray-950/75',
  106. ])
  107. ></div>
  108. <div
  109. @class([
  110. 'fixed inset-0 z-40',
  111. 'overflow-hidden' => ! ($slideOver || ($width === MaxWidth::Screen)),
  112. 'cursor-pointer' => $closeByClickingAway,
  113. ])
  114. >
  115. <div
  116. x-ref="modalContainer"
  117. @if ($closeByClickingAway)
  118. x-on:click.self="{{ $closeEventHandler }}"
  119. @endif
  120. {{
  121. $attributes->class([
  122. 'relative min-h-full flex items-start justify-center',
  123. 'mb-auto mt-8 p-4' => ! ($slideOver || ($width === MaxWidth::Screen)),
  124. ])
  125. }}
  126. >
  127. <div
  128. x-data="{ isShown: false }"
  129. x-init="
  130. $nextTick(() => {
  131. isShown = isOpen
  132. $watch('isOpen', () => (isShown = isOpen))
  133. })
  134. "
  135. x-on:keydown.window.escape="{{ $closeEventHandler }}"
  136. x-show="isShown"
  137. x-transition:enter="duration-300"
  138. x-transition:leave="duration-300"
  139. @if ($width === MaxWidth::Screen)
  140. @elseif ($slideOver)
  141. x-transition:enter-start="translate-x-full rtl:-translate-x-full"
  142. x-transition:enter-end="translate-x-0"
  143. x-transition:leave-start="translate-x-0"
  144. x-transition:leave-end="translate-x-full rtl:-translate-x-full"
  145. @else
  146. x-transition:enter-start="scale-95 opacity-0"
  147. x-transition:enter-end="scale-100 opacity-100"
  148. x-transition:leave-start="scale-100 opacity-100"
  149. x-transition:leave-end="scale-95 opacity-0"
  150. @endif
  151. @class([
  152. 'fi-modal-window pointer-events-auto relative flex w-full cursor-default flex-col bg-white shadow-xl ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10',
  153. 'fi-modal-slide-over-window ms-auto overflow-y-auto' => $slideOver,
  154. // Using an arbitrary value instead of the h-dvh class that was added in Tailwind CSS v3.4.0
  155. // to ensure compatibility with custom themes that may use an older version of Tailwind CSS.
  156. 'h-[100dvh]' => $slideOver || ($width === MaxWidth::Screen),
  157. 'mx-auto rounded-xl' => ! ($slideOver || ($width === MaxWidth::Screen)),
  158. 'hidden' => ! $visible,
  159. match ($width) {
  160. MaxWidth::ExtraSmall => 'max-w-xs',
  161. MaxWidth::Small => 'max-w-sm',
  162. MaxWidth::Medium => 'max-w-md',
  163. MaxWidth::Large => 'max-w-lg',
  164. MaxWidth::ExtraLarge => 'max-w-xl',
  165. MaxWidth::TwoExtraLarge => 'max-w-2xl',
  166. MaxWidth::ThreeExtraLarge => 'max-w-3xl',
  167. MaxWidth::FourExtraLarge => 'max-w-4xl',
  168. MaxWidth::FiveExtraLarge => 'max-w-5xl',
  169. MaxWidth::SixExtraLarge => 'max-w-6xl',
  170. MaxWidth::SevenExtraLarge => 'max-w-7xl',
  171. MaxWidth::Full => 'max-w-full',
  172. MaxWidth::MinContent => 'max-w-min',
  173. MaxWidth::MaxContent => 'max-w-max',
  174. MaxWidth::FitContent => 'max-w-fit',
  175. MaxWidth::Prose => 'max-w-prose',
  176. MaxWidth::ScreenSmall => 'max-w-screen-sm',
  177. MaxWidth::ScreenMedium => 'max-w-screen-md',
  178. MaxWidth::ScreenLarge => 'max-w-screen-lg',
  179. MaxWidth::ScreenExtraLarge => 'max-w-screen-xl',
  180. MaxWidth::ScreenTwoExtraLarge => 'max-w-screen-2xl',
  181. MaxWidth::Screen => 'fixed inset-0',
  182. default => $width,
  183. },
  184. ])
  185. >
  186. @if ($heading || $header)
  187. <div
  188. @class([
  189. 'fi-modal-header flex px-6 pt-6',
  190. 'fi-sticky sticky top-0 z-10 border-b border-gray-200 bg-white pb-6 dark:border-white/10 dark:bg-gray-900' => $stickyHeader,
  191. 'rounded-t-xl' => $stickyHeader && ! ($slideOver || ($width === MaxWidth::Screen)),
  192. match ($alignment) {
  193. Alignment::Start, Alignment::Left => 'gap-x-5',
  194. Alignment::Center => 'flex-col',
  195. default => null,
  196. },
  197. ])
  198. >
  199. @if ($closeButton)
  200. <div
  201. @class([
  202. 'absolute',
  203. 'end-4 top-4' => ! $slideOver,
  204. 'end-6 top-6' => $slideOver,
  205. ])
  206. >
  207. <x-filament::icon-button
  208. color="gray"
  209. icon="heroicon-o-x-mark"
  210. icon-alias="modal.close-button"
  211. icon-size="lg"
  212. :label="__('filament::components/modal.actions.close.label')"
  213. tabindex="-1"
  214. :x-on:click="$closeEventHandler"
  215. class="fi-modal-close-btn"
  216. />
  217. </div>
  218. @endif
  219. @if ($header)
  220. {{ $header }}
  221. @else
  222. @if ($icon)
  223. <div
  224. @class([
  225. 'mb-5 flex items-center justify-center' => $alignment === Alignment::Center,
  226. ])
  227. >
  228. <div
  229. @class([
  230. 'rounded-full',
  231. match ($iconColor) {
  232. 'gray' => 'fi-color-gray bg-gray-100 dark:bg-gray-500/20',
  233. default => 'fi-color-custom bg-custom-100 dark:bg-custom-500/20',
  234. },
  235. match ($alignment) {
  236. Alignment::Start, Alignment::Left => 'p-2',
  237. Alignment::Center => 'p-3',
  238. default => null,
  239. },
  240. ])
  241. @style([
  242. \Filament\Support\get_color_css_variables(
  243. $iconColor,
  244. shades: [100, 400, 500, 600],
  245. alias: 'modal.icon',
  246. ) => $iconColor !== 'gray',
  247. ])
  248. >
  249. <x-filament::icon
  250. :alias="$iconAlias"
  251. :icon="$icon"
  252. @class([
  253. 'fi-modal-icon h-6 w-6',
  254. match ($iconColor) {
  255. 'gray' => 'text-gray-500 dark:text-gray-400',
  256. default => 'text-custom-600 dark:text-custom-400',
  257. },
  258. ])
  259. />
  260. </div>
  261. </div>
  262. @endif
  263. <div
  264. @class([
  265. 'text-center' => $alignment === Alignment::Center,
  266. ])
  267. >
  268. <x-filament::modal.heading>
  269. {{ $heading }}
  270. </x-filament::modal.heading>
  271. @if (filled($description))
  272. <x-filament::modal.description
  273. class="mt-2"
  274. >
  275. {{ $description }}
  276. </x-filament::modal.description>
  277. @endif
  278. </div>
  279. @endif
  280. </div>
  281. @endif
  282. @if (! \Filament\Support\is_slot_empty($slot))
  283. <div
  284. @class([
  285. 'fi-modal-content flex flex-col gap-y-4 py-6 overflow-y-auto',
  286. 'max-h-[calc(80vh-4rem)]' => ! ($slideOver || ($width === MaxWidth::Screen)),
  287. 'flex-1' => ($width === MaxWidth::Screen) || $slideOver,
  288. 'pe-6 ps-[5.25rem]' => $icon && ($alignment === Alignment::Start),
  289. 'px-6' => ! ($icon && ($alignment === Alignment::Start)),
  290. ])
  291. >
  292. {{ $slot }}
  293. </div>
  294. @endif
  295. @if ((! \Filament\Support\is_slot_empty($footer)) || (is_array($footerActions) && count($footerActions)) || (! is_array($footerActions) && (! \Filament\Support\is_slot_empty($footerActions))))
  296. <div
  297. @class([
  298. 'fi-modal-footer w-full',
  299. 'pe-6 ps-[5.25rem]' => $icon && ($alignment === Alignment::Start) && ($footerActionsAlignment !== Alignment::Center) && (! $stickyFooter),
  300. 'px-6' => ! ($icon && ($alignment === Alignment::Start) && ($footerActionsAlignment !== Alignment::Center) && (! $stickyFooter)),
  301. 'fi-sticky sticky bottom-0 border-t border-gray-200 bg-white py-5 dark:border-white/10 dark:bg-gray-900' => $stickyFooter,
  302. 'rounded-b-xl' => $stickyFooter && ! ($slideOver || ($width === MaxWidth::Screen)),
  303. 'pb-6' => ! $stickyFooter,
  304. 'mt-6' => (! $stickyFooter) && \Filament\Support\is_slot_empty($slot),
  305. 'mt-auto' => $slideOver,
  306. ])
  307. >
  308. @if (! \Filament\Support\is_slot_empty($footer))
  309. {{ $footer }}
  310. @else
  311. <div
  312. @class([
  313. 'fi-modal-footer-actions gap-3',
  314. match ($footerActionsAlignment) {
  315. Alignment::Start, Alignment::Left => 'flex flex-wrap items-center',
  316. Alignment::Center => 'flex flex-col-reverse sm:grid sm:grid-cols-[repeat(auto-fit,minmax(0,1fr))]',
  317. Alignment::End, Alignment::Right => 'flex flex-row-reverse flex-wrap items-center',
  318. default => null,
  319. },
  320. ])
  321. >
  322. @if (is_array($footerActions))
  323. @foreach ($footerActions as $action)
  324. {{ $action }}
  325. @endforeach
  326. @else
  327. {{ $footerActions }}
  328. @endif
  329. </div>
  330. @endif
  331. </div>
  332. @endif
  333. </div>
  334. </div>
  335. </div>
  336. </div>
  337. </div>