Files
paperclip/ui/src/lib/project-order.ts
Dotta f60c1001ec refactor: rename packages to @paperclipai and CLI binary to paperclipai
Rename all workspace packages from @paperclip/* to @paperclipai/* and
the CLI binary from `paperclip` to `paperclipai` in preparation for
npm publishing. Bump CLI version to 0.1.0 and add package metadata
(description, keywords, license, repository, files). Update all
imports, documentation, user-facing messages, and tests accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 08:45:26 -06:00

71 lines
2.1 KiB
TypeScript

import type { Project } from "@paperclipai/shared";
export const PROJECT_ORDER_UPDATED_EVENT = "paperclip:project-order-updated";
const PROJECT_ORDER_STORAGE_PREFIX = "paperclip.projectOrder";
const ANONYMOUS_USER_ID = "anonymous";
type ProjectOrderUpdatedDetail = {
storageKey: string;
orderedIds: string[];
};
function normalizeIdList(value: unknown): string[] {
if (!Array.isArray(value)) return [];
return value.filter((item): item is string => typeof item === "string" && item.length > 0);
}
function resolveUserId(userId: string | null | undefined): string {
if (!userId) return ANONYMOUS_USER_ID;
const trimmed = userId.trim();
return trimmed.length > 0 ? trimmed : ANONYMOUS_USER_ID;
}
export function getProjectOrderStorageKey(companyId: string, userId: string | null | undefined): string {
return `${PROJECT_ORDER_STORAGE_PREFIX}:${companyId}:${resolveUserId(userId)}`;
}
export function readProjectOrder(storageKey: string): string[] {
try {
const raw = localStorage.getItem(storageKey);
if (!raw) return [];
return normalizeIdList(JSON.parse(raw));
} catch {
return [];
}
}
export function writeProjectOrder(storageKey: string, orderedIds: string[]) {
const normalized = normalizeIdList(orderedIds);
try {
localStorage.setItem(storageKey, JSON.stringify(normalized));
} catch {
// Ignore storage write failures in restricted browser contexts.
}
if (typeof window !== "undefined") {
window.dispatchEvent(
new CustomEvent<ProjectOrderUpdatedDetail>(PROJECT_ORDER_UPDATED_EVENT, {
detail: { storageKey, orderedIds: normalized },
}),
);
}
}
export function sortProjectsByStoredOrder(projects: Project[], orderedIds: string[]): Project[] {
if (projects.length === 0) return [];
if (orderedIds.length === 0) return projects;
const byId = new Map(projects.map((project) => [project.id, project]));
const sorted: Project[] = [];
for (const id of orderedIds) {
const project = byId.get(id);
if (!project) continue;
sorted.push(project);
byId.delete(id);
}
for (const project of byId.values()) {
sorted.push(project);
}
return sorted;
}