mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-10-29 08:04:50 +00:00
initiall commit
This commit is contained in:
commit
7ddfb1f52b
276 files changed
+37629
No files matched your search
@@ -0,0 +1,68 @@
|
||||
import { createSignal, onMount, onCleanup, Accessor } from "solid-js";
|
||||
|
||||
interface UseIntersectionObserverOptions extends IntersectionObserverInit {
|
||||
freezeOnceVisible?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to observe element visibility using Intersection Observer API
|
||||
* Useful for lazy loading, infinite scroll, and animations on scroll
|
||||
*/
|
||||
export function useIntersectionObserver(
|
||||
elementRef: Accessor<HTMLElement | undefined>,
|
||||
options: UseIntersectionObserverOptions = {}
|
||||
): Accessor<IntersectionObserverEntry | undefined> {
|
||||
const [entry, setEntry] = createSignal<IntersectionObserverEntry>();
|
||||
const { freezeOnceVisible = false, ...observerOptions } = options;
|
||||
|
||||
onMount(() => {
|
||||
const element = elementRef();
|
||||
if (!element) return;
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
setEntry(entry);
|
||||
|
||||
if (freezeOnceVisible && entry.isIntersecting) {
|
||||
observer.disconnect();
|
||||
}
|
||||
},
|
||||
observerOptions
|
||||
);
|
||||
|
||||
observer.observe(element);
|
||||
|
||||
onCleanup(() => {
|
||||
observer.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for lazy loading images
|
||||
*/
|
||||
export function useLazyImage(
|
||||
imageRef: Accessor<HTMLImageElement | undefined>,
|
||||
src: string
|
||||
): Accessor<boolean> {
|
||||
const [loaded, setLoaded] = createSignal(false);
|
||||
|
||||
const entry = useIntersectionObserver(imageRef, {
|
||||
threshold: 0.1,
|
||||
freezeOnceVisible: true,
|
||||
});
|
||||
|
||||
createSignal(() => {
|
||||
const img = imageRef();
|
||||
const isVisible = entry()?.isIntersecting;
|
||||
|
||||
if (img && isVisible && !loaded()) {
|
||||
img.src = src;
|
||||
img.onload = () => setLoaded(true);
|
||||
}
|
||||
});
|
||||
|
||||
return loaded;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import { onCleanup, onMount } from "solid-js";
|
||||
|
||||
export interface KeyboardShortcut {
|
||||
key: string;
|
||||
ctrl?: boolean;
|
||||
shift?: boolean;
|
||||
alt?: boolean;
|
||||
meta?: boolean;
|
||||
description?: string;
|
||||
action: (event: KeyboardEvent) => void;
|
||||
preventDefault?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for registering keyboard shortcuts
|
||||
*/
|
||||
export function useKeyboardShortcuts(shortcuts: KeyboardShortcut[]) {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
for (const shortcut of shortcuts) {
|
||||
const keyMatches = event.key.toLowerCase() === shortcut.key.toLowerCase();
|
||||
const ctrlMatches = shortcut.ctrl === undefined || event.ctrlKey === shortcut.ctrl;
|
||||
const shiftMatches = shortcut.shift === undefined || event.shiftKey === shortcut.shift;
|
||||
const altMatches = shortcut.alt === undefined || event.altKey === shortcut.alt;
|
||||
const metaMatches = shortcut.meta === undefined || event.metaKey === shortcut.meta;
|
||||
|
||||
if (keyMatches && ctrlMatches && shiftMatches && altMatches && metaMatches) {
|
||||
if (shortcut.preventDefault !== false) {
|
||||
event.preventDefault();
|
||||
}
|
||||
shortcut.action(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
});
|
||||
|
||||
onCleanup(() => {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Format shortcut for display
|
||||
*/
|
||||
export function formatShortcut(shortcut: KeyboardShortcut): string {
|
||||
const parts: string[] = [];
|
||||
|
||||
const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0;
|
||||
|
||||
if (shortcut.ctrl) parts.push(isMac ? "⌃" : "Ctrl");
|
||||
if (shortcut.alt) parts.push(isMac ? "⌥" : "Alt");
|
||||
if (shortcut.shift) parts.push(isMac ? "⇧" : "Shift");
|
||||
if (shortcut.meta) parts.push(isMac ? "⌘" : "Win");
|
||||
|
||||
parts.push(shortcut.key.toUpperCase());
|
||||
|
||||
return parts.join(isMac ? "" : "+");
|
||||
}
|
||||
|
||||
/**
|
||||
* Common keyboard shortcuts
|
||||
*/
|
||||
export const commonShortcuts = {
|
||||
save: { key: "s", ctrl: true, meta: true, description: "Save" },
|
||||
copy: { key: "c", ctrl: true, meta: true, description: "Copy" },
|
||||
paste: { key: "v", ctrl: true, meta: true, description: "Paste" },
|
||||
cut: { key: "x", ctrl: true, meta: true, description: "Cut" },
|
||||
undo: { key: "z", ctrl: true, meta: true, description: "Undo" },
|
||||
redo: { key: "z", ctrl: true, meta: true, shift: true, description: "Redo" },
|
||||
selectAll: { key: "a", ctrl: true, meta: true, description: "Select All" },
|
||||
find: { key: "f", ctrl: true, meta: true, description: "Find" },
|
||||
newTab: { key: "t", ctrl: true, meta: true, description: "New Tab" },
|
||||
closeTab: { key: "w", ctrl: true, meta: true, description: "Close Tab" },
|
||||
refresh: { key: "r", ctrl: true, meta: true, description: "Refresh" },
|
||||
commandPalette: { key: "k", ctrl: true, meta: true, description: "Command Palette" },
|
||||
settings: { key: ",", ctrl: true, meta: true, description: "Settings" },
|
||||
escape: { key: "Escape", description: "Cancel/Close" },
|
||||
enter: { key: "Enter", description: "Confirm/Submit" },
|
||||
arrowUp: { key: "ArrowUp", description: "Move Up" },
|
||||
arrowDown: { key: "ArrowDown", description: "Move Down" },
|
||||
arrowLeft: { key: "ArrowLeft", description: "Move Left" },
|
||||
arrowRight: { key: "ArrowRight", description: "Move Right" },
|
||||
};
|
||||
Reference in new issue
Block a user