feat: categories and popups #171
@ -348,28 +348,35 @@ const CategoryCheckbox: React.FC<CategoryCheckboxProps> = ({
|
|||||||
const pathString = path.join(':')
|
const pathString = path.join(':')
|
||||||
setIsSingleChecked(selectedSingles.includes(name))
|
setIsSingleChecked(selectedSingles.includes(name))
|
||||||
setIsCombinationChecked(selectedCombinations.includes(pathString))
|
setIsCombinationChecked(selectedCombinations.includes(pathString))
|
||||||
|
// Recursive function to gather all descendant paths
|
||||||
const childPaths =
|
const collectChildPaths = (
|
||||||
category.sub && Array.isArray(category.sub)
|
category: string | Category,
|
||||||
? category.sub.map((sub) =>
|
basePath: string[]
|
||||||
|
) => {
|
||||||
|
if (!category.sub || !Array.isArray(category.sub)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
let paths: string[] = []
|
||||||
|
for (const sub of category.sub) {
|
||||||
|
const subPath =
|
||||||
typeof sub === 'string'
|
typeof sub === 'string'
|
||||||
? [...path, sub].join(':')
|
? [...basePath, sub].join(':')
|
||||||
: [...path, sub.name].join(':')
|
: [...basePath, sub.name].join(':')
|
||||||
)
|
paths.push(subPath)
|
||||||
: []
|
if (typeof sub === 'object') {
|
||||||
|
paths = paths.concat(collectChildPaths(sub, [...basePath, sub.name]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
const childPaths = collectChildPaths(category, path)
|
||||||
const anyChildCombinationSelected = childPaths.some((childPath) =>
|
const anyChildCombinationSelected = childPaths.some((childPath) =>
|
||||||
selectedCombinations.includes(childPath)
|
selectedCombinations.includes(childPath)
|
||||||
)
|
)
|
||||||
|
setIsIndeterminate(
|
||||||
if (
|
anyChildCombinationSelected && !selectedCombinations.includes(pathString)
|
||||||
anyChildCombinationSelected &&
|
)
|
||||||
!selectedCombinations.includes(pathString)
|
}, [category, name, path, selectedCombinations, selectedSingles])
|
||||||
) {
|
|
||||||
setIsIndeterminate(true)
|
|
||||||
} else {
|
|
||||||
setIsIndeterminate(false)
|
|
||||||
}
|
|
||||||
}, [selectedSingles, selectedCombinations, path, name, category.sub])
|
|
||||||
|
|
||||||
const handleSingleChange = () => {
|
const handleSingleChange = () => {
|
||||||
setIsSingleChecked(!isSingleChecked)
|
setIsSingleChecked(!isSingleChecked)
|
||||||
@ -407,17 +414,13 @@ const CategoryCheckbox: React.FC<CategoryCheckboxProps> = ({
|
|||||||
input.indeterminate = isIndeterminate
|
input.indeterminate = isIndeterminate
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className='CheckboxMain'
|
className={`CheckboxMain ${
|
||||||
|
isIndeterminate ? 'CheckboxIndeterminate' : ''
|
||||||
|
}`}
|
||||||
checked={isCombinationChecked}
|
checked={isCombinationChecked}
|
||||||
onChange={handleCombinationChange}
|
onChange={handleCombinationChange}
|
||||||
/>
|
/>
|
||||||
<label
|
<label htmlFor={name} className='form-label labelMain'>
|
||||||
htmlFor={name}
|
|
||||||
className='form-label labelMain'
|
|
||||||
style={{
|
|
||||||
color: isIndeterminate ? 'green' : 'white'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{capitalizeEachWord(name)}
|
{capitalizeEachWord(name)}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
@ -530,6 +530,15 @@ h6 {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.CheckboxMain.CheckboxIndeterminate::before {
|
||||||
|
content: '\2501';
|
||||||
|
transition: ease 0.2s;
|
||||||
|
transform: scale(1);
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 0 8px 0 rgb(0, 0, 0, 0.1);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
.CheckboxMain:checked::before {
|
.CheckboxMain:checked::before {
|
||||||
transition: ease 0.2s;
|
transition: ease 0.2s;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user