1919 <span v-else class =" inline-flex items-center" >
2020 {{ column.label }}
2121 <span v-if =" isColumnSortable(column)" class =" text-lightTableHeadingText dark:text-darkTableHeadingText" >
22- <!-- Unsorted indicator -->
23- <svg v-if =" !isSorted(column)" class =" w-3 h-3 ms-1.5 opacity-30" aria-hidden =" true" xmlns =" http://www.w3.org/2000/svg" fill =" currentColor" viewBox =" 0 0 24 24" ><path d =" M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z" ></path ></svg >
24- <!-- Sorted ascending indicator -->
25- <svg v-else-if =" currentSortDirection === 'asc'" class =" w-3 h-3 ms-1.5" fill =" currentColor" viewBox =" 0 0 24 24" ><path d =" M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 0z" ></path ></svg >
26- <!-- Sorted descending indicator (rotated) -->
27- <svg v-else class =" w-3 h-3 ms-1.5 rotate-180" fill =" currentColor" viewBox =" 0 0 24 24" ><path d =" M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 0z" ></path ></svg >
22+ <!-- Unsorted -->
23+ <svg v-if =" currentSortField !== column.fieldName" class =" w-3 h-3 ms-1.5 opacity-30" aria-hidden =" true" xmlns =" http://www.w3.org/2000/svg" fill =" currentColor" viewBox =" 0 0 24 24" ><path d =" M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z" /></svg >
24+
25+ <!-- Sorted ascending -->
26+ <svg v-else-if =" currentSortDirection === 'asc'" class =" w-3 h-3 ms-1.5" fill =" currentColor" viewBox =" 0 0 24 24" ><path d =" M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 0z" /></svg >
27+
28+ <!-- Sorted descending -->
29+ <svg v-else class =" w-3 h-3 ms-1.5 rotate-180" fill =" currentColor" viewBox =" 0 0 24 24" ><path d =" M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 0z" /></svg >
2830 </span >
2931 </span >
3032 </th >
293295 }
294296 }
295297
296- function isColumnSortable(column : { fieldName: string ; sortable? : boolean }) {
297- return !! props .sortable && column .sortable !== false ;
298- }
298+ function isColumnSortable(col : { fieldName: string ; sortable? : boolean }) {
299+ return !! props .sortable && col .sortable !== false ;
300+ }
299301
300- function isSorted(column : { fieldName: string }) {
301- return currentSortField .value === column .fieldName ;
302+ function onHeaderClick(col : {fieldName: string ; sortable? : boolean }) {
303+ if (! isColumnSortable (col )) return ;
304+ if (currentSortField .value !== col .fieldName ) {
305+ currentSortField .value = col .fieldName ;
306+ currentSortDirection .value = props .defaultSortDirection ?? ' asc' ;
307+ } else {
308+ currentSortDirection .value =
309+ currentSortDirection .value === ' asc' ? ' desc' :
310+ currentSortField .value ? (currentSortField .value = undefined , props .defaultSortDirection ?? ' asc' ) :
311+ ' asc' ;
302312 }
313+ }
303314
304- function getAriaSort(column : { fieldName: string ; sortable? : boolean }) {
305- if (! isColumnSortable (column )) return undefined ;
306- if (! isSorted ( column ) ) return ' none' ;
307- return currentSortDirection .value === ' asc' ? ' ascending' : ' descending' ;
308- }
315+ function getAriaSort(col : { fieldName: string ; sortable? : boolean }) {
316+ if (! isColumnSortable (col )) return undefined ;
317+ if (currentSortField . value !== col . fieldName ) return ' none' ;
318+ return currentSortDirection .value === ' asc' ? ' ascending' : ' descending' ;
319+ }
309320
310- function onHeaderClick(column : { fieldName: string ; sortable? : boolean }) {
311- if (! isColumnSortable (column )) return ;
312- if (currentSortField .value !== column .fieldName ) {
313- currentSortField .value = column .fieldName ;
314- currentSortDirection .value = props .defaultSortDirection ?? ' asc' ;
315- } else {
316- if (currentSortDirection .value === ' asc' ) {
317- currentSortDirection .value = ' desc' ;
318- } else if (currentSortDirection .value === ' desc' ) {
319- currentSortField .value = undefined ;
320- currentSortDirection .value = props .defaultSortDirection ?? ' asc' ;
321- } else {
322- currentSortDirection .value = ' asc' ;
323- }
324- }
325- }
326-
327- function getValueByPath(obj : any , path : string | undefined ) {
328- if (! path ) return undefined ;
329- return path .split (' .' ).reduce ((acc : any , key : string ) => (acc == null ? acc : acc [key ]), obj );
330- }
331-
332- function compareValues(a : any , b : any ) {
333- if (a == null && b == null ) return 0 ;
334- if (a == null ) return 1 ;
335- if (b == null ) return - 1 ;
336- if (typeof a === ' number' && typeof b === ' number' ) return a - b ;
337- const aDate = a instanceof Date ? a : undefined ;
338- const bDate = b instanceof Date ? b : undefined ;
339- if (aDate && bDate ) return aDate .getTime () - bDate .getTime ();
340- return String (a ).localeCompare (String (b ), undefined , { numeric: true , sensitivity: ' base' });
341- }
342-
343- function sortArrayData(data : { [key : string ]: any }[], sortField ? : string , sortDirection : ' asc' | ' desc' = ' asc' ) {
344- if (! props .sortable || ! sortField ) return data ;
345- const copy = data .slice ();
346- copy .sort ((rowA , rowB ) => {
347- const aVal = getValueByPath (rowA , sortField );
348- const bVal = getValueByPath (rowB , sortField );
349- const cmp = compareValues (aVal , bVal );
350- return sortDirection === ' asc' ? cmp : - cmp ;
351- });
352- return copy ;
353- }
321+ const collator = new Intl .Collator (undefined , { numeric: true , sensitivity: ' base' });
354322
323+ function sortArrayData(data : any [], sortField ? : string , dir : ' asc' | ' desc' = ' asc' ) {
324+ if (! props .sortable || ! sortField ) return data ;
325+ const get = (o : any , p : string ) => p .split (' .' ).reduce ((a : any ,k )=> a ?.[k ], o );
326+ return [... data ].sort ((a ,b ) => {
327+ let av = get (a , sortField ), bv = get (b , sortField );
328+ if (av == null && bv == null ) return 0 ;
329+ if (av == null ) return 1 ; if (bv == null ) return - 1 ;
330+ if (av instanceof Date && bv instanceof Date ) return dir === ' asc' ? av .getTime () - bv .getTime () : bv .getTime () - av .getTime ();
331+ if (typeof av === ' number' && typeof bv === ' number' ) return dir === ' asc' ? av - bv : bv - av ;
332+ const cmp = collator .compare (String (av ), String (bv ));
333+ return dir === ' asc' ? cmp : - cmp ;
334+ });
335+ }
355336 </script >
0 commit comments