|
@@ -0,0 +1,220 @@
|
|
|
+<template>
|
|
|
+ <div
|
|
|
+ class="node-book"
|
|
|
+ >
|
|
|
+ <section
|
|
|
+ class="node-book-stack no-events-container"
|
|
|
+ :style="`--count: ${nodes.length - 1}; --h: ${stackHeight}px;`"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ v-for="({ parent, children }, i) in nodes" :key="parent.id"
|
|
|
+ class="node-book-stack-item node-book-stack-item-parent splitted"
|
|
|
+ :class="{ active: i === nodes.length - 1 }"
|
|
|
+ :style="`--nth: ${i}`"
|
|
|
+ >
|
|
|
+ <node-view-child-list :children="parent.children" :parent-id="parent.id" smartphone />
|
|
|
+
|
|
|
+ <node-view
|
|
|
+ :node="parent"
|
|
|
+ type="ref"
|
|
|
+ mode="view"
|
|
|
+ @open-node="$emit('open-node', $event)"
|
|
|
+ @open-child="$emit('open-node', parent.id, $event)"
|
|
|
+ @close-node="$emit('close-node', $event)"
|
|
|
+ />
|
|
|
+
|
|
|
+ <section
|
|
|
+ class="node-book-stack no-events-container"
|
|
|
+ :style="`--count: ${children.length }; --h: ${getChildrenStackHeight(children.length)}px;`"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ v-for="(child, j) in children" :key="child.id + '-cont'"
|
|
|
+ class="node-book-stack-item"
|
|
|
+ :class="{ active: j === children.length - 1 }"
|
|
|
+ :style="`--nth: ${j}`"
|
|
|
+ >
|
|
|
+ <node-view
|
|
|
+ :key="child.id"
|
|
|
+ :node="child"
|
|
|
+ mode="view"
|
|
|
+ type="prod"
|
|
|
+ @open-node="$emit('open-node', $event)"
|
|
|
+ @close-node="$emit('close-node', parent.id, $event)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { NodeViewChildList, NodeView } from '@/components/nodes'
|
|
|
+
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'NodeBook',
|
|
|
+
|
|
|
+ components: {
|
|
|
+ NodeViewChildList,
|
|
|
+ NodeView
|
|
|
+ },
|
|
|
+
|
|
|
+ props: {
|
|
|
+ nodes: { type: Array, required: true }
|
|
|
+ },
|
|
|
+
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ height: undefined
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ computed: {
|
|
|
+ stackHeight () {
|
|
|
+ return Math.min(150 / (this.nodes.length - 1), 75)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ methods: {
|
|
|
+ updateSize () {
|
|
|
+ this.height = this.$el.getBoundingClientRect().height
|
|
|
+ },
|
|
|
+
|
|
|
+ getChildrenStackHeight (childrenLen) {
|
|
|
+ return this.stackHeight / childrenLen || this.stackHeight
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ mounted () {
|
|
|
+ window.addEventListener('resize', () => this.updateSize())
|
|
|
+ this.updateSize()
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.node-book {
|
|
|
+ min-height: 100%;
|
|
|
+ // top: -100%;
|
|
|
+
|
|
|
+ @include media-breakpoint-up($layout-bp) {
|
|
|
+ height: 100%;
|
|
|
+
|
|
|
+ // ╭─╴╶┬╴╭─┐╭─╴╷ ╭
|
|
|
+ // ╰─╮ │ ├─┤│ ├┴╮
|
|
|
+ // ╶─╯ ╵ ╵ ╵╰─╴╵ ╵
|
|
|
+
|
|
|
+ &-stack {
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ &-item {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ position: absolute;
|
|
|
+ top: calc(var(--h) * var(--nth));
|
|
|
+ height: calc(100% - (var(--h) * var(--nth)));
|
|
|
+
|
|
|
+ &-parent > .node-view {
|
|
|
+ border-right: $line;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-parent > .node-view {
|
|
|
+ border-top: $line;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:not(.node-book-stack-item-parent):first-child {
|
|
|
+ border-top: $line;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // BLURS
|
|
|
+ &-parent:not(.active) {
|
|
|
+ &::before,
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ pointer-events: none;
|
|
|
+ position: absolute;
|
|
|
+ z-index: 1;
|
|
|
+ display: block;
|
|
|
+ top: $border-width;
|
|
|
+ height: calc(var(--h) - #{$border-width});
|
|
|
+ background-color: rgba($white, .5);
|
|
|
+ }
|
|
|
+ &::before {
|
|
|
+ width: calc(50% - #{$border-width});
|
|
|
+ left: 0;
|
|
|
+ }
|
|
|
+ &::after {
|
|
|
+ width: 50%;
|
|
|
+ left: 50%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &-parent.active {
|
|
|
+ background-color: rgba($white, .5);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:not(.active) {
|
|
|
+ ::v-deep {
|
|
|
+ .node-view {
|
|
|
+ overflow-y: hidden;
|
|
|
+
|
|
|
+ &-header {
|
|
|
+ z-index: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .node-view-child-list {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // ::v-deep .node-view:not(:hover) {
|
|
|
+ // .node-view-header {
|
|
|
+ // padding-top: $node-view-spacer-sm-y;
|
|
|
+ // padding-bottom: $node-view-spacer-sm-y;
|
|
|
+ // }
|
|
|
+ //
|
|
|
+ // h4 {
|
|
|
+ // font-size: 2rem;
|
|
|
+ // > * {
|
|
|
+ // display: inline !important;
|
|
|
+ // }
|
|
|
+ // .edition {
|
|
|
+ // display: none !important;
|
|
|
+ // }
|
|
|
+ // display: block;
|
|
|
+ // display: -webkit-box;
|
|
|
+ // -webkit-line-clamp: 1;
|
|
|
+ // -webkit-box-orient: vertical;
|
|
|
+ // text-overflow: ellipsis;
|
|
|
+ // overflow: hidden;
|
|
|
+ // max-height: 1.5em;
|
|
|
+ // }
|
|
|
+ //
|
|
|
+ // .node-view-header-prod h4 {
|
|
|
+ // font-size: 1rem;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ //
|
|
|
+ // &:hover {
|
|
|
+ // ::v-deep .node-view:hover .node-view-header {
|
|
|
+ // z-index: calc(var(--count) + 10);
|
|
|
+ // border-bottom: $line;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ }
|
|
|
+
|
|
|
+ &.splitted {
|
|
|
+ display: flex;
|
|
|
+ flex-basis: 50%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|