Skip to content

Commit

Permalink
revamped updateClassList command
Browse files Browse the repository at this point in the history
  • Loading branch information
bkrmendy committed Oct 9, 2024
1 parent 7279feb commit 99d8f4a
Showing 1 changed file with 61 additions and 29 deletions.
90 changes: 61 additions & 29 deletions editor/src/components/canvas/commands/update-class-list-command.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,108 @@
import { mapDropNulls } from '../../../core/shared/array-utils'
import * as EP from '../../../core/shared/element-path'
import { emptyComments, jsExpressionValue } from '../../../core/shared/element-template'
import type { ElementPath } from '../../../core/shared/project-file-types'
import * as PP from '../../../core/shared/property-path'
import type { PropertiesToUpdate } from '../../../core/tailwind/tailwind-class-list-utils'
import {
addNewClasses,
getClassListFromParsedClassList,
getParsedClassList,
removeClasses,
updateExistingClasses,
} from '../../../core/tailwind/tailwind-class-list-utils'
import { getTailwindConfigCached } from '../../../core/tailwind/tailwind-compilation'
import { getClassNameAttribute } from '../../../core/tailwind/tailwind-options'
import { getElementFromProjectContents, type EditorState } from '../../editor/store/editor-state'
import { applyValuesAtPath } from './adjust-number-command'
import type { BaseCommand, CommandFunction, WhenToRun } from './commands'
import { getClassNameAttribute } from '../../../core/tailwind/tailwind-options'
import { assertNever } from '../../../core/shared/utils'

export interface UpdateClassList extends BaseCommand {
type: 'UPDATE_CLASS_LIST'
element: ElementPath
classNameUpdate: ClassListUpdate
classNameUpdates: ClassListUpdate[]
}

export type ClassListUpdate =
| { type: 'add'; className: string }
| { type: 'remove'; className: string }
| { type: 'add'; property: string; value: string }
| { type: 'remove'; property: string }

export const add = (className: string): ClassListUpdate => ({ type: 'add', className: className })
export const remove = (className: string): ClassListUpdate => ({
export const add = ({ property, value }: { property: string; value: string }): ClassListUpdate => ({
type: 'add',
property: property,
value: value,
})
export const remove = (property: string): ClassListUpdate => ({
type: 'remove',
className: className,
property: property,
})

export function updateClassListCommand(
whenToRun: WhenToRun,
element: ElementPath,
classNameUpdate: ClassListUpdate,
classNameUpdates: ClassListUpdate[],
): UpdateClassList {
return {
type: 'UPDATE_CLASS_LIST',
whenToRun: whenToRun,
element: element,
classNameUpdate: classNameUpdate,
classNameUpdates: classNameUpdates,
}
}

export const runUpdateClassList: CommandFunction<UpdateClassList> = (
editorState: EditorState,
command: UpdateClassList,
) => {
const { element, classNameUpdate } = command
const classPrefix = classNameUpdate.className.split('-')[0] + '-' // TODO: parse this with the tailwind parsing lib
const { element, classNameUpdates } = command

const currentClassNameAttribute =
getClassNameAttribute(getElementFromProjectContents(element, editorState.projectContents))
?.value ?? ''
const currentClassNameAttribute = getClassNameAttribute(
getElementFromProjectContents(element, editorState.projectContents),
)?.value

const currentClasses = currentClassNameAttribute.split(' ')

// Filter out classes with the same prefix and add the new class
const updatedClasses = currentClasses.filter((c) => !c.startsWith(classPrefix))
switch (classNameUpdate.type) {
case 'add':
updatedClasses.push(classNameUpdate.className)
break
case 'remove':
break
default:
assertNever(classNameUpdate)
if (currentClassNameAttribute == null) {
return {
editorStatePatches: [],
commandDescription: `Update class list for ${EP.toUid(element)} with ${classNameUpdates}`,
}
}

const parsedClassList = getParsedClassList(
currentClassNameAttribute,
getTailwindConfigCached(editorState),
)

const propertiesToRemove = mapDropNulls(
(update) => (update.type !== 'remove' ? null : update.property),
classNameUpdates,
)

const propertiesToUpdate: PropertiesToUpdate = classNameUpdates.reduce(
(acc: { [property: string]: string }, val) =>
val.type === 'remove' ? acc : { ...acc, [val.property]: val.value },
{},
)

const updatedClassList = [
removeClasses(propertiesToRemove),
updateExistingClasses(propertiesToUpdate),
addNewClasses(propertiesToUpdate),
].reduce((classList, fn) => fn(classList), parsedClassList)

const newClassList = getClassListFromParsedClassList(
updatedClassList,
getTailwindConfigCached(editorState),
)

const { editorStatePatch } = applyValuesAtPath(editorState, element, [
{
path: PP.create('className'),
value: jsExpressionValue(updatedClasses.join(' '), emptyComments),
value: jsExpressionValue(newClassList, emptyComments),
},
])

return {
editorStatePatches: [editorStatePatch],
commandDescription: `Update class list for ${EP.toUid(element)} with ${classNameUpdate}`,
commandDescription: `Update class list for ${EP.toUid(element)} to ${newClassList}`,
}
}

0 comments on commit 99d8f4a

Please sign in to comment.