Skip to content

Commit

Permalink
Merge pull request #5068 from nextcloud-libraries/chore/noid/breadcru…
Browse files Browse the repository at this point in the history
…mbs-cleanup

[next] chore(NcBreadcrumbs): simplify code
  • Loading branch information
raimund-schluessler authored Jan 31, 2024
2 parents ee9f6f3 + 0ca613e commit 9116758
Showing 1 changed file with 80 additions and 92 deletions.
172 changes: 80 additions & 92 deletions src/components/NcBreadcrumbs/NcBreadcrumbs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export default {
// Is the menu open or not
open: false,
},
breadcrumbsRefs: {},
breadcrumbsRefs: [],
}
},
created() {
Expand Down Expand Up @@ -262,13 +262,11 @@ export default {
if (!this.$refs.container) {
return
}
// All breadcrumb components passed into the default slot
const breadcrumbs = Object.values(this.breadcrumbsRefs)

const nrCrumbs = breadcrumbs.length
const nrCrumbs = this.breadcrumbsRefs.length
const hiddenIndices = []
const availableWidth = this.$refs.container.offsetWidth
let totalWidth = this.getTotalWidth(breadcrumbs)
let totalWidth = this.getTotalWidth()
// If we have breadcrumbs actions, we have to take their width into account too.
if (this.$refs.breadcrumb__actions) {
totalWidth += this.$refs.breadcrumb__actions.offsetWidth
Expand All @@ -284,7 +282,7 @@ export default {
// We hide elements alternating to the left and right
const currentIndex = startIndex + ((i % 2) ? i + 1 : i) / 2 * Math.pow(-1, i + (nrCrumbs % 2))
// Calculate the remaining overflow width after hiding this breadcrumb
overflow -= this.getWidth(breadcrumbs[currentIndex]?.$el, currentIndex === (breadcrumbs.length - 1))
overflow -= this.getWidth(this.breadcrumbsRefs[currentIndex]?.$el, currentIndex === (this.breadcrumbsRefs.length - 1))
hiddenIndices.push(currentIndex)
i++
}
Expand Down Expand Up @@ -317,11 +315,10 @@ export default {
/**
* Calculates the total width of all breadcrumbs
*
* @param {Array} breadcrumbs All breadcrumbs
* @return {number} The total width
*/
getTotalWidth(breadcrumbs) {
return breadcrumbs.reduce((width, crumb, index) => width + this.getWidth(crumb?.$el, index === (breadcrumbs.length - 1)), 0)
getTotalWidth() {
return this.breadcrumbsRefs.reduce((width, crumb, index) => width + this.getWidth(crumb.$el, index === (this.breadcrumbsRefs.length - 1)), 0)
},
/**
* Calculates the width of the provided element
Expand Down Expand Up @@ -464,8 +461,7 @@ export default {
* add it to the array of all crumbs.
*/
hideCrumbs() {
const crumbs = Object.values(this.breadcrumbsRefs)
crumbs.forEach((crumb, i) => {
this.breadcrumbsRefs.forEach((crumb, i) => {
if (crumb?.$el?.classList) {
if (this.hiddenIndices.includes(i)) {
crumb.$el.classList.add(`${crumbClass}--hidden`)
Expand Down Expand Up @@ -520,7 +516,7 @@ export default {
* and don't write to this.breadcrumbsRefs directly
* to not trigger a myriad of re-renders.
*/
const breadcrumbsRefs = {}
const breadcrumbsRefs = []
// Add the breadcrumbs to the array of the created VNodes, check if hiding them is necessary.
breadcrumbs = breadcrumbs.map((crumb, index) => cloneVNode(crumb, {
ref: (crumb) => {
Expand All @@ -529,92 +525,84 @@ export default {
}))

// The array of all created VNodes
let crumbs = []

if (!this.hiddenIndices.length) {
// We don't hide any breadcrumbs.
crumbs = breadcrumbs
} else {
const crumbs = [...breadcrumbs]
if (this.hiddenIndices.length) {
/**
* We show the first half of the breadcrumbs before the Actions dropdown menu
* which shows the hidden breadcrumbs.
*/
// Add the breadcrumbs to the array of the created VNodes, check if hiding them is necessary.
crumbs = breadcrumbs.slice(0, Math.round(breadcrumbs.length / 2))

// The Actions menu
// Use a breadcrumb component for the hidden breadcrumbs
crumbs.push(h(NcBreadcrumb, {
class: 'dropdown',
...this.menuBreadcrumbProps,
// Hide the dropdown menu from screen-readers,
// since the crumbs in the menu are still in the list.
'aria-hidden': true,
// Add a ref to the Actions menu
ref: 'actionsBreadcrumb',
key: 'actions-breadcrumb-1',
// Add handlers so the Actions menu opens on hover
onDragenter: () => { this.menuBreadcrumbProps.open = true },
onDragleave: this.closeActions,
// Make sure we keep the same open state
// as the Actions component
'onUpdate:open': (open) => {
this.menuBreadcrumbProps.open = open
},
// Add all hidden breadcrumbs as ActionRouter or ActionLink
}, {
default: () => this.hiddenIndices.map(index => {
const crumb = breadcrumbs[index]
const {
// Get the parameters from the breadcrumb component props
to,
href,
disableDrop,
name,
// Props to forward
...propsToForward
} = crumb.props
// Do not forward the ref, otherwise it will be null if the hidden crumb gets destroyed
delete propsToForward.ref

// Decide whether to show the breadcrumbs as ActionButton, ActionRouter or ActionLink
let element = NcActionButton
let path = ''
if (href) {
element = NcActionLink
path = href
}
if (to) {
element = NcActionRouter
path = to
}
const folderIcon = h(IconFolder, {
size: 20,
})
return h(element, {
...propsToForward,
class: crumbClass,
href: href || null,
to: to || null,
// Prevent the breadcrumbs from being draggable
draggable: false,
// Add the drag and drop handlers
onDragstart: this.dragStart,
onDrop: ($event) => this.dropped($event, path, disableDrop),
onDragover: this.dragOver,
onDragenter: ($event) => this.dragEnter($event, disableDrop),
onDragleave: ($event) => this.dragLeave($event, disableDrop),
crumbs.splice(Math.round(breadcrumbs.length / 2), 0,

// The Actions menu
// Use a breadcrumb component for the hidden breadcrumbs
h(NcBreadcrumb, {
class: 'dropdown',
...this.menuBreadcrumbProps,
// Hide the dropdown menu from screen-readers,
// since the crumbs in the menu are still in the list.
'aria-hidden': true,
// Add a ref to the Actions menu
ref: 'actionsBreadcrumb',
key: 'actions-breadcrumb-1',
// Add handlers so the Actions menu opens on hover
onDragenter: () => { this.menuBreadcrumbProps.open = true },
onDragleave: this.closeActions,
// Make sure we keep the same open state
// as the Actions component
'onUpdate:open': (open) => {
this.menuBreadcrumbProps.open = open
},
{
default: () => name,
icon: () => folderIcon,
})
// Add all hidden breadcrumbs as ActionRouter or ActionLink
}, {
default: () => this.hiddenIndices.map(index => {
const crumb = breadcrumbs[index]
const {
// Get the parameters from the breadcrumb component props
to,
href,
disableDrop,
name,
// Props to forward
...propsToForward
} = crumb.props
// Do not forward the ref, otherwise it will be null if the hidden crumb gets destroyed
delete propsToForward.ref

// Decide whether to show the breadcrumbs as ActionButton, ActionRouter or ActionLink
let element = NcActionButton
let path = ''
if (href) {
element = NcActionLink
path = href
}
if (to) {
element = NcActionRouter
path = to
}
const folderIcon = h(IconFolder, {
size: 20,
})
return h(element, {
...propsToForward,
class: crumbClass,
href: href || null,
to: to || null,
// Prevent the breadcrumbs from being draggable
draggable: false,
// Add the drag and drop handlers
onDragstart: this.dragStart,
onDrop: ($event) => this.dropped($event, path, disableDrop),
onDragover: this.dragOver,
onDragenter: ($event) => this.dragEnter($event, disableDrop),
onDragleave: ($event) => this.dragLeave($event, disableDrop),
},
{
default: () => name,
icon: () => folderIcon,
})
}),
}),
}))

// The second half of the breadcrumbs
const crumbs2 = breadcrumbs.slice(Math.round(breadcrumbs.length / 2))
crumbs = crumbs.concat(crumbs2)
)
}

const wrapper = [h('nav', { 'aria-label': this.ariaLabel }, [h('ul', { class: 'breadcrumb__crumbs' }, [crumbs])])]
Expand Down

0 comments on commit 9116758

Please sign in to comment.