Skip to content

Sorting Methods

Sorting methods let plugins contribute reusable sort strategies to lists, menus, sheets, and other app surfaces. Access the registry through ctx.sortingMethods after requesting the registry.sorting-method permission.

{
"recall": {
"permissions": ["registry.sorting-method"]
}
}
import type { SortingMethod } from "@jrtilak-recall/runtime";
const subjectNameSort: SortingMethod<Subject> = {
id: "focus-tools.subject-name",
name: "Subject name",
shortName: "Name",
defaultOrder: "asc",
icon: "Sorting01Icon",
appliesWhen: {
scope: "subjects",
hasProperty: "name",
},
onSort(items, sortOrder) {
return [...items].sort((left, right) => {
const result = left.name.localeCompare(right.name);
return sortOrder === "asc" ? result : -result;
});
},
};
FieldDescription
idStable, preferably namespaced registry id.
nameLabel for normal UI surfaces.
shortNameLabel for compact UI surfaces.
defaultOrder"asc" or "desc", used when no override is supplied.
iconHuge Icons name shown beside the method.
appliesWhenRequired property and supported runtime scope.
onSortFunction that returns the items in the requested order.

Return a new array from onSort() when possible. Mutating the input can affect code that still holds the original array.

appliesWhen.scope identifies the supported surface; use "*" for every scope. appliesWhen.hasProperty must exist on at least one input item.

Use canApplySortingMethod() when filtering methods before showing them:

import { canApplySortingMethod } from "@jrtilak-recall/runtime";
const availableMethods = (await ctx.sortingMethods.list<Subject>()).filter(
(method) =>
canApplySortingMethod(method, {
items: subjects,
scope: "subjects",
}),
);

ctx.sortingMethods.sort() performs the same check before calling onSort().

Register one or more methods together and retain the returned lifecycle handle:

const registration = await ctx.sortingMethods.register({
methods: [subjectNameSort],
});
const sortedSubjects = await ctx.sortingMethods.sort({
items: subjects,
methodId: "focus-tools.subject-name",
scope: "subjects",
sortOrder: "desc",
});
await registration.dispose();

The method’s defaultOrder is used when sortOrder is omitted. sort() returns the original items when the method id is missing or unknown, the method does not apply, the method throws, or it returns a non-array value.

Plugin registrations reject existing method ids. Prefer namespaced ids and dispose only registrations owned by your plugin. remove(id) removes one plugin-owned method explicitly.

list<TItem>() returns the current registered methods. Subscribe to listChange when a UI needs to update as methods are added or removed:

const subscription = await ctx.sortingMethods.on("listChange", ({ methods }) => {
renderSortingMethods(methods);
});
await subscription.dispose();