Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[next] chore(NcBreadcrumbs): simplify code #5068

Merged
merged 3 commits into from
Jan 31, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading