You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

custom-table-repeater.blade.php 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. @php
  2. use Filament\Forms\Components\Actions\Action;
  3. use Filament\Support\Enums\Alignment;
  4. use Filament\Support\Enums\MaxWidth;
  5. $containers = $getChildComponentContainers();
  6. $addAction = $getAction($getAddActionName());
  7. $cloneAction = $getAction($getCloneActionName());
  8. $deleteAction = $getAction($getDeleteActionName());
  9. $moveDownAction = $getAction($getMoveDownActionName());
  10. $moveUpAction = $getAction($getMoveUpActionName());
  11. $reorderAction = $getAction($getReorderActionName());
  12. $isReorderableWithButtons = $isReorderableWithButtons();
  13. $extraItemActions = $getExtraItemActions();
  14. $extraActions = $getExtraActions();
  15. $visibleExtraItemActions = [];
  16. $visibleExtraActions = [];
  17. $headers = $getHeaders();
  18. $renderHeader = $shouldRenderHeader();
  19. $stackAt = $getStackAt();
  20. $hasContainers = count($containers) > 0;
  21. $emptyLabel = $getEmptyLabel();
  22. $streamlined = $isStreamlined();
  23. $reorderAtStart = $isReorderAtStart();
  24. $statePath = $getStatePath();
  25. foreach ($extraActions as $extraAction) {
  26. $visibleExtraActions = array_filter(
  27. $extraActions,
  28. fn (Action $action): bool => $action->isVisible(),
  29. );
  30. }
  31. foreach ($extraItemActions as $extraItemAction) {
  32. $visibleExtraItemActions = array_filter(
  33. $extraItemActions,
  34. fn (Action $action): bool => $action->isVisible(),
  35. );
  36. }
  37. $hasActions = $reorderAction->isVisible()
  38. || $cloneAction->isVisible()
  39. || $deleteAction->isVisible()
  40. || $moveUpAction->isVisible()
  41. || $moveDownAction->isVisible()
  42. || filled($visibleExtraItemActions);
  43. @endphp
  44. <x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
  45. <div
  46. x-data="{}"
  47. {{ $attributes->merge($getExtraAttributes())->class([
  48. 'table-repeater-component space-y-6 relative',
  49. 'streamlined' => $streamlined,
  50. match ($stackAt) {
  51. 'sm', MaxWidth::Small => 'break-point-sm',
  52. 'lg', MaxWidth::Large => 'break-point-lg',
  53. 'xl', MaxWidth::ExtraLarge => 'break-point-xl',
  54. '2xl', MaxWidth::TwoExtraLarge => 'break-point-2xl',
  55. default => 'break-point-md',
  56. }
  57. ]) }}
  58. >
  59. @if (count($containers) || $emptyLabel !== false)
  60. <div class="table-repeater-container rounded-xl relative ring-1 ring-gray-950/5 dark:ring-white/20">
  61. <table class="w-full">
  62. <thead @class([
  63. 'table-repeater-header-hidden sr-only' => ! $renderHeader,
  64. 'table-repeater-header rounded-t-xl overflow-hidden border-b border-gray-950/5 dark:border-white/20' => $renderHeader,
  65. ])>
  66. <tr class="text-xs md:divide-x rtl:divide-x-reverse md:divide-gray-950/5 dark:md:divide-white/20">
  67. {{-- Move actions column to start if reorderAtStart is true --}}
  68. @if ($hasActions && count($containers) && $reorderAtStart)
  69. <th class="table-repeater-header-column w-px first:rounded-tl-xl rtl:first:rounded-tr-xl rtl:first:rounded-tl-none p-2 bg-gray-100 dark:bg-gray-900/60">
  70. <span class="sr-only">
  71. {{ trans('table-repeater::components.repeater.row_actions.label') }}
  72. </span>
  73. </th>
  74. @endif
  75. @foreach ($headers as $key => $header)
  76. <th
  77. @class([
  78. 'table-repeater-header-column p-2 font-medium first:rounded-tl-xl rtl:first:rounded-tr-xl rtl:first:rounded-tl-none last:rounded-tr-xl bg-gray-100 dark:text-gray-300 dark:bg-gray-900/60',
  79. match($header->getAlignment()) {
  80. 'center', Alignment::Center => 'text-center',
  81. 'right', 'end', Alignment::Right, Alignment::End => 'text-end',
  82. default => 'text-start'
  83. }
  84. ])
  85. style="width: {{ $header->getWidth() }}"
  86. >
  87. {{ $header->getLabel() }}
  88. @if ($header->isRequired())
  89. <span class="whitespace-nowrap">
  90. <sup class="font-medium text-danger-700 dark:text-danger-400">*</sup>
  91. </span>
  92. @endif
  93. </th>
  94. @endforeach
  95. @if ($hasActions && count($containers))
  96. <th class="table-repeater-header-column w-px last:rounded-tr-xl rtl:last:rounded-tr-none rtl:last:rounded-tl-xl p-2 bg-gray-100 dark:bg-gray-900/60">
  97. <span class="sr-only">
  98. {{ trans('table-repeater::components.repeater.row_actions.label') }}
  99. </span>
  100. </th>
  101. @endif
  102. </tr>
  103. </thead>
  104. <tbody
  105. x-sortable
  106. wire:end.stop="{{ 'mountFormComponentAction(\'' . $statePath . '\', \'reorder\', { items: $event.target.sortable.toArray() })' }}"
  107. class="table-repeater-rows-wrapper divide-y divide-gray-950/5 dark:divide-white/20"
  108. >
  109. @if (count($containers))
  110. @foreach ($containers as $uuid => $row)
  111. @php
  112. $visibleExtraItemActions = array_filter(
  113. $extraItemActions,
  114. fn (Action $action): bool => $action(['item' => $uuid])->isVisible(),
  115. );
  116. @endphp
  117. <tr
  118. wire:key="{{ $this->getId() }}.{{ $row->getStatePath() }}.{{ $field::class }}.item"
  119. x-sortable-item="{{ $uuid }}"
  120. class="table-repeater-row"
  121. >
  122. {{-- Add reorder action column at start if reorderAtStart is true --}}
  123. @if ($hasActions && $reorderAtStart && $reorderAction->isVisible())
  124. <td class="table-repeater-column p-2 w-px align-top">
  125. <ul class="flex items-center table-repeater-row-actions gap-x-3 px-2">
  126. <li x-sortable-handle class="shrink-0">
  127. {{ $reorderAction }}
  128. </li>
  129. </ul>
  130. </td>
  131. @endif
  132. @php($counter = 0)
  133. @foreach($row->getComponents() as $cell)
  134. @if($cell instanceof \Filament\Forms\Components\Hidden || $cell->isHidden())
  135. {{ $cell }}
  136. @else
  137. <td
  138. @class([
  139. 'table-repeater-column align-top',
  140. 'p-2' => ! $streamlined,
  141. 'has-hidden-label' => $cell->isLabelHidden(),
  142. match($headers[$counter++]->getAlignment()) {
  143. 'center', Alignment::Center => 'text-center',
  144. 'right', 'end', Alignment::Right, Alignment::End => 'text-end',
  145. default => 'text-start'
  146. }
  147. ])
  148. style="width: {{ $cell->getMaxWidth() ?? 'auto' }}"
  149. >
  150. {{ $cell }}
  151. </td>
  152. @endif
  153. @endforeach
  154. @if ($hasActions)
  155. <td class="table-repeater-column p-2 w-px align-top">
  156. <ul class="flex items-center table-repeater-row-actions gap-x-3 px-2">
  157. @foreach ($visibleExtraItemActions as $extraItemAction)
  158. <li>
  159. {{ $extraItemAction(['item' => $uuid]) }}
  160. </li>
  161. @endforeach
  162. @if ($reorderAction->isVisible() && ! $reorderAtStart)
  163. <li x-sortable-handle class="shrink-0">
  164. {{ $reorderAction }}
  165. </li>
  166. @endif
  167. @if ($isReorderableWithButtons)
  168. @if (! $loop->first)
  169. <li>
  170. {{ $moveUpAction(['item' => $uuid]) }}
  171. </li>
  172. @endif
  173. @if (! $loop->last)
  174. <li>
  175. {{ $moveDownAction(['item' => $uuid]) }}
  176. </li>
  177. @endif
  178. @endif
  179. @if ($cloneAction->isVisible())
  180. <li>
  181. {{ $cloneAction(['item' => $uuid]) }}
  182. </li>
  183. @endif
  184. @if ($deleteAction->isVisible())
  185. <li>
  186. {{ $deleteAction(['item' => $uuid]) }}
  187. </li>
  188. @endif
  189. </ul>
  190. </td>
  191. @endif
  192. </tr>
  193. @endforeach
  194. @else
  195. <tr class="table-repeater-row table-repeater-empty-row">
  196. <td colspan="{{ count($headers) + intval($hasActions) }}"
  197. class="table-repeater-column table-repeater-empty-column p-4 w-px text-center italic">
  198. {{ $emptyLabel ?: trans('table-repeater::components.repeater.empty.label') }}
  199. </td>
  200. </tr>
  201. @endif
  202. </tbody>
  203. </table>
  204. </div>
  205. @endif
  206. @if ($addAction->isVisible() || filled($visibleExtraActions))
  207. <ul
  208. @class([
  209. 'relative flex gap-4',
  210. match ($getAddActionAlignment()) {
  211. Alignment::Start, Alignment::Left => 'justify-start',
  212. Alignment::End, Alignment::Right => 'justify-end',
  213. default => 'justify-center',
  214. },
  215. ])
  216. >
  217. @if ($addAction->isVisible())
  218. <li>
  219. {{ $addAction }}
  220. </li>
  221. @endif
  222. @if (filled($visibleExtraActions))
  223. @foreach ($visibleExtraActions as $extraAction)
  224. <li>
  225. {{ ($extraAction) }}
  226. </li>
  227. @endforeach
  228. @endif
  229. </ul>
  230. @endif
  231. </div>
  232. </x-dynamic-component>