Tables.svelte 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. function handleRowClick(row, index) {
  31. dispatch('rowClick', { row, index });
  32. }
  33. </script>
  34. <div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
  35. <div class="flex items-center justify-between px-5 py-4 border-b border-gray-200 dark:border-gray-700">
  36. <h3 class="text-base font-semibold text-gray-800 dark:text-gray-100">{title}</h3>
  37. {#if showAdd}
  38. <button
  39. 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"
  40. type="button"
  41. title="Adicionar"
  42. on:click={handleAddTop}
  43. >
  44. <img src={plusWhite} alt="Adicionar" class="w-6 h-6" />
  45. <span class="sr-only">Adicionar</span>
  46. </button>
  47. {/if}
  48. </div>
  49. <div class="overflow-x-auto">
  50. <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
  51. <thead class="bg-gray-50 dark:bg-gray-700">
  52. <tr>
  53. {#each columns as col}
  54. <th class="px-6 py-3 text-left text-sm font-semibold uppercase tracking-wide text-gray-700 dark:text-gray-200">
  55. {col.label}
  56. </th>
  57. {/each}
  58. {#if showActions}
  59. <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>
  60. {/if}
  61. </tr>
  62. </thead>
  63. <tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
  64. {#if data.length > 0}
  65. {#each data as row, index}
  66. <tr class="hover:bg-gray-50 dark:hover:bg-gray-700/60 cursor-pointer" on:click={() => handleRowClick(row, index)} on:dblclick={() => handleEditRow(row, index)}>
  67. {#each columns as col}
  68. <td class="px-6 py-3 text-base text-gray-700 dark:text-gray-300">
  69. {row[col.key]}
  70. </td>
  71. {/each}
  72. {#if showActions}
  73. <td class="px-6 py-3 text-sm text-right whitespace-nowrap">
  74. <div class="inline-flex items-center gap-2">
  75. {#if showEdit}
  76. <button
  77. 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"
  78. type="button"
  79. title="Editar"
  80. on:click|stopPropagation={() => handleEditRow(row, index)}
  81. >
  82. <img src={editLight} alt="Editar" class="w-5 h-5 block dark:hidden" />
  83. <img src={editDark} alt="Editar" class="w-5 h-5 hidden dark:block" />
  84. <span class="sr-only">Editar</span>
  85. </button>
  86. {/if}
  87. {#if showDelete}
  88. <button
  89. 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"
  90. type="button"
  91. title="Excluir"
  92. on:click|stopPropagation={() => handleDeleteRow(row, index)}
  93. >
  94. <img src={trashLight} alt="Excluir" class="w-5 h-5 block dark:hidden" />
  95. <img src={trashDark} alt="Excluir" class="w-5 h-5 hidden dark:block" />
  96. <span class="sr-only">Excluir</span>
  97. </button>
  98. {/if}
  99. </div>
  100. </td>
  101. {/if}
  102. </tr>
  103. {/each}
  104. {:else}
  105. <tr>
  106. <td colspan={columns.length + (showActions ? 1 : 0)} class="px-4 py-6 text-center text-gray-400 dark:text-gray-500">
  107. Nenhum dado encontrado
  108. </td>
  109. </tr>
  110. {/if}
  111. </tbody>
  112. </table>
  113. </div>
  114. </div>