sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
150 lines (122 loc) • 3.66 kB
text/typescript
/* eslint-disable camelcase */
import {negate} from 'lodash'
import {type _PaneMenuGroup, type _PaneMenuItem, type _PaneMenuNode} from './components/pane/types'
import {type DocumentFieldMenuActionNode, type PaneMenuItem, type PaneMenuItemGroup} from './types'
export function isMenuNodeButton(node: _PaneMenuNode): node is _PaneMenuItem | _PaneMenuGroup {
return (node.type === 'item' || node.type === 'group') && node.renderAsButton
}
export const isNotMenuNodeButton = negate(isMenuNodeButton)
export function resolveMenuNodes(params: {
actionHandler: (item: PaneMenuItem) => void
fieldActions?: DocumentFieldMenuActionNode[]
menuItems: PaneMenuItem[]
menuItemGroups: PaneMenuItemGroup[]
}): _PaneMenuNode[] {
const {fieldActions = [], menuItems, menuItemGroups} = params
const nodes: _PaneMenuNode[] = []
let keyOffset = 0
for (let i = 0; i < fieldActions.length; i += 1) {
const a = fieldActions[i]
nodes.push(mapFieldActionToPaneMenuNode(a, `${i}-${a.type}`))
}
keyOffset += nodes.length
const groups: _PaneMenuGroup[] = []
for (const itemGroup of menuItemGroups) {
const group = groups.find((g) => g.key === itemGroup.id)
if (!group) {
groups.push({
type: 'group',
key: itemGroup.id,
children: [],
expanded: true,
renderAsButton: false,
title: itemGroup.title,
i18n: itemGroup.i18n,
})
}
}
const ungroupedItems: _PaneMenuItem[] = []
for (let i = 0; i < menuItems.length; i += 1) {
const item = menuItems[i]
let group = item.group && groups.find((g) => g.key === item.group)
if (item.group && !group) {
group = {
type: 'group',
key: item.group,
expanded: true,
icon: item.icon,
title: item.group,
children: [],
renderAsButton: false,
}
groups.push(group)
}
if (group) {
group.children.push({
type: 'item',
key: `${keyOffset + i}-item`,
hotkey: item.shortcut,
icon: item.icon,
intent: item.intent,
onAction: () => params.actionHandler(item),
renderAsButton: item.showAsAction ?? false,
selected: item.selected,
title: item.title,
i18n: item.i18n,
tone: item.tone,
})
} else {
ungroupedItems.push({
type: 'item',
key: `${keyOffset + i}-item`,
hotkey: item.shortcut,
icon: item.icon,
intent: item.intent,
onAction: () => params.actionHandler(item),
renderAsButton: item.showAsAction ?? false,
selected: item.selected,
title: item.title,
i18n: item.i18n,
tone: item.tone,
})
}
}
return [...ungroupedItems, ...groups, ...nodes]
}
function mapFieldActionToPaneMenuNode(a: DocumentFieldMenuActionNode, key: string): _PaneMenuNode {
if (a.type === 'divider') {
return {
type: 'divider',
key,
}
}
if (a.type === 'group') {
return {
type: 'group',
key,
children: a.children.map((child, childIdx) =>
mapFieldActionToPaneMenuNode(child, `${key}-${childIdx}-${child.type}`),
),
disabled: a.disabled,
expanded: a.expanded ?? true,
icon: a.icon,
title: a.title,
i18n: a.i18n,
renderAsButton: a.renderAsButton ?? false,
}
}
return {
type: 'item',
key,
intent: a.intent,
disabled: a.disabled,
icon: a.icon,
iconRight: a.iconRight,
onAction: a.onAction,
renderAsButton: a.renderAsButton ?? false,
selected: a.selected,
title: a.title,
i18n: a.i18n,
tone: a.tone,
}
}