Files
metabuilder/packages/data_table/seed/scripts/sorting.lua

132 lines
3.2 KiB
Lua

-- Sorting utilities for data tables
-- Provides column sorting logic and state management
---@class Sorting
local M = {}
---@alias SortDirection "asc" | "desc" | nil
---@class SortState
---@field column_id string|nil Column being sorted
---@field direction SortDirection Sort direction
---@class SortedResult
---@field data table[] Sorted data array
---@field state SortState Current sort state
---Create initial sort state
---@return SortState
function M.createSortState()
return {
column_id = nil,
direction = nil
}
end
---Compare two values for sorting
---@param a any First value
---@param b any Second value
---@param direction SortDirection Sort direction
---@return boolean Whether a should come before b
function M.compare(a, b, direction)
local aVal = a
local bVal = b
-- Handle nil values (push to end)
if aVal == nil and bVal == nil then return false end
if aVal == nil then return direction == "desc" end
if bVal == nil then return direction == "asc" end
-- Handle different types
local aType = type(aVal)
local bType = type(bVal)
if aType ~= bType then
aVal = tostring(aVal)
bVal = tostring(bVal)
end
-- Compare based on type
if aType == "number" then
if direction == "desc" then
return aVal > bVal
else
return aVal < bVal
end
else
-- String comparison (case-insensitive)
local aLower = string.lower(tostring(aVal))
local bLower = string.lower(tostring(bVal))
if direction == "desc" then
return aLower > bLower
else
return aLower < bLower
end
end
end
---Sort data by a column
---@param data table[] Array of row data objects
---@param column_id string Column identifier to sort by
---@param direction SortDirection Sort direction ("asc" or "desc")
---@return table[] Sorted data array (new array, original unchanged)
function M.sortByColumn(data, column_id, direction)
if not column_id or not direction then
return data
end
-- Create a copy to avoid mutating original
local sorted = {}
for i, row in ipairs(data) do
sorted[i] = row
end
table.sort(sorted, function(a, b)
return M.compare(a[column_id], b[column_id], direction)
end)
return sorted
end
---Toggle sort state for a column
---@param state SortState Current sort state
---@param column_id string Column identifier clicked
---@return SortState New sort state
function M.toggleSort(state, column_id)
if state.column_id ~= column_id then
-- New column: start with ascending
return {
column_id = column_id,
direction = "asc"
}
elseif state.direction == "asc" then
-- Same column, was ascending: switch to descending
return {
column_id = column_id,
direction = "desc"
}
else
-- Same column, was descending: clear sort
return {
column_id = nil,
direction = nil
}
end
end
---Get sort indicator for a column
---@param state SortState Current sort state
---@param column_id string Column identifier to check
---@return string|nil Sort indicator ("▲", "▼", or nil)
function M.getSortIndicator(state, column_id)
if state.column_id ~= column_id then
return nil
elseif state.direction == "asc" then
return ""
else
return ""
end
end
return M