Better form themes (#465)

* Working on custom radius + input size

* Fix date input clear vertical align

* Moslty finished implementing small size

* Polishing larger theme

* Finish large theme

* Added size/radius options in form editor

* Darken help text, improve switch input help location

* Slight form editor improvement

* Fix styling

* Polish of the form editor
This commit is contained in:
Julien Nahum
2024-06-27 17:52:49 +02:00
committed by GitHub
parent a84abf9f72
commit 2ca2d97e8e
46 changed files with 1058 additions and 494 deletions

69
client/lib/forms/themes/ThemeBuilder.js vendored Normal file
View File

@@ -0,0 +1,69 @@
import {twMerge} from 'tailwind-merge'
import {themes} from './form-themes.js'
export const sizes = ['sm', 'md', 'lg']
class ThemeBuilder {
constructor(theme = 'default', options = {}) {
this.theme = themes[theme] || themes.default
this.size = options.size || 'md'
this.borderRadius = options.borderRadius || 'small'
}
extractSizedClasses(baseConfig) {
if (typeof baseConfig === 'object' &&
sizes.every((size) => baseConfig[size])) {
return baseConfig[this.size]
}
return baseConfig
}
mergeNestedClasses(baseConfig, componentConfig) {
const mergedConfig = {}
const allKeys = new Set([
...Object.keys(baseConfig),
...Object.keys(componentConfig),
])
allKeys.forEach((key) => {
const baseValue = this.extractSizedClasses(baseConfig[key])
const componentValue = this.extractSizedClasses(componentConfig[key])
if (key === 'borderRadius') {
// Special case for border radius
const borderRadiusClass = baseConfig.borderRadius?.[this.borderRadius] || ''
mergedConfig[key] = twMerge(borderRadiusClass, componentValue)
} else if (
typeof baseValue === 'object' &&
baseValue !== null &&
!Array.isArray(baseValue)) {
mergedConfig[key] = this.mergeNestedClasses(baseValue, componentValue || {})
} else {
mergedConfig[key] = twMerge(baseValue || '', componentValue || '')
}
})
return mergedConfig
}
getComponentTheme(componentName = 'default') {
const baseComponentConfig = this.theme.default || {}
const componentConfig = this.theme[componentName] || {}
return this.mergeNestedClasses(baseComponentConfig, componentConfig)
}
// Get all components classes for the selected theme
getAllComponents() {
const allComponents = {}
Object.keys(this.theme).forEach((componentName) => {
allComponents[componentName] = this.getComponentTheme(componentName)
})
return allComponents
}
}
export default ThemeBuilder