NodeBook.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <template>
  2. <div
  3. class="node-book"
  4. >
  5. <section
  6. class="node-book-stack no-events-container"
  7. :style="`--count: ${nodes.length - 1}; --h: ${stackHeight}px;`"
  8. >
  9. <div
  10. v-for="({ parent, children }, i) in nodes" :key="parent.id"
  11. class="node-book-stack-item node-book-stack-item-parent splitted"
  12. :class="{ active: i === nodes.length - 1 }"
  13. :style="`--nth: ${i}`"
  14. >
  15. <node-view-child-list :children="parent.children" :parent-id="parent.id" smartphone />
  16. <node-view
  17. :node="parent"
  18. type="ref"
  19. mode="view"
  20. @open-node="$emit('open-node', $event)"
  21. @open-child="$emit('open-node', parent.id, $event)"
  22. @close-node="$emit('close-node', $event)"
  23. />
  24. <section
  25. class="node-book-stack no-events-container"
  26. :style="`--count: ${children.length }; --h: ${getChildrenStackHeight(children.length)}px;`"
  27. >
  28. <div
  29. v-for="(child, j) in children" :key="child.id + '-cont'"
  30. class="node-book-stack-item"
  31. :class="{ active: j === children.length - 1 }"
  32. :style="`--nth: ${j}`"
  33. >
  34. <node-view
  35. :key="child.id"
  36. :node="child"
  37. mode="view"
  38. type="prod"
  39. @open-node="$emit('open-node', $event)"
  40. @close-node="$emit('close-node', parent.id, $event)"
  41. />
  42. </div>
  43. </section>
  44. </div>
  45. </section>
  46. </div>
  47. </template>
  48. <script>
  49. import { NodeViewChildList, NodeView } from '@/components/nodes'
  50. export default {
  51. name: 'NodeBook',
  52. components: {
  53. NodeViewChildList,
  54. NodeView
  55. },
  56. props: {
  57. nodes: { type: Array, required: true }
  58. },
  59. data () {
  60. return {
  61. height: undefined
  62. }
  63. },
  64. computed: {
  65. stackHeight () {
  66. return Math.min(150 / (this.nodes.length - 1), 75)
  67. }
  68. },
  69. methods: {
  70. updateSize () {
  71. this.height = this.$el.getBoundingClientRect().height
  72. },
  73. getChildrenStackHeight (childrenLen) {
  74. return this.stackHeight / childrenLen || this.stackHeight
  75. }
  76. },
  77. mounted () {
  78. window.addEventListener('resize', () => this.updateSize())
  79. this.updateSize()
  80. }
  81. }
  82. </script>
  83. <style lang="scss" scoped>
  84. .node-book {
  85. min-height: 100%;
  86. // top: -100%;
  87. @include media-breakpoint-up($layout-bp) {
  88. height: 100%;
  89. // ╭─╴╶┬╴╭─┐╭─╴╷ ╭
  90. // ╰─╮ │ ├─┤│ ├┴╮
  91. // ╶─╯ ╵ ╵ ╵╰─╴╵ ╵
  92. &-stack {
  93. position: relative;
  94. height: 100%;
  95. width: 100%;
  96. display: flex;
  97. flex-direction: column;
  98. &-item {
  99. width: 100%;
  100. height: 100%;
  101. position: absolute;
  102. top: calc(var(--h) * var(--nth));
  103. height: calc(100% - (var(--h) * var(--nth)));
  104. &-parent > .node-view {
  105. border-right: $line;
  106. }
  107. &-parent > .node-view {
  108. border-top: $line;
  109. }
  110. &:not(.node-book-stack-item-parent):first-child {
  111. border-top: $line;
  112. }
  113. // BLURS
  114. &-parent:not(.active) {
  115. &::before,
  116. &::after {
  117. content: '';
  118. pointer-events: none;
  119. position: absolute;
  120. z-index: 1;
  121. display: block;
  122. top: $border-width;
  123. height: calc(var(--h) - #{$border-width});
  124. background-color: rgba($white, .5);
  125. }
  126. &::before {
  127. width: calc(50% - #{$border-width});
  128. left: 0;
  129. }
  130. &::after {
  131. width: 50%;
  132. left: 50%;
  133. }
  134. }
  135. &-parent.active {
  136. background-color: rgba($white, .5);
  137. }
  138. &:not(.active) {
  139. ::v-deep {
  140. .node-view {
  141. overflow-y: hidden;
  142. &-header {
  143. z-index: 0;
  144. }
  145. }
  146. .node-view-child-list {
  147. display: none;
  148. }
  149. }
  150. // ::v-deep .node-view:not(:hover) {
  151. // .node-view-header {
  152. // padding-top: $node-view-spacer-sm-y;
  153. // padding-bottom: $node-view-spacer-sm-y;
  154. // }
  155. //
  156. // h4 {
  157. // font-size: 2rem;
  158. // > * {
  159. // display: inline !important;
  160. // }
  161. // .edition {
  162. // display: none !important;
  163. // }
  164. // display: block;
  165. // display: -webkit-box;
  166. // -webkit-line-clamp: 1;
  167. // -webkit-box-orient: vertical;
  168. // text-overflow: ellipsis;
  169. // overflow: hidden;
  170. // max-height: 1.5em;
  171. // }
  172. //
  173. // .node-view-header-prod h4 {
  174. // font-size: 1rem;
  175. // }
  176. // }
  177. //
  178. // &:hover {
  179. // ::v-deep .node-view:hover .node-view-header {
  180. // z-index: calc(var(--count) + 10);
  181. // border-bottom: $line;
  182. // }
  183. // }
  184. }
  185. &.splitted {
  186. display: flex;
  187. flex-basis: 50%;
  188. }
  189. }
  190. }
  191. }
  192. }
  193. </style>