2020-10-22 18:42:03 +02:00
|
|
|
<script>
|
2022-04-22 17:03:47 +02:00
|
|
|
import { Icon, StatusLight } from "@budibase/bbui"
|
2022-03-21 14:38:53 +01:00
|
|
|
import { createEventDispatcher, getContext } from "svelte"
|
2021-04-23 11:18:34 +02:00
|
|
|
|
2020-10-22 18:42:03 +02:00
|
|
|
export let icon
|
|
|
|
export let withArrow = false
|
|
|
|
export let withActions = true
|
|
|
|
export let indentLevel = 0
|
|
|
|
export let text
|
|
|
|
export let border = true
|
|
|
|
export let selected = false
|
|
|
|
export let opened = false
|
|
|
|
export let draggable = false
|
2021-12-09 14:08:16 +01:00
|
|
|
export let iconText
|
|
|
|
export let iconColor
|
2022-04-22 17:03:47 +02:00
|
|
|
export let scrollable = false
|
|
|
|
export let color
|
2022-05-17 14:32:16 +02:00
|
|
|
export let highlighted = false
|
2021-07-29 11:22:45 +02:00
|
|
|
|
2022-03-21 14:38:53 +01:00
|
|
|
const scrollApi = getContext("scroll")
|
2021-07-29 11:22:45 +02:00
|
|
|
const dispatch = createEventDispatcher()
|
2022-03-21 14:38:53 +01:00
|
|
|
|
|
|
|
let contentRef
|
|
|
|
$: selected && contentRef && scrollToView()
|
2021-07-29 11:22:45 +02:00
|
|
|
|
2022-03-21 15:46:59 +01:00
|
|
|
const onClick = () => {
|
|
|
|
scrollToView()
|
|
|
|
dispatch("click")
|
|
|
|
}
|
|
|
|
|
|
|
|
const onIconClick = e => {
|
|
|
|
e.stopPropagation()
|
2021-07-29 11:22:45 +02:00
|
|
|
dispatch("iconClick")
|
|
|
|
}
|
2022-03-21 14:38:53 +01:00
|
|
|
|
|
|
|
const scrollToView = () => {
|
|
|
|
if (!scrollApi || !contentRef) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
const bounds = contentRef.getBoundingClientRect()
|
|
|
|
scrollApi.scrollTo(bounds)
|
|
|
|
}
|
2020-10-22 18:42:03 +02:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<div
|
2020-10-27 16:26:07 +01:00
|
|
|
class="nav-item"
|
2020-10-22 18:42:03 +02:00
|
|
|
class:border
|
|
|
|
class:selected
|
2022-04-25 20:33:43 +02:00
|
|
|
class:withActions
|
2022-05-17 14:32:16 +02:00
|
|
|
class:scrollable
|
|
|
|
class:highlighted
|
2022-05-13 11:12:16 +02:00
|
|
|
style={`padding-left: calc(${indentLevel * 14}px)`}
|
2020-10-22 18:42:03 +02:00
|
|
|
{draggable}
|
|
|
|
on:dragend
|
|
|
|
on:dragstart
|
|
|
|
on:dragover
|
|
|
|
on:drop
|
2022-03-21 15:46:59 +01:00
|
|
|
on:click={onClick}
|
2020-10-22 18:42:03 +02:00
|
|
|
ondragover="return false"
|
2021-04-23 11:18:34 +02:00
|
|
|
ondragenter="return false"
|
|
|
|
>
|
2022-03-21 14:38:53 +01:00
|
|
|
<div class="nav-item-content" bind:this={contentRef}>
|
|
|
|
{#if withArrow}
|
2022-05-13 11:12:16 +02:00
|
|
|
<div
|
|
|
|
class:opened
|
|
|
|
class:relative={indentLevel === 0}
|
|
|
|
class:absolute={indentLevel > 0}
|
|
|
|
class="icon arrow"
|
|
|
|
on:click={onIconClick}
|
|
|
|
>
|
2022-03-21 14:38:53 +01:00
|
|
|
<Icon size="S" name="ChevronRight" />
|
|
|
|
</div>
|
|
|
|
{/if}
|
2021-01-12 17:49:11 +01:00
|
|
|
|
2022-03-21 14:38:53 +01:00
|
|
|
<slot name="icon" />
|
|
|
|
{#if iconText}
|
|
|
|
<div class="iconText" style={iconColor ? `color: ${iconColor};` : ""}>
|
|
|
|
{iconText}
|
|
|
|
</div>
|
|
|
|
{:else if icon}
|
|
|
|
<div class="icon">
|
|
|
|
<Icon color={iconColor} size="S" name={icon} />
|
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
<div class="text">{text}</div>
|
|
|
|
{#if withActions}
|
|
|
|
<div class="actions">
|
|
|
|
<slot />
|
|
|
|
</div>
|
|
|
|
{/if}
|
2022-04-22 17:03:47 +02:00
|
|
|
{#if color}
|
2022-04-25 20:33:43 +02:00
|
|
|
<div class="light">
|
|
|
|
<StatusLight size="L" {color} />
|
|
|
|
</div>
|
2022-04-22 17:03:47 +02:00
|
|
|
{/if}
|
2022-03-21 14:38:53 +01:00
|
|
|
</div>
|
2020-10-22 18:42:03 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<style>
|
2020-10-27 16:26:07 +01:00
|
|
|
.nav-item {
|
2020-10-22 18:42:03 +02:00
|
|
|
cursor: pointer;
|
|
|
|
color: var(--grey-7);
|
2021-04-13 19:07:45 +02:00
|
|
|
transition: background-color
|
|
|
|
var(--spectrum-global-animation-duration-100, 130ms) ease-in-out;
|
2022-04-25 20:33:43 +02:00
|
|
|
padding: 0 var(--spacing-l) 0;
|
2022-03-18 20:52:11 +01:00
|
|
|
height: 32px;
|
|
|
|
display: flex;
|
2022-04-22 17:03:47 +02:00
|
|
|
flex-direction: row;
|
|
|
|
justify-content: flex-start;
|
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
.nav-item.scrollable {
|
2022-03-21 14:38:53 +01:00
|
|
|
flex-direction: column;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: flex-start;
|
2020-10-22 18:42:03 +02:00
|
|
|
}
|
2022-05-17 14:32:16 +02:00
|
|
|
.nav-item.highlighted {
|
|
|
|
background-color: var(--spectrum-global-color-gray-200);
|
|
|
|
}
|
2020-10-27 16:26:07 +01:00
|
|
|
.nav-item.selected {
|
2022-05-17 14:32:16 +02:00
|
|
|
background-color: var(--spectrum-global-color-gray-300);
|
2020-10-22 18:42:03 +02:00
|
|
|
color: var(--ink);
|
|
|
|
}
|
2020-10-27 16:26:07 +01:00
|
|
|
.nav-item:hover {
|
2022-05-17 14:32:16 +02:00
|
|
|
background-color: var(--spectrum-global-color-gray-300);
|
2020-10-22 18:42:03 +02:00
|
|
|
}
|
2020-10-27 16:26:07 +01:00
|
|
|
.nav-item:hover .actions {
|
2022-04-25 21:17:09 +02:00
|
|
|
visibility: visible;
|
2020-10-22 18:42:03 +02:00
|
|
|
}
|
2022-03-21 14:38:53 +01:00
|
|
|
.nav-item-content {
|
|
|
|
flex: 1 1 auto;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
|
|
|
justify-content: flex-start;
|
|
|
|
align-items: center;
|
|
|
|
gap: var(--spacing-xs);
|
|
|
|
width: max-content;
|
2022-04-25 20:33:43 +02:00
|
|
|
overflow: hidden;
|
2022-04-25 21:17:09 +02:00
|
|
|
position: relative;
|
2022-05-13 11:12:16 +02:00
|
|
|
padding-left: var(--spacing-l);
|
2022-05-19 20:14:12 +02:00
|
|
|
pointer-events: none;
|
2022-03-21 14:38:53 +01:00
|
|
|
}
|
|
|
|
|
2022-05-13 13:05:55 +02:00
|
|
|
/* Needed to fully display the actions icon */
|
|
|
|
.nav-item.scrollable .nav-item-content {
|
|
|
|
padding-right: 1px;
|
|
|
|
}
|
|
|
|
|
2020-10-22 18:42:03 +02:00
|
|
|
.icon {
|
2022-05-13 11:12:16 +02:00
|
|
|
flex: 0 0 24px;
|
2020-10-22 18:42:03 +02:00
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
2022-05-13 11:12:16 +02:00
|
|
|
color: var(--spectrum-global-color-gray-600);
|
2020-10-22 18:42:03 +02:00
|
|
|
}
|
|
|
|
.icon.arrow {
|
2022-05-13 11:12:16 +02:00
|
|
|
flex: 0 0 20px;
|
|
|
|
}
|
|
|
|
.icon.arrow.absolute {
|
|
|
|
position: absolute;
|
|
|
|
left: 0;
|
|
|
|
padding: 8px;
|
|
|
|
margin-left: -8px;
|
|
|
|
}
|
|
|
|
.icon.arrow :global(svg) {
|
|
|
|
width: 12px;
|
|
|
|
height: 12px;
|
|
|
|
}
|
|
|
|
.icon.arrow.relative {
|
|
|
|
position: relative;
|
|
|
|
margin: 0 -6px 0 -4px;
|
2020-10-22 18:42:03 +02:00
|
|
|
}
|
|
|
|
.icon.arrow.opened {
|
|
|
|
transform: rotate(90deg);
|
|
|
|
}
|
2022-04-25 21:17:09 +02:00
|
|
|
.iconText {
|
|
|
|
margin-top: 1px;
|
|
|
|
font-size: var(--spectrum-global-dimension-font-size-50);
|
|
|
|
flex: 0 0 34px;
|
|
|
|
}
|
2020-10-22 18:42:03 +02:00
|
|
|
|
|
|
|
.text {
|
2021-05-25 11:11:41 +02:00
|
|
|
font-weight: 600;
|
2022-05-13 11:12:16 +02:00
|
|
|
font-size: 12px;
|
2022-03-18 20:52:11 +01:00
|
|
|
white-space: nowrap;
|
2020-11-05 12:48:49 +01:00
|
|
|
overflow: hidden;
|
|
|
|
text-overflow: ellipsis;
|
2022-04-22 17:03:47 +02:00
|
|
|
flex: 1 1 auto;
|
2022-05-13 11:12:16 +02:00
|
|
|
color: var(--spectrum-global-color-gray-800);
|
2022-04-22 17:03:47 +02:00
|
|
|
}
|
|
|
|
.scrollable .text {
|
2022-03-21 14:38:53 +01:00
|
|
|
flex: 0 0 auto;
|
2022-04-22 17:03:47 +02:00
|
|
|
max-width: 160px;
|
2020-10-22 18:42:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.actions {
|
|
|
|
cursor: pointer;
|
|
|
|
position: relative;
|
2022-04-25 21:17:09 +02:00
|
|
|
display: grid;
|
2022-03-21 10:57:55 +01:00
|
|
|
place-items: center;
|
2022-04-25 21:17:09 +02:00
|
|
|
visibility: hidden;
|
2020-10-22 18:42:03 +02:00
|
|
|
}
|
2022-04-25 20:33:43 +02:00
|
|
|
.actions,
|
|
|
|
.light :global(.spectrum-StatusLight) {
|
|
|
|
width: 20px;
|
|
|
|
height: 20px;
|
|
|
|
margin-left: var(--spacing-s);
|
|
|
|
}
|
2022-04-25 21:17:09 +02:00
|
|
|
.light {
|
|
|
|
position: absolute;
|
|
|
|
right: 0;
|
2021-12-09 14:08:16 +01:00
|
|
|
}
|
2022-04-25 20:33:43 +02:00
|
|
|
.nav-item.withActions:hover .light {
|
|
|
|
display: none;
|
|
|
|
}
|
2020-10-22 18:42:03 +02:00
|
|
|
</style>
|