Tables.svelte 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. <script>
  2. import { createEventDispatcher } from 'svelte';
  3. import plusWhite from '$lib/assets/icons/plus-white.svg';
  4. import editLight from '$lib/assets/icons/edit-light.svg';
  5. import editDark from '$lib/assets/icons/edit-dark.svg';
  6. import trashLight from '$lib/assets/icons/trash-light.svg';
  7. import trashDark from '$lib/assets/icons/trash-dark.svg';
  8. // Título do bloco da tabela
  9. export let title = 'Lista';
  10. // Ex: [{ key: "nome", label: "Nome" }, { key: "preco", label: "Preço" }]
  11. export let columns = [];
  12. // Ex: [{ nome: "Produto 1", preco: 100 }, { nome: "Produto 2", preco: 200 }]
  13. export let data = [];
  14. // Controla exibição da coluna de ações
  15. export let showActions = true;
  16. // Controla botões individuais de ação
  17. export let showAdd = true;
  18. export let showEdit = true;
  19. export let showDelete = true;
  20. const dispatch = createEventDispatcher();
  21. function handleAddTop() {
  22. dispatch('addTop');
  23. }
  24. function handleEditRow(row, index) {
  25. dispatch('editRow', { row, index });
  26. }
  27. function handleDeleteRow(row, index) {
  28. dispatch('deleteRow', { row, index });
  29. }
  30. </script>
  31. <div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
  32. <div class="flex items-center justify-between px-5 py-4 border-b border-gray-200 dark:border-gray-700">
  33. <h3 class="text-base font-semibold text-gray-800 dark:text-gray-100">{title}</h3>
  34. {#if showAdd}
  35. <button
  36. class="inline-flex items-center justify-center rounded-md bg-blue-600 hover:bg-blue-700 text-white w-10 h-10 focus:outline-none focus:ring-2 focus:ring-blue-500"
  37. type="button"
  38. title="Adicionar"
  39. on:click={handleAddTop}
  40. >
  41. <img src={plusWhite} alt="Adicionar" class="w-6 h-6" />
  42. <span class="sr-only">Adicionar</span>
  43. </button>
  44. {/if}
  45. </div>
  46. <div class="overflow-x-auto">
  47. <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
  48. <thead class="bg-gray-50 dark:bg-gray-700">
  49. <tr>
  50. {#each columns as col}
  51. <th class="px-6 py-3 text-left text-sm font-semibold uppercase tracking-wide text-gray-700 dark:text-gray-200">
  52. {col.label}
  53. </th>
  54. {/each}
  55. {#if showActions}
  56. <th class="px-6 py-3 text-right text-sm font-semibold uppercase tracking-wide text-gray-700 dark:text-gray-200">Ações</th>
  57. {/if}
  58. </tr>
  59. </thead>
  60. <tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
  61. {#if data.length > 0}
  62. {#each data as row, index}
  63. <tr class="hover:bg-gray-50 dark:hover:bg-gray-700/60" on:dblclick={() => handleEditRow(row, index)}>
  64. {#each columns as col}
  65. <td class="px-6 py-3 text-base text-gray-700 dark:text-gray-300">
  66. {row[col.key]}
  67. </td>
  68. {/each}
  69. {#if showActions}
  70. <td class="px-6 py-3 text-sm text-right whitespace-nowrap">
  71. <div class="inline-flex items-center gap-2">
  72. {#if showEdit}
  73. <button
  74. class="inline-flex items-center justify-center w-9 h-9 rounded-md border border-gray-200 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700"
  75. type="button"
  76. title="Editar"
  77. on:click={() => handleEditRow(row, index)}
  78. >
  79. <img src={editLight} alt="Editar" class="w-5 h-5 block dark:hidden" />
  80. <img src={editDark} alt="Editar" class="w-5 h-5 hidden dark:block" />
  81. <span class="sr-only">Editar</span>
  82. </button>
  83. {/if}
  84. {#if showDelete}
  85. <button
  86. class="inline-flex items-center justify-center w-9 h-9 rounded-md border border-gray-200 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700"
  87. type="button"
  88. title="Excluir"
  89. on:click={() => handleDeleteRow(row, index)}
  90. >
  91. <img src={trashLight} alt="Excluir" class="w-5 h-5 block dark:hidden" />
  92. <img src={trashDark} alt="Excluir" class="w-5 h-5 hidden dark:block" />
  93. <span class="sr-only">Excluir</span>
  94. </button>
  95. {/if}
  96. </div>
  97. </td>
  98. {/if}
  99. </tr>
  100. {/each}
  101. {:else}
  102. <tr>
  103. <td colspan={columns.length + (showActions ? 1 : 0)} class="px-4 py-6 text-center text-gray-400 dark:text-gray-500">
  104. Nenhum dado encontrado
  105. </td>
  106. </tr>
  107. {/if}
  108. </tbody>
  109. </table>
  110. </div>
  111. </div>