summaryrefslogtreecommitdiff
path: root/apps/web/src/lib/selection/state.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-03-27 00:55:15 +0100
committerMaze Winther <mazewinther@gmail.com>2026-03-29 15:56:48 +0200
commit4d127a038bf768eded68aae3cfa5c1b12241bdac (patch)
tree16bbb801caf6770546cff4fdb37b6408ec9ead98 /apps/web/src/lib/selection/state.ts
parent82817cb50cb0487350573d6129130aec705f924b (diff)
downloadopencut-4d127a038bf768eded68aae3cfa5c1b12241bdac.tar.gz
chore: normalize line endings
Diffstat (limited to 'apps/web/src/lib/selection/state.ts')
-rw-r--r--apps/web/src/lib/selection/state.ts330
1 files changed, 165 insertions, 165 deletions
diff --git a/apps/web/src/lib/selection/state.ts b/apps/web/src/lib/selection/state.ts
index b4c454fb..b0ba3089 100644
--- a/apps/web/src/lib/selection/state.ts
+++ b/apps/web/src/lib/selection/state.ts
@@ -1,165 +1,165 @@
-import type {
- BoxSelectionChange,
- SelectionState,
-} from "@/lib/selection/types";
-
-function dedupeIds({ ids }: { ids: string[] }) {
- return [...new Set(ids)];
-}
-
-function getRangeIds({
- orderedIds,
- anchorId,
- targetId,
-}: {
- orderedIds: string[];
- anchorId: string;
- targetId: string;
-}) {
- const anchorIndex = orderedIds.indexOf(anchorId);
- const targetIndex = orderedIds.indexOf(targetId);
-
- if (anchorIndex === -1 || targetIndex === -1) {
- return [targetId];
- }
-
- const rangeStart = Math.min(anchorIndex, targetIndex);
- const rangeEnd = Math.max(anchorIndex, targetIndex);
- return orderedIds.slice(rangeStart, rangeEnd + 1);
-}
-
-export function replaceSelection({
- ids,
- anchorId,
-}: {
- ids: string[];
- anchorId?: string | null;
-}): SelectionState {
- const selectedIds = dedupeIds({ ids });
- return {
- selectedIds,
- anchorId: anchorId ?? selectedIds[selectedIds.length - 1] ?? null,
- };
-}
-
-export function clearSelection(): SelectionState {
- return {
- selectedIds: [],
- anchorId: null,
- };
-}
-
-export function pruneSelection({
- state,
- orderedIds,
-}: {
- state: SelectionState;
- orderedIds: string[];
-}): SelectionState {
- const validIds = new Set(orderedIds);
- const selectedIds = state.selectedIds.filter((id) => validIds.has(id));
- const anchorId =
- state.anchorId && validIds.has(state.anchorId)
- ? state.anchorId
- : selectedIds[selectedIds.length - 1] ?? null;
- const isUnchanged =
- selectedIds.length === state.selectedIds.length &&
- anchorId === state.anchorId;
-
- if (isUnchanged) {
- return state;
- }
-
- return {
- selectedIds,
- anchorId,
- };
-}
-
-export function isSelected({
- state,
- id,
-}: {
- state: SelectionState;
- id: string;
-}) {
- return state.selectedIds.includes(id);
-}
-
-export function toggleSelection({
- state,
- id,
-}: {
- state: SelectionState;
- id: string;
-}): SelectionState {
- if (isSelected({ state, id })) {
- const selectedIds = state.selectedIds.filter((selectedId) => selectedId !== id);
- const anchorId =
- state.anchorId === id
- ? selectedIds[selectedIds.length - 1] ?? null
- : state.anchorId;
- return replaceSelection({
- ids: selectedIds,
- anchorId,
- });
- }
-
- return replaceSelection({
- ids: [...state.selectedIds, id],
- anchorId: id,
- });
-}
-
-export function selectRange({
- state,
- orderedIds,
- targetId,
- isAdditive,
-}: {
- state: SelectionState;
- orderedIds: string[];
- targetId: string;
- isAdditive: boolean;
-}): SelectionState {
- const anchorId =
- state.anchorId ??
- state.selectedIds[state.selectedIds.length - 1] ??
- targetId;
- const rangeIds = getRangeIds({
- orderedIds,
- anchorId,
- targetId,
- });
- const selectedIds = isAdditive
- ? dedupeIds({
- ids: [...state.selectedIds, ...rangeIds],
- })
- : rangeIds;
-
- return replaceSelection({
- ids: selectedIds,
- anchorId,
- });
-}
-
-export function applyBoxSelection({
- intersectedIds,
- initialSelectedIds,
- initialAnchorId,
- isAdditive,
-}: BoxSelectionChange): SelectionState {
- const selectedIds = isAdditive
- ? dedupeIds({
- ids: [...initialSelectedIds, ...intersectedIds],
- })
- : intersectedIds;
- const anchorId = isAdditive
- ? initialAnchorId ?? intersectedIds[intersectedIds.length - 1] ?? null
- : intersectedIds[intersectedIds.length - 1] ?? null;
-
- return replaceSelection({
- ids: selectedIds,
- anchorId,
- });
-}
+import type {
+ BoxSelectionChange,
+ SelectionState,
+} from "@/lib/selection/types";
+
+function dedupeIds({ ids }: { ids: string[] }) {
+ return [...new Set(ids)];
+}
+
+function getRangeIds({
+ orderedIds,
+ anchorId,
+ targetId,
+}: {
+ orderedIds: string[];
+ anchorId: string;
+ targetId: string;
+}) {
+ const anchorIndex = orderedIds.indexOf(anchorId);
+ const targetIndex = orderedIds.indexOf(targetId);
+
+ if (anchorIndex === -1 || targetIndex === -1) {
+ return [targetId];
+ }
+
+ const rangeStart = Math.min(anchorIndex, targetIndex);
+ const rangeEnd = Math.max(anchorIndex, targetIndex);
+ return orderedIds.slice(rangeStart, rangeEnd + 1);
+}
+
+export function replaceSelection({
+ ids,
+ anchorId,
+}: {
+ ids: string[];
+ anchorId?: string | null;
+}): SelectionState {
+ const selectedIds = dedupeIds({ ids });
+ return {
+ selectedIds,
+ anchorId: anchorId ?? selectedIds[selectedIds.length - 1] ?? null,
+ };
+}
+
+export function clearSelection(): SelectionState {
+ return {
+ selectedIds: [],
+ anchorId: null,
+ };
+}
+
+export function pruneSelection({
+ state,
+ orderedIds,
+}: {
+ state: SelectionState;
+ orderedIds: string[];
+}): SelectionState {
+ const validIds = new Set(orderedIds);
+ const selectedIds = state.selectedIds.filter((id) => validIds.has(id));
+ const anchorId =
+ state.anchorId && validIds.has(state.anchorId)
+ ? state.anchorId
+ : selectedIds[selectedIds.length - 1] ?? null;
+ const isUnchanged =
+ selectedIds.length === state.selectedIds.length &&
+ anchorId === state.anchorId;
+
+ if (isUnchanged) {
+ return state;
+ }
+
+ return {
+ selectedIds,
+ anchorId,
+ };
+}
+
+export function isSelected({
+ state,
+ id,
+}: {
+ state: SelectionState;
+ id: string;
+}) {
+ return state.selectedIds.includes(id);
+}
+
+export function toggleSelection({
+ state,
+ id,
+}: {
+ state: SelectionState;
+ id: string;
+}): SelectionState {
+ if (isSelected({ state, id })) {
+ const selectedIds = state.selectedIds.filter((selectedId) => selectedId !== id);
+ const anchorId =
+ state.anchorId === id
+ ? selectedIds[selectedIds.length - 1] ?? null
+ : state.anchorId;
+ return replaceSelection({
+ ids: selectedIds,
+ anchorId,
+ });
+ }
+
+ return replaceSelection({
+ ids: [...state.selectedIds, id],
+ anchorId: id,
+ });
+}
+
+export function selectRange({
+ state,
+ orderedIds,
+ targetId,
+ isAdditive,
+}: {
+ state: SelectionState;
+ orderedIds: string[];
+ targetId: string;
+ isAdditive: boolean;
+}): SelectionState {
+ const anchorId =
+ state.anchorId ??
+ state.selectedIds[state.selectedIds.length - 1] ??
+ targetId;
+ const rangeIds = getRangeIds({
+ orderedIds,
+ anchorId,
+ targetId,
+ });
+ const selectedIds = isAdditive
+ ? dedupeIds({
+ ids: [...state.selectedIds, ...rangeIds],
+ })
+ : rangeIds;
+
+ return replaceSelection({
+ ids: selectedIds,
+ anchorId,
+ });
+}
+
+export function applyBoxSelection({
+ intersectedIds,
+ initialSelectedIds,
+ initialAnchorId,
+ isAdditive,
+}: BoxSelectionChange): SelectionState {
+ const selectedIds = isAdditive
+ ? dedupeIds({
+ ids: [...initialSelectedIds, ...intersectedIds],
+ })
+ : intersectedIds;
+ const anchorId = isAdditive
+ ? initialAnchorId ?? intersectedIds[intersectedIds.length - 1] ?? null
+ : intersectedIds[intersectedIds.length - 1] ?? null;
+
+ return replaceSelection({
+ ids: selectedIds,
+ anchorId,
+ });
+}