cleanup
This commit is contained in:
@@ -37,26 +37,24 @@ const LoginRoute = () => {
|
||||
|
||||
let combined = extract(location.search);
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
const hash = window.location.hash || '';
|
||||
const queryIndex = hash.indexOf('?');
|
||||
if (queryIndex !== -1) {
|
||||
const hashQuery = hash.slice(queryIndex + 1);
|
||||
const hashParams = extract(`?${hashQuery}`);
|
||||
combined = {
|
||||
token: combined.token || hashParams.token,
|
||||
username: combined.username || hashParams.username,
|
||||
preferredTenantId: combined.preferredTenantId || hashParams.preferredTenantId,
|
||||
};
|
||||
}
|
||||
if (!combined.token) {
|
||||
const searchParams = extract(window.location.search);
|
||||
combined = {
|
||||
token: combined.token || searchParams.token,
|
||||
username: combined.username || searchParams.username,
|
||||
preferredTenantId: combined.preferredTenantId || searchParams.preferredTenantId,
|
||||
};
|
||||
}
|
||||
const hash = window.location.hash || '';
|
||||
const queryIndex = hash.indexOf('?');
|
||||
if (queryIndex !== -1) {
|
||||
const hashQuery = hash.slice(queryIndex + 1);
|
||||
const hashParams = extract(`?${hashQuery}`);
|
||||
combined = {
|
||||
token: combined.token || hashParams.token,
|
||||
username: combined.username || hashParams.username,
|
||||
preferredTenantId: combined.preferredTenantId || hashParams.preferredTenantId,
|
||||
};
|
||||
}
|
||||
if (!combined.token) {
|
||||
const searchParams = extract(window.location.search);
|
||||
combined = {
|
||||
token: combined.token || searchParams.token,
|
||||
username: combined.username || searchParams.username,
|
||||
preferredTenantId: combined.preferredTenantId || searchParams.preferredTenantId,
|
||||
};
|
||||
}
|
||||
|
||||
return combined;
|
||||
@@ -96,10 +94,6 @@ const LoginRoute = () => {
|
||||
);
|
||||
|
||||
const clearMagicParamsFromUrl = useCallback(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const removableKeys = ['magic_token', 'username', 'preferred_tenant_id'];
|
||||
const currentSearch = new URLSearchParams(window.location.search);
|
||||
let searchChanged = false;
|
||||
@@ -184,7 +178,7 @@ const LoginRoute = () => {
|
||||
|
||||
const handlePasskeyLogin = useCallback(
|
||||
async (rawUsername) => {
|
||||
const username = typeof rawUsername === 'string' ? rawUsername.trim() : '';
|
||||
const username = rawUsername?.trim?.() || '';
|
||||
if (!username) {
|
||||
setStatusMessage('Enter your username before using a passkey.', 'error');
|
||||
return;
|
||||
@@ -381,7 +375,7 @@ const LoginRoute = () => {
|
||||
|
||||
const handleSignup = useCallback(
|
||||
async (rawUsername) => {
|
||||
const username = typeof rawUsername === 'string' ? rawUsername.trim() : '';
|
||||
const username = rawUsername?.trim?.() || '';
|
||||
if (!username) {
|
||||
setStatusMessage('Choose a username to create your account.', 'error');
|
||||
return;
|
||||
@@ -459,8 +453,8 @@ const LoginRoute = () => {
|
||||
);
|
||||
|
||||
const redirectTarget = useMemo(() => {
|
||||
const target = location.state?.from;
|
||||
if (typeof target === 'string' && target.startsWith('/')) {
|
||||
const target = String(location.state?.from ?? '');
|
||||
if (target.startsWith('/')) {
|
||||
return target;
|
||||
}
|
||||
return '/documents';
|
||||
|
||||
@@ -12,8 +12,16 @@ import { useSidebarContext } from '../sidebar/SidebarContext';
|
||||
const PanelManagerContext = createContext(null);
|
||||
|
||||
const PANEL_LIMITS = {
|
||||
sidebar: { minRatio: 1 / 6, maxRatio: 1 / 4 },
|
||||
detail: { minRatio: 1 / 4, maxRatio: 3 / 4 },
|
||||
sidebar: {
|
||||
minRatio: 1 / 6,
|
||||
maxRatio: 1 / 4,
|
||||
minPx: 240,
|
||||
},
|
||||
detail: {
|
||||
minRatio: 1 / 4,
|
||||
maxRatio: 3 / 4,
|
||||
minPx: 320,
|
||||
},
|
||||
};
|
||||
|
||||
const STORAGE_KEYS = {
|
||||
@@ -30,8 +38,10 @@ const clampPanelWidth = (panel, value) => {
|
||||
return numeric;
|
||||
}
|
||||
const viewport = window.innerWidth;
|
||||
const minLimit = Math.max(0, Math.round(viewport * limits.minRatio));
|
||||
const rawMax = Math.max(minLimit, Math.round(viewport * limits.maxRatio));
|
||||
const ratioMin = Math.round(viewport * limits.minRatio);
|
||||
const ratioMax = Math.round(viewport * limits.maxRatio);
|
||||
const minLimit = Math.max(0, Math.max(ratioMin, limits.minPx));
|
||||
const rawMax = Math.max(minLimit, ratioMax);
|
||||
const maxAllowed = Math.min(rawMax, viewport - 160);
|
||||
const targetMax = Math.max(minLimit, maxAllowed);
|
||||
return Math.min(Math.max(numeric, minLimit), targetMax);
|
||||
|
||||
@@ -16,10 +16,12 @@ export const resolveApiPath = (path = '') => path;
|
||||
const makeRowKey = (type, id) =>
|
||||
id ? `${type}${ROW_KEY_SEPARATOR}${id}` : `${type}${ROW_KEY_SEPARATOR}`;
|
||||
|
||||
const getRowType = (key) => (typeof key === 'string' ? key.split(ROW_KEY_SEPARATOR, 1)[0] : '');
|
||||
const getRowType = (key) => (
|
||||
typeof key?.split === 'function' ? key.split(ROW_KEY_SEPARATOR, 1)[0] : ''
|
||||
);
|
||||
|
||||
export const getRowId = (key) => {
|
||||
if (typeof key !== 'string') return '';
|
||||
if (typeof key?.indexOf !== 'function' || typeof key?.slice !== 'function') return '';
|
||||
const separatorIndex = key.indexOf(ROW_KEY_SEPARATOR);
|
||||
if (separatorIndex === -1) return key;
|
||||
return key.slice(separatorIndex + 1);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useContext, useEffect, useMemo, useReducer } from 'react';
|
||||
import api from '../lib/api';
|
||||
|
||||
const storage = typeof window !== 'undefined' ? window.sessionStorage : undefined;
|
||||
const storage = window.sessionStorage;
|
||||
|
||||
const STORED_TOKEN = storage?.getItem('papercrate_token') ?? '';
|
||||
let STORED_TENANT = null;
|
||||
|
||||
@@ -11,9 +11,6 @@ const SORT_DIRECTION_STORAGE_KEY = 'papercrate_sort_direction';
|
||||
const INCLUDE_DESCENDANTS_STORAGE_KEY = 'papercrate_include_descendants';
|
||||
|
||||
const readSessionStorage = (key) => {
|
||||
if (typeof window === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return window.sessionStorage.getItem(key);
|
||||
} catch (error) {
|
||||
@@ -23,9 +20,6 @@ const readSessionStorage = (key) => {
|
||||
};
|
||||
|
||||
const writeSessionStorage = (key, value) => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
window.sessionStorage.setItem(key, value);
|
||||
} catch (error) {
|
||||
|
||||
@@ -59,7 +59,7 @@ export const useWorkspaceSelection = ({
|
||||
|
||||
const selectEntry = useCallback(
|
||||
(entry, event) => {
|
||||
const rowKey = typeof entry === 'string' ? entry : entry?.rowKey;
|
||||
const rowKey = entry?.rowKey ?? (typeof entry?.split === 'function' ? entry : null);
|
||||
if (!rowKey) return;
|
||||
handleEntrySelection(rowKey, event);
|
||||
},
|
||||
|
||||
@@ -251,7 +251,7 @@ const DesktopWorkspace = ({
|
||||
|
||||
commitSize();
|
||||
|
||||
if (typeof ResizeObserver === 'undefined') {
|
||||
if (!('ResizeObserver' in window)) {
|
||||
window.addEventListener('resize', commitSize);
|
||||
return () => {
|
||||
window.removeEventListener('resize', commitSize);
|
||||
@@ -292,7 +292,7 @@ const DesktopWorkspace = ({
|
||||
|
||||
const requestCanvasFocus = useCallback(() => {
|
||||
const canvas = containerRef.current;
|
||||
if (!canvas || typeof canvas.focus !== 'function') {
|
||||
if (!canvas?.focus) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -306,20 +306,14 @@ const DesktopWorkspace = ({
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
focusTarget();
|
||||
const raf = window.requestAnimationFrame;
|
||||
if (raf) {
|
||||
raf(() => focusTarget());
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof window.requestAnimationFrame === 'function') {
|
||||
window.requestAnimationFrame(() => {
|
||||
focusTarget();
|
||||
});
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
focusTarget();
|
||||
}, 0);
|
||||
}
|
||||
setTimeout(() => {
|
||||
focusTarget();
|
||||
}, 0);
|
||||
}, []);
|
||||
|
||||
const tagInteractions = useDeskTagInteractions({
|
||||
@@ -756,8 +750,8 @@ const DesktopWorkspaceView = ({
|
||||
return (
|
||||
<>
|
||||
<div className="desk-shell" onPointerDown={(event) => {
|
||||
if (event.target === event.currentTarget && typeof onClearSelection === 'function') {
|
||||
onClearSelection();
|
||||
if (event.target === event.currentTarget) {
|
||||
onClearSelection?.();
|
||||
}
|
||||
focusShell();
|
||||
}}
|
||||
@@ -771,8 +765,8 @@ const DesktopWorkspaceView = ({
|
||||
onDragLeave={handleCanvasDragLeave}
|
||||
onDrop={handleCanvasDrop}
|
||||
onPointerDown={(event) => {
|
||||
if (event.target === event.currentTarget && typeof onClearSelection === 'function') {
|
||||
onClearSelection();
|
||||
if (event.target === event.currentTarget) {
|
||||
onClearSelection?.();
|
||||
}
|
||||
focusShell();
|
||||
}}
|
||||
|
||||
@@ -10,12 +10,13 @@ const openDatabase = () => {
|
||||
}
|
||||
|
||||
currentDbPromise.value = new Promise((resolve, reject) => {
|
||||
if (typeof indexedDB === 'undefined') {
|
||||
const dbApi = window.indexedDB;
|
||||
if (!dbApi) {
|
||||
reject(new Error('IndexedDB not available'));
|
||||
return;
|
||||
}
|
||||
|
||||
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
||||
const request = dbApi.open(DB_NAME, DB_VERSION);
|
||||
|
||||
request.onupgradeneeded = () => {
|
||||
const db = request.result;
|
||||
|
||||
@@ -14,7 +14,7 @@ export const preventAll = (event) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const safeInvoke = (fn, ...args) => (typeof fn === 'function' ? fn(...args) : undefined);
|
||||
export const safeInvoke = (fn, ...args) => fn?.(...args);
|
||||
|
||||
export const getPointerPosition = (event, { fallbackToPage = true } = {}) => {
|
||||
if (!event) {
|
||||
|
||||
@@ -20,8 +20,7 @@ const usePreviewMetadata = (documents, getDocumentAsset, ensureAssetUrl) => {
|
||||
}
|
||||
|
||||
const docId = String(doc.id);
|
||||
const resolveAsset = (type) =>
|
||||
(typeof getDocumentAsset === 'function' ? getDocumentAsset(doc, type) : null);
|
||||
const resolveAsset = (type) => getDocumentAsset?.(doc, type) ?? null;
|
||||
|
||||
let asset = resolveAsset('preview') || resolveAsset('thumbnail');
|
||||
let view = createAssetView(asset);
|
||||
|
||||
@@ -183,9 +183,6 @@ export const useDeskPointer = ({
|
||||
}
|
||||
|
||||
longPressActiveRef.current = true;
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
longPressTimerRef.current = window.setTimeout(() => {
|
||||
if (!longPressActiveRef.current || pointerMovedRef.current) {
|
||||
@@ -229,8 +226,8 @@ export const useDeskPointer = ({
|
||||
pointerMovedRef.current = false;
|
||||
resetLongPressState();
|
||||
|
||||
const pointerButton = typeof event.button === 'number' ? event.button : 0;
|
||||
const pointerType = typeof event.pointerType === 'string' ? event.pointerType : '';
|
||||
const pointerButton = Number.isFinite(event?.button) ? event.button : 0;
|
||||
const pointerType = String(event?.pointerType ?? '');
|
||||
const metaKey = (event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey;
|
||||
const modifierActive = Boolean(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
|
||||
|
||||
@@ -322,12 +319,10 @@ export const useDeskPointer = ({
|
||||
&& !pointerState.longPressTriggered
|
||||
&& pointerState.docId === doc.id
|
||||
) {
|
||||
const expectedButton = typeof pointerState.pointerButton === 'number'
|
||||
const expectedButton = Number.isFinite(pointerState?.pointerButton)
|
||||
? pointerState.pointerButton
|
||||
: 0;
|
||||
const releasedButton = typeof event.button === 'number'
|
||||
? event.button
|
||||
: expectedButton;
|
||||
const releasedButton = Number.isFinite(event?.button) ? event.button : expectedButton;
|
||||
const isPrimaryRelease = expectedButton === 0 && releasedButton === 0;
|
||||
const stillSelected = Array.isArray(selectedDocumentIds)
|
||||
&& selectedDocumentIds.includes(doc.id);
|
||||
@@ -401,11 +396,7 @@ export const useDeskPointer = ({
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
typeof openOverlayForDoc === 'function'
|
||||
&& Array.isArray(selectedDocumentIds)
|
||||
&& selectedDocumentIds.length > 0
|
||||
) {
|
||||
if (openOverlayForDoc && Array.isArray(selectedDocumentIds) && selectedDocumentIds.length > 0) {
|
||||
event.preventDefault();
|
||||
const targetId = selectedDocumentIds[selectedDocumentIds.length - 1];
|
||||
if (targetId) {
|
||||
@@ -427,9 +418,7 @@ export const useDeskPointer = ({
|
||||
handleShellKeyDown,
|
||||
focusShell: () => {
|
||||
const shell = containerRef.current;
|
||||
if (shell && typeof shell.focus === 'function') {
|
||||
shell.focus({ preventScroll: true });
|
||||
}
|
||||
shell?.focus?.({ preventScroll: true });
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -51,9 +51,6 @@ export const useDeskTagInteractions = ({
|
||||
const removalCursorActiveRef = useRef(false);
|
||||
|
||||
const updateRemovalCursor = useCallback((active) => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
if (removalCursorActiveRef.current === active) {
|
||||
return;
|
||||
}
|
||||
@@ -100,8 +97,9 @@ export const useDeskTagInteractions = ({
|
||||
}
|
||||
};
|
||||
const scheduleShowNode = () => {
|
||||
if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') {
|
||||
window.requestAnimationFrame(showNode);
|
||||
const raf = window.requestAnimationFrame;
|
||||
if (raf) {
|
||||
raf(showNode);
|
||||
} else {
|
||||
setTimeout(showNode, 0);
|
||||
}
|
||||
|
||||
@@ -9,11 +9,15 @@ const DRAG_HYSTERESIS_SQUARED = DRAG_HYSTERESIS_PX * DRAG_HYSTERESIS_PX;
|
||||
const EDGE_COLLISION_THRESHOLD = 0.5;
|
||||
|
||||
const getEventTargetElement = (event) => {
|
||||
if (typeof Element === 'undefined' || !event) {
|
||||
if (!event) {
|
||||
return null;
|
||||
}
|
||||
const ElementCtor = window.Element;
|
||||
if (!ElementCtor) {
|
||||
return null;
|
||||
}
|
||||
const candidate = event.target || (event.nativeEvent ? event.nativeEvent.target : null);
|
||||
return candidate instanceof Element ? candidate : null;
|
||||
return candidate instanceof ElementCtor ? candidate : null;
|
||||
};
|
||||
|
||||
const useDocumentDrag = (options = {}) => {
|
||||
@@ -63,9 +67,7 @@ const useDocumentDrag = (options = {}) => {
|
||||
openOverlayForDoc(data.docId, data.originInfo);
|
||||
return;
|
||||
}
|
||||
if (typeof onInspectDocument === 'function') {
|
||||
onInspectDocument(data.docId, event);
|
||||
}
|
||||
onInspectDocument?.(data.docId, event);
|
||||
},
|
||||
});
|
||||
const dragStateRef = useRef(null);
|
||||
@@ -83,7 +85,7 @@ const useDocumentDrag = (options = {}) => {
|
||||
|
||||
const clearDragTransforms = useCallback(() => {
|
||||
const map = dragTransformsRef?.current;
|
||||
if (!map || typeof map.clear !== 'function') {
|
||||
if (!map?.clear) {
|
||||
return;
|
||||
}
|
||||
map.clear();
|
||||
@@ -118,7 +120,7 @@ const useDocumentDrag = (options = {}) => {
|
||||
const state = dragStateRef.current;
|
||||
if (state && state.pointerId === pointerId) {
|
||||
const capturedTarget = state.capturedTarget;
|
||||
if (capturedTarget && typeof capturedTarget.releasePointerCapture === 'function') {
|
||||
if (capturedTarget?.releasePointerCapture) {
|
||||
try {
|
||||
capturedTarget.releasePointerCapture(pointerId);
|
||||
} catch (error) {
|
||||
@@ -141,7 +143,7 @@ const useDocumentDrag = (options = {}) => {
|
||||
const handlePointerDown = useCallback(
|
||||
(event, docIdInput, options = {}) => {
|
||||
const targetElement = getEventTargetElement(event);
|
||||
if (targetElement && typeof targetElement.closest === 'function' && targetElement.closest('[data-desk-tag-chip="true"]')) {
|
||||
if (targetElement?.closest && targetElement.closest('[data-desk-tag-chip="true"]')) {
|
||||
return;
|
||||
}
|
||||
preventAll(event);
|
||||
@@ -167,9 +169,8 @@ const useDocumentDrag = (options = {}) => {
|
||||
: null;
|
||||
const stackSelectionAppliedInitial = Boolean(options?.stackSelectionApplied);
|
||||
const wasSelectedAtPointerDown = Boolean(options?.wasSelected);
|
||||
const pointerModifierActive = typeof options?.modifierActive === 'boolean'
|
||||
? options.modifierActive
|
||||
: Boolean(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
|
||||
const pointerModifierActive =
|
||||
options?.modifierActive ?? Boolean(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
|
||||
const stackReplace = Boolean(options?.stackReplace);
|
||||
|
||||
let selectionIds = Array.isArray(selectedDocumentIds)
|
||||
@@ -227,8 +228,8 @@ const useDocumentDrag = (options = {}) => {
|
||||
const entry = layoutRef.current.get(docKey) || null;
|
||||
const defaultCenterX = canvasPadding + docWidth / 2;
|
||||
const defaultCenterY = canvasPadding + docHeight / 2;
|
||||
const centerX = typeof entry?.centerX === 'number' ? entry.centerX : defaultCenterX;
|
||||
const centerY = typeof entry?.centerY === 'number' ? entry.centerY : defaultCenterY;
|
||||
const centerX = Number.isFinite(entry?.centerX) ? entry.centerX : defaultCenterX;
|
||||
const centerY = Number.isFinite(entry?.centerY) ? entry.centerY : defaultCenterY;
|
||||
|
||||
const modifierPressed = pointerModifierActive;
|
||||
if (!modifierPressed) {
|
||||
@@ -255,7 +256,7 @@ const useDocumentDrag = (options = {}) => {
|
||||
}
|
||||
|
||||
const capturedTarget = event.currentTarget instanceof HTMLElement ? event.currentTarget : null;
|
||||
if (capturedTarget && typeof capturedTarget.setPointerCapture === 'function') {
|
||||
if (capturedTarget?.setPointerCapture) {
|
||||
try {
|
||||
capturedTarget.setPointerCapture(event.pointerId);
|
||||
} catch (error) {
|
||||
@@ -286,9 +287,9 @@ const useDocumentDrag = (options = {}) => {
|
||||
const itemHeight = itemSize.height || docHeight;
|
||||
const itemEntry = layoutRef.current.get(id) || null;
|
||||
const itemCenterX =
|
||||
typeof itemEntry?.centerX === 'number' ? itemEntry.centerX : canvasPadding + itemWidth / 2;
|
||||
Number.isFinite(itemEntry?.centerX) ? itemEntry.centerX : canvasPadding + itemWidth / 2;
|
||||
const itemCenterY =
|
||||
typeof itemEntry?.centerY === 'number' ? itemEntry.centerY : canvasPadding + itemHeight / 2;
|
||||
Number.isFinite(itemEntry?.centerY) ? itemEntry.centerY : canvasPadding + itemHeight / 2;
|
||||
const baseOffsetX = itemCenterX - centerX;
|
||||
const baseOffsetY = itemCenterY - centerY;
|
||||
const initialRotation = itemEntry?.rotation ?? 0;
|
||||
@@ -310,9 +311,9 @@ const useDocumentDrag = (options = {}) => {
|
||||
});
|
||||
|
||||
const eventTimestamp =
|
||||
typeof event.timeStamp === 'number' && Number.isFinite(event.timeStamp)
|
||||
(Number.isFinite(event?.timeStamp))
|
||||
? event.timeStamp
|
||||
: typeof performance !== 'undefined' && typeof performance.now === 'function'
|
||||
: performance?.now
|
||||
? performance.now()
|
||||
: Date.now();
|
||||
|
||||
@@ -540,9 +541,9 @@ const useDocumentDrag = (options = {}) => {
|
||||
state.lastClientX = event.clientX;
|
||||
state.lastClientY = event.clientY;
|
||||
state.lastTimestamp =
|
||||
typeof event.timeStamp === 'number' && Number.isFinite(event.timeStamp)
|
||||
(Number.isFinite(event?.timeStamp))
|
||||
? event.timeStamp
|
||||
: typeof performance !== 'undefined' && typeof performance.now === 'function'
|
||||
: performance?.now
|
||||
? performance.now()
|
||||
: Date.now();
|
||||
|
||||
@@ -663,9 +664,9 @@ const useDocumentDrag = (options = {}) => {
|
||||
Math.abs(pointerLocalX) <= halfWidth && Math.abs(pointerLocalY) <= halfHeight;
|
||||
|
||||
const currentTimestamp =
|
||||
typeof event.timeStamp === 'number' && Number.isFinite(event.timeStamp)
|
||||
(Number.isFinite(event?.timeStamp))
|
||||
? event.timeStamp
|
||||
: typeof performance !== 'undefined' && typeof performance.now === 'function'
|
||||
: performance?.now
|
||||
? performance.now()
|
||||
: Date.now();
|
||||
const previousTimestamp = state.lastTimestamp ?? currentTimestamp;
|
||||
|
||||
@@ -688,25 +688,19 @@ export class WorkspaceEngine {
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
if (typeof window === 'undefined') {
|
||||
this.inertiaAnimations.delete(key);
|
||||
return;
|
||||
}
|
||||
const existing = this.inertiaAnimations.get(key);
|
||||
if (existing && typeof window.cancelAnimationFrame === 'function') {
|
||||
if (existing?.frameId != null) {
|
||||
window.cancelAnimationFrame(existing.frameId);
|
||||
}
|
||||
this.inertiaAnimations.delete(key);
|
||||
}
|
||||
|
||||
disposeInertiaAnimations() {
|
||||
if (typeof window !== 'undefined' && typeof window.cancelAnimationFrame === 'function') {
|
||||
this.inertiaAnimations.forEach((animation) => {
|
||||
if (animation?.frameId != null) {
|
||||
window.cancelAnimationFrame(animation.frameId);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.inertiaAnimations.forEach((animation) => {
|
||||
if (animation?.frameId != null) {
|
||||
window.cancelAnimationFrame(animation.frameId);
|
||||
}
|
||||
});
|
||||
this.inertiaAnimations.clear();
|
||||
}
|
||||
|
||||
@@ -768,7 +762,8 @@ export class WorkspaceEngine {
|
||||
}
|
||||
|
||||
startInertiaAnimation(docId, baseState) {
|
||||
if (typeof window === 'undefined' || typeof window.requestAnimationFrame !== 'function') {
|
||||
const raf = window.requestAnimationFrame;
|
||||
if (!raf) {
|
||||
return;
|
||||
}
|
||||
const key = docId != null ? String(docId) : null;
|
||||
@@ -778,10 +773,7 @@ export class WorkspaceEngine {
|
||||
|
||||
this.cancelInertiaAnimation(key);
|
||||
|
||||
const now =
|
||||
typeof performance !== 'undefined' && typeof performance.now === 'function'
|
||||
? performance.now()
|
||||
: Date.now();
|
||||
const now = performance?.now ? performance.now() : Date.now();
|
||||
|
||||
const simulationState = {
|
||||
...baseState,
|
||||
@@ -807,10 +799,10 @@ export class WorkspaceEngine {
|
||||
this.persistLayoutSnapshot();
|
||||
return;
|
||||
}
|
||||
simulationState.frameId = window.requestAnimationFrame(step);
|
||||
simulationState.frameId = raf(step);
|
||||
};
|
||||
|
||||
simulationState.frameId = window.requestAnimationFrame(step);
|
||||
simulationState.frameId = raf(step);
|
||||
this.inertiaAnimations.set(key, simulationState);
|
||||
}
|
||||
|
||||
@@ -885,14 +877,10 @@ export class WorkspaceEngine {
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined' && typeof window.setTimeout === 'function') {
|
||||
this.persistDebounceId = window.setTimeout(() => {
|
||||
this.persistDebounceId = null;
|
||||
void persistTask();
|
||||
}, 100);
|
||||
} else {
|
||||
await persistTask();
|
||||
}
|
||||
this.persistDebounceId = window.setTimeout(() => {
|
||||
this.persistDebounceId = null;
|
||||
void persistTask();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
ensureLayoutForItems() {
|
||||
@@ -1223,8 +1211,9 @@ export const useWorkspaceSnapshot = (engine, useSyncExternalStoreHook) => {
|
||||
};
|
||||
|
||||
/* istanbul ignore next */
|
||||
if (typeof module !== 'undefined' && module && module.exports) {
|
||||
module.exports = {
|
||||
const commonJsModule = globalThis?.module;
|
||||
if (commonJsModule?.exports) {
|
||||
commonJsModule.exports = {
|
||||
WorkspaceEngine,
|
||||
DESK_CANVAS_PADDING,
|
||||
DESK_ROTATION_RANGE,
|
||||
|
||||
@@ -5,19 +5,12 @@ import { clamp } from '../utils/math';
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
const ensureDocumentRoot = () => {
|
||||
if (typeof document === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
return document.body;
|
||||
};
|
||||
|
||||
const PreviewZoomOverlay = ({
|
||||
open = false,
|
||||
display = null,
|
||||
onClose = noop,
|
||||
}) => {
|
||||
const portalTarget = ensureDocumentRoot();
|
||||
const portalTarget = document.body;
|
||||
const [isNativeScale, setIsNativeScale] = useState(false);
|
||||
const [naturalSize, setNaturalSize] = useState({ width: null, height: null });
|
||||
const [renderBackdrop, setRenderBackdrop] = useState(false);
|
||||
@@ -125,21 +118,13 @@ const PreviewZoomOverlay = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
if (previouslyFocusedRef.current && typeof previouslyFocusedRef.current.focus === 'function') {
|
||||
previouslyFocusedRef.current.focus();
|
||||
}
|
||||
previouslyFocusedRef.current?.focus?.();
|
||||
previouslyFocusedRef.current = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
const active = document.activeElement;
|
||||
if (active && typeof active.focus === 'function') {
|
||||
previouslyFocusedRef.current = active;
|
||||
} else {
|
||||
previouslyFocusedRef.current = null;
|
||||
}
|
||||
}
|
||||
const active = document.activeElement;
|
||||
previouslyFocusedRef.current = active?.focus ? active : null;
|
||||
}, [open]);
|
||||
|
||||
const activeDisplay = open && display?.url ? display : displaySnapshot;
|
||||
@@ -163,10 +148,7 @@ const PreviewZoomOverlay = ({
|
||||
}
|
||||
|
||||
const frame = requestAnimationFrame(() => {
|
||||
const scrollEl = scrollRef.current;
|
||||
if (scrollEl && typeof scrollEl.focus === 'function') {
|
||||
scrollEl.focus({ preventScroll: true });
|
||||
}
|
||||
scrollRef.current?.focus?.({ preventScroll: true });
|
||||
});
|
||||
|
||||
return () => cancelAnimationFrame(frame);
|
||||
|
||||
@@ -18,7 +18,7 @@ export const sortCorrespondents = (entries = []) =>
|
||||
export const buildCorrespondentOptions = (entries = []) => {
|
||||
const seen = new Set();
|
||||
return entries.reduce((options, entry) => {
|
||||
const name = typeof entry?.name === 'string' ? entry.name.trim() : '';
|
||||
const name = entry?.name?.trim?.() || '';
|
||||
if (!name) {
|
||||
return options;
|
||||
}
|
||||
@@ -38,20 +38,14 @@ const normalizeQuickAddOption = (option) => {
|
||||
if (option == null) {
|
||||
return null;
|
||||
}
|
||||
if (typeof option === 'string') {
|
||||
const label = option.trim();
|
||||
return label ? { id: label, label, original: option } : null;
|
||||
}
|
||||
const label = typeof option.label === 'string'
|
||||
? option.label.trim()
|
||||
: typeof option.name === 'string'
|
||||
? option.name.trim()
|
||||
: '';
|
||||
const isObject = typeof option === 'object';
|
||||
const labelSource = isObject ? option.label ?? option.name ?? '' : option;
|
||||
const label = labelSource?.trim?.() || '';
|
||||
if (!label) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
id: option.id ?? label,
|
||||
id: isObject && option.id ? option.id : label,
|
||||
label,
|
||||
original: option,
|
||||
};
|
||||
@@ -75,9 +69,10 @@ export const TagSection = ({
|
||||
const handleSelect = useCallback(
|
||||
(option) => {
|
||||
if (!onAdd) return;
|
||||
const label =
|
||||
(option && typeof option === 'object' && option.label) ||
|
||||
(typeof option === 'string' ? option : '');
|
||||
const labelSource = option && typeof option === 'object'
|
||||
? option.label ?? option.name ?? ''
|
||||
: option;
|
||||
const label = labelSource?.trim?.() || '';
|
||||
if (!label) {
|
||||
return;
|
||||
}
|
||||
@@ -117,7 +112,7 @@ export const TagSection = ({
|
||||
});
|
||||
|
||||
tags.forEach((tag) => {
|
||||
const label = typeof tag?.label === 'string' ? tag.label.trim() : '';
|
||||
const label = tag?.label?.trim?.() || '';
|
||||
if (!label) {
|
||||
return;
|
||||
}
|
||||
@@ -244,7 +239,7 @@ export const CorrespondentSection = ({
|
||||
});
|
||||
|
||||
entries.forEach((entry) => {
|
||||
const label = typeof entry?.name === 'string' ? entry.name.trim() : '';
|
||||
const label = entry?.name?.trim?.() || '';
|
||||
if (!label) {
|
||||
return;
|
||||
}
|
||||
@@ -274,9 +269,10 @@ export const CorrespondentSection = ({
|
||||
}
|
||||
const source = item.payload ?? item;
|
||||
const resolvedName =
|
||||
(source && typeof source.name === 'string' && source.name.trim())
|
||||
|| (typeof source === 'string' ? source.trim() : '')
|
||||
|| (source && typeof source.label === 'string' ? source.label.trim() : '');
|
||||
source?.name?.trim?.()
|
||||
|| source?.label?.trim?.()
|
||||
|| source?.trim?.()
|
||||
|| '';
|
||||
if (!resolvedName) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ const useLazyVisibility = (rootRef, resetKey) => {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof window === 'undefined' || typeof IntersectionObserver === 'undefined') {
|
||||
if (!('IntersectionObserver' in window)) {
|
||||
setIsVisible(true);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -10,15 +10,24 @@ const STATE_ORDER = {
|
||||
|
||||
const normalizeItems = (items) =>
|
||||
(Array.isArray(items) ? items : [])
|
||||
.filter((item) => item && typeof item.label === 'string' && item.label.trim().length > 0)
|
||||
.map((item) => ({
|
||||
id: item.id ?? item.label,
|
||||
label: item.label.trim(),
|
||||
state: item.state === 'all' ? 'all' : item.state === 'partial' ? 'partial' : 'none',
|
||||
count: typeof item.count === 'number' ? item.count : null,
|
||||
total: typeof item.total === 'number' ? item.total : null,
|
||||
payload: item.payload ?? item,
|
||||
}));
|
||||
.map((item) => {
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
const trimmedLabel = item.label?.trim?.() || '';
|
||||
if (!trimmedLabel) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
id: item.id ?? trimmedLabel,
|
||||
label: trimmedLabel,
|
||||
state: item.state === 'all' ? 'all' : item.state === 'partial' ? 'partial' : 'none',
|
||||
count: typeof item.count === 'number' ? item.count : null,
|
||||
total: typeof item.total === 'number' ? item.total : null,
|
||||
payload: item.payload ?? item,
|
||||
};
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
const SelectionAssignmentMenu = ({
|
||||
label,
|
||||
|
||||
@@ -34,9 +34,8 @@ const buildFolderTreeOptions = (tree) => {
|
||||
if (!node || !node.id) {
|
||||
return;
|
||||
}
|
||||
const name = typeof node.name === 'string' && node.name.trim().length
|
||||
? node.name.trim()
|
||||
: 'Folder';
|
||||
const trimmedName = node?.name?.trim?.();
|
||||
const name = trimmedName?.length ? trimmedName : 'Folder';
|
||||
const nextSegments = parentSegments.concat([name]);
|
||||
const label = nextSegments.join('/');
|
||||
entries.push({ id: node.id, label });
|
||||
|
||||
@@ -8,11 +8,7 @@ export const resolveCorrespondents = (doc) => {
|
||||
|
||||
doc.correspondents.forEach((entry = {}, index) => {
|
||||
const { id, name } = entry;
|
||||
if (typeof name !== 'string') {
|
||||
return;
|
||||
}
|
||||
|
||||
const trimmedName = name.trim();
|
||||
const trimmedName = name?.trim?.();
|
||||
if (!trimmedName) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ const useBulkDocumentActions = ({
|
||||
}) => {
|
||||
const handleBulkCorrespondentAdd = useCallback(
|
||||
async ({ name, input, documentIds }) => {
|
||||
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||
const trimmed = name?.trim?.() || '';
|
||||
if (!trimmed) {
|
||||
setStatusMessage('Correspondent name is required.', 'error');
|
||||
return;
|
||||
|
||||
@@ -10,7 +10,7 @@ export const isPrimaryPointerEvent = (event) => {
|
||||
if (typeof event.button === 'number' && event.button !== 0) {
|
||||
return false;
|
||||
}
|
||||
const type = typeof event.type === 'string' ? event.type.toLowerCase() : '';
|
||||
const type = event?.type?.toLowerCase?.() ?? '';
|
||||
return type === 'click' || type === 'pointerdown' || type === 'pointerup';
|
||||
};
|
||||
|
||||
|
||||
@@ -6,15 +6,14 @@ const focusInput = (node) => {
|
||||
}
|
||||
const applyFocus = () => {
|
||||
node.focus();
|
||||
if (typeof node.select === 'function') {
|
||||
node.select();
|
||||
}
|
||||
node.select?.();
|
||||
};
|
||||
if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') {
|
||||
window.requestAnimationFrame(applyFocus);
|
||||
} else {
|
||||
applyFocus();
|
||||
const raf = window.requestAnimationFrame;
|
||||
if (raf) {
|
||||
raf(applyFocus);
|
||||
return;
|
||||
}
|
||||
applyFocus();
|
||||
};
|
||||
|
||||
const identity = (value) => value;
|
||||
|
||||
@@ -68,7 +68,7 @@ const useAuthManager = ({
|
||||
}
|
||||
|
||||
const status = response.status;
|
||||
const url = typeof config.url === 'string' ? config.url : '';
|
||||
const url = String(config?.url ?? '');
|
||||
const isAuthRoute = url.includes('/auth/login') || url.includes('/auth/refresh');
|
||||
|
||||
if (status === 401 && !config._retry && !isAuthRoute) {
|
||||
|
||||
@@ -32,7 +32,7 @@ const useCorrespondents = ({
|
||||
}
|
||||
|
||||
const payload = {};
|
||||
if (typeof changes.name === 'string') {
|
||||
if (typeof changes?.name?.trim === 'function') {
|
||||
const trimmed = changes.name.trim();
|
||||
if (!trimmed) {
|
||||
throw new Error('Correspondent name cannot be empty.');
|
||||
@@ -60,7 +60,7 @@ const useCorrespondents = ({
|
||||
|
||||
const handleCorrespondentCreate = useCallback(
|
||||
async ({ name }) => {
|
||||
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||
const trimmed = name?.trim?.() || '';
|
||||
if (!trimmed) {
|
||||
throw new Error('Correspondent name is required.');
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ const useDocumentCorrespondentActions = ({
|
||||
if (!document?.id) {
|
||||
throw new Error('Missing document for correspondent assignment.');
|
||||
}
|
||||
const trimmed = typeof name === 'string' ? name.trim() : '';
|
||||
const trimmed = name?.trim?.() || '';
|
||||
if (!trimmed) {
|
||||
setStatusMessage('Correspondent name is required.', 'error');
|
||||
return;
|
||||
|
||||
@@ -29,10 +29,6 @@ const useDocumentDragHandlers = ({
|
||||
({ documents = [], folders = [] } = {}) => {
|
||||
destroyDragPreview();
|
||||
|
||||
if (typeof document === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const docEntries = (documents || []).filter(Boolean);
|
||||
const folderEntries = (folders || []).filter(Boolean);
|
||||
const totalCount = docEntries.length + folderEntries.length;
|
||||
@@ -108,7 +104,7 @@ const useDocumentDragHandlers = ({
|
||||
}
|
||||
} else {
|
||||
const payload = item.payload;
|
||||
const folderId = typeof payload === 'string' ? payload : payload?.id;
|
||||
const folderId = payload?.id ?? (typeof payload?.trim === 'function' ? payload : null);
|
||||
const rowEl = folderId
|
||||
? document.getElementById(`folder-row-${folderId}`)
|
||||
|| document.getElementById(`folder-card-${folderId}`)
|
||||
@@ -160,7 +156,7 @@ const useDocumentDragHandlers = ({
|
||||
|
||||
const handleDocumentDragStart = useCallback(
|
||||
(event, documentOrId) => {
|
||||
const documentId = typeof documentOrId === 'string' ? documentOrId : documentOrId?.id;
|
||||
const documentId = documentOrId?.id ?? (typeof documentOrId?.trim === 'function' ? documentOrId : null);
|
||||
if (!documentId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ const useDocumentMutations = ({
|
||||
|
||||
const handleDocumentTitleUpdate = useCallback(
|
||||
async (documentId, nextTitle) => {
|
||||
const trimmed = typeof nextTitle === 'string' ? nextTitle.trim() : '';
|
||||
const trimmed = nextTitle?.trim?.() || '';
|
||||
if (!trimmed) {
|
||||
setStatusMessage('Document title cannot be empty.', 'error');
|
||||
return false;
|
||||
@@ -418,7 +418,7 @@ const useDocumentMutations = ({
|
||||
const resolveTagForCache = () => {
|
||||
const lookupTag = tagLookupById.get(tagId);
|
||||
const source = lookupTag ?? tagData;
|
||||
if (!source || source.id == null || typeof source.label !== 'string') {
|
||||
if (!source || source.id == null || typeof source.label?.trim !== 'function') {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -98,7 +98,7 @@ const useDocumentTagging = ({
|
||||
|
||||
const handleBulkTagAddFromDetail = useCallback(
|
||||
async ({ label, input, documentIds }) => {
|
||||
const trimmed = typeof label === 'string' ? label.trim() : '';
|
||||
const trimmed = label?.trim?.() || '';
|
||||
if (!trimmed) {
|
||||
setStatusMessage('Enter a tag label.', 'error');
|
||||
return;
|
||||
@@ -131,7 +131,7 @@ const useDocumentTagging = ({
|
||||
|
||||
const handleBulkTagRemoveFromDetail = useCallback(
|
||||
async ({ label, input, documentIds }) => {
|
||||
const trimmed = typeof label === 'string' ? label.trim() : '';
|
||||
const trimmed = label?.trim?.() || '';
|
||||
if (!trimmed) {
|
||||
setStatusMessage('Enter a tag label to remove.', 'error');
|
||||
return;
|
||||
@@ -201,4 +201,3 @@ const useDocumentTagging = ({
|
||||
};
|
||||
|
||||
export default useDocumentTagging;
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ const mapFilesToEntries = (filesInput) => {
|
||||
return files
|
||||
.filter(Boolean)
|
||||
.map((file) => {
|
||||
const relativePath =
|
||||
typeof file.webkitRelativePath === 'string' ? file.webkitRelativePath : '';
|
||||
const relativePath = file?.webkitRelativePath ?? '';
|
||||
const segments = relativePath
|
||||
? relativePath
|
||||
.split('/')
|
||||
@@ -213,10 +212,7 @@ const useDocumentUploads = ({
|
||||
|
||||
const fileFromItem = typeof item.getAsFile === 'function' ? item.getAsFile() : null;
|
||||
if (fileFromItem) {
|
||||
const relativePath =
|
||||
typeof fileFromItem.webkitRelativePath === 'string'
|
||||
? fileFromItem.webkitRelativePath
|
||||
: '';
|
||||
const relativePath = fileFromItem?.webkitRelativePath ?? '';
|
||||
const segments = relativePath
|
||||
? relativePath
|
||||
.split('/')
|
||||
@@ -246,8 +242,7 @@ const useDocumentUploads = ({
|
||||
|
||||
Array.from(dataTransfer.files || []).forEach((file) => {
|
||||
if (!file) return;
|
||||
const relativePath =
|
||||
typeof file.webkitRelativePath === 'string' ? file.webkitRelativePath : '';
|
||||
const relativePath = file?.webkitRelativePath ?? '';
|
||||
const segments = relativePath
|
||||
? relativePath
|
||||
.split('/')
|
||||
|
||||
@@ -135,9 +135,6 @@ const useDocumentsWorkspace = ({
|
||||
const tenantIdRef = useRef(currentTenantId);
|
||||
const detailPanelControlRef = useRef({ open: () => {}, close: () => {} });
|
||||
const setTagRemovalCursor = useCallback((active) => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
if (tagRemovalCursorActiveRef.current === active) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ const useFolderTreeActions = ({
|
||||
setStatusMessage('Log in to rename folders.', 'error');
|
||||
return false;
|
||||
}
|
||||
const trimmed = typeof nextName === 'string' ? nextName.trim() : '';
|
||||
const trimmed = nextName?.trim?.() || '';
|
||||
if (!trimmed) {
|
||||
setStatusMessage('Folder name cannot be empty.', 'error');
|
||||
return false;
|
||||
|
||||
@@ -34,7 +34,7 @@ const useTags = ({
|
||||
}
|
||||
|
||||
const payload = {};
|
||||
if (typeof changes.label === 'string') {
|
||||
if (typeof changes?.label?.trim === 'function') {
|
||||
payload.label = changes.label;
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(changes, 'color')) {
|
||||
|
||||
@@ -4,7 +4,7 @@ const noop = () => {};
|
||||
|
||||
const normalizeMessage = (error) => {
|
||||
if (!error) return 'Something went wrong.';
|
||||
if (typeof error === 'string') {
|
||||
if (typeof error?.trim === 'function') {
|
||||
return error;
|
||||
}
|
||||
const { response, message } = error;
|
||||
|
||||
@@ -4,10 +4,6 @@ export const DOCUMENT_VIEWER_PORTRAIT_HEIGHT_RATIO = 0.4;
|
||||
const PORTRAIT_RATIO_STYLE_ID = 'document-viewer-portrait-ratio-style';
|
||||
|
||||
const ensurePortraitRatioStyle = () => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const cssValue = String(DOCUMENT_VIEWER_PORTRAIT_HEIGHT_RATIO);
|
||||
const cssText = `:root { --document-viewer-portrait-height-ratio: ${cssValue}; }`;
|
||||
|
||||
@@ -23,12 +19,7 @@ const ensurePortraitRatioStyle = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const computeStackedLayoutBreakpoint = () => {
|
||||
if (typeof window === 'undefined') {
|
||||
return 900;
|
||||
}
|
||||
return window.innerWidth / 2;
|
||||
};
|
||||
const computeStackedLayoutBreakpoint = () => window.innerWidth / 2;
|
||||
|
||||
export const useViewerLayoutMode = (ref, dependency) => {
|
||||
const [isStacked, setIsStacked] = useState(false);
|
||||
@@ -61,7 +52,7 @@ export const useViewerLayoutMode = (ref, dependency) => {
|
||||
|
||||
measure();
|
||||
|
||||
if (typeof ResizeObserver === 'undefined') {
|
||||
if (!('ResizeObserver' in window)) {
|
||||
window.addEventListener('resize', measure);
|
||||
return () => {
|
||||
if (frame) {
|
||||
|
||||
@@ -39,8 +39,7 @@ const ApiTokensSection = ({
|
||||
const [newTokenExpires, setNewTokenExpires] = useState('');
|
||||
const [newTokenCapabilitySetId, setNewTokenCapabilitySetId] = useState('');
|
||||
const [formError, setFormError] = useState(null);
|
||||
const supportsClipboardWrite = typeof navigator !== 'undefined'
|
||||
&& Boolean(navigator?.clipboard?.writeText);
|
||||
const supportsClipboardWrite = Boolean(navigator?.clipboard?.writeText);
|
||||
const [canCopyToken, setCanCopyToken] = useState(supportsClipboardWrite);
|
||||
const [copyFeedback, setCopyFeedback] = useState(null);
|
||||
|
||||
@@ -61,7 +60,7 @@ const ApiTokensSection = ({
|
||||
const capabilitySelectionOptions = useMemo(() => (
|
||||
Array.isArray(capabilities)
|
||||
? capabilities.map((capability) => {
|
||||
if (typeof capability !== 'string') {
|
||||
if (typeof capability?.split !== 'function') {
|
||||
return { value: capability, label: String(capability) };
|
||||
}
|
||||
const [namespace, action] = capability.split(':');
|
||||
@@ -147,9 +146,7 @@ const ApiTokensSection = ({
|
||||
|
||||
useEffect(() => {
|
||||
setCopyFeedback(null);
|
||||
if (typeof navigator !== 'undefined') {
|
||||
setCanCopyToken(Boolean(navigator?.clipboard?.writeText));
|
||||
}
|
||||
setCanCopyToken(Boolean(navigator?.clipboard?.writeText));
|
||||
}, [createdToken]);
|
||||
|
||||
const handleNewCapabilitySetChange = useCallback((event) => {
|
||||
|
||||
@@ -37,7 +37,7 @@ const CapabilitySetsSection = ({
|
||||
const capabilitySelectionOptions = useMemo(() => (
|
||||
Array.isArray(capabilities)
|
||||
? capabilities.map((capability) => {
|
||||
if (typeof capability !== 'string') {
|
||||
if (typeof capability?.split !== 'function') {
|
||||
return { value: capability, label: String(capability) };
|
||||
}
|
||||
const [namespace, action] = capability.split(':');
|
||||
|
||||
@@ -377,7 +377,7 @@ const Sidebar = ({
|
||||
}, [cycleThemeMode]);
|
||||
|
||||
const themeMenuSection =
|
||||
typeof neutralHue === 'number' || typeof neutralHue === 'string'
|
||||
neutralHue != null
|
||||
? (
|
||||
<div className="menu__section">
|
||||
<div className="menu__heading menu__heading--with-actions">
|
||||
@@ -604,9 +604,7 @@ const Sidebar = ({
|
||||
size={16}
|
||||
/>
|
||||
</button>
|
||||
{tenantMenuOpen
|
||||
&& tenantMenuStyle
|
||||
&& typeof document !== 'undefined'
|
||||
{tenantMenuOpen && tenantMenuStyle
|
||||
? createPortal(
|
||||
<div
|
||||
className={menuClassName}
|
||||
|
||||
@@ -26,21 +26,6 @@ const loadInitialThemeSettings = () => {
|
||||
mode: DEFAULT_THEME_MODE,
|
||||
};
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
if (typeof document !== 'undefined') {
|
||||
const root = document.documentElement;
|
||||
const current = root.style.getPropertyValue('--neutral-hue');
|
||||
const parsed = Number.parseInt(current, 10);
|
||||
return {
|
||||
neutralHue: Number.isNaN(parsed) ? defaults.neutralHue : parsed,
|
||||
neutralChroma: defaults.neutralChroma,
|
||||
neutralContrast: defaults.neutralContrast,
|
||||
mode: defaults.mode,
|
||||
};
|
||||
}
|
||||
return defaults;
|
||||
}
|
||||
|
||||
const root = document.documentElement;
|
||||
const readNumberVar = (name, fallback) => {
|
||||
const inlineValue = root.style.getPropertyValue(name);
|
||||
@@ -48,12 +33,10 @@ const loadInitialThemeSettings = () => {
|
||||
if (!Number.isNaN(inlineParsed)) {
|
||||
return inlineParsed;
|
||||
}
|
||||
if (typeof window !== 'undefined' && window.getComputedStyle) {
|
||||
const computedValue = window.getComputedStyle(root).getPropertyValue(name);
|
||||
const computedParsed = Number.parseFloat(computedValue);
|
||||
if (!Number.isNaN(computedParsed)) {
|
||||
return computedParsed;
|
||||
}
|
||||
const computedValue = window.getComputedStyle(root).getPropertyValue(name);
|
||||
const computedParsed = Number.parseFloat(computedValue);
|
||||
if (!Number.isNaN(computedParsed)) {
|
||||
return computedParsed;
|
||||
}
|
||||
return fallback;
|
||||
};
|
||||
@@ -120,9 +103,6 @@ const loadInitialThemeSettings = () => {
|
||||
};
|
||||
|
||||
const loadInitialCollapsedState = (defaultValue) => {
|
||||
if (typeof window === 'undefined') {
|
||||
return Boolean(defaultValue);
|
||||
}
|
||||
try {
|
||||
const stored = window.sessionStorage.getItem(SIDEBAR_COLLAPSE_STORAGE_KEY);
|
||||
if (stored === '1' || stored === 'true') {
|
||||
@@ -146,30 +126,18 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
|
||||
const [themeMode, setThemeModeState] = useState(initialTheme.mode);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
document.documentElement.style.setProperty('--neutral-hue', `${neutralHue}deg`);
|
||||
}, [neutralHue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
document.documentElement.style.setProperty('--neutral-chroma', String(neutralChroma));
|
||||
}, [neutralChroma]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
document.documentElement.style.setProperty('--neutral-contrast', String(neutralContrast));
|
||||
}, [neutralContrast]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const root = document.documentElement;
|
||||
if (themeMode === 'system') {
|
||||
root.removeAttribute('data-theme');
|
||||
@@ -179,9 +147,6 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
|
||||
}, [themeMode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const payload = JSON.stringify({
|
||||
neutralHue,
|
||||
@@ -199,7 +164,7 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
|
||||
|
||||
const setNeutralHue = useCallback((value) => {
|
||||
setNeutralHueState((prev) => {
|
||||
if (value === '' || value === null || typeof value === 'undefined') {
|
||||
if (value === '' || value === null || value === undefined) {
|
||||
return DEFAULT_NEUTRAL_HUE;
|
||||
}
|
||||
const parsed = Number(value);
|
||||
@@ -213,7 +178,7 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
|
||||
|
||||
const setNeutralChroma = useCallback((value) => {
|
||||
setNeutralChromaState((prev) => {
|
||||
if (value === '' || value === null || typeof value === 'undefined') {
|
||||
if (value === '' || value === null || value === undefined) {
|
||||
return DEFAULT_NEUTRAL_CHROMA;
|
||||
}
|
||||
const parsed = Number(value);
|
||||
@@ -231,7 +196,7 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
|
||||
|
||||
const setNeutralContrast = useCallback((value) => {
|
||||
setNeutralContrastState((prev) => {
|
||||
if (value === '' || value === null || typeof value === 'undefined') {
|
||||
if (value === '' || value === null || value === undefined) {
|
||||
return DEFAULT_NEUTRAL_CONTRAST;
|
||||
}
|
||||
const parsed = Number(value);
|
||||
@@ -265,9 +230,6 @@ export const SidebarProvider = ({ initialCollapsed = false, children }) => {
|
||||
}, [themeMode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
window.sessionStorage.setItem(SIDEBAR_COLLAPSE_STORAGE_KEY, collapsed ? '1' : '0');
|
||||
} catch (error) {
|
||||
|
||||
@@ -6,10 +6,7 @@ class TagManager {
|
||||
}
|
||||
|
||||
normalizeLabel(label) {
|
||||
if (typeof label !== 'string') {
|
||||
return '';
|
||||
}
|
||||
return label.trim();
|
||||
return label?.trim?.() || '';
|
||||
}
|
||||
|
||||
buildPayload({ label, color } = {}) {
|
||||
@@ -18,7 +15,7 @@ class TagManager {
|
||||
throw new Error('Tag label is required.');
|
||||
}
|
||||
const payload = { label: normalizedLabel };
|
||||
const trimmedColor = typeof color === 'string' && color.trim().length ? color.trim() : null;
|
||||
const trimmedColor = color?.trim?.() || null;
|
||||
payload.color = trimmedColor || this.colorGenerator();
|
||||
return payload;
|
||||
}
|
||||
|
||||
@@ -80,14 +80,15 @@ const BreadcrumbTrail = ({
|
||||
};
|
||||
|
||||
const scheduleMeasure = () => {
|
||||
if (typeof window === 'undefined' || typeof window.requestAnimationFrame !== 'function') {
|
||||
const raf = window.requestAnimationFrame;
|
||||
if (!raf) {
|
||||
measure();
|
||||
return;
|
||||
}
|
||||
if (measureRafRef.current) {
|
||||
cancelAnimationFrame(measureRafRef.current);
|
||||
}
|
||||
measureRafRef.current = window.requestAnimationFrame(() => {
|
||||
measureRafRef.current = raf(() => {
|
||||
measureRafRef.current = null;
|
||||
measure();
|
||||
});
|
||||
@@ -95,7 +96,7 @@ const BreadcrumbTrail = ({
|
||||
|
||||
scheduleMeasure();
|
||||
|
||||
if (typeof ResizeObserver === 'undefined') {
|
||||
if (!('ResizeObserver' in window)) {
|
||||
return () => {
|
||||
if (measureRafRef.current) {
|
||||
cancelAnimationFrame(measureRafRef.current);
|
||||
@@ -364,7 +365,6 @@ const BreadcrumbTrail = ({
|
||||
{ellipsisMenuOpen
|
||||
&& hasHiddenEntries
|
||||
&& ellipsisMenuStyle
|
||||
&& typeof document !== 'undefined'
|
||||
? createPortal(
|
||||
<div
|
||||
className="menu menu--floating"
|
||||
|
||||
@@ -6,20 +6,21 @@ const normalizeOption = (option, index) => {
|
||||
if (option == null) {
|
||||
return null;
|
||||
}
|
||||
if (typeof option === 'string') {
|
||||
if (option && typeof option === 'object') {
|
||||
const label = option.label ?? option.name;
|
||||
if (label == null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
id: option,
|
||||
label: option,
|
||||
id: option.id ?? label,
|
||||
label: String(label),
|
||||
original: option,
|
||||
index,
|
||||
};
|
||||
}
|
||||
const label = option.label ?? option.name;
|
||||
if (!label) {
|
||||
return null;
|
||||
}
|
||||
const label = String(option);
|
||||
return {
|
||||
id: option.id ?? label,
|
||||
id: label,
|
||||
label,
|
||||
original: option,
|
||||
index,
|
||||
@@ -90,7 +91,7 @@ const QuickAddMenu = ({
|
||||
() =>
|
||||
options
|
||||
.map((option, index) => normalizeOption(option, index))
|
||||
.filter((option) => option && typeof option.label === 'string'),
|
||||
.filter(Boolean),
|
||||
[options],
|
||||
);
|
||||
|
||||
|
||||
@@ -3,15 +3,7 @@ import { clamp } from '../utils/math';
|
||||
|
||||
const DEFAULT_VIEWPORT_MARGIN = 8;
|
||||
|
||||
const resolveViewportWidth = () => {
|
||||
if (typeof window !== 'undefined' && typeof window.innerWidth === 'number') {
|
||||
return window.innerWidth;
|
||||
}
|
||||
if (typeof document !== 'undefined' && document.documentElement) {
|
||||
return document.documentElement.clientWidth;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
const resolveViewportWidth = () => window.innerWidth || document.documentElement.clientWidth || 0;
|
||||
|
||||
const computeWidth = (anchorWidth, minWidth, matchAnchorWidth) => {
|
||||
if (matchAnchorWidth) {
|
||||
@@ -29,7 +21,7 @@ const formatStyle = (metrics) => {
|
||||
top: metrics.top,
|
||||
left: metrics.left,
|
||||
};
|
||||
if (typeof metrics.minWidth === 'number') {
|
||||
if (Number.isFinite(metrics.minWidth)) {
|
||||
style['--floating-min-width'] = `${Math.max(metrics.minWidth, 0)}px`;
|
||||
}
|
||||
if (metrics.width) {
|
||||
@@ -59,7 +51,7 @@ const useFloatingMenu = ({
|
||||
|
||||
const updatePosition = useCallback(() => {
|
||||
const anchor = anchorRef?.current;
|
||||
if (!anchor || typeof window === 'undefined') {
|
||||
if (!anchor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -109,7 +101,7 @@ const useFloatingMenu = ({
|
||||
}
|
||||
|
||||
const viewportWidth = resolveViewportWidth();
|
||||
const viewportHeight = typeof window !== 'undefined' ? window.innerHeight : 0;
|
||||
const viewportHeight = window.innerHeight || 0;
|
||||
const safeMargin = viewportMargin ?? DEFAULT_VIEWPORT_MARGIN;
|
||||
const menuHeight = menu?.offsetHeight ?? 0;
|
||||
|
||||
@@ -200,8 +192,9 @@ const useFloatingMenu = ({
|
||||
}
|
||||
|
||||
let ignoreFocusEvents = true;
|
||||
const rafId = typeof window !== 'undefined'
|
||||
? window.requestAnimationFrame(() => {
|
||||
const raf = window.requestAnimationFrame;
|
||||
const rafId = raf
|
||||
? raf(() => {
|
||||
ignoreFocusEvents = false;
|
||||
})
|
||||
: null;
|
||||
|
||||
@@ -12,10 +12,10 @@ const base64ToBase64url = (value = '') =>
|
||||
value.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
|
||||
|
||||
const decodeBase64 = (value) => {
|
||||
if (typeof window !== 'undefined' && typeof window.atob === 'function') {
|
||||
if (window.atob) {
|
||||
return window.atob(value);
|
||||
}
|
||||
const bufferCtor = typeof globalThis !== 'undefined' ? globalThis.Buffer : undefined;
|
||||
const bufferCtor = globalThis?.Buffer;
|
||||
if (bufferCtor) {
|
||||
return bufferCtor.from(value, 'base64').toString('binary');
|
||||
}
|
||||
@@ -23,10 +23,10 @@ const decodeBase64 = (value) => {
|
||||
};
|
||||
|
||||
const encodeBase64 = (binary) => {
|
||||
if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
|
||||
if (window.btoa) {
|
||||
return window.btoa(binary);
|
||||
}
|
||||
const bufferCtor = typeof globalThis !== 'undefined' ? globalThis.Buffer : undefined;
|
||||
const bufferCtor = globalThis?.Buffer;
|
||||
if (bufferCtor) {
|
||||
return bufferCtor.from(binary, 'binary').toString('base64');
|
||||
}
|
||||
@@ -54,11 +54,7 @@ export const arrayBufferToBase64url = (buffer) => {
|
||||
};
|
||||
|
||||
export const isWebAuthnAvailable = () =>
|
||||
typeof window !== 'undefined'
|
||||
&& typeof navigator !== 'undefined'
|
||||
&& navigator.credentials
|
||||
&& typeof navigator.credentials.create === 'function'
|
||||
&& typeof navigator.credentials.get === 'function';
|
||||
Boolean(navigator?.credentials?.create && navigator.credentials.get);
|
||||
|
||||
export const preparePublicKeyCreationOptions = (challengeResponse) => {
|
||||
if (!challengeResponse || !challengeResponse.publicKey) {
|
||||
@@ -118,10 +114,7 @@ export const serializeRegistrationCredential = (credential) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const transports =
|
||||
typeof credential?.response?.getTransports === 'function'
|
||||
? credential.response.getTransports()
|
||||
: undefined;
|
||||
const transports = credential?.response?.getTransports?.();
|
||||
|
||||
return {
|
||||
id: credential.id,
|
||||
@@ -132,10 +125,7 @@ export const serializeRegistrationCredential = (credential) => {
|
||||
attestationObject: arrayBufferToBase64url(credential.response.attestationObject),
|
||||
transports: transports && transports.length ? Array.from(transports) : undefined,
|
||||
},
|
||||
clientExtensionResults:
|
||||
typeof credential.getClientExtensionResults === 'function'
|
||||
? credential.getClientExtensionResults()
|
||||
: {},
|
||||
clientExtensionResults: credential.getClientExtensionResults?.() || {},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -156,9 +146,6 @@ export const serializeAuthenticationCredential = (credential) => {
|
||||
? arrayBufferToBase64url(credential.response.userHandle)
|
||||
: undefined,
|
||||
},
|
||||
clientExtensionResults:
|
||||
typeof credential.getClientExtensionResults === 'function'
|
||||
? credential.getClientExtensionResults()
|
||||
: {},
|
||||
clientExtensionResults: credential.getClientExtensionResults?.() || {},
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user