@likable-hair/svelte 4.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,6 +25,25 @@ onMount(() => {
25
25
  updateHeaderHeight();
26
26
  window.addEventListener('resize', updateHeaderHeight);
27
27
  tableContainer?.addEventListener("scroll", setReachedBottomOrTop);
28
+ if (tableContainer?.scrollHeight && tableContainer.clientHeight && tableContainer?.scrollHeight <= tableContainer?.clientHeight) {
29
+ tableContainer.style.marginRight = '0px';
30
+ }
31
+ if (resizableColumns) {
32
+ for (const head of [...headers, { value: 'non-resizable', minWidth: DEFAULT_MIN_WIDTH_PX + 'px', maxWidth: DEFAULT_MAX_WIDTH_PX + 'px' }, { value: 'slot-append', minWidth: DEFAULT_MIN_WIDTH_PX + 'px', maxWidth: DEFAULT_MAX_WIDTH_PX + 'px' }]) {
33
+ let th;
34
+ if (head.value == 'non-resizable' || head.value == 'slot-append') {
35
+ th = document.getElementsByClassName(head.value).item(0);
36
+ }
37
+ else {
38
+ th = document.getElementById(head.value);
39
+ }
40
+ if (!!th) {
41
+ resizeHeader(th, head);
42
+ }
43
+ }
44
+ let table = document.getElementsByClassName('table')[0];
45
+ table.classList.add('resizable');
46
+ }
28
47
  return () => {
29
48
  window.removeEventListener('resize', updateHeaderHeight);
30
49
  tableContainer?.removeEventListener("scroll", setReachedBottomOrTop);
@@ -76,8 +95,9 @@ const [send, receive] = crossfade({
76
95
  };
77
96
  },
78
97
  });
79
- let { headers = [], headersToShowInTable = headers, subHeaders = [], customizeHeaders = false, rows = [], sortedBy = $bindable(), sortDirection = $bindable("asc"), cellEdit = false, lang = "en", noItemsText = lang == 'en' ? "No items to show" : 'Nessun elemento da visualizzare', showSelect = false, showSelectContainer = true, selectMode = "single", selectedItems = $bindable([]), showExpand = false, loading = false, disabled = false, filters = $bindable([]), searchBarColumns, searchBarVisible = false, searchBarPlaceholder = lang == 'en' ? "Type to search..." : "Scrivi per cercare...", filtersVisible = false, quickFiltersVisible = false, editFilterMode = "one-edit", showActiveFilters = true, quickFilters = [], actionsForSelectedItems = [], totalRows = rows.length, searchText = $bindable(), renderedRowsNumber = 100, sectionRowsNumber = 20, sectionThreshold = 2, backwardThresholdPixel = 100, forwardThresholdPixel = 100, uniqueKey = 'id', numberOfResultsVisible = false, endLineVisible = false, class: clazz = {}, onapplyCustomQuickFilter, oncellClick, onfetchData, onfiltersChange, onsort, onremoveAllFilters, onremoveCustomQuickFilter, onremoveFilter, onrowClick, onsaveCellEdit, onsaveHeadersToShow, searchBarSnippet, customFilterChipSnippet, customFilterSnippet, filterAppendSnippet, onscroll, selectionSnippet: selectionInternalSnippet, itemLabelSnippet: itemLabelInternalSnippet, chipLabelSnippet, headerSnippet, headerLabelSnippet, rowAppendSnippet, rowActionsSnippet, customRowSnippet, subRowAppendSnippet, subHeaderLabelSnippet, subHeaderSnippet, subRowActionsSnippet, customSubRowSnippet, customQuickFilterSnippet, appendSnippet, } = $props();
80
- let openCellEditor = $state(false), cellEditorActivator = $state(), cellEditorContainer = $state(), menuElementCellEditor = $state(), menuElementQuickFilters = $state(), cellEditorInfoActive = $state(), saveEditDisabled = $state(false), searchBarInput = $state(undefined), openQuickFilter = $state(false), quickFilterActivator = $state(), quickFilterActive = $state(), globalBuilder = new FilterBuilder(), slotSelectActionsContainer, isSelectedAll = $state(false), calendarOpened = $state(false), calendarOpened2 = $state(false), selectedIndexes = [], cellEditorIndexRow = $state(), cellEditorIndexHeader = $state(), cellEditorSubItem = $state(), currentSectionNumber = $state(0), tableBody = $state(), tableContainer = $state(), userScrolling = $state(true), reachedBottom = $state(false), reachedTop = false;
98
+ let { headers = [], headersToShowInTable = headers, subHeaders = [], customizeHeaders = false, rows = [], sortedBy = $bindable(), sortDirection = $bindable("asc"), cellEdit = false, lang = "en", noItemsText = lang == 'en' ? "No items to show" : 'Nessun elemento da visualizzare', showSelect = false, showSelectContainer = true, selectMode = "single", selectedItems = $bindable([]), showExpand = false, loading = false, disabled = false, filters = $bindable([]), searchBarColumns, searchBarVisible = false, searchBarPlaceholder = lang == 'en' ? "Type to search..." : "Scrivi per cercare...", filtersVisible = false, quickFiltersVisible = false, editFilterMode = "one-edit", showActiveFilters = true, quickFilters = [], actionsForSelectedItems = [], totalRows = rows.length, searchText = $bindable(), renderedRowsNumber = 100, sectionRowsNumber = 20, sectionThreshold = 2, backwardThresholdPixel = 100, forwardThresholdPixel = 100, uniqueKey = 'id', numberOfResultsVisible = false, endLineVisible = false, resizableColumns = false, resizedColumnSizeWithPadding = {}, class: clazz = {}, onapplyCustomQuickFilter, oncellClick, onfetchData, onfiltersChange, onsort, onremoveAllFilters, onremoveCustomQuickFilter, onremoveFilter, onrowClick, onsaveCellEdit, onsaveHeadersToShow, oncolumnResize, searchBarSnippet, customFilterChipSnippet, customFilterSnippet, filterAppendSnippet, onscroll, selectionSnippet: selectionInternalSnippet, itemLabelSnippet: itemLabelInternalSnippet, chipLabelSnippet, headerSnippet, headerLabelSnippet, rowAppendSnippet, rowActionsSnippet, customRowSnippet, subRowAppendSnippet, subHeaderLabelSnippet, subHeaderSnippet, subRowActionsSnippet, customSubRowSnippet, customQuickFilterSnippet, appendSnippet, } = $props();
99
+ let openCellEditor = $state(false), cellEditorActivator = $state(), cellEditorContainer = $state(), menuElementCellEditor = $state(), menuElementQuickFilters = $state(), cellEditorInfoActive = $state(), saveEditDisabled = $state(false), searchBarInput = $state(undefined), openQuickFilter = $state(false), quickFilterActivator = $state(), quickFilterActive = $state(), globalBuilder = new FilterBuilder(), slotSelectActionsContainer, isSelectedAll = $state(false), calendarOpened = $state(false), calendarOpened2 = $state(false), selectedIndexes = [], cellEditorIndexRow = $state(), cellEditorIndexHeader = $state(), cellEditorSubItem = $state(), currentSectionNumber = $state(0), tableBody = $state(), tableContainer = $state(), userScrolling = $state(true), reachedBottom = $state(false), reachedTop = false, resizing = false, remainingWidth = $state(0);
100
+ const DEFAULT_MIN_WIDTH_PX = 100, DEFAULT_MAX_WIDTH_PX = 400;
81
101
  let totalSections = $derived((totalRows - renderedRowsNumber) / sectionRowsNumber);
82
102
  let hasMoreToRender = $derived(totalSections > currentSectionNumber);
83
103
  let totalCachedSections = $derived((rows.length - renderedRowsNumber) / sectionRowsNumber);
@@ -111,7 +131,7 @@ function saveHeadersToShow() {
111
131
  openHeaderDrawer = false;
112
132
  }
113
133
  function handleHeaderClick(header) {
114
- if (header.sortable && !loading) {
134
+ if (header.sortable && !loading && !resizing) {
115
135
  if (!!sortedBy && header.value == sortedBy) {
116
136
  if (sortDirection == "asc")
117
137
  sortDirection = "desc";
@@ -698,29 +718,31 @@ async function handleLoadForward() {
698
718
  }
699
719
  }
700
720
  async function handleLoadBackward() {
701
- userScrolling = false;
702
- const anchorIndex = 0;
703
- const anchorUniqueKey = renderedRows[anchorIndex].item[uniqueKey];
704
- const anchorElement = findAnchorElement(anchorUniqueKey);
705
- const anchorOffsetBefore = anchorElement?.getBoundingClientRect().top || 0;
706
- let removedRowCount = 0;
707
- for (let i = renderedRows.length - 1; removedRowCount < sectionRowsNumber; i--) {
708
- let row = tableBody?.children.item(i);
709
- removedRowCount++;
710
- const rowKey = row?.getAttribute("data-key");
711
- const isExpanded = expandedRows.some(r => r.item[uniqueKey] == rowKey);
712
- if (isExpanded) {
713
- i--;
721
+ if (currentSectionNumber > 0) {
722
+ userScrolling = false;
723
+ const anchorIndex = 0;
724
+ const anchorUniqueKey = renderedRows[anchorIndex].item[uniqueKey];
725
+ const anchorElement = findAnchorElement(anchorUniqueKey);
726
+ const anchorOffsetBefore = anchorElement?.getBoundingClientRect().top || 0;
727
+ let removedRowCount = 0;
728
+ for (let i = renderedRows.length - 1; removedRowCount < sectionRowsNumber; i--) {
729
+ let row = tableBody?.children.item(i);
730
+ removedRowCount++;
731
+ const rowKey = row?.getAttribute("data-key");
732
+ const isExpanded = expandedRows.some(r => r.item[uniqueKey] == rowKey);
733
+ if (isExpanded) {
734
+ i--;
735
+ }
736
+ }
737
+ currentSectionNumber = currentSectionNumber - 1;
738
+ await tick();
739
+ if (tableContainer) {
740
+ const anchorElementAfter = findAnchorElement(anchorUniqueKey);
741
+ const anchorOffsetAfter = anchorElementAfter?.getBoundingClientRect().top || 0;
742
+ const offsetDiff = anchorOffsetAfter - anchorOffsetBefore;
743
+ tableContainer.scrollTop += offsetDiff;
744
+ userScrolling = true;
714
745
  }
715
- }
716
- currentSectionNumber = currentSectionNumber - 1;
717
- await tick();
718
- if (tableContainer) {
719
- const anchorElementAfter = findAnchorElement(anchorUniqueKey);
720
- const anchorOffsetAfter = anchorElementAfter?.getBoundingClientRect().top || 0;
721
- const offsetDiff = anchorOffsetAfter - anchorOffsetBefore;
722
- tableContainer.scrollTop += offsetDiff;
723
- userScrolling = true;
724
746
  }
725
747
  }
726
748
  function findAnchorElement(key) {
@@ -734,6 +756,126 @@ function findAnchorElement(key) {
734
756
  }
735
757
  return undefined;
736
758
  }
759
+ function resize(node) {
760
+ let th = node.parentElement;
761
+ let resizingInner = false;
762
+ if (!!th) {
763
+ let { width } = th.getBoundingClientRect();
764
+ function mouseMoveHandler(e) {
765
+ if (resizingInner && !!th && !!tableContainer) {
766
+ width += e.movementX;
767
+ const { paddingLeft, paddingRight } = getComputedStyle(th);
768
+ const minWidth = headers.find(h => h.value === th.id)?.minWidth;
769
+ let minWidthPx;
770
+ if (!!minWidth && minWidth.endsWith('px')) {
771
+ minWidthPx = parseInt(minWidth, 10);
772
+ }
773
+ const maxWidth = headers.find(h => h.value === th.id)?.maxWidth;
774
+ let maxWidthPx;
775
+ if (!!maxWidth && maxWidth.endsWith('px')) {
776
+ maxWidthPx = parseInt(maxWidth, 10);
777
+ }
778
+ const actualMinWidth = (minWidthPx || DEFAULT_MIN_WIDTH_PX) - parseFloat(paddingLeft) - parseFloat(paddingRight);
779
+ const actualMaxWidth = (maxWidthPx || DEFAULT_MAX_WIDTH_PX) - parseFloat(paddingLeft) - parseFloat(paddingRight);
780
+ if (width > actualMinWidth && width < actualMaxWidth) {
781
+ th.style.width = width + 'px';
782
+ resizedColumnSizeWithPadding[th.id] = th.getBoundingClientRect().width;
783
+ resizedColumnSizeWithPadding = {
784
+ ...resizedColumnSizeWithPadding,
785
+ };
786
+ }
787
+ }
788
+ }
789
+ function mouseUpHandler(e, setResize = true) {
790
+ if (!!th) {
791
+ resizingInner = false;
792
+ let { paddingLeft, paddingRight } = getComputedStyle(th);
793
+ width = th.getBoundingClientRect().width - parseFloat(paddingLeft) - parseFloat(paddingRight);
794
+ if (setResize) {
795
+ setTimeout(() => resizing = false, 20);
796
+ }
797
+ if (oncolumnResize) {
798
+ oncolumnResize({
799
+ detail: {
800
+ id: th.id,
801
+ newWidthPx: width
802
+ }
803
+ });
804
+ }
805
+ }
806
+ }
807
+ function mouseDownHandler(e) {
808
+ if (!!th) {
809
+ resizing = true;
810
+ resizingInner = true;
811
+ let { paddingLeft, paddingRight } = getComputedStyle(th);
812
+ width = th.getBoundingClientRect().width - parseFloat(paddingLeft) - parseFloat(paddingRight);
813
+ }
814
+ }
815
+ node.addEventListener('mousedown', mouseDownHandler);
816
+ document.addEventListener('mouseup', mouseUpHandler);
817
+ document.addEventListener('mousemove', mouseMoveHandler);
818
+ return {
819
+ destroy() {
820
+ node.removeEventListener('mousedown', mouseDownHandler);
821
+ document.removeEventListener('mouseup', mouseUpHandler);
822
+ document.removeEventListener('mousemove', mouseMoveHandler);
823
+ }
824
+ };
825
+ }
826
+ }
827
+ $effect(() => {
828
+ if (resizableColumns &&
829
+ !!tableContainer &&
830
+ resizableColumns &&
831
+ headersToShowInTable.length > 0 &&
832
+ resizedColumnSizeWithPadding &&
833
+ headersToShow.length > 0 &&
834
+ mainHeader) {
835
+ tick().then(updateRemainingWidth);
836
+ }
837
+ });
838
+ async function updateRemainingWidth() {
839
+ if (tableContainer != null && !!tableContainer && mainHeader) {
840
+ const containerWidth = tableContainer.getBoundingClientRect().width - 30;
841
+ if (containerWidth) {
842
+ const totalResizableWidth = headersToShowInTable.reduce((sum, head) => {
843
+ let th = document.getElementById(head.value);
844
+ if (!!th) {
845
+ resizeHeader(th, head);
846
+ }
847
+ const width = th?.getBoundingClientRect().width || 0;
848
+ return sum + width + 1;
849
+ }, 0);
850
+ const extraStaticWidth = Array.from(mainHeader.querySelectorAll('th.non-resizable, th.slot-append, th.customize-headers'))
851
+ .reduce((sum, th) => sum + th.getBoundingClientRect().width + 1, 0);
852
+ remainingWidth = Math.max(0, containerWidth - totalResizableWidth - extraStaticWidth);
853
+ }
854
+ }
855
+ }
856
+ function resizeHeader(th, header) {
857
+ if (!resizedColumnSizeWithPadding[header.value]) {
858
+ let widthWihtPadding = th.getBoundingClientRect().width;
859
+ let minWidth = header.minWidth, minWidthPx = DEFAULT_MIN_WIDTH_PX;
860
+ if (!!minWidth && minWidth.endsWith('px')) {
861
+ minWidthPx = parseInt(minWidth, 10);
862
+ }
863
+ if (widthWihtPadding < minWidthPx) {
864
+ widthWihtPadding = minWidthPx;
865
+ }
866
+ let maxWidth = header.maxWidth, maxWidthPx = DEFAULT_MAX_WIDTH_PX;
867
+ if (!!maxWidth && maxWidth.endsWith('px')) {
868
+ maxWidthPx = parseInt(maxWidth, 10);
869
+ }
870
+ if (widthWihtPadding > maxWidthPx) {
871
+ widthWihtPadding = maxWidthPx;
872
+ }
873
+ resizedColumnSizeWithPadding[header.value] = widthWihtPadding;
874
+ }
875
+ let { paddingLeft, paddingRight } = getComputedStyle(th);
876
+ let width = resizedColumnSizeWithPadding[header.value] - parseFloat(paddingLeft) - parseFloat(paddingRight);
877
+ th.style.width = `${width}px`;
878
+ }
737
879
  </script>
738
880
 
739
881
  {#if !!rows && Array.isArray(rows) && !!headersToShowInTable && Array.isArray(headersToShowInTable)}
@@ -880,7 +1022,8 @@ function findAnchorElement(key) {
880
1022
  style:width="30px"
881
1023
  style:min-width="30px"
882
1024
  style:text-align="center"
883
- >
1025
+ class="non-resizable"
1026
+ >
884
1027
  {#if selectMode === "multiple"}
885
1028
  <Checkbox
886
1029
  id="select-all"
@@ -894,16 +1037,22 @@ function findAnchorElement(key) {
894
1037
  {#if showExpand}
895
1038
  <th
896
1039
  style:min-width="60px"
1040
+ style:max-width="60px"
897
1041
  style:text-align="center"
1042
+ class="non-resizable"
898
1043
  ></th>
899
1044
  {/if}
900
1045
  {#each headersToShowInTable as header, index}
901
1046
  <th
902
- style:width={header.width}
1047
+ style={`${resizableColumns || !header.width ? '' : `width: ${header.width}`}`}
903
1048
  style:min-width={header.minWidth}
904
1049
  class:sortable={header.sortable}
905
1050
  onclick={() => handleHeaderClick(header)}
1051
+ id={header.value}
906
1052
  >
1053
+ {#if resizableColumns}
1054
+ <div class="resizer" use:resize></div>
1055
+ {/if}
907
1056
  {#if headerSnippet}
908
1057
  {@render headerSnippet({ header })}
909
1058
  {:else}
@@ -952,17 +1101,27 @@ function findAnchorElement(key) {
952
1101
  </th>
953
1102
  {/each}
954
1103
  {#if rowActionsSnippet || rowAppendSnippet}
955
- <th>
1104
+ <th
1105
+ class="slot-append"
1106
+ >
956
1107
  {@render rowAppendSnippet?.({ index: -1, row: undefined })}
957
1108
  </th>
958
1109
  {/if}
1110
+ {#if resizableColumns && remainingWidth}
1111
+ <th
1112
+ style:width={remainingWidth + 'px'}
1113
+ class="filler"
1114
+ aria-hidden="true"
1115
+ ></th>
1116
+ {/if}
959
1117
  {#if customizeHeaders}
960
1118
  <th
961
- style:width="30px"
962
- style:min-width="30px"
1119
+ style:width="15px"
1120
+ style:min-width="15px"
963
1121
  style:text-align="center"
1122
+ class="customize-headers"
964
1123
  >
965
- <div style="display: flex; gap: 8px;">
1124
+ <div style="display: flex; justify-content: center;">
966
1125
  <Icon
967
1126
  name="mdi-plus-circle-outline"
968
1127
  onclick={() => (openHeaderDrawer = true)}
@@ -1102,6 +1261,7 @@ function findAnchorElement(key) {
1102
1261
  <td
1103
1262
  colspan={headersToShowInTable.length + 1}
1104
1263
  style:border="none"
1264
+ class="expanded-row"
1105
1265
  >
1106
1266
  <table style="display: table;">
1107
1267
  <thead class="table-header table-subheader">
@@ -1685,10 +1845,25 @@ function findAnchorElement(key) {
1685
1845
  border-collapse: separate;
1686
1846
  }
1687
1847
 
1848
+ .table.resizable {
1849
+ table-layout: fixed;
1850
+ width: fit-content;
1851
+ }
1852
+
1853
+ .slot-append {
1854
+ width: 1px;
1855
+ min-width: unset;
1856
+ box-sizing: content-box;
1857
+ }
1858
+
1688
1859
  .table-header {
1689
1860
  position: sticky;
1690
1861
  top: 0;
1691
1862
  z-index: 2;
1863
+ height: var(
1864
+ --dynamic-table-header-height,
1865
+ var(--dynamic-table-default-header-height)
1866
+ );
1692
1867
  }
1693
1868
 
1694
1869
  @media not all and (min-resolution:.001dpcm) {
@@ -1729,12 +1904,6 @@ function findAnchorElement(key) {
1729
1904
  );
1730
1905
  }
1731
1906
 
1732
- .table-header th.sortable {
1733
- cursor: pointer;
1734
- transition: all 0.1s ease-in;
1735
- user-select: none;
1736
- }
1737
-
1738
1907
  .table-header th.sortable:hover {
1739
1908
  color: var(
1740
1909
  --dynamic-table-header-hover-color,
@@ -1777,13 +1946,6 @@ function findAnchorElement(key) {
1777
1946
  );
1778
1947
  }
1779
1948
 
1780
- .thead {
1781
- height: var(
1782
- --dynamic-table-header-height,
1783
- var(--dynamic-table-default-header-height)
1784
- );
1785
- }
1786
-
1787
1949
  table {
1788
1950
  border-collapse: separate;
1789
1951
  width: 100%;
@@ -1793,12 +1955,28 @@ function findAnchorElement(key) {
1793
1955
  text-align: start;
1794
1956
  padding-left: 10px;
1795
1957
  min-width: 100px;
1958
+ position: relative;
1959
+ user-select: none;
1960
+ box-sizing: content-box;
1796
1961
  }
1797
1962
 
1798
1963
  td {
1799
1964
  padding-left: 10px;
1800
1965
  border: 1px solid transparent;
1801
1966
  }
1967
+ table.table > tbody > tr > td {
1968
+ overflow: hidden;
1969
+ text-overflow: ellipsis;
1970
+ }
1971
+
1972
+ table.table > thead > tr > th {
1973
+ overflow: hidden;
1974
+ text-overflow: ellipsis;
1975
+ }
1976
+
1977
+ table.table > tbody > tr > td.expanded-row {
1978
+ overflow: visible;
1979
+ }
1802
1980
 
1803
1981
  .hover-cell:hover, .hover-cell:focus, .cell-edit-activator {
1804
1982
  cursor: pointer;
@@ -2009,4 +2187,17 @@ function findAnchorElement(key) {
2009
2187
  align-items: center;
2010
2188
  gap: 4px;
2011
2189
  }
2190
+
2191
+ .resizer {
2192
+ position: absolute;
2193
+ top: 0;
2194
+ right: 0;
2195
+ width: 6px;
2196
+ height: 100%;
2197
+ cursor: col-resize;
2198
+ z-index: 100;
2199
+ }
2200
+ .filler {
2201
+ padding: 0 !important;
2202
+ }
2012
2203
  </style>
@@ -43,6 +43,7 @@ declare class __sveltets_Render<Item extends {
43
43
  info?: string;
44
44
  } | undefined;
45
45
  info?: string;
46
+ maxWidth?: string;
46
47
  })[] | undefined;
47
48
  headersToShowInTable?: (import("../../simple/lists/SimpleTable.svelte").Header<unknown> & {
48
49
  cellEditorInfo?: {
@@ -75,6 +76,7 @@ declare class __sveltets_Render<Item extends {
75
76
  info?: string;
76
77
  } | undefined;
77
78
  info?: string;
79
+ maxWidth?: string;
78
80
  })[] | undefined;
79
81
  subHeaders?: (import("../../simple/lists/SimpleTable.svelte").Header<unknown> & {
80
82
  cellEditorInfo?: {
@@ -107,6 +109,7 @@ declare class __sveltets_Render<Item extends {
107
109
  info?: string;
108
110
  } | undefined;
109
111
  info?: string;
112
+ maxWidth?: string;
110
113
  })[] | undefined;
111
114
  customizeHeaders?: boolean;
112
115
  rows?: {
@@ -154,6 +157,10 @@ declare class __sveltets_Render<Item extends {
154
157
  uniqueKey?: "disableEdit" | "rowDisableBackgroundColor" | keyof Item | undefined;
155
158
  numberOfResultsVisible?: boolean;
156
159
  endLineVisible?: boolean;
160
+ resizableColumns?: boolean;
161
+ resizedColumnSizeWithPadding?: {
162
+ [value: string]: number;
163
+ } | undefined;
157
164
  class?: {
158
165
  container?: string;
159
166
  header?: string;
@@ -218,6 +225,12 @@ declare class __sveltets_Render<Item extends {
218
225
  setQuickFilterValue: (quickFilter: QuickFilter, value?: any) => void;
219
226
  };
220
227
  }) => void) | undefined;
228
+ oncolumnResize?: ((event: {
229
+ detail: {
230
+ id: string;
231
+ newWidthPx: number;
232
+ };
233
+ }) => void) | undefined;
221
234
  searchBarSnippet?: Snippet<[{
222
235
  handleSearchChange: (searchText: string | undefined) => void;
223
236
  }]> | undefined;
@@ -265,6 +278,7 @@ declare class __sveltets_Render<Item extends {
265
278
  info?: string;
266
279
  } | undefined;
267
280
  info?: string;
281
+ maxWidth?: string;
268
282
  };
269
283
  }]> | undefined;
270
284
  headerLabelSnippet?: Snippet<[{
@@ -299,6 +313,7 @@ declare class __sveltets_Render<Item extends {
299
313
  info?: string;
300
314
  } | undefined;
301
315
  info?: string;
316
+ maxWidth?: string;
302
317
  };
303
318
  }]> | undefined;
304
319
  rowAppendSnippet?: Snippet<[{
@@ -361,6 +376,7 @@ declare class __sveltets_Render<Item extends {
361
376
  info?: string;
362
377
  } | undefined;
363
378
  info?: string;
379
+ maxWidth?: string;
364
380
  };
365
381
  row: {
366
382
  item: Item & {
@@ -405,6 +421,7 @@ declare class __sveltets_Render<Item extends {
405
421
  info?: string;
406
422
  } | undefined;
407
423
  info?: string;
424
+ maxWidth?: string;
408
425
  };
409
426
  }]> | undefined;
410
427
  subHeaderLabelSnippet?: Snippet<[{
@@ -439,6 +456,7 @@ declare class __sveltets_Render<Item extends {
439
456
  info?: string;
440
457
  } | undefined;
441
458
  info?: string;
459
+ maxWidth?: string;
442
460
  };
443
461
  }]> | undefined;
444
462
  subRowAppendSnippet?: Snippet<[{
@@ -489,6 +507,7 @@ declare class __sveltets_Render<Item extends {
489
507
  info?: string;
490
508
  } | undefined;
491
509
  info?: string;
510
+ maxWidth?: string;
492
511
  };
493
512
  row: Item & {
494
513
  disableEdit?: boolean;
@@ -12,7 +12,7 @@ let { headers = [], items = [], sortedBy = $bindable(undefined), sortDirection =
12
12
  { label: "20", value: 20 },
13
13
  { label: "50", value: 50 },
14
14
  { label: "100", value: 100 },
15
- ], hideRowsPerPage = false, totalElements = undefined, rowsPerPage = $bindable(20), filters = $bindable([]), searchBarColumns = undefined, searchBarVisible = true, searchBarPlaceholder = "Type something to search...", lang = "en", editFilterMode = "one-edit", showActiveFilters = true, resizableColumns = false, resizedColumnSizeWithPadding = {}, pointerOnRowHover = undefined, calculateRowStyles = undefined, calculateRowClasses = undefined, class: clazz = {}, onfiltersChange, onpaginationChange, onremoveFilter, onremoveAllFilters, customFilterChipSnippet, customFilterSnippet, filterAppendSnippet, onrowClick, appendSnippet, customSnippet, headerLabelSnippet, headerSnippet, rowActionsSnippet, onsort, footerSnippet, rangeDescriptorSnippet, searchBarSnippet, noDataSnippet, } = $props();
15
+ ], hideRowsPerPage = false, totalElements = undefined, rowsPerPage = $bindable(20), filters = $bindable([]), searchBarColumns = undefined, searchBarVisible = true, searchBarPlaceholder = "Type something to search...", lang = "en", editFilterMode = "one-edit", showActiveFilters = true, resizableColumns = false, resizedColumnSizeWithPadding = {}, pointerOnRowHover = undefined, doubleClickActive = false, doubleClickDelay = 250, calculateRowStyles = undefined, calculateRowClasses = undefined, class: clazz = {}, onfiltersChange, onpaginationChange, onremoveFilter, onremoveAllFilters, customFilterChipSnippet, customFilterSnippet, filterAppendSnippet, onrowClick, onrowDoubleClick, appendSnippet, customSnippet, headerLabelSnippet, headerSnippet, rowActionsSnippet, onsort, footerSnippet, rangeDescriptorSnippet, searchBarSnippet, noDataSnippet, oncolumnResize, } = $props();
16
16
  let searchBarInput = $state(), searchText = $state();
17
17
  let rowsPerPageSelection = $state([]);
18
18
  $effect(() => {
@@ -139,7 +139,11 @@ function buildFilters(params) {
139
139
  bind:sortDirection
140
140
  {pointerOnRowHover}
141
141
  onsort={handleOnSort}
142
+ {doubleClickActive}
143
+ {doubleClickDelay}
144
+ {lang}
142
145
  {onrowClick}
146
+ {onrowDoubleClick}
143
147
  {calculateRowStyles}
144
148
  {calculateRowClasses}
145
149
  {resizableColumns}
@@ -150,6 +154,7 @@ function buildFilters(params) {
150
154
  {headerSnippet}
151
155
  {headerLabelSnippet}
152
156
  {noDataSnippet}
157
+ {oncolumnResize}
153
158
  >
154
159
  </SimpleTable>
155
160
 
@@ -6,11 +6,87 @@ import Dropdown from "../forms/Dropdown.svelte";
6
6
  import { type ComponentProps, type Snippet } from "svelte";
7
7
  import Filters from "../search/Filters.svelte";
8
8
  import type Builder from "../../../utils/filters/builder";
9
- declare const PaginatedTable: import("svelte").Component<{
10
- headers?: ComponentProps<typeof SimpleTable>["headers"];
11
- items?: ComponentProps<typeof SimpleTable>["items"];
12
- sortedBy?: ComponentProps<typeof SimpleTable>["sortedBy"];
13
- sortDirection?: ComponentProps<typeof SimpleTable>["sortDirection"];
9
+ declare const PaginatedTable: import("svelte").Component<Omit<{
10
+ headers: import("../../simple/lists/SimpleTable.svelte").Header<unknown>[];
11
+ items: {
12
+ [key: string]: any;
13
+ }[];
14
+ sortedBy?: string;
15
+ sortDirection?: "asc" | "desc";
16
+ resizableColumns?: boolean;
17
+ resizedColumnSizeWithPadding?: {
18
+ [value: string]: number;
19
+ } | undefined;
20
+ pointerOnRowHover?: boolean;
21
+ lang?: "it" | "en";
22
+ doubleClickActive?: boolean;
23
+ doubleClickDelay?: number;
24
+ calculateRowStyles?: import("../../simple/lists/SimpleTable.svelte").CalculateRowStyles<{
25
+ [key: string]: any;
26
+ }> | undefined;
27
+ calculateRowClasses?: import("../../simple/lists/SimpleTable.svelte").CalculateRowClasses<{
28
+ [key: string]: any;
29
+ }> | undefined;
30
+ onsort?: ((event: {
31
+ detail: {
32
+ sortedBy: string | undefined;
33
+ sortDirection: string;
34
+ };
35
+ }) => void) | undefined;
36
+ onrowClick?: ((event: {
37
+ detail: {
38
+ item: {
39
+ [key: string]: any;
40
+ };
41
+ };
42
+ }) => void) | undefined;
43
+ onrowDoubleClick?: ((event: {
44
+ detail: {
45
+ item: {
46
+ [key: string]: any;
47
+ };
48
+ };
49
+ }) => void) | undefined;
50
+ oncolumnResize?: ((event: {
51
+ detail: {
52
+ id: string;
53
+ newWidthPx: number;
54
+ };
55
+ }) => void) | undefined;
56
+ headerSnippet?: Snippet<[{
57
+ head: import("../../simple/lists/SimpleTable.svelte").Header<unknown>;
58
+ }]> | undefined;
59
+ headerLabelSnippet?: Snippet<[{
60
+ head: import("../../simple/lists/SimpleTable.svelte").Header<unknown>;
61
+ }]> | undefined;
62
+ appendSnippet?: Snippet<[{
63
+ index: number;
64
+ item?: {
65
+ [key: string]: any;
66
+ } | undefined;
67
+ }]> | undefined;
68
+ rowActionsSnippet?: Snippet<[{
69
+ index: number;
70
+ item: {
71
+ [key: string]: any;
72
+ };
73
+ }]> | undefined;
74
+ customSnippet?: Snippet<[{
75
+ index: number;
76
+ columnIndex: number;
77
+ header: import("../../simple/lists/SimpleTable.svelte").Header<unknown>;
78
+ item: {
79
+ [key: string]: any;
80
+ };
81
+ }]> | undefined;
82
+ noDataSnippet?: Snippet<[]>;
83
+ class?: {
84
+ container?: string;
85
+ header?: string;
86
+ row?: string;
87
+ cell?: string;
88
+ } | undefined;
89
+ }, "class"> & {
14
90
  page?: NonNullable<ComponentProps<typeof Paginator>["page"]>;
15
91
  maxPage?: ComponentProps<typeof Paginator>["maxPage"];
16
92
  rowsPerPageOptions?: ComponentProps<typeof Dropdown>["items"];
@@ -21,16 +97,8 @@ declare const PaginatedTable: import("svelte").Component<{
21
97
  searchBarColumns?: string[];
22
98
  searchBarVisible?: boolean;
23
99
  searchBarPlaceholder?: string;
24
- lang?: "it" | "en";
25
100
  editFilterMode?: "one-edit" | "multi-edit";
26
101
  showActiveFilters?: boolean;
27
- resizableColumns?: boolean;
28
- resizedColumnSizeWithPadding?: {
29
- [value: string]: number;
30
- };
31
- pointerOnRowHover?: boolean;
32
- calculateRowStyles?: ComponentProps<typeof SimpleTable>["calculateRowStyles"];
33
- calculateRowClasses?: ComponentProps<typeof SimpleTable>["calculateRowClasses"];
34
102
  class?: {
35
103
  simpleTable?: ComponentProps<typeof SimpleTable>["class"];
36
104
  };
@@ -51,14 +119,6 @@ declare const PaginatedTable: import("svelte").Component<{
51
119
  filterAppendSnippet?: ComponentProps<typeof Filters>["appendSnippet"];
52
120
  customFilterChipSnippet?: ComponentProps<typeof Filters>["customChipSnippet"];
53
121
  customFilterSnippet?: ComponentProps<typeof Filters>["customSnippet"];
54
- onsort?: ComponentProps<typeof SimpleTable>["onsort"];
55
- onrowClick?: ComponentProps<typeof SimpleTable>["onrowClick"];
56
- customSnippet?: ComponentProps<typeof SimpleTable>["customSnippet"];
57
- rowActionsSnippet?: ComponentProps<typeof SimpleTable>["rowActionsSnippet"];
58
- appendSnippet?: ComponentProps<typeof SimpleTable>["appendSnippet"];
59
- headerSnippet?: ComponentProps<typeof SimpleTable>["headerSnippet"];
60
- headerLabelSnippet?: ComponentProps<typeof SimpleTable>["headerLabelSnippet"];
61
- noDataSnippet?: ComponentProps<typeof SimpleTable>["noDataSnippet"];
62
122
  searchBarSnippet?: Snippet<[{
63
123
  handleSearchChange: (searchText: string | undefined) => void;
64
124
  }]>;
@@ -6,7 +6,11 @@ import './SimpleTable.css';
6
6
  import Icon from '../media/Icon.svelte';
7
7
  import { onMount } from 'svelte';
8
8
  import NoData from '../common/NoData.svelte';
9
- let { headers = [], items = [], sortedBy = $bindable(undefined), sortDirection = $bindable("asc"), resizableColumns = false, resizedColumnSizeWithPadding = $bindable(), pointerOnRowHover = false, lang = 'en', calculateRowStyles = undefined, calculateRowClasses = undefined, oncolumnResize, onrowClick, onsort, headerSnippet, headerLabelSnippet, appendSnippet, rowActionsSnippet, customSnippet, noDataSnippet, class: clazz = {}, } = $props();
9
+ let { headers = [], items = [], sortedBy = $bindable(undefined), sortDirection = $bindable("asc"), resizableColumns = false, resizedColumnSizeWithPadding = $bindable(), pointerOnRowHover = false, lang = 'en', doubleClickActive = false, doubleClickDelay = 250, calculateRowStyles = undefined, calculateRowClasses = undefined, oncolumnResize, onrowClick, onrowDoubleClick, onsort, headerSnippet, headerLabelSnippet, appendSnippet, rowActionsSnippet, customSnippet, noDataSnippet, class: clazz = {}, } = $props();
10
+ if (!onrowClick && !!onrowDoubleClick) {
11
+ throw new Error('cannot define an onrowDoubleClick event without defining an onrowClick event');
12
+ }
13
+ let clickTimeout = undefined;
10
14
  onMount(() => {
11
15
  if (resizableColumns) {
12
16
  if (!resizedColumnSizeWithPadding)
@@ -72,12 +76,39 @@ function handleHeaderClick(header) {
72
76
  }
73
77
  }
74
78
  function handleRowClick(item) {
75
- if (onrowClick) {
76
- onrowClick({
77
- detail: {
78
- item
79
+ if (doubleClickActive) {
80
+ if (clickTimeout) {
81
+ clearTimeout(clickTimeout);
82
+ clickTimeout = undefined;
83
+ if (onrowDoubleClick) {
84
+ onrowDoubleClick({
85
+ detail: {
86
+ item
87
+ }
88
+ });
79
89
  }
80
- });
90
+ }
91
+ else {
92
+ clickTimeout = setTimeout(() => {
93
+ if (onrowClick) {
94
+ onrowClick({
95
+ detail: {
96
+ item
97
+ }
98
+ });
99
+ }
100
+ clickTimeout = undefined;
101
+ }, doubleClickDelay);
102
+ }
103
+ }
104
+ else {
105
+ if (onrowClick) {
106
+ onrowClick({
107
+ detail: {
108
+ item
109
+ }
110
+ });
111
+ }
81
112
  }
82
113
  }
83
114
  function formatDate(dateTime, dateFormat) {
@@ -32,6 +32,8 @@ declare class __sveltets_Render<Item extends {
32
32
  } | undefined;
33
33
  pointerOnRowHover?: boolean;
34
34
  lang?: "it" | "en";
35
+ doubleClickActive?: boolean;
36
+ doubleClickDelay?: number;
35
37
  calculateRowStyles?: CalculateRowStyles<Item> | undefined;
36
38
  calculateRowClasses?: CalculateRowClasses<Item> | undefined;
37
39
  onsort?: ((event: {
@@ -45,6 +47,11 @@ declare class __sveltets_Render<Item extends {
45
47
  item: Item;
46
48
  };
47
49
  }) => void) | undefined;
50
+ onrowDoubleClick?: ((event: {
51
+ detail: {
52
+ item: Item;
53
+ };
54
+ }) => void) | undefined;
48
55
  oncolumnResize?: ((event: {
49
56
  detail: {
50
57
  id: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@likable-hair/svelte",
3
3
  "description": "A Svelte component for likablehair and others",
4
- "version": "4.0.0",
4
+ "version": "4.0.1",
5
5
  "scripts": {
6
6
  "host": "vite --host",
7
7
  "dev": "vite dev",
@@ -28,7 +28,7 @@
28
28
  "dist"
29
29
  ],
30
30
  "peerDependencies": {
31
- "svelte": "^4.2.9"
31
+ "svelte": "^5.0.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@orama/orama": "^3.1.4",