feat: bilingual support (FA/EN), IRANSans typography, RTL layout, and interactive product detail pages
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { generateKeyBetween, generateNKeysBetween } from "fractional-indexing";
|
||||
|
||||
export interface Ordered {
|
||||
readonly id: string;
|
||||
readonly order: string;
|
||||
}
|
||||
|
||||
export function compareOrdered(a: Ordered, b: Ordered): number {
|
||||
if (a.order !== b.order) {
|
||||
return a.order < b.order ? -1 : 1;
|
||||
}
|
||||
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
||||
}
|
||||
|
||||
/** Where `item` sorts into `sorted`: its own index when present, else its insertion index. */
|
||||
export function rankOf(sorted: readonly Ordered[], item: Ordered): number {
|
||||
let low = 0;
|
||||
let high = sorted.length;
|
||||
while (low < high) {
|
||||
const middle = (low + high) >>> 1;
|
||||
if (compareOrdered(sorted[middle]!, item) < 0) {
|
||||
low = middle + 1;
|
||||
} else {
|
||||
high = middle;
|
||||
}
|
||||
}
|
||||
return low;
|
||||
}
|
||||
|
||||
/** A key after every item in `sorted`. */
|
||||
export function appendKey(sorted: readonly Ordered[]): string {
|
||||
return (
|
||||
between(sorted[sorted.length - 1]?.order ?? null, null) ??
|
||||
generateKeyBetween(null, null)
|
||||
);
|
||||
}
|
||||
|
||||
/** Keys that put `sorted[from]` at `index` among the other items; `repairs` re-key those only when no key fits between its new neighbours. */
|
||||
export function placeAt(
|
||||
sorted: readonly Ordered[],
|
||||
from: number,
|
||||
index: number,
|
||||
): { key: string; repairs: Array<{ id: string; order: string }> } {
|
||||
const other = (at: number) => sorted[at < from ? at : at + 1];
|
||||
const key = between(
|
||||
other(index - 1)?.order ?? null,
|
||||
other(index)?.order ?? null,
|
||||
);
|
||||
if (key !== undefined) {
|
||||
return { key, repairs: [] };
|
||||
}
|
||||
const keys = generateNKeysBetween(null, null, sorted.length);
|
||||
return {
|
||||
key: keys[index]!,
|
||||
repairs: sorted
|
||||
.filter((_, at) => at !== from)
|
||||
.map((item, at) => ({
|
||||
id: item.id,
|
||||
order: keys[at < index ? at : at + 1]!,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
/** The index of `item` in `sorted`, or -1. */
|
||||
export function indexOf(sorted: readonly Ordered[], item: Ordered): number {
|
||||
const rank = rankOf(sorted, item);
|
||||
return sorted[rank] === item ? rank : -1;
|
||||
}
|
||||
|
||||
function between(a: string | null, b: string | null): string | undefined {
|
||||
try {
|
||||
return generateKeyBetween(a, b);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user