Socket
Socket
Sign inDemoInstall

@dark-engine/native-navigation

Package Overview
Dependencies
32
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.2.0 to 1.3.0

56

dist/cjs/animations/src/animated/animated.js

@@ -5,29 +5,33 @@ 'use strict';

const core_1 = require('@dark-engine/core');
const Animated = (0, core_1.component)(({ spring, fn, slot }) => {
const cursor = (0, core_1.$$scope)().getCursorFiber();
const scope = (0, core_1.useMemo)(() => ({ element: null, notify: null }), []);
const notify = () => scope.element && fn(scope.element, spring.value());
scope.notify = notify;
(0, core_1.useInsertionEffect)(() => {
const make = () => {
const fiber = cursor.hook.owner;
(0, core_1.walk)(fiber.child, (fiber, _, stop) => {
if (fiber.element) {
scope.element = fiber.element;
return stop();
}
});
notify();
};
if ((0, core_1.$$scope)().getIsHydrateZone()) {
(0, core_1.nextTick)(make);
} else {
make();
}
return spring.on(() => scope.notify());
}, [spring]);
notify();
return slot;
});
const Animated = (0, core_1.component)(
({ spring, fn, slot }) => {
const cursor = (0, core_1.__useCursor)();
const { isHydration } = (0, core_1.__useSSR)();
const scope = (0, core_1.useMemo)(() => ({ element: null, notify: null }), []);
const notify = () => scope.element && fn(scope.element, spring.value());
scope.notify = notify;
(0, core_1.useInsertionEffect)(() => {
const make = () => {
const fiber = cursor.hook.owner;
(0, core_1.walk)(fiber.child, (fiber, _, stop) => {
if (fiber.element) {
scope.element = fiber.element;
return stop();
}
});
notify();
};
if (isHydration) {
(0, core_1.nextTick)(make);
} else {
make();
}
return spring.on(() => scope.notify());
}, [spring]);
notify();
return slot;
},
{ displayName: 'Animated' },
);
exports.Animated = Animated;
//# sourceMappingURL=animated.js.map
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.VERSION = void 0;
exports.VERSION = '1.2.0';
exports.LIB = exports.VERSION = void 0;
exports.VERSION = '1.3.0';
exports.LIB = '@dark-engine/animations';
//# sourceMappingURL=constants.js.map

@@ -71,5 +71,5 @@ 'use strict';

}
notify() {
notify(skip = false) {
this.sync();
this.event('item-change');
!skip && this.event('item-change');
}

@@ -76,0 +76,0 @@ setConfigurator(fn) {

@@ -9,2 +9,4 @@ 'use strict';

stiff: { tension: 210, friction: 20 },
slow: { tension: 280, friction: 60 },
molasses: { tension: 280, friction: 120 },
};

@@ -11,0 +13,0 @@ function preset(name) {

@@ -14,3 +14,7 @@ 'use strict';

timerId = null;
events = new Map();
emitter = new core_1.EventEmitter();
hasTransitions = false;
setHasTransitions(x) {
this.hasTransitions = x;
}
getCtrls() {

@@ -80,15 +84,10 @@ return this.ctrls;

on(event, handler) {
if (!this.events.has(event)) {
this.events.set(event, new Set());
}
const subs = this.events.get(event);
subs.add(handler);
return () => subs.delete(handler);
return this.emitter.on(event, handler);
}
event(name, value = null) {
this.events.has(name) && this.events.get(name).forEach(x => x(value));
event(event, value = null) {
this.emitter.emit(event, value);
}
completeSeries() {
const isCompleted = !this.detectIsPlaying();
isCompleted && this.event('series-end');
isCompleted && !this.hasTransitions && this.event('series-end');
}

@@ -95,0 +94,0 @@ defer(fn) {

@@ -6,3 +6,7 @@ 'use strict';

function useChain(chain, timesteps, timeframe = 1000) {
const scope = (0, core_1.useMemo)(() => ({ offs: [] }), []);
(0, core_1.useMemo)(() => {
scope.offs.forEach(x => x());
scope.offs = [];
const { offs } = scope;
chain.forEach((api, idx) => {

@@ -12,5 +16,2 @@ api.chain(idx > 0);

});
}, [...chain]);
(0, core_1.useLayoutEffect)(() => {
const offs = [];
for (let i = 0; i < chain.length; i++) {

@@ -22,3 +23,7 @@ const api = chain[i];

const time = timesteps[i + 1] * timeframe;
const off = api.on('series-start', () => (0, core_1.nextTick)(() => nextApi.start()));
const off = api.on('series-start', () => {
(0, core_1.nextTick)(() => {
nextApi.start();
});
});
nextApi.delay(time);

@@ -31,6 +36,6 @@ offs.push(off);

}
return () => offs.forEach(x => x());
}, [...chain]);
(0, core_1.useLayoutEffect)(() => () => scope.offs.forEach(x => x()), []);
}
exports.useChain = useChain;
//# sourceMappingURL=use-chain.js.map

@@ -8,3 +8,3 @@ 'use strict';

const utils_1 = require('../utils');
function useSprings(count, configurator, deps) {
function useSprings(count, configurator, deps = []) {
const state = (0, core_1.useMemo)(() => (0, state_1.getSharedState)() || new state_1.SharedState(), []);

@@ -37,2 +37,3 @@ const scope = (0, core_1.useMemo)(() => {

return {
marker: 'spring-api',
start: fn => {

@@ -56,4 +57,4 @@ if (scope.inChain) {

}, []);
(0, core_1.useEffect)(() => {
if (!deps) return;
(0, core_1.useLayoutEffect)(() => {
if (deps.length === 0) return;
const { inChain } = scope;

@@ -65,3 +66,3 @@ if (inChain) {

}
}, deps || []);
}, [...deps]);
(0, core_1.useLayoutEffect)(() => () => api.cancel(), []);

@@ -68,0 +69,0 @@ return [springs, api];

@@ -18,2 +18,3 @@ 'use strict';

..._api,
marker: 'trail-api',
reverse: value => (value ? state.setFlow(state_1.Flow.LEFT) : state.setFlow(state_1.Flow.RIGHT)),

@@ -20,0 +21,0 @@ };

@@ -5,11 +5,12 @@ 'use strict';

const core_1 = require('@dark-engine/core');
const controller_1 = require('../controller');
const state_1 = require('../state');
const controller_1 = require('../controller');
const utils_1 = require('../utils');
function useTransition(items, getKey, configurator) {
const forceUpdate = (0, core_1.useUpdate)();
const update = () => (0, core_1.batch)(forceUpdate);
const update = () => (scope.isNonBlocking ? (0, core_1.startTransition)(forceUpdate) : forceUpdate());
const state = (0, core_1.useMemo)(() => new state_1.SharedState(), []);
const scope = (0, core_1.useMemo)(
() => ({
transitions: [],
ctrlsMap: new Map(),

@@ -23,2 +24,3 @@ itemsMap: new Map(),

inChain: false,
isNonBlocking: false,
pending: null,

@@ -30,3 +32,26 @@ configurator,

scope.configurator = configurator;
(0, core_1.useMemo)(() => setup({ items, getKey, configurator, state, ctrlsMap: scope.ctrlsMap }), []);
scope.isNonBlocking = core_1.scheduler.detectIsTransition();
(0, core_1.useMemo)(() => {
const make = items => {
const { transitions, ctrlsMap, fakesMap, items: $items } = scope;
const configurator = (idx, item) => scope.configurator(idx, item);
const { ctrls, itemsMap } = setup({ items, getKey, configurator, state, ctrlsMap });
const { insMap, remMap, movMap, stabMap, replaced } = diff($items, items, getKey);
scope.hasReplaces = replaced.size > 0;
state.setCtrls(ctrls);
replaced.forEach(key => ctrlsMap.get(key).setIsReplaced(true));
transitions.push(
...animate({ action: Action.LEAVE, space: fakesMap, state, scope }),
...animate({ action: Action.ENTER, space: insMap, state, scope }),
...animate({ action: Action.LEAVE, space: remMap, state, scope }),
...animate({ action: Action.UPDATE, space: movMap, state, scope }),
...animate({ action: Action.UPDATE, space: stabMap, state, scope }),
);
state.setHasTransitions(transitions.length > 0);
scope.items = items;
scope.itemsMap = itemsMap;
scope.fromApi = false;
};
make((0, utils_1.uniq)(items, getKey));
}, [items]);
const transition = (0, core_1.useMemo)(

@@ -58,2 +83,3 @@ () => render => {

return {
marker: 'transition-api',
start: fn => {

@@ -64,2 +90,3 @@ scope.fromApi = true;

scope.pending = null;
update();
} else {

@@ -78,39 +105,27 @@ state.start(fn);

}, []);
(0, core_1.useEffect)(() => {
(0, core_1.useLayoutEffect)(() => {
if (scope.transitions.length === 0) return;
const { inChain } = scope;
const nextItems = (0, utils_1.uniq)(items, getKey);
const start = items => {
const { ctrlsMap, fakesMap, items: $items } = scope;
const configurator = (idx, item) => scope.configurator(idx, item);
const { ctrls, itemsMap } = setup({ items, getKey, configurator, state, ctrlsMap });
const { hasChanges, insMap, remMap, movMap, stabMap, replaced } = diff($items, items, getKey);
scope.hasReplaces = replaced.size > 0;
state.setCtrls(ctrls);
replaced.forEach(key => ctrlsMap.get(key).setIsReplaced(true));
const start = () => {
state.event('series-start');
animate({ action: Action.LEAVE, space: fakesMap, state, scope });
animate({ action: Action.ENTER, space: insMap, state, scope });
animate({ action: Action.LEAVE, space: remMap, state, scope });
animate({ action: Action.UPDATE, space: movMap, state, scope });
animate({ action: Action.UPDATE, space: stabMap, state, scope });
scope.items = items;
scope.itemsMap = itemsMap;
scope.fromApi = false;
hasChanges && forceUpdate();
scope.transitions.forEach(x => x.fn());
scope.transitions = [];
state.setHasTransitions(false);
};
if (inChain) {
scope.pending = () => state.defer(() => start(nextItems));
scope.pending = () => state.defer(start);
} else {
start(nextItems);
start();
}
}, [items]);
});
(0, core_1.useLayoutEffect)(() => {
const offs = [];
offs.push(
const offs = [
api.on('item-end', e => handleItemEnd(e, scope)),
api.on('series-end', () => handleSeriesEnd(update, state, scope)),
);
return () => offs.forEach(x => x());
];
return () => {
offs.forEach(x => x());
api.cancel();
};
}, []);
(0, core_1.useLayoutEffect)(() => () => api.cancel(), []);
return [transition, api];

@@ -173,3 +188,2 @@ }

let n = 0;
let hasChanges = false;
const insMap = new Map();

@@ -189,6 +203,4 @@ const remMap = new Map();

replaced.add(prevKey);
hasChanges = true;
} else {
insMap.set(nextKey, i);
hasChanges = true;
p++;

@@ -199,3 +211,2 @@ size++;

remMap.set(prevKey, i);
hasChanges = true;
n++;

@@ -205,3 +216,2 @@ size++;

movMap.set(nextKey, i);
hasChanges = true;
}

@@ -213,3 +223,2 @@ } else if (nextKey !== null) {

return {
hasChanges,
insMap,

@@ -223,2 +232,3 @@ remMap,

function animate(options) {
const transitions = [];
const { space, action, state, scope } = options;

@@ -237,2 +247,3 @@ const { configurator, ctrlsMap, fakesMap } = scope;

let $ctrl = ctrl;
let $key = key;
if (isEnter) {

@@ -246,2 +257,3 @@ const isReplaced = ctrl.getIsReplaced();

$ctrl = fake;
$key = fakeKey;
prepare({ ctrl: fake, key: fakeKey, idx, item, configurator });

@@ -256,12 +268,15 @@ ctrlsMap.set(fakeKey, fake);

}
to && withTrail(() => $ctrl.start(() => ({ to })), $idx, trail);
const start = () => $ctrl.start(() => ({ to }));
const fn = to && withTrail(start, $idx, $ctrl, trail);
fn && transitions.push(new Transition($key, fn));
$idx++;
}
return transitions;
}
function withTrail(fn, idx, trail) {
function withTrail(start, idx, ctrl, trail) {
if ((0, core_1.detectIsNumber)(trail)) {
setTimeout(fn, idx * trail);
} else {
fn();
ctrl.setIsPlaying(true);
return () => setTimeout(start, idx * trail);
}
return start;
}

@@ -304,3 +319,3 @@ function prepare(options) {

ctrl.replaceValue({ ...enter });
ctrl.notify();
ctrl.notify(true);
ctrls.push(ctrl);

@@ -311,2 +326,10 @@ }

}
class Transition {
key;
fn;
constructor(key, fn) {
this.key = key;
this.fn = fn;
}
}
var Action;

@@ -313,0 +336,0 @@ (function (Action) {

'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.uniq = exports.range = exports.illegal = exports.fix = void 0;
exports.illegal = exports.uniq = exports.range = exports.fix = void 0;
const core_1 = require('@dark-engine/core');
const constants_1 = require('../constants');
const fix = (x, precision = 4) => Number(x.toFixed(precision));
exports.fix = fix;
const illegal = value => {
throw new Error(value);
};
exports.illegal = illegal;
const range = x =>

@@ -26,2 +24,4 @@ Array(x)

exports.uniq = uniq;
const illegal = x => (0, core_1.illegal)(x, constants_1.LIB);
exports.illegal = illegal;
//# sourceMappingURL=utils.js.map
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.TransitionName = exports.SLASH_MARK = exports.VERSION = void 0;
exports.VERSION = '1.2.0';
exports.TransitionName = exports.SLASH_MARK = exports.LIB = exports.VERSION = void 0;
exports.VERSION = '1.3.0';
exports.LIB = '@dark-engine/native-navigation';
exports.SLASH_MARK = '/';

@@ -6,0 +7,0 @@ var TransitionName;

@@ -5,2 +5,3 @@ 'use strict';

const core_1 = require('@nativescript/core');
const core_2 = require('@dark-engine/core');
const utils_1 = require('../utils');

@@ -10,3 +11,3 @@ class NavigationHistory {

cursor = -1;
subscribers = new Set();
emitter = new core_2.EventEmitter();
frame;

@@ -25,3 +26,3 @@ page;

this.dispose = () => {
this.subscribers.clear();
this.emitter = new core_2.EventEmitter();
this.stack = [];

@@ -33,3 +34,3 @@ this.cursor = -1;

this.dispose = () => {
this.subscribers.clear();
this.emitter = new core_2.EventEmitter();
this.stack = [];

@@ -41,5 +42,3 @@ this.cursor = -1;

mapSubscribers(action, options) {
for (const subscriber of this.subscribers) {
subscriber(this.getValue(), action, options);
}
this.emitter.emit('change', { pathname: this.getValue(), action, options });
}

@@ -68,5 +67,4 @@ getValue() {

}
subscribe(subscriber) {
this.subscribers.add(subscriber);
return () => this.subscribers.delete(subscriber);
subscribe(event, subscriber) {
return this.emitter.on(event, subscriber);
}

@@ -73,0 +71,0 @@ push(pathname, options) {

@@ -11,100 +11,98 @@ 'use strict';

const utils_1 = require('../utils');
const NavigationContainer = (0, core_2.forwardRef)(
(0, core_2.component)(
({ slot, defaultPathname = constants_1.SLASH_MARK, renderActionBar, onNavigate }, ref) => {
const frameRef = (0, core_2.useRef)(null);
const pageRef = (0, core_2.useRef)(null);
const [pathname, setPathname] = (0, core_2.useState)((0, utils_1.normalizePathname)(defaultPathname));
const [transition, setTransition] = (0, core_2.useState)(null);
const scope = (0, core_2.useMemo)(
() => ({ history: null, inTransition: false, transitions: { forward: [], backward: [] } }),
[],
);
const {
transitions: { forward, backward },
} = scope;
(0, core_2.useLayoutEffect)(() => {
const history = (0, history_1.createNavigationHistory)(pathname, frameRef.current, pageRef.current);
const unsubscribe = history.subscribe((pathname, action, options) => {
const isReplace = action === history_1.HistoryAction.REPLACE;
const isBack = action === history_1.HistoryAction.BACK;
setPathname(pathname);
!isReplace && scheduleTransition(pathname, isBack, options);
(0, core_2.detectIsFunction)(onNavigate) && onNavigate(pathname);
});
scope.history = history;
return () => {
unsubscribe();
history.dispose();
const NavigationContainer = (0, core_2.component)(
({ slot, ref, defaultPathname = constants_1.SLASH_MARK, renderActionBar, onNavigate }) => {
const frameRef = (0, core_2.useRef)(null);
const pageRef = (0, core_2.useRef)(null);
const [pathname, setPathname] = (0, core_2.useState)((0, utils_1.normalizePathname)(defaultPathname));
const [transition, setTransition] = (0, core_2.useState)(null);
const scope = (0, core_2.useMemo)(
() => ({ history: null, inTransition: false, transitions: { forward: [], backward: [] } }),
[],
);
const {
transitions: { forward, backward },
} = scope;
(0, core_2.useLayoutEffect)(() => {
const history = (0, history_1.createNavigationHistory)(pathname, frameRef.current, pageRef.current);
const unsubscribe = history.subscribe('change', ({ pathname, action, options }) => {
const isReplace = action === history_1.HistoryAction.REPLACE;
const isBack = action === history_1.HistoryAction.BACK;
setPathname(pathname);
!isReplace && scheduleTransition(pathname, isBack, options);
(0, core_2.detectIsFunction)(onNavigate) && onNavigate(pathname);
});
scope.history = history;
return () => {
unsubscribe();
history.dispose();
};
}, []);
(0, core_2.useEffect)(() => {
if (!transition) return;
const timeout = transition.options.animated ? transition.options.transition.duration : 0;
const timerId = setTimeout(() => {
scope.inTransition = false;
executeTransitions();
}, timeout + WAITING_TIMEOUT);
return () => clearTimeout(timerId);
}, [transition]);
const scheduleTransition = (to, isBack, options) => {
if (isBack) {
const transition = backward.pop();
forward.push(transition);
} else {
const from = scope.history.getBack();
const forwardTransition = {
from,
to,
isBack: false,
options: resolveNavigationOptions(options),
};
}, []);
(0, core_2.useEffect)(() => {
if (!transition) return;
const timeout = transition.options.animated ? transition.options.transition.duration : 0;
const timerId = setTimeout(() => {
scope.inTransition = false;
executeTransitions();
}, timeout + WAITING_TIMEOUT);
return () => clearTimeout(timerId);
}, [transition]);
const scheduleTransition = (to, isBack, options) => {
if (isBack) {
const transition = backward.pop();
forward.push(transition);
} else {
const from = scope.history.getBack();
const forwardTransition = {
from,
to,
isBack: false,
options: resolveNavigationOptions(options),
};
const backwardTransition = {
...forwardTransition,
isBack: true,
from: forwardTransition.to,
to: forwardTransition.from,
};
forward.push(forwardTransition);
backward.push(backwardTransition);
}
executeTransitions();
};
const executeTransitions = () => {
if (scope.inTransition) return;
const transition = forward.shift();
if (!transition) return setTransition(null);
scope.inTransition = true;
setTransition(transition);
};
const push = (0, core_2.useEvent)((pathname, options) => scope.history.push(pathname, options));
const replace = (0, core_2.useEvent)(pathname => scope.history.replace(pathname));
const back = (0, core_2.useEvent)(() => scope.history.back());
const getParams = (0, core_2.useEvent)(pathname => (scope.history ? scope.history.getParams(pathname) : null));
const subscribe = (0, core_2.useEvent)(subscriber => scope.history.subscribe(subscriber));
const contextValue = (0, core_2.useMemo)(
() => ({ pathname, transition, push, replace, back, getParams, subscribe }),
[pathname, transition],
);
(0, core_2.useImperativeHandle)(ref, () => ({ navigateTo: push, goBack: back }), []);
const hasActionBar = (0, core_2.detectIsFunction)(renderActionBar);
return (0, jsx_runtime_1.jsxs)(NavigationContext.Provider, {
value: contextValue,
children: [
(0, jsx_runtime_1.jsx)(platform_native_1.Frame, {
children: (0, jsx_runtime_1.jsxs)(platform_native_1.Page, {
actionBarHidden: !hasActionBar,
children: [hasActionBar && renderActionBar({ pathname, goBack: back }), slot],
}),
const backwardTransition = {
...forwardTransition,
isBack: true,
from: forwardTransition.to,
to: forwardTransition.from,
};
forward.push(forwardTransition);
backward.push(backwardTransition);
}
executeTransitions();
};
const executeTransitions = () => {
if (scope.inTransition) return;
const transition = forward.shift();
if (!transition) return setTransition(null);
scope.inTransition = true;
setTransition(transition);
};
const push = (0, core_2.useEvent)((pathname, options) => scope.history.push(pathname, options));
const replace = (0, core_2.useEvent)(pathname => scope.history.replace(pathname));
const back = (0, core_2.useEvent)(() => scope.history.back());
const getParams = (0, core_2.useEvent)(pathname => (scope.history ? scope.history.getParams(pathname) : null));
const subscribe = (0, core_2.useEvent)((event, subscriber) => scope.history.subscribe(event, subscriber));
const contextValue = (0, core_2.useMemo)(
() => ({ pathname, transition, push, replace, back, getParams, subscribe }),
[pathname, transition],
);
(0, core_2.useImperativeHandle)(ref, () => ({ navigateTo: push, goBack: back }), []);
const hasActionBar = (0, core_2.detectIsFunction)(renderActionBar);
return (0, jsx_runtime_1.jsxs)(NavigationContext.Provider, {
value: contextValue,
children: [
(0, jsx_runtime_1.jsx)(platform_native_1.Frame, {
children: (0, jsx_runtime_1.jsxs)(platform_native_1.Page, {
actionBarHidden: !hasActionBar,
children: [hasActionBar && renderActionBar({ pathname, goBack: back }), slot],
}),
(0, jsx_runtime_1.jsx)(platform_native_1.Frame, {
ref: frameRef,
hidden: true,
children: (0, jsx_runtime_1.jsx)(platform_native_1.Page, { ref: pageRef, actionBarHidden: true }),
}),
],
});
},
{ displayName: 'NavigationContainer' },
),
}),
(0, jsx_runtime_1.jsx)(platform_native_1.Frame, {
ref: frameRef,
hidden: true,
children: (0, jsx_runtime_1.jsx)(platform_native_1.Page, { ref: pageRef, actionBarHidden: true }),
}),
],
});
},
{ displayName: 'NavigationContainer' },
);

@@ -111,0 +109,0 @@ exports.NavigationContainer = NavigationContainer;

@@ -12,69 +12,66 @@ 'use strict';

const visitedMap = {};
const Navigator = (0, core_2.forwardRef)(
(0, core_2.component)(
({ slot, onNavigate }, ref) => {
const { pathname, transition, replace, subscribe } = (0, navigation_container_1.useNavigationContext)();
const { prefix } = useScreenNavigatorContext();
const rootRef = (0, core_2.useRef)(null);
const names = slot.map(x => x.props.name);
const pathnames = names.map(x => (0, utils_1.createPathname)(x, prefix));
const scope = (0, core_2.useMemo)(() => ({ refsMap: {} }), []);
const hiddensMap = (0, core_2.useMemo)(
() => createHiddensMap({ transition, pathnames, pathname, prefix }),
[transition],
);
visitedMap[pathname] = true;
(0, core_2.useLayoutEffect)(() => {
const entry = pathnames[0];
detectCanReplacePathname(pathname, entry, prefix) && replace(entry);
}, [pathname]);
(0, core_2.useLayoutEffect)(() => {
const canStartTransition = detectCanStartTransition(transition, pathnames, prefix);
if (!canStartTransition || !transition.options.animated) return;
const targetFrom = matchRef(scope.refsMap, transition.from);
const targetTo = matchRef(scope.refsMap, transition.to);
const size = rootRef.current.getActualSize();
const animation = createAnimation({ targetFrom, targetTo, transition, size });
setTimeout(() => {
animation.play().then(() => {
targetFrom.opacity = 0;
targetFrom.translateX = 0;
targetFrom.hidden = true;
targetTo.opacity = 1;
targetTo.translateX = 0;
targetTo.hidden = false;
setTimeout(() => {
targetFrom.opacity = 1;
});
const Navigator = (0, core_2.component)(
({ slot, onNavigate }) => {
const { pathname, transition, replace, subscribe } = (0, navigation_container_1.useNavigationContext)();
const { prefix } = useScreenNavigatorContext();
const rootRef = (0, core_2.useRef)(null);
const names = slot.map(x => x.props.name);
const pathnames = names.map(x => (0, utils_1.createPathname)(x, prefix));
const scope = (0, core_2.useMemo)(() => ({ refsMap: {} }), []);
const hiddensMap = (0, core_2.useMemo)(
() => createHiddensMap({ transition, pathnames, pathname, prefix }),
[transition],
);
visitedMap[pathname] = true;
(0, core_2.useLayoutEffect)(() => {
const entry = pathnames[0];
detectCanReplacePathname(pathname, entry, prefix) && replace(entry);
}, [pathname]);
(0, core_2.useLayoutEffect)(() => {
const canStartTransition = detectCanStartTransition(transition, pathnames, prefix);
if (!canStartTransition || !transition.options.animated) return;
const targetFrom = matchRef(scope.refsMap, transition.from);
const targetTo = matchRef(scope.refsMap, transition.to);
const size = rootRef.current.getActualSize();
const animation = createAnimation({ targetFrom, targetTo, transition, size });
setTimeout(() => {
animation.play().then(() => {
targetFrom.opacity = 0;
targetFrom.translateX = 0;
targetFrom.hidden = true;
targetTo.opacity = 1;
targetTo.translateX = 0;
targetTo.hidden = false;
setTimeout(() => {
targetFrom.opacity = 1;
});
});
}, [transition]);
(0, core_2.useEffect)(() => {
const syncNavigation = pathname => (0, core_2.detectIsFunction)(onNavigate) && onNavigate(pathname);
syncNavigation(pathname);
const unsubscribe = subscribe(pathname => syncNavigation(pathname));
return () => unsubscribe();
}, []);
(0, core_2.useImperativeHandle)(ref, () => ({}));
return (0, jsx_runtime_1.jsx)(platform_native_1.AbsoluteLayout, {
ref: rootRef,
width: FULL,
height: FULL,
children: slot.map(x => {
const name = x.props.name;
const key = (0, utils_1.createPathname)(name, prefix);
const isHidden = Boolean(hiddensMap[key]);
const setRef = ref => {
scope.refsMap[key] = ref;
};
return (0, jsx_runtime_1.jsx)(
platform_native_1.StackLayout,
{ ref: setRef, width: FULL, height: FULL, hidden: isHidden, children: x },
key,
);
}),
});
},
{ displayName: 'StackNavigator.Root' },
),
}, [transition]);
(0, core_2.useEffect)(() => {
const syncNavigation = pathname => (0, core_2.detectIsFunction)(onNavigate) && onNavigate(pathname);
syncNavigation(pathname);
const unsubscribe = subscribe('change', ({ pathname }) => syncNavigation(pathname));
return () => unsubscribe();
}, []);
return (0, jsx_runtime_1.jsx)(platform_native_1.AbsoluteLayout, {
ref: rootRef,
width: FULL,
height: FULL,
children: slot.map(x => {
const name = x.props.name;
const key = (0, utils_1.createPathname)(name, prefix);
const isHidden = Boolean(hiddensMap[key]);
const setRef = ref => {
scope.refsMap[key] = ref;
};
return (0, jsx_runtime_1.jsx)(
platform_native_1.StackLayout,
{ ref: setRef, width: FULL, height: FULL, hidden: isHidden, children: x },
key,
);
}),
});
},
{ displayName: 'StackNavigator.Root' },
);

@@ -81,0 +78,0 @@ const Screen = (0, core_2.component)(

@@ -13,3 +13,2 @@ 'use strict';

({ bottomNavigationOptions, slot }) => {
const navRef = (0, core_2.useRef)(null);
const layoutRef = (0, core_2.useRef)(null);

@@ -60,3 +59,2 @@ const bottomRef = (0, core_2.useRef)(null);

(0, jsx_runtime_1.jsx)(stack_navigator_1.StackNavigator.Root, {
ref: navRef,
children: descriptorKeys.map(key => {

@@ -63,0 +61,0 @@ const { component, slot } = descriptorsMap[key];

'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.detectIsMatch =
exports.illegal =
exports.detectIsMatch =
exports.detectIsVisited =

@@ -10,12 +11,10 @@ exports.getSegments =

void 0;
const core_1 = require('@dark-engine/core');
const constants_1 = require('../constants');
const createPathname = (name, prefix) => {
return normalizePathname(`${prefix}${name}`);
};
const createPathname = (name, prefix) => normalizePathname(`${prefix}${name}`);
exports.createPathname = createPathname;
function normalizePathname(pathname) {
const normal = prependSlash(
return prependSlash(
pathname.split(constants_1.SLASH_MARK).filter(Boolean).join(constants_1.SLASH_MARK) + constants_1.SLASH_MARK,
);
return normal;
}

@@ -28,4 +27,3 @@ exports.normalizePathname = normalizePathname;

function getSegments(pathname, prefix) {
const segments = pathname.replace(prefix, '').split(constants_1.SLASH_MARK).filter(Boolean);
return segments;
return pathname.replace(prefix, '').split(constants_1.SLASH_MARK).filter(Boolean);
}

@@ -43,6 +41,7 @@ exports.getSegments = getSegments;

function detectIsMatch(currentPathname, pathname) {
const isMatch = currentPathname.indexOf(pathname) !== -1;
return isMatch;
return currentPathname.indexOf(pathname) !== -1;
}
exports.detectIsMatch = detectIsMatch;
const illegal = x => (0, core_1.illegal)(x, constants_1.LIB);
exports.illegal = illegal;
//# sourceMappingURL=utils.js.map

@@ -1,29 +0,41 @@

import { component, useMemo, useInsertionEffect, $$scope, walk, nextTick } from '@dark-engine/core';
const Animated = component(({ spring, fn, slot }) => {
const cursor = $$scope().getCursorFiber();
const scope = useMemo(() => ({ element: null, notify: null }), []);
const notify = () => scope.element && fn(scope.element, spring.value());
scope.notify = notify;
useInsertionEffect(() => {
const make = () => {
const fiber = cursor.hook.owner;
walk(fiber.child, (fiber, _, stop) => {
if (fiber.element) {
scope.element = fiber.element;
return stop();
}
});
notify();
};
if ($$scope().getIsHydrateZone()) {
nextTick(make);
} else {
make();
}
return spring.on(() => scope.notify());
}, [spring]);
notify();
return slot;
});
import {
component,
useMemo,
useInsertionEffect,
walk,
nextTick,
__useCursor as useCursor,
__useSSR as useSSR,
} from '@dark-engine/core';
const Animated = component(
({ spring, fn, slot }) => {
const cursor = useCursor();
const { isHydration } = useSSR();
const scope = useMemo(() => ({ element: null, notify: null }), []);
const notify = () => scope.element && fn(scope.element, spring.value());
scope.notify = notify;
useInsertionEffect(() => {
const make = () => {
const fiber = cursor.hook.owner;
walk(fiber.child, (fiber, _, stop) => {
if (fiber.element) {
scope.element = fiber.element;
return stop();
}
});
notify();
};
if (isHydration) {
nextTick(make);
} else {
make();
}
return spring.on(() => scope.notify());
}, [spring]);
notify();
return slot;
},
{ displayName: 'Animated' },
);
export { Animated };
//# sourceMappingURL=animated.js.map

@@ -1,2 +0,3 @@

export const VERSION = '1.2.0';
export const VERSION = '1.3.0';
export const LIB = '@dark-engine/animations';
//# sourceMappingURL=constants.js.map

@@ -66,5 +66,5 @@ import { platform, falseFn, detectIsUndefined, getTime } from '@dark-engine/core';

}
notify() {
notify(skip = false) {
this.sync();
this.event('item-change');
!skip && this.event('item-change');
}

@@ -71,0 +71,0 @@ setConfigurator(fn) {

@@ -6,2 +6,4 @@ const presets = {

stiff: { tension: 210, friction: 20 },
slow: { tension: 280, friction: 60 },
molasses: { tension: 280, friction: 120 },
};

@@ -8,0 +10,0 @@ function preset(name) {

@@ -1,2 +0,2 @@

import { detectIsEmpty } from '@dark-engine/core';
import { EventEmitter, detectIsEmpty } from '@dark-engine/core';
class SharedState {

@@ -11,3 +11,7 @@ ctrls = [];

timerId = null;
events = new Map();
emitter = new EventEmitter();
hasTransitions = false;
setHasTransitions(x) {
this.hasTransitions = x;
}
getCtrls() {

@@ -77,15 +81,10 @@ return this.ctrls;

on(event, handler) {
if (!this.events.has(event)) {
this.events.set(event, new Set());
}
const subs = this.events.get(event);
subs.add(handler);
return () => subs.delete(handler);
return this.emitter.on(event, handler);
}
event(name, value = null) {
this.events.has(name) && this.events.get(name).forEach(x => x(value));
event(event, value = null) {
this.emitter.emit(event, value);
}
completeSeries() {
const isCompleted = !this.detectIsPlaying();
isCompleted && this.event('series-end');
isCompleted && !this.hasTransitions && this.event('series-end');
}

@@ -92,0 +91,0 @@ defer(fn) {

import { useMemo, useLayoutEffect, nextTick } from '@dark-engine/core';
function useChain(chain, timesteps, timeframe = 1000) {
const scope = useMemo(() => ({ offs: [] }), []);
useMemo(() => {
scope.offs.forEach(x => x());
scope.offs = [];
const { offs } = scope;
chain.forEach((api, idx) => {

@@ -8,5 +12,2 @@ api.chain(idx > 0);

});
}, [...chain]);
useLayoutEffect(() => {
const offs = [];
for (let i = 0; i < chain.length; i++) {

@@ -18,3 +19,7 @@ const api = chain[i];

const time = timesteps[i + 1] * timeframe;
const off = api.on('series-start', () => nextTick(() => nextApi.start()));
const off = api.on('series-start', () => {
nextTick(() => {
nextApi.start();
});
});
nextApi.delay(time);

@@ -27,6 +32,6 @@ offs.push(off);

}
return () => offs.forEach(x => x());
}, [...chain]);
useLayoutEffect(() => () => scope.offs.forEach(x => x()), []);
}
export { useChain };
//# sourceMappingURL=use-chain.js.map

@@ -1,6 +0,6 @@

import { useMemo, useLayoutEffect, useEffect } from '@dark-engine/core';
import { useMemo, useLayoutEffect } from '@dark-engine/core';
import { SharedState, getSharedState } from '../state';
import { Controller } from '../controller';
import { range } from '../utils';
function useSprings(count, configurator, deps) {
function useSprings(count, configurator, deps = []) {
const state = useMemo(() => getSharedState() || new SharedState(), []);

@@ -33,2 +33,3 @@ const scope = useMemo(() => {

return {
marker: 'spring-api',
start: fn => {

@@ -52,4 +53,4 @@ if (scope.inChain) {

}, []);
useEffect(() => {
if (!deps) return;
useLayoutEffect(() => {
if (deps.length === 0) return;
const { inChain } = scope;

@@ -61,3 +62,3 @@ if (inChain) {

}
}, deps || []);
}, [...deps]);
useLayoutEffect(() => () => api.cancel(), []);

@@ -64,0 +65,0 @@ return [springs, api];

@@ -15,2 +15,3 @@ import { useMemo } from '@dark-engine/core';

..._api,
marker: 'trail-api',
reverse: value => (value ? state.setFlow(Flow.LEFT) : state.setFlow(Flow.RIGHT)),

@@ -17,0 +18,0 @@ };

import {
Fragment,
batch,
useMemo,
useUpdate,
useEffect,
useLayoutEffect,
detectIsArray,
detectIsNumber,
startTransition,
scheduler,
} from '@dark-engine/core';
import { Controller } from '../controller';
import { SharedState } from '../state';
import { Controller } from '../controller';
import { uniq } from '../utils';
function useTransition(items, getKey, configurator) {
const forceUpdate = useUpdate();
const update = () => batch(forceUpdate);
const update = () => (scope.isNonBlocking ? startTransition(forceUpdate) : forceUpdate());
const state = useMemo(() => new SharedState(), []);
const scope = useMemo(
() => ({
transitions: [],
ctrlsMap: new Map(),

@@ -28,2 +29,3 @@ itemsMap: new Map(),

inChain: false,
isNonBlocking: false,
pending: null,

@@ -35,3 +37,26 @@ configurator,

scope.configurator = configurator;
useMemo(() => setup({ items, getKey, configurator, state, ctrlsMap: scope.ctrlsMap }), []);
scope.isNonBlocking = scheduler.detectIsTransition();
useMemo(() => {
const make = items => {
const { transitions, ctrlsMap, fakesMap, items: $items } = scope;
const configurator = (idx, item) => scope.configurator(idx, item);
const { ctrls, itemsMap } = setup({ items, getKey, configurator, state, ctrlsMap });
const { insMap, remMap, movMap, stabMap, replaced } = diff($items, items, getKey);
scope.hasReplaces = replaced.size > 0;
state.setCtrls(ctrls);
replaced.forEach(key => ctrlsMap.get(key).setIsReplaced(true));
transitions.push(
...animate({ action: Action.LEAVE, space: fakesMap, state, scope }),
...animate({ action: Action.ENTER, space: insMap, state, scope }),
...animate({ action: Action.LEAVE, space: remMap, state, scope }),
...animate({ action: Action.UPDATE, space: movMap, state, scope }),
...animate({ action: Action.UPDATE, space: stabMap, state, scope }),
);
state.setHasTransitions(transitions.length > 0);
scope.items = items;
scope.itemsMap = itemsMap;
scope.fromApi = false;
};
make(uniq(items, getKey));
}, [items]);
const transition = useMemo(

@@ -63,2 +88,3 @@ () => render => {

return {
marker: 'transition-api',
start: fn => {

@@ -69,2 +95,3 @@ scope.fromApi = true;

scope.pending = null;
update();
} else {

@@ -83,39 +110,27 @@ state.start(fn);

}, []);
useEffect(() => {
useLayoutEffect(() => {
if (scope.transitions.length === 0) return;
const { inChain } = scope;
const nextItems = uniq(items, getKey);
const start = items => {
const { ctrlsMap, fakesMap, items: $items } = scope;
const configurator = (idx, item) => scope.configurator(idx, item);
const { ctrls, itemsMap } = setup({ items, getKey, configurator, state, ctrlsMap });
const { hasChanges, insMap, remMap, movMap, stabMap, replaced } = diff($items, items, getKey);
scope.hasReplaces = replaced.size > 0;
state.setCtrls(ctrls);
replaced.forEach(key => ctrlsMap.get(key).setIsReplaced(true));
const start = () => {
state.event('series-start');
animate({ action: Action.LEAVE, space: fakesMap, state, scope });
animate({ action: Action.ENTER, space: insMap, state, scope });
animate({ action: Action.LEAVE, space: remMap, state, scope });
animate({ action: Action.UPDATE, space: movMap, state, scope });
animate({ action: Action.UPDATE, space: stabMap, state, scope });
scope.items = items;
scope.itemsMap = itemsMap;
scope.fromApi = false;
hasChanges && forceUpdate();
scope.transitions.forEach(x => x.fn());
scope.transitions = [];
state.setHasTransitions(false);
};
if (inChain) {
scope.pending = () => state.defer(() => start(nextItems));
scope.pending = () => state.defer(start);
} else {
start(nextItems);
start();
}
}, [items]);
});
useLayoutEffect(() => {
const offs = [];
offs.push(
const offs = [
api.on('item-end', e => handleItemEnd(e, scope)),
api.on('series-end', () => handleSeriesEnd(update, state, scope)),
);
return () => offs.forEach(x => x());
];
return () => {
offs.forEach(x => x());
api.cancel();
};
}, []);
useLayoutEffect(() => () => api.cancel(), []);
return [transition, api];

@@ -177,3 +192,2 @@ }

let n = 0;
let hasChanges = false;
const insMap = new Map();

@@ -193,6 +207,4 @@ const remMap = new Map();

replaced.add(prevKey);
hasChanges = true;
} else {
insMap.set(nextKey, i);
hasChanges = true;
p++;

@@ -203,3 +215,2 @@ size++;

remMap.set(prevKey, i);
hasChanges = true;
n++;

@@ -209,3 +220,2 @@ size++;

movMap.set(nextKey, i);
hasChanges = true;
}

@@ -217,3 +227,2 @@ } else if (nextKey !== null) {

return {
hasChanges,
insMap,

@@ -227,2 +236,3 @@ remMap,

function animate(options) {
const transitions = [];
const { space, action, state, scope } = options;

@@ -241,2 +251,3 @@ const { configurator, ctrlsMap, fakesMap } = scope;

let $ctrl = ctrl;
let $key = key;
if (isEnter) {

@@ -250,2 +261,3 @@ const isReplaced = ctrl.getIsReplaced();

$ctrl = fake;
$key = fakeKey;
prepare({ ctrl: fake, key: fakeKey, idx, item, configurator });

@@ -260,12 +272,15 @@ ctrlsMap.set(fakeKey, fake);

}
to && withTrail(() => $ctrl.start(() => ({ to })), $idx, trail);
const start = () => $ctrl.start(() => ({ to }));
const fn = to && withTrail(start, $idx, $ctrl, trail);
fn && transitions.push(new Transition($key, fn));
$idx++;
}
return transitions;
}
function withTrail(fn, idx, trail) {
function withTrail(start, idx, ctrl, trail) {
if (detectIsNumber(trail)) {
setTimeout(fn, idx * trail);
} else {
fn();
ctrl.setIsPlaying(true);
return () => setTimeout(start, idx * trail);
}
return start;
}

@@ -308,3 +323,3 @@ function prepare(options) {

ctrl.replaceValue({ ...enter });
ctrl.notify();
ctrl.notify(true);
ctrls.push(ctrl);

@@ -315,2 +330,10 @@ }

}
class Transition {
key;
fn;
constructor(key, fn) {
this.key = key;
this.fn = fn;
}
}
var Action;

@@ -317,0 +340,0 @@ (function (Action) {

@@ -0,5 +1,4 @@

import { illegal as $illegal } from '@dark-engine/core';
import { LIB } from '../constants';
const fix = (x, precision = 4) => Number(x.toFixed(precision));
const illegal = value => {
throw new Error(value);
};
const range = x =>

@@ -19,3 +18,4 @@ Array(x)

};
export { fix, illegal, range, uniq };
const illegal = x => $illegal(x, LIB);
export { fix, range, uniq, illegal };
//# sourceMappingURL=utils.js.map

@@ -1,2 +0,3 @@

export const VERSION = '1.2.0';
export const VERSION = '1.3.0';
export const LIB = '@dark-engine/native-navigation';
export const SLASH_MARK = '/';

@@ -3,0 +4,0 @@ export var TransitionName;

import { isAndroid, Application } from '@nativescript/core';
import { EventEmitter } from '@dark-engine/core';
import { normalizePathname } from '../utils';

@@ -6,3 +7,3 @@ class NavigationHistory {

cursor = -1;
subscribers = new Set();
emitter = new EventEmitter();
frame;

@@ -21,3 +22,3 @@ page;

this.dispose = () => {
this.subscribers.clear();
this.emitter = new EventEmitter();
this.stack = [];

@@ -29,3 +30,3 @@ this.cursor = -1;

this.dispose = () => {
this.subscribers.clear();
this.emitter = new EventEmitter();
this.stack = [];

@@ -37,5 +38,3 @@ this.cursor = -1;

mapSubscribers(action, options) {
for (const subscriber of this.subscribers) {
subscriber(this.getValue(), action, options);
}
this.emitter.emit('change', { pathname: this.getValue(), action, options });
}

@@ -64,5 +63,4 @@ getValue() {

}
subscribe(subscriber) {
this.subscribers.add(subscriber);
return () => this.subscribers.delete(subscriber);
subscribe(event, subscriber) {
return this.emitter.on(event, subscriber);
}

@@ -69,0 +67,0 @@ push(pathname, options) {

@@ -5,3 +5,2 @@ import { jsxs as _jsxs, jsx as _jsx } from '@dark-engine/core/jsx-runtime';

component,
forwardRef,
useRef,

@@ -22,96 +21,94 @@ useEffect,

import { normalizePathname } from '../utils';
const NavigationContainer = forwardRef(
component(
({ slot, defaultPathname = SLASH_MARK, renderActionBar, onNavigate }, ref) => {
const frameRef = useRef(null);
const pageRef = useRef(null);
const [pathname, setPathname] = useState(normalizePathname(defaultPathname));
const [transition, setTransition] = useState(null);
const scope = useMemo(
() => ({ history: null, inTransition: false, transitions: { forward: [], backward: [] } }),
[],
);
const {
transitions: { forward, backward },
} = scope;
useLayoutEffect(() => {
const history = createNavigationHistory(pathname, frameRef.current, pageRef.current);
const unsubscribe = history.subscribe((pathname, action, options) => {
const isReplace = action === HistoryAction.REPLACE;
const isBack = action === HistoryAction.BACK;
setPathname(pathname);
!isReplace && scheduleTransition(pathname, isBack, options);
detectIsFunction(onNavigate) && onNavigate(pathname);
});
scope.history = history;
return () => {
unsubscribe();
history.dispose();
const NavigationContainer = component(
({ slot, ref, defaultPathname = SLASH_MARK, renderActionBar, onNavigate }) => {
const frameRef = useRef(null);
const pageRef = useRef(null);
const [pathname, setPathname] = useState(normalizePathname(defaultPathname));
const [transition, setTransition] = useState(null);
const scope = useMemo(
() => ({ history: null, inTransition: false, transitions: { forward: [], backward: [] } }),
[],
);
const {
transitions: { forward, backward },
} = scope;
useLayoutEffect(() => {
const history = createNavigationHistory(pathname, frameRef.current, pageRef.current);
const unsubscribe = history.subscribe('change', ({ pathname, action, options }) => {
const isReplace = action === HistoryAction.REPLACE;
const isBack = action === HistoryAction.BACK;
setPathname(pathname);
!isReplace && scheduleTransition(pathname, isBack, options);
detectIsFunction(onNavigate) && onNavigate(pathname);
});
scope.history = history;
return () => {
unsubscribe();
history.dispose();
};
}, []);
useEffect(() => {
if (!transition) return;
const timeout = transition.options.animated ? transition.options.transition.duration : 0;
const timerId = setTimeout(() => {
scope.inTransition = false;
executeTransitions();
}, timeout + WAITING_TIMEOUT);
return () => clearTimeout(timerId);
}, [transition]);
const scheduleTransition = (to, isBack, options) => {
if (isBack) {
const transition = backward.pop();
forward.push(transition);
} else {
const from = scope.history.getBack();
const forwardTransition = {
from,
to,
isBack: false,
options: resolveNavigationOptions(options),
};
}, []);
useEffect(() => {
if (!transition) return;
const timeout = transition.options.animated ? transition.options.transition.duration : 0;
const timerId = setTimeout(() => {
scope.inTransition = false;
executeTransitions();
}, timeout + WAITING_TIMEOUT);
return () => clearTimeout(timerId);
}, [transition]);
const scheduleTransition = (to, isBack, options) => {
if (isBack) {
const transition = backward.pop();
forward.push(transition);
} else {
const from = scope.history.getBack();
const forwardTransition = {
from,
to,
isBack: false,
options: resolveNavigationOptions(options),
};
const backwardTransition = {
...forwardTransition,
isBack: true,
from: forwardTransition.to,
to: forwardTransition.from,
};
forward.push(forwardTransition);
backward.push(backwardTransition);
}
executeTransitions();
};
const executeTransitions = () => {
if (scope.inTransition) return;
const transition = forward.shift();
if (!transition) return setTransition(null);
scope.inTransition = true;
setTransition(transition);
};
const push = useEvent((pathname, options) => scope.history.push(pathname, options));
const replace = useEvent(pathname => scope.history.replace(pathname));
const back = useEvent(() => scope.history.back());
const getParams = useEvent(pathname => (scope.history ? scope.history.getParams(pathname) : null));
const subscribe = useEvent(subscriber => scope.history.subscribe(subscriber));
const contextValue = useMemo(
() => ({ pathname, transition, push, replace, back, getParams, subscribe }),
[pathname, transition],
);
useImperativeHandle(ref, () => ({ navigateTo: push, goBack: back }), []);
const hasActionBar = detectIsFunction(renderActionBar);
return _jsxs(NavigationContext.Provider, {
value: contextValue,
children: [
_jsx(Frame, {
children: _jsxs(Page, {
actionBarHidden: !hasActionBar,
children: [hasActionBar && renderActionBar({ pathname, goBack: back }), slot],
}),
const backwardTransition = {
...forwardTransition,
isBack: true,
from: forwardTransition.to,
to: forwardTransition.from,
};
forward.push(forwardTransition);
backward.push(backwardTransition);
}
executeTransitions();
};
const executeTransitions = () => {
if (scope.inTransition) return;
const transition = forward.shift();
if (!transition) return setTransition(null);
scope.inTransition = true;
setTransition(transition);
};
const push = useEvent((pathname, options) => scope.history.push(pathname, options));
const replace = useEvent(pathname => scope.history.replace(pathname));
const back = useEvent(() => scope.history.back());
const getParams = useEvent(pathname => (scope.history ? scope.history.getParams(pathname) : null));
const subscribe = useEvent((event, subscriber) => scope.history.subscribe(event, subscriber));
const contextValue = useMemo(
() => ({ pathname, transition, push, replace, back, getParams, subscribe }),
[pathname, transition],
);
useImperativeHandle(ref, () => ({ navigateTo: push, goBack: back }), []);
const hasActionBar = detectIsFunction(renderActionBar);
return _jsxs(NavigationContext.Provider, {
value: contextValue,
children: [
_jsx(Frame, {
children: _jsxs(Page, {
actionBarHidden: !hasActionBar,
children: [hasActionBar && renderActionBar({ pathname, goBack: back }), slot],
}),
_jsx(Frame, { ref: frameRef, hidden: true, children: _jsx(Page, { ref: pageRef, actionBarHidden: true }) }),
],
});
},
{ displayName: 'NavigationContainer' },
),
}),
_jsx(Frame, { ref: frameRef, hidden: true, children: _jsx(Page, { ref: pageRef, actionBarHidden: true }) }),
],
});
},
{ displayName: 'NavigationContainer' },
);

@@ -118,0 +115,0 @@ const NavigationContext = createContext(null);

@@ -7,3 +7,2 @@ import { jsx as _jsx } from '@dark-engine/core/jsx-runtime';

detectIsFunction,
forwardRef,
memo,

@@ -15,3 +14,2 @@ useContext,

useRef,
useImperativeHandle,
} from '@dark-engine/core';

@@ -23,62 +21,59 @@ import { AbsoluteLayout, StackLayout } from '@dark-engine/platform-native';

const visitedMap = {};
const Navigator = forwardRef(
component(
({ slot, onNavigate }, ref) => {
const { pathname, transition, replace, subscribe } = useNavigationContext();
const { prefix } = useScreenNavigatorContext();
const rootRef = useRef(null);
const names = slot.map(x => x.props.name);
const pathnames = names.map(x => createPathname(x, prefix));
const scope = useMemo(() => ({ refsMap: {} }), []);
const hiddensMap = useMemo(() => createHiddensMap({ transition, pathnames, pathname, prefix }), [transition]);
visitedMap[pathname] = true;
useLayoutEffect(() => {
const entry = pathnames[0];
detectCanReplacePathname(pathname, entry, prefix) && replace(entry);
}, [pathname]);
useLayoutEffect(() => {
const canStartTransition = detectCanStartTransition(transition, pathnames, prefix);
if (!canStartTransition || !transition.options.animated) return;
const targetFrom = matchRef(scope.refsMap, transition.from);
const targetTo = matchRef(scope.refsMap, transition.to);
const size = rootRef.current.getActualSize();
const animation = createAnimation({ targetFrom, targetTo, transition, size });
setTimeout(() => {
animation.play().then(() => {
targetFrom.opacity = 0;
targetFrom.translateX = 0;
targetFrom.hidden = true;
targetTo.opacity = 1;
targetTo.translateX = 0;
targetTo.hidden = false;
setTimeout(() => {
targetFrom.opacity = 1;
});
const Navigator = component(
({ slot, onNavigate }) => {
const { pathname, transition, replace, subscribe } = useNavigationContext();
const { prefix } = useScreenNavigatorContext();
const rootRef = useRef(null);
const names = slot.map(x => x.props.name);
const pathnames = names.map(x => createPathname(x, prefix));
const scope = useMemo(() => ({ refsMap: {} }), []);
const hiddensMap = useMemo(() => createHiddensMap({ transition, pathnames, pathname, prefix }), [transition]);
visitedMap[pathname] = true;
useLayoutEffect(() => {
const entry = pathnames[0];
detectCanReplacePathname(pathname, entry, prefix) && replace(entry);
}, [pathname]);
useLayoutEffect(() => {
const canStartTransition = detectCanStartTransition(transition, pathnames, prefix);
if (!canStartTransition || !transition.options.animated) return;
const targetFrom = matchRef(scope.refsMap, transition.from);
const targetTo = matchRef(scope.refsMap, transition.to);
const size = rootRef.current.getActualSize();
const animation = createAnimation({ targetFrom, targetTo, transition, size });
setTimeout(() => {
animation.play().then(() => {
targetFrom.opacity = 0;
targetFrom.translateX = 0;
targetFrom.hidden = true;
targetTo.opacity = 1;
targetTo.translateX = 0;
targetTo.hidden = false;
setTimeout(() => {
targetFrom.opacity = 1;
});
});
}, [transition]);
useEffect(() => {
const syncNavigation = pathname => detectIsFunction(onNavigate) && onNavigate(pathname);
syncNavigation(pathname);
const unsubscribe = subscribe(pathname => syncNavigation(pathname));
return () => unsubscribe();
}, []);
useImperativeHandle(ref, () => ({}));
return _jsx(AbsoluteLayout, {
ref: rootRef,
width: FULL,
height: FULL,
children: slot.map(x => {
const name = x.props.name;
const key = createPathname(name, prefix);
const isHidden = Boolean(hiddensMap[key]);
const setRef = ref => {
scope.refsMap[key] = ref;
};
return _jsx(StackLayout, { ref: setRef, width: FULL, height: FULL, hidden: isHidden, children: x }, key);
}),
});
},
{ displayName: 'StackNavigator.Root' },
),
}, [transition]);
useEffect(() => {
const syncNavigation = pathname => detectIsFunction(onNavigate) && onNavigate(pathname);
syncNavigation(pathname);
const unsubscribe = subscribe('change', ({ pathname }) => syncNavigation(pathname));
return () => unsubscribe();
}, []);
return _jsx(AbsoluteLayout, {
ref: rootRef,
width: FULL,
height: FULL,
children: slot.map(x => {
const name = x.props.name;
const key = createPathname(name, prefix);
const isHidden = Boolean(hiddensMap[key]);
const setRef = ref => {
scope.refsMap[key] = ref;
};
return _jsx(StackLayout, { ref: setRef, width: FULL, height: FULL, hidden: isHidden, children: x }, key);
}),
});
},
{ displayName: 'StackNavigator.Root' },
);

@@ -85,0 +80,0 @@ const Screen = component(

@@ -20,3 +20,2 @@ import { jsx as _jsx, jsxs as _jsxs } from '@dark-engine/core/jsx-runtime';

({ bottomNavigationOptions, slot }) => {
const navRef = useRef(null);
const layoutRef = useRef(null);

@@ -67,3 +66,2 @@ const bottomRef = useRef(null);

_jsx(StackNavigator.Root, {
ref: navRef,
children: descriptorKeys.map(key => {

@@ -70,0 +68,0 @@ const { component, slot } = descriptorsMap[key];

@@ -1,8 +0,6 @@

import { SLASH_MARK } from '../constants';
const createPathname = (name, prefix) => {
return normalizePathname(`${prefix}${name}`);
};
import { illegal as $illegal } from '@dark-engine/core';
import { SLASH_MARK, LIB } from '../constants';
const createPathname = (name, prefix) => normalizePathname(`${prefix}${name}`);
function normalizePathname(pathname) {
const normal = prependSlash(pathname.split(SLASH_MARK).filter(Boolean).join(SLASH_MARK) + SLASH_MARK);
return normal;
return prependSlash(pathname.split(SLASH_MARK).filter(Boolean).join(SLASH_MARK) + SLASH_MARK);
}

@@ -13,4 +11,3 @@ function prependSlash(pathname) {

function getSegments(pathname, prefix) {
const segments = pathname.replace(prefix, '').split(SLASH_MARK).filter(Boolean);
return segments;
return pathname.replace(prefix, '').split(SLASH_MARK).filter(Boolean);
}

@@ -26,6 +23,6 @@ function detectIsVisited(map, pathname) {

function detectIsMatch(currentPathname, pathname) {
const isMatch = currentPathname.indexOf(pathname) !== -1;
return isMatch;
return currentPathname.indexOf(pathname) !== -1;
}
export { createPathname, normalizePathname, prependSlash, getSegments, detectIsVisited, detectIsMatch };
const illegal = x => $illegal(x, LIB);
export { createPathname, normalizePathname, prependSlash, getSegments, detectIsVisited, detectIsMatch, illegal };
//# sourceMappingURL=utils.js.map
import { type Component, type TagVirtualNodeFactory } from '@dark-engine/core';
import { type SpringValue } from '../shared';
import { type Spring } from '../spring';
declare const Animated: import('@dark-engine/core').ComponentFactory<
{
spring: Spring<string>;
fn: StyleFn<unknown, string>;
slot: Component | TagVirtualNodeFactory;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
},
unknown
>;
declare const Animated: import('@dark-engine/core').ComponentFactory<{
spring: Spring<string>;
fn: StyleFn<unknown, string>;
slot: Component | TagVirtualNodeFactory;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
}>;
type StyleFn<E = unknown, T extends string = string> = (element: E, value: SpringValue<T>) => void;
export { Animated };

@@ -1,1 +0,2 @@

export declare const VERSION = '1.2.0';
export declare const VERSION = '1.3.0';
export declare const LIB = '@dark-engine/animations';

@@ -38,3 +38,3 @@ import { type ElementKey } from '@dark-engine/core';

setRight(x: Controller<T>): void;
notify(): void;
notify(skip?: boolean): void;
setConfigurator(fn: ConfiguratorFn<T>): void;

@@ -41,0 +41,0 @@ setImmediate(fn: ImmediateFn<T>): void;

import { type SpringConfig } from '../shared';
type Preset = Pick<SpringConfig, 'tension' | 'friction'>;
type PresetName = 'no-wobble' | 'gentle' | 'wobbly' | 'stiff';
type PresetName = 'no-wobble' | 'gentle' | 'wobbly' | 'stiff' | 'slow' | 'molasses';
declare function preset(name: PresetName): Preset;
export { preset };

@@ -13,3 +13,5 @@ import { type ElementKey } from '@dark-engine/core';

private timerId;
private events;
private emitter;
private hasTransitions;
setHasTransitions(x: boolean): void;
getCtrls(): Controller<T, unknown>[];

@@ -32,3 +34,3 @@ setCtrls(ctrls: Array<Controller<T>>): void;

on(event: AnimationEventName, handler: AnimationEventHandler<T>): () => boolean;
event(name: AnimationEventName, value?: AnimationEventValue<T>): void;
event(event: AnimationEventName, value?: AnimationEventValue<T>): void;
completeSeries(): void;

@@ -35,0 +37,0 @@ defer(fn: () => void): void;

import { type SpringApi } from '../use-springs';
type Api = Pick<SpringApi, 'start' | 'chain' | 'delay' | 'on'>;
type Api = Pick<SpringApi, 'marker' | 'start' | 'chain' | 'delay' | 'on'>;
declare function useChain(chain: Array<Api>, timesteps?: Array<number>, timeframe?: number): void;
export { useChain };

@@ -12,2 +12,3 @@ import { type AnimationEventName, type AnimationEventHandler } from '../state';

export type SpringApi<T extends string = string> = {
marker: string;
start: (fn?: StartFn<T>) => void;

@@ -20,5 +21,5 @@ chain: (value: boolean) => void;

cancel: () => void;
on: (event: AnimationEventName, handler: AnimationEventHandler<T>) => () => void;
on: (event: AnimationEventName, handler: AnimationEventHandler<T>) => () => boolean;
isCanceled: () => void;
};
export { useSprings };
import { type Component, type TagVirtualNodeFactory, type ElementKey } from '@dark-engine/core';
import { type SpringValue } from '../shared';
import { type BaseItemConfig } from '../controller';
import { type SpringApi } from '../use-springs';
import { type SpringValue } from '../shared';
import { type Spring } from '../spring';

@@ -6,0 +6,0 @@ export type TransitionItemConfig<T extends string> = {

declare const fix: (x: number, precision?: number) => number;
declare const illegal: (value: string) => never;
declare const range: (x: number) => number[];
declare const uniq: <T>(items: T[], selector: (x: T) => unknown) => T[];
export { fix, illegal, range, uniq };
declare const illegal: (x: string) => void;
export { fix, range, uniq, illegal };

@@ -1,2 +0,3 @@

export declare const VERSION = '1.2.0';
export declare const VERSION = '1.3.0';
export declare const LIB = '@dark-engine/native-navigation';
export declare const SLASH_MARK = '/';

@@ -3,0 +4,0 @@ export declare enum TransitionName {

import { type Frame, type Page } from '@nativescript/core';
import { type SubscriberWithValue } from '@dark-engine/core';
import { type NavigationOptions } from '../navigation-container';

@@ -6,3 +7,3 @@ declare class NavigationHistory {

private cursor;
private subscribers;
private emitter;
private frame;

@@ -18,3 +19,3 @@ private page;

getParams(pathname: string): ParamsMap;
subscribe(subscriber: HistorySubscriber): () => boolean;
subscribe(event: HistoryEvent, subscriber: SubscriberWithValue<HistoryValue>): () => boolean;
push(pathname: string, options?: NavigationOptions): void;

@@ -24,3 +25,8 @@ replace(pathname: string): void;

}
export type HistorySubscriber = (pathname: string, action: HistoryAction, options?: NavigationOptions) => void;
export type HistoryEvent = 'change';
export type HistoryValue = {
pathname: string;
action: HistoryAction;
options?: NavigationOptions;
};
export declare enum HistoryAction {

@@ -27,0 +33,0 @@ PUSH = 'PUSH',

@@ -1,3 +0,3 @@

import { type DarkElement } from '@dark-engine/core';
import { type HistorySubscriber, type ParamsMap, type ParamsObject } from '../history';
import { type DarkElement, type Ref, type SubscriberWithValue } from '@dark-engine/core';
import { type HistoryEvent, type HistoryValue, type ParamsMap, type ParamsObject } from '../history';
import { TransitionName } from '../constants';

@@ -12,13 +12,10 @@ export type NavigationContainerRef = {

};
declare const NavigationContainer: import('@dark-engine/core').ComponentFactory<
{
slot: DarkElement;
defaultPathname: string;
renderActionBar?: (options: RenderActionBarOptions) => DarkElement;
onNavigate?: (pathname: string) => void;
ref?: import('@dark-engine/core').Ref<NavigationContainerRef>;
key?: import('@dark-engine/core').ElementKey;
},
NavigationContainerRef
>;
declare const NavigationContainer: import('@dark-engine/core').ComponentFactory<{
ref?: Ref<NavigationContainerRef> & Ref<unknown>;
slot: DarkElement;
defaultPathname: string;
renderActionBar?: (options: RenderActionBarOptions) => DarkElement;
onNavigate?: (pathname: string) => void;
key?: import('@dark-engine/core').ElementKey;
}>;
export type Transition = {

@@ -50,5 +47,5 @@ from: string;

getParams: (pathname: string) => ParamsMap;
subscribe: (subscriber: HistorySubscriber) => () => void;
subscribe: (event: HistoryEvent, subscriber: SubscriberWithValue<HistoryValue>) => () => boolean;
};
declare function useNavigationContext(): NavigationContextValue;
export { NavigationContainer, useNavigationContext };

@@ -12,3 +12,2 @@ import {

};
export type StackNavigatorRef = {};
export type StackScreenProps = {

@@ -21,23 +20,16 @@ name: string;

declare const StackNavigator: {
Root: ComponentFactory<
{
slot: Array<ScreenComponent>;
onNavigate?: (pathname: string) => void;
ref?: import('@dark-engine/core').Ref<StackNavigatorRef>;
key?: import('@dark-engine/core').ElementKey;
} & Omit<StandardComponentProps, 'ref'> &
import('@dark-engine/core').RefProps<StackNavigatorRef>,
StackNavigatorRef
>;
Screen: ComponentFactory<
{
name: string;
component?: ComponentFactory;
initialParams?: ParamsObject;
slot?: () => DarkElement;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
},
unknown
>;
Root: ComponentFactory<{
slot: Array<ScreenComponent>;
onNavigate?: (pathname: string) => void;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
}>;
Screen: ComponentFactory<{
name: string;
component?: ComponentFactory;
initialParams?: ParamsObject;
slot?: () => DarkElement;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
}>;
};

@@ -44,0 +36,0 @@ type ScreenNavigatorContextValue = {

@@ -19,25 +19,18 @@ import { type DarkElement, type Component, type StandardComponentProps } from '@dark-engine/core';

declare const TabNavigator: {
Root: import('@dark-engine/core').ComponentFactory<
{
bottomNavigationOptions?: Partial<BottomNavigationOptions>;
slot: Array<Component<TabScreenProps & StandardComponentProps>>;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
} & Omit<StandardComponentProps, 'ref'> &
import('@dark-engine/core').RefProps<unknown>,
unknown
>;
Screen: import('@dark-engine/core').ComponentFactory<
{
renderTab?: (name: string, isActive: boolean) => DarkElement;
name: string;
component?: import('@dark-engine/core').ComponentFactory;
initialParams?: import('../history').ParamsObject;
slot?: () => DarkElement;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
},
unknown
>;
Root: import('@dark-engine/core').ComponentFactory<{
bottomNavigationOptions?: Partial<BottomNavigationOptions>;
slot: Array<Component<TabScreenProps & StandardComponentProps>>;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
}>;
Screen: import('@dark-engine/core').ComponentFactory<{
renderTab?: (name: string, isActive: boolean) => DarkElement;
name: string;
component?: import('@dark-engine/core').ComponentFactory;
initialParams?: import('../history').ParamsObject;
slot?: () => DarkElement;
key?: import('@dark-engine/core').ElementKey;
ref?: import('@dark-engine/core').Ref<unknown>;
}>;
};
export { TabNavigator };

@@ -0,3 +1,3 @@

import { type Push, type Back } from '../navigation-container';
import { type ParamsMap } from '../history';
import { type Push, type Back } from '../navigation-container';
type Navigation = {

@@ -4,0 +4,0 @@ match: {

@@ -7,2 +7,3 @@ declare const createPathname: (name: string, prefix: string) => string;

declare function detectIsMatch(currentPathname: string, pathname: string): boolean;
export { createPathname, normalizePathname, prependSlash, getSegments, detectIsVisited, detectIsMatch };
declare const illegal: (x: string) => void;
export { createPathname, normalizePathname, prependSlash, getSegments, detectIsVisited, detectIsMatch, illegal };
{
"name": "@dark-engine/native-navigation",
"version": "1.2.0",
"version": "1.3.0",
"description": "Dark navigation for NativeScript platform",

@@ -37,3 +37,3 @@ "author": "AlexPlex",

"devDependencies": {
"@nativescript/core": "8.6.2"
"@nativescript/core": "8.7.2"
},

@@ -40,0 +40,0 @@ "peerDependencies": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc