Comparing version 0.9.31 to 0.9.32
{ | ||
"name": "aurumjs", | ||
"version": "0.9.31", | ||
"version": "0.9.32", | ||
"main": "prebuilt/esnext/aurumjs.js", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -10,2 +10,3 @@ export * from './rendering/webcomponent.js'; | ||
export { aurumToVDOM, VDOM, VDOMNode } from './rendering/renderers/vdom_adapter.js'; | ||
export * from './builtin_components/lazy.js'; | ||
export * from './builtin_components/router.js'; | ||
@@ -12,0 +13,0 @@ export * from './builtin_components/suspense.js'; |
@@ -6,2 +6,3 @@ export * from './rendering/webcomponent.js'; | ||
export { aurumToVDOM, VDOM } from './rendering/renderers/vdom_adapter.js'; | ||
export * from './builtin_components/lazy.js'; | ||
export * from './builtin_components/router.js'; | ||
@@ -8,0 +9,0 @@ export * from './builtin_components/suspense.js'; |
@@ -1,5 +0,8 @@ | ||
import { AurumComponentAPI, Renderable } from '../rendering/aurum_element.js'; | ||
import { AurumComponentAPI, AurumElementModel, Renderable } from '../rendering/aurum_element.js'; | ||
import { DataSource } from '../stream/data_source.js'; | ||
export declare function AurumRouter(props: { | ||
hashRouting?: boolean; | ||
urlPreprocessing?: (url: string) => string; | ||
validateNavigation?: (url: string, route: AurumElementModel<RouteProps>) => boolean; | ||
urlProvider?: DataSource<string>; | ||
}, children: Renderable[], api: AurumComponentAPI): DataSource<Renderable[]>; | ||
@@ -6,0 +9,0 @@ export interface RouteProps { |
import { DataSource } from '../stream/data_source.js'; | ||
import { dsDiff, dsMap, dsTap, dsUnique } from '../stream/data_source_operators.js'; | ||
import { urlHashEmitter } from '../stream/emitters.js'; | ||
import { dsDiff, dsFilter, dsMap, dsTap, dsUnique } from '../stream/data_source_operators.js'; | ||
import { urlHashEmitter, urlPathEmitter } from '../stream/emitters.js'; | ||
import { resolveChildren } from '../utilities/transclusion.js'; | ||
@@ -26,3 +26,6 @@ export function AurumRouter(props, children, api) { | ||
const urlDataSource = new DataSource(); | ||
if (typeof window !== 'undefined') { | ||
if (props.urlProvider) { | ||
props.urlProvider.pipe(urlDataSource, api.cancellationToken); | ||
} | ||
else if (typeof window !== 'undefined') { | ||
if (props.hashRouting) { | ||
@@ -33,11 +36,3 @@ urlHashEmitter(urlDataSource, true, api.cancellationToken); | ||
urlDataSource.update(window.location.pathname); | ||
window.addEventListener('popstate', () => { | ||
urlDataSource.update(window.location.pathname); | ||
}); | ||
window.addEventListener('pushstate', () => { | ||
urlDataSource.update(window.location.pathname); | ||
}); | ||
window.addEventListener('replacestate', () => { | ||
urlDataSource.update(window.location.pathname); | ||
}); | ||
urlPathEmitter(urlDataSource, api.cancellationToken); | ||
} | ||
@@ -57,5 +52,5 @@ } | ||
.withInitial(urlDataSource.value) | ||
.transform(dsMap((p) => selectRoute(p, resolvedChildren, activeRoute))); | ||
.transform(dsMap((url) => (props.urlPreprocessing ? props.urlPreprocessing(url) : url)), dsMap((path) => ({ path, route: selectRoute(path, resolvedChildren) })), dsFilter((r) => (props.validateNavigation ? props.validateNavigation(r.path, r.route) : true)), dsTap((r) => activeRoute.update(r.route)), dsMap((r) => r.route.children)); | ||
} | ||
function selectRoute(url, routes, activeRoute) { | ||
function selectRoute(url, routes) { | ||
let selected; | ||
@@ -85,10 +80,3 @@ if (url === undefined || url === null) { | ||
} | ||
if (selected) { | ||
activeRoute.update(selected); | ||
return selected.children; | ||
} | ||
else { | ||
activeRoute.update(undefined); | ||
return undefined; | ||
} | ||
return selected; | ||
} | ||
@@ -95,0 +83,0 @@ export function Route(props, children) { |
@@ -180,3 +180,3 @@ import { ArrayDataSource, DataSource } from '../stream/data_source.js'; | ||
else { | ||
throw new Error('not implemented'); | ||
throw invalidRenderableError(child); | ||
} | ||
@@ -196,3 +196,3 @@ } | ||
else { | ||
throw new Error('not implemented'); | ||
throw invalidRenderableError(child); | ||
} | ||
@@ -207,2 +207,24 @@ } | ||
} | ||
function invalidRenderableError(child) { | ||
return new Error(`Aurum was given an unsupported type to render "${child?.constructor?.name ?? typeof child}". This can happen if you pass a component function directly to Aurum instead of "rendering" it using JSX syntax or Aurum.factory | ||
Example: | ||
// Wrong | ||
<div> | ||
{LoginComponent} | ||
</div> | ||
vs | ||
// Correct | ||
<div> | ||
<LoginComponent/> | ||
</div> | ||
or | ||
// Correct | ||
<div> | ||
{Aurum.factory(LoginComponent, {})} | ||
</div>`); | ||
} | ||
/** | ||
@@ -209,0 +231,0 @@ * @internal |
@@ -10,3 +10,4 @@ import { DataSource, ArrayDataSource } from './data_source.js'; | ||
export declare function intervalEmitter<T = void>(target: DataSource<T> | DuplexDataSource<T> | Stream<T, any> | ArrayDataSource<T>, interval: number, value: T, cancellationToken?: CancellationToken): void; | ||
export declare function urlHashEmitter(target: DataSource<string> | DuplexDataSource<string> | Stream<string, any> | ArrayDataSource<string>, stripInHashParameters?: boolean, cancellationToken?: CancellationToken): void; | ||
export declare function urlPathEmitter(target: DataSource<string> | DuplexDataSource<string> | Stream<string, any> | ArrayDataSource<string> | ((path: string) => void), cancellationToken?: CancellationToken): void; | ||
export declare function urlHashEmitter(target: DataSource<string> | DuplexDataSource<string> | Stream<string, any> | ArrayDataSource<string> | ((path: string) => void), stripInHashParameters?: boolean, cancellationToken?: CancellationToken): void; | ||
/** | ||
@@ -13,0 +14,0 @@ * Convenience function to stream the window size to a data source |
@@ -6,2 +6,3 @@ import { DataSource, ArrayDataSource } from './data_source.js'; | ||
import { dsDebounce, dsTap } from './data_source_operators.js'; | ||
import { EventEmitter } from '../aurumjs.js'; | ||
/** | ||
@@ -22,2 +23,5 @@ * Convenience function to update a stream at fixed intervals | ||
} | ||
else if (typeof target === 'function') { | ||
target(value); | ||
} | ||
else { | ||
@@ -27,2 +31,28 @@ target.update(value); | ||
} | ||
export function urlPathEmitter(target, cancellationToken) { | ||
observeHistory(); | ||
historyEvent.subscribe(() => { | ||
updateSource(target, location.pathname); | ||
}, cancellationToken); | ||
} | ||
let historyEvent; | ||
function observeHistory() { | ||
if (historyEvent) { | ||
return; | ||
} | ||
historyEvent = new EventEmitter(); | ||
const originalReplaceState = history.replaceState.bind(history); | ||
const originalPushState = history.pushState.bind(history); | ||
window.addEventListener('popstate', () => { | ||
historyEvent.fire(); | ||
}); | ||
history.replaceState = (...args) => { | ||
originalReplaceState.apply(history, args); | ||
historyEvent.fire(); | ||
}; | ||
history.pushState = (...args) => { | ||
originalPushState.apply(history, args); | ||
historyEvent.fire(); | ||
}; | ||
} | ||
export function urlHashEmitter(target, stripInHashParameters = false, cancellationToken) { | ||
@@ -29,0 +59,0 @@ updateSource(target, stripInHashParameters ? getUrlHash() : location.hash); |
export declare enum OperationType { | ||
FILTER = 0, | ||
CLOSE = 1, | ||
NOOP = 2, | ||
MAP = 3, | ||
DELAY = 4, | ||
MAP_DELAY = 5, | ||
DELAY_FILTER = 6, | ||
MAP_DELAY_FILTER = 7 | ||
NOOP = 1, | ||
MAP = 2, | ||
DELAY = 3, | ||
MAP_DELAY = 4, | ||
DELAY_FILTER = 5, | ||
MAP_DELAY_FILTER = 6 | ||
} | ||
@@ -11,0 +10,0 @@ interface SourceOperator { |
export var OperationType; | ||
(function (OperationType) { | ||
OperationType[OperationType["FILTER"] = 0] = "FILTER"; | ||
OperationType[OperationType["CLOSE"] = 1] = "CLOSE"; | ||
OperationType[OperationType["NOOP"] = 2] = "NOOP"; | ||
OperationType[OperationType["MAP"] = 3] = "MAP"; | ||
OperationType[OperationType["DELAY"] = 4] = "DELAY"; | ||
OperationType[OperationType["MAP_DELAY"] = 5] = "MAP_DELAY"; | ||
OperationType[OperationType["DELAY_FILTER"] = 6] = "DELAY_FILTER"; | ||
OperationType[OperationType["MAP_DELAY_FILTER"] = 7] = "MAP_DELAY_FILTER"; | ||
OperationType[OperationType["NOOP"] = 1] = "NOOP"; | ||
OperationType[OperationType["MAP"] = 2] = "MAP"; | ||
OperationType[OperationType["DELAY"] = 3] = "DELAY"; | ||
OperationType[OperationType["MAP_DELAY"] = 4] = "MAP_DELAY"; | ||
OperationType[OperationType["DELAY_FILTER"] = 5] = "DELAY_FILTER"; | ||
OperationType[OperationType["MAP_DELAY_FILTER"] = 6] = "MAP_DELAY_FILTER"; | ||
})(OperationType || (OperationType = {})); | ||
//# sourceMappingURL=operator_model.js.map |
@@ -0,1 +1,2 @@ | ||
import { urlHashEmitter, urlPathEmitter } from '../aurumjs.js'; | ||
export class UrlStorage { | ||
@@ -8,3 +9,3 @@ state; | ||
this.observeUrl(); | ||
window.addEventListener('hashchange', () => this.checkUpdate()); | ||
urlHashEmitter(() => this.checkUpdate()); | ||
this.checkUpdate(); | ||
@@ -14,6 +15,5 @@ } | ||
this.originalReplaceState = history.replaceState.bind(history); | ||
history.replaceState = (...args) => { | ||
this.originalReplaceState.apply(history, args); | ||
urlPathEmitter(() => { | ||
this.checkUpdate(); | ||
}; | ||
}); | ||
} | ||
@@ -20,0 +20,0 @@ get length() { |
@@ -79,2 +79,3 @@ export * from './rendering/webcomponent.js'; | ||
export * from './builtin_components/lazy.js'; | ||
export * from './builtin_components/router.js'; | ||
@@ -81,0 +82,0 @@ export * from './builtin_components/suspense.js'; |
import { AurumComponentAPI, AurumElementModel, Renderable } from '../rendering/aurum_element.js'; | ||
import { DataSource, ReadOnlyArrayDataSource } from '../stream/data_source.js'; | ||
import { dsDiff, dsMap, dsTap, dsUnique } from '../stream/data_source_operators.js'; | ||
import { urlHashEmitter } from '../stream/emitters.js'; | ||
import { dsDiff, dsFilter, dsMap, dsTap, dsUnique } from '../stream/data_source_operators.js'; | ||
import { urlHashEmitter, urlPathEmitter } from '../stream/emitters.js'; | ||
import { resolveChildren } from '../utilities/transclusion.js'; | ||
@@ -10,2 +10,6 @@ | ||
hashRouting?: boolean; | ||
urlPreprocessing?: (url: string) => string; | ||
validateNavigation?: (url: string, route: AurumElementModel<RouteProps>) => boolean; | ||
// For server side rendering or other cases where the url is not available from the browser. Can be useful for testing | ||
urlProvider?: DataSource<string>; | ||
}, | ||
@@ -40,3 +44,5 @@ children: Renderable[], | ||
if (typeof window !== 'undefined') { | ||
if (props.urlProvider) { | ||
props.urlProvider.pipe(urlDataSource, api.cancellationToken); | ||
} else if (typeof window !== 'undefined') { | ||
if (props.hashRouting) { | ||
@@ -46,11 +52,3 @@ urlHashEmitter(urlDataSource, true, api.cancellationToken); | ||
urlDataSource.update(window.location.pathname); | ||
window.addEventListener('popstate', () => { | ||
urlDataSource.update(window.location.pathname); | ||
}); | ||
window.addEventListener('pushstate', () => { | ||
urlDataSource.update(window.location.pathname); | ||
}); | ||
window.addEventListener('replacestate', () => { | ||
urlDataSource.update(window.location.pathname); | ||
}); | ||
urlPathEmitter(urlDataSource, api.cancellationToken); | ||
} | ||
@@ -77,11 +75,13 @@ } | ||
.withInitial(urlDataSource.value) | ||
.transform(dsMap((p) => selectRoute(p, resolvedChildren, activeRoute))); | ||
.transform( | ||
dsMap((url) => (props.urlPreprocessing ? props.urlPreprocessing(url) : url)), | ||
dsMap((path) => ({ path, route: selectRoute(path, resolvedChildren) })), | ||
dsFilter((r) => (props.validateNavigation ? props.validateNavigation(r.path, r.route) : true)), | ||
dsTap((r) => activeRoute.update(r.route)), | ||
dsMap((r) => r.route.children) | ||
); | ||
} | ||
function selectRoute( | ||
url: string, | ||
routes: ReadOnlyArrayDataSource<AurumElementModel<RouteProps>>, | ||
activeRoute: DataSource<AurumElementModel<RouteProps>> | ||
): Renderable[] { | ||
let selected; | ||
function selectRoute(url: string, routes: ReadOnlyArrayDataSource<AurumElementModel<RouteProps>>): AurumElementModel<RouteProps> { | ||
let selected: AurumElementModel<RouteProps>; | ||
if (url === undefined || url === null) { | ||
@@ -109,9 +109,3 @@ selected = routes.find((r) => r.factory === DefaultRoute); | ||
if (selected) { | ||
activeRoute.update(selected); | ||
return selected.children; | ||
} else { | ||
activeRoute.update(undefined); | ||
return undefined; | ||
} | ||
return selected; | ||
} | ||
@@ -118,0 +112,0 @@ |
@@ -254,3 +254,3 @@ import { ArrayDataSource, CollectionChange, DataSource, ReadOnlyArrayDataSource, ReadOnlyDataSource } from '../stream/data_source.js'; | ||
} else { | ||
throw new Error('not implemented'); | ||
throw invalidRenderableError(child); | ||
} | ||
@@ -267,3 +267,3 @@ } else { | ||
} else { | ||
throw new Error('not implemented'); | ||
throw invalidRenderableError(child); | ||
} | ||
@@ -288,2 +288,27 @@ } | ||
function invalidRenderableError(child: never) { | ||
return new Error(`Aurum was given an unsupported type to render "${ | ||
(child as any)?.constructor?.name ?? typeof child | ||
}". This can happen if you pass a component function directly to Aurum instead of "rendering" it using JSX syntax or Aurum.factory | ||
Example: | ||
// Wrong | ||
<div> | ||
{LoginComponent} | ||
</div> | ||
vs | ||
// Correct | ||
<div> | ||
<LoginComponent/> | ||
</div> | ||
or | ||
// Correct | ||
<div> | ||
{Aurum.factory(LoginComponent, {})} | ||
</div>`); | ||
} | ||
/** | ||
@@ -290,0 +315,0 @@ * @internal |
@@ -7,2 +7,3 @@ import { DataSource, ArrayDataSource } from './data_source.js'; | ||
import { dsDebounce, dsTap } from './data_source_operators.js'; | ||
import { EventEmitter } from '../aurumjs.js'; | ||
@@ -23,3 +24,3 @@ /** | ||
function updateSource<T = void>(target: DataSource<T> | DuplexDataSource<T> | Stream<T, any> | ArrayDataSource<T>, value: T) { | ||
function updateSource<T = void>(target: DataSource<T> | DuplexDataSource<T> | Stream<T, any> | ArrayDataSource<T> | ((param: T) => void), value: T) { | ||
if (target instanceof ArrayDataSource) { | ||
@@ -29,2 +30,4 @@ target.push(value); | ||
target.updateDownstream(value); | ||
} else if (typeof target === 'function') { | ||
target(value); | ||
} else { | ||
@@ -35,4 +38,38 @@ target.update(value); | ||
export function urlPathEmitter( | ||
target: DataSource<string> | DuplexDataSource<string> | Stream<string, any> | ArrayDataSource<string> | ((path: string) => void), | ||
cancellationToken?: CancellationToken | ||
): void { | ||
observeHistory(); | ||
historyEvent.subscribe(() => { | ||
updateSource(target, location.pathname); | ||
}, cancellationToken); | ||
} | ||
let historyEvent: EventEmitter<void>; | ||
function observeHistory() { | ||
if (historyEvent) { | ||
return; | ||
} | ||
historyEvent = new EventEmitter(); | ||
const originalReplaceState = history.replaceState.bind(history); | ||
const originalPushState = history.pushState.bind(history); | ||
window.addEventListener('popstate', () => { | ||
historyEvent.fire(); | ||
}); | ||
history.replaceState = (...args: any[]) => { | ||
originalReplaceState.apply(history, args); | ||
historyEvent.fire(); | ||
}; | ||
history.pushState = (...args: any[]) => { | ||
originalPushState.apply(history, args); | ||
historyEvent.fire(); | ||
}; | ||
} | ||
export function urlHashEmitter( | ||
target: DataSource<string> | DuplexDataSource<string> | Stream<string, any> | ArrayDataSource<string>, | ||
target: DataSource<string> | DuplexDataSource<string> | Stream<string, any> | ArrayDataSource<string> | ((path: string) => void), | ||
stripInHashParameters: boolean = false, | ||
@@ -39,0 +76,0 @@ cancellationToken?: CancellationToken |
export enum OperationType { | ||
FILTER, | ||
CLOSE, | ||
NOOP, | ||
@@ -5,0 +4,0 @@ MAP, |
@@ -0,1 +1,2 @@ | ||
import { urlHashEmitter, urlPathEmitter } from '../aurumjs.js'; | ||
import { MapLike } from './common.js'; | ||
@@ -11,3 +12,3 @@ | ||
this.observeUrl(); | ||
window.addEventListener('hashchange', () => this.checkUpdate()); | ||
urlHashEmitter(() => this.checkUpdate()); | ||
this.checkUpdate(); | ||
@@ -18,6 +19,5 @@ } | ||
this.originalReplaceState = history.replaceState.bind(history); | ||
history.replaceState = (...args: any[]) => { | ||
this.originalReplaceState.apply(history, args); | ||
urlPathEmitter(() => { | ||
this.checkUpdate(); | ||
}; | ||
}); | ||
} | ||
@@ -24,0 +24,0 @@ |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1947974
222
26380