( componentToClone: IComponent, components: IComponents, )
| 3 | import { generateId } from './generateId' |
| 4 | |
| 5 | export const duplicateComponent = ( |
| 6 | componentToClone: IComponent, |
| 7 | components: IComponents, |
| 8 | ) => { |
| 9 | const clonedComponents: IComponents = {} |
| 10 | |
| 11 | const cloneComponent = (component: IComponent) => { |
| 12 | const newid = generateId() |
| 13 | const children = component.children.map(child => { |
| 14 | return cloneComponent(components[child]) |
| 15 | }) |
| 16 | |
| 17 | let newComponentName = component.componentName |
| 18 | if (newComponentName) { |
| 19 | const matches = /^([a-zA-Z]*)(\d+)?$/g.exec(newComponentName) |
| 20 | // Get all components with a similar name (same base component name + number suffix) |
| 21 | const similarComponents = filter( |
| 22 | components, |
| 23 | comp => !!comp.componentName?.includes(matches![1]), |
| 24 | ) |
| 25 | let highestNumber = 0 |
| 26 | // Get the highest suffix number |
| 27 | similarComponents.forEach(comp => { |
| 28 | const nameMatches = /^([a-zA-Z]*)(\d+)?$/g.exec(comp.componentName!) |
| 29 | const number = nameMatches?.length === 2 ? 0 : Number(nameMatches![2]) |
| 30 | |
| 31 | if (number > highestNumber) { |
| 32 | highestNumber = number |
| 33 | } |
| 34 | }) |
| 35 | // Use the suffix number + 1 to name our duplicated component |
| 36 | newComponentName = newComponentName.replace( |
| 37 | /^([a-zA-Z]*)(\d+)?$/g, |
| 38 | `$1${highestNumber + 1}`, |
| 39 | ) |
| 40 | } |
| 41 | |
| 42 | clonedComponents[newid] = { |
| 43 | ...component, |
| 44 | id: newid, |
| 45 | props: { ...component.props }, |
| 46 | children, |
| 47 | componentName: newComponentName, |
| 48 | } |
| 49 | |
| 50 | children.forEach(child => { |
| 51 | clonedComponents[child].parent = newid |
| 52 | }) |
| 53 | |
| 54 | return newid |
| 55 | } |
| 56 | |
| 57 | const newId = cloneComponent(componentToClone) |
| 58 | |
| 59 | return { |
| 60 | newId, |
| 61 | clonedComponents, |
| 62 | } |
no test coverage detected