@ssgoi/core 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,76 +0,0 @@
1
- import { createTransitionCallback } from "./create-transition-callback";
2
- import type { Transition, TransitionCallback } from "./types";
3
-
4
- /**
5
- * Key type for transitions - can be string or symbol
6
- */
7
- type TransitionKey = string | symbol;
8
-
9
- /**
10
- * Centralized transition management
11
- * Uses string/symbol keys for all storage
12
- */
13
-
14
- // Map to store transition definitions by key
15
- const transitionDefinitions = new Map<TransitionKey, Transition>();
16
-
17
- // Map to store transition callbacks by key
18
- const transitionCallbacks = new Map<TransitionKey, TransitionCallback>();
19
-
20
- /**
21
- * Registers a transition with a key and returns the callback
22
- * Usage: registerTransition('fade', { in: fadeIn, out: fadeOut })
23
- */
24
- function registerTransition(
25
- key: TransitionKey,
26
- transition: Transition
27
- ): TransitionCallback {
28
- transitionDefinitions.set(key, transition);
29
-
30
- // Return existing callback if it exists
31
- let callback = transitionCallbacks.get(key);
32
- if (callback) {
33
- return callback;
34
- }
35
-
36
- // Create new callback
37
- callback = createTransitionCallback(
38
- () => {
39
- const trans = transitionDefinitions.get(key);
40
- if (!trans) {
41
- console.warn(`Transition "${String(key)}" not found`);
42
- return {};
43
- }
44
- return trans;
45
- },
46
- {
47
- onCleanupEnd: () => unregisterTransition(key),
48
- }
49
- );
50
- transitionCallbacks.set(key, callback);
51
- return callback;
52
- }
53
-
54
- /**
55
- * Unregisters a transition and cleans up associated resources
56
- */
57
- function unregisterTransition(key: TransitionKey): void {
58
- transitionDefinitions.delete(key);
59
- transitionCallbacks.delete(key);
60
- }
61
-
62
- /**
63
- * Framework-agnostic transition function that can be used as a ref
64
- * Usage: <div ref={transition({ key: 'fade', in, out })} />
65
- */
66
- export function transition(options: {
67
- key: TransitionKey;
68
- in?: Transition["in"];
69
- out?: Transition["out"];
70
- }): TransitionCallback {
71
- // Register transition and get callback
72
- return registerTransition(options.key, {
73
- in: options.in,
74
- out: options.out,
75
- });
76
- }
@@ -1,55 +0,0 @@
1
- interface BlurOptions {
2
- amount?: number;
3
- scale?: boolean;
4
- fade?: boolean;
5
- spring?: {
6
- stiffness?: number;
7
- damping?: number;
8
- };
9
- }
10
-
11
- export const blur = (options: BlurOptions = {}) => {
12
- const {
13
- amount = 10,
14
- scale = false,
15
- fade = true,
16
- spring = { stiffness: 300, damping: 30 }
17
- } = options;
18
-
19
- return {
20
- in: (element: HTMLElement) => ({
21
- spring,
22
- tick: (progress: number) => {
23
- const blurValue = (1 - progress) * amount;
24
- const filters = [`blur(${blurValue}px)`];
25
-
26
- element.style.filter = filters.join(' ');
27
-
28
- if (scale) {
29
- element.style.transform = `scale(${0.8 + progress * 0.2})`;
30
- }
31
-
32
- if (fade) {
33
- element.style.opacity = progress.toString();
34
- }
35
- }
36
- }),
37
- out: (element: HTMLElement) => ({
38
- spring,
39
- tick: (progress: number) => {
40
- const blurValue = (1 - progress) * amount;
41
- const filters = [`blur(${blurValue}px)`];
42
-
43
- element.style.filter = filters.join(' ');
44
-
45
- if (scale) {
46
- element.style.transform = `scale(${0.8 + progress * 0.2})`;
47
- }
48
-
49
- if (fade) {
50
- element.style.opacity = progress.toString();
51
- }
52
- }
53
- })
54
- };
55
- };
@@ -1,61 +0,0 @@
1
- interface BounceOptions {
2
- height?: number;
3
- scale?: boolean;
4
- fade?: boolean;
5
- spring?: {
6
- stiffness?: number;
7
- damping?: number;
8
- };
9
- }
10
-
11
- export const bounce = (options: BounceOptions = {}) => {
12
- const {
13
- height = 20,
14
- scale = true,
15
- fade = false,
16
- spring = { stiffness: 800, damping: 15 }
17
- } = options;
18
-
19
- return {
20
- in: (element: HTMLElement) => ({
21
- spring,
22
- tick: (progress: number) => {
23
- const transforms = [];
24
-
25
- // Bounce effect using sine wave
26
- const bounceOffset = Math.sin(progress * Math.PI) * height * (1 - progress);
27
- transforms.push(`translateY(${-bounceOffset}px)`);
28
-
29
- if (scale) {
30
- transforms.push(`scale(${0.8 + progress * 0.2})`);
31
- }
32
-
33
- element.style.transform = transforms.join(' ');
34
-
35
- if (fade) {
36
- element.style.opacity = progress.toString();
37
- }
38
- }
39
- }),
40
- out: (element: HTMLElement) => ({
41
- spring,
42
- tick: (progress: number) => {
43
- const transforms = [];
44
-
45
- // Bounce effect using sine wave
46
- const bounceOffset = Math.sin(progress * Math.PI) * height * (1 - progress);
47
- transforms.push(`translateY(${-bounceOffset}px)`);
48
-
49
- if (scale) {
50
- transforms.push(`scale(${0.8 + progress * 0.2})`);
51
- }
52
-
53
- element.style.transform = transforms.join(' ');
54
-
55
- if (fade) {
56
- element.style.opacity = progress.toString();
57
- }
58
- }
59
- })
60
- };
61
- };
@@ -1,33 +0,0 @@
1
- interface FadeOptions {
2
- from?: number;
3
- to?: number;
4
- spring?: {
5
- stiffness?: number;
6
- damping?: number;
7
- };
8
- }
9
-
10
- export const fade = (options: FadeOptions = {}) => {
11
- const {
12
- from = 0,
13
- to = 1,
14
- spring = { stiffness: 300, damping: 30 }
15
- } = options;
16
-
17
- return {
18
- in: (element: HTMLElement) => ({
19
- spring,
20
- tick: (progress: number) => {
21
- const opacity = from + (to - from) * progress;
22
- element.style.opacity = opacity.toString();
23
- }
24
- }),
25
- out: (element: HTMLElement) => ({
26
- spring,
27
- tick: (progress: number) => {
28
- const opacity = from + (to - from) * progress;
29
- element.style.opacity = opacity.toString();
30
- }
31
- })
32
- };
33
- };
@@ -1,7 +0,0 @@
1
- export * from './fade';
2
- export * from './scale';
3
- export * from './slide';
4
- export * from './rotate';
5
- export * from './bounce';
6
- export * from './blur';
7
- export * from './none';
@@ -1,27 +0,0 @@
1
- interface NoneOptions {
2
- spring?: {
3
- stiffness?: number;
4
- damping?: number;
5
- };
6
- }
7
-
8
- export const none = (options: NoneOptions = {}) => {
9
- const {
10
- spring = { stiffness: 1000, damping: 100 }
11
- } = options;
12
-
13
- return {
14
- in: (_element: HTMLElement) => ({
15
- spring,
16
- tick: (_progress: number) => {
17
- // No animation, just instantly show
18
- }
19
- }),
20
- out: (_element: HTMLElement) => ({
21
- spring,
22
- tick: (_progress: number) => {
23
- // No animation, just instantly hide
24
- }
25
- })
26
- };
27
- };
@@ -1,57 +0,0 @@
1
- interface RotateOptions {
2
- degrees?: number;
3
- clockwise?: boolean;
4
- scale?: boolean;
5
- fade?: boolean;
6
- spring?: {
7
- stiffness?: number;
8
- damping?: number;
9
- };
10
- }
11
-
12
- export const rotate = (options: RotateOptions = {}) => {
13
- const {
14
- degrees = 360,
15
- clockwise = true,
16
- scale = false,
17
- fade = false,
18
- spring = { stiffness: 500, damping: 25 }
19
- } = options;
20
-
21
- const rotation = clockwise ? degrees : -degrees;
22
-
23
- return {
24
- in: (element: HTMLElement) => ({
25
- spring,
26
- tick: (progress: number) => {
27
- const transforms = [`rotate(${progress * rotation}deg)`];
28
-
29
- if (scale) {
30
- transforms.push(`scale(${progress})`);
31
- }
32
-
33
- element.style.transform = transforms.join(' ');
34
-
35
- if (fade) {
36
- element.style.opacity = progress.toString();
37
- }
38
- }
39
- }),
40
- out: (element: HTMLElement) => ({
41
- spring,
42
- tick: (progress: number) => {
43
- const transforms = [`rotate(${progress * rotation}deg)`];
44
-
45
- if (scale) {
46
- transforms.push(`scale(${progress})`);
47
- }
48
-
49
- element.style.transform = transforms.join(' ');
50
-
51
- if (fade) {
52
- element.style.opacity = progress.toString();
53
- }
54
- }
55
- })
56
- };
57
- };
@@ -1,34 +0,0 @@
1
- interface ScaleOptions {
2
- duration?: number;
3
- from?: number;
4
- to?: number;
5
- spring?: {
6
- stiffness?: number;
7
- damping?: number;
8
- };
9
- }
10
-
11
- export const scale = (options: ScaleOptions = {}) => {
12
- const {
13
- from = 0,
14
- to = 1,
15
- spring = { stiffness: 300, damping: 30 }
16
- } = options;
17
-
18
- return {
19
- in: (element: HTMLElement) => ({
20
- spring,
21
- tick: (progress: number) => {
22
- const value = from + (to - from) * progress;
23
- element.style.transform = `scale(${value})`;
24
- }
25
- }),
26
- out: (element: HTMLElement) => ({
27
- spring,
28
- tick: (progress: number) => {
29
- const value = from + (to - from) * progress;
30
- element.style.transform = `scale(${value})`;
31
- }
32
- })
33
- };
34
- };
@@ -1,53 +0,0 @@
1
- interface SlideOptions {
2
- direction?: 'left' | 'right' | 'up' | 'down';
3
- distance?: number;
4
- fade?: boolean;
5
- spring?: {
6
- stiffness?: number;
7
- damping?: number;
8
- };
9
- }
10
-
11
- export const slide = (options: SlideOptions = {}) => {
12
- const {
13
- direction = 'left',
14
- distance = 100,
15
- fade = true,
16
- spring = { stiffness: 400, damping: 35 }
17
- } = options;
18
-
19
- const getTransform = (progress: number) => {
20
- const offset = (1 - progress) * distance;
21
- switch (direction) {
22
- case 'left':
23
- return `translateX(${-offset}px)`;
24
- case 'right':
25
- return `translateX(${offset}px)`;
26
- case 'up':
27
- return `translateY(${-offset}px)`;
28
- case 'down':
29
- return `translateY(${offset}px)`;
30
- }
31
- };
32
-
33
- return {
34
- in: (element: HTMLElement) => ({
35
- spring,
36
- tick: (progress: number) => {
37
- element.style.transform = getTransform(progress);
38
- if (fade) {
39
- element.style.opacity = progress.toString();
40
- }
41
- }
42
- }),
43
- out: (element: HTMLElement) => ({
44
- spring,
45
- tick: (progress: number) => {
46
- element.style.transform = getTransform(progress);
47
- if (fade) {
48
- element.style.opacity = progress.toString();
49
- }
50
- }
51
- })
52
- };
53
- };
package/src/lib/types.ts DELETED
@@ -1,60 +0,0 @@
1
- export type TransitionKey = string | symbol;
2
-
3
- export type SpringConfig = {
4
- stiffness?: number;
5
- damping?: number;
6
- };
7
-
8
- export type TransitionConfig = {
9
- // Spring physics configuration
10
- spring?: SpringConfig; // Default: { stiffness: 300, damping: 30 }
11
-
12
- // Callback for each frame with progress value (0-1)
13
- tick?: (progress: number) => void;
14
-
15
- // Prepare element before animation (typically for out transitions)
16
- prepare?: (element: HTMLElement) => void;
17
-
18
- // Called when animation starts
19
- onStart?: () => void;
20
-
21
- // Called when animation ends
22
- onEnd?: () => void;
23
- };
24
-
25
- export type GetTransitionConfig<TContext = undefined> =
26
- TContext extends undefined
27
- ? (node: HTMLElement) => TransitionConfig | Promise<TransitionConfig>
28
- : (
29
- node: HTMLElement,
30
- context: TContext
31
- ) => TransitionConfig | Promise<TransitionConfig>;
32
-
33
- export type Transition<TContext = undefined> = {
34
- in?: GetTransitionConfig<TContext>;
35
- out?: GetTransitionConfig<TContext>;
36
- };
37
-
38
- export type TransitionCallback = (
39
- element: HTMLElement | null
40
- ) => void | (() => void);
41
-
42
- export type SggoiTransitionContext = {
43
- scrollOffset: { x: number; y: number };
44
- };
45
-
46
- export type SggoiTransition = Transition<SggoiTransitionContext>;
47
-
48
- export type SsgoiConfig = {
49
- transitions: {
50
- from: string;
51
- to: string;
52
- transition: SggoiTransition;
53
- symmetric?: boolean;
54
- }[];
55
- defaultTransition?: SggoiTransition;
56
- };
57
-
58
- export type SsgoiContext = (
59
- path: string
60
- ) => Transition & { key: TransitionKey };
package/src/lib/utils.ts DELETED
@@ -1,39 +0,0 @@
1
- /**
2
- * Applies common styles for outgoing page elements
3
- * Makes the element absolute positioned to allow the incoming page to take its place
4
- */
5
- export const prepareOutgoing = (element: HTMLElement): void => {
6
- element.style.position = "absolute";
7
- element.style.width = "100%";
8
- element.style.top = "0";
9
- element.style.left = "0";
10
- };
11
-
12
- /**
13
- * Gets the scrolling element that contains the given element
14
- * Returns the first scrollable parent element or document.documentElement
15
- */
16
- export const getScrollingElement = (element: HTMLElement): HTMLElement => {
17
- let current = element.parentElement;
18
-
19
- while (current && current !== document.body) {
20
- const style = window.getComputedStyle(current);
21
- const overflow = style.overflow + style.overflowY + style.overflowX;
22
-
23
- // Check if element is scrollable
24
- if (overflow.includes('auto') || overflow.includes('scroll')) {
25
- return current;
26
- }
27
-
28
- // Also check if element has scroll even without explicit overflow
29
- if (current.scrollHeight > current.clientHeight ||
30
- current.scrollWidth > current.clientWidth) {
31
- return current;
32
- }
33
-
34
- current = current.parentElement;
35
- }
36
-
37
- // Return document element as fallback (handles body/html scrolling)
38
- return document.documentElement;
39
- };
@@ -1,29 +0,0 @@
1
- import type { SpringConfig, SggoiTransition } from "../types";
2
- import { prepareOutgoing } from "../utils";
3
-
4
- interface FadeOptions {
5
- spring?: Partial<SpringConfig>;
6
- }
7
-
8
- export const fade = (options: FadeOptions = {}): SggoiTransition => {
9
- const spring: SpringConfig = {
10
- stiffness: options.spring?.stiffness ?? 300,
11
- damping: options.spring?.damping ?? 30,
12
- };
13
-
14
- return {
15
- in: (element) => ({
16
- spring,
17
- tick: (progress) => {
18
- element.style.opacity = progress.toString();
19
- },
20
- }),
21
- out: (element) => ({
22
- spring,
23
- tick: (progress) => {
24
- element.style.opacity = progress.toString();
25
- },
26
- prepare: prepareOutgoing,
27
- }),
28
- };
29
- };