109 lines
2.4 KiB
JavaScript

import { prop, computed, container, pick } from 'frptools';
import { Icon } from './icon.js';
import { router } from '../../services/router.js';
import { defineElement as el, subscribeToRender } from '../../utils/domvm.js';
import { injectStyle, styled } from '../../services/style.js';
import { CLICKABLE } from '../styles.js';
let seq = 0;
export function AppBarView(vm, params, key, opts) {
const stateStack = container([], arr => arr.length);
const companionScrollTop = prop(0);
const currentState = computed(stack => stack[0] || {}, [stateStack]);
const title = computed(pick('title', ''), [currentState]);
const renderActions = computed(pick('actions'), [currentState]);
const up = computed(pick('up'), [currentState]);
const upButton = computed(pick('name', 'arrow_left'), [up]);
const upAction = computed(
upState => (upState.onclick ? upState.onclick : [popState, upState.navigateTo]),
[up]
);
const stateStyle = computed(pick('style', {}), [currentState]);
const boxShadowStyle = computed(
t => (t === 0 ? 'none' : `0px ${Math.min(t / 10, 3)}px 3px rgba(0, 0, 0, .2)`),
[companionScrollTop]
);
const containerStyle = computed(
(boxShadow, style) => ({
css: Object.assign({ boxShadow }, style)
}),
[boxShadowStyle, stateStyle]
);
if (opts.appbar) {
throw new Error('Cannot have more than one AppBar.');
}
function pushState(newState) {
stateStack.unshift(Object.assign({ _seq: seq++ }, newState));
}
function popState(navigateTo) {
stateStack.shift();
if (navigateTo) {
router.goto(navigateTo);
}
}
opts.appbar = {
pushState,
popState,
companionScrollTop
};
subscribeToRender(vm, [containerStyle, renderActions, up, title]);
return (vm, params) => {
const _buttons = renderActions() || (() => {});
return appBarContainer(containerStyle(), [
up()
? upButtonContainer(
{
onclick: upAction()
},
[
Icon({
name: upButton(),
size: 0.75
})
]
)
: null,
titleContainer(title()),
headerRight(_buttons())
]);
};
}
const appBarContainer = styled({
justifyContent: 'space-between',
padding: '1em',
zIndex: 1000,
display: 'flex',
alignItems: 'center',
width: '100%'
});
const upButtonContainer = styled(
{
marginRight: '1em'
},
CLICKABLE
);
const headerRight = styled({
display: 'flex',
alignItems: 'center'
});
const titleContainer = styled({
fontSize: '20pt',
flex: 1
});