/* * This file belongs to Hoist, an application development toolkit * developed by Extremely Heavy Industries (www.xh.io | info@xh.io) * * Copyright © 2026 Extremely Heavy Industries Inc. */ import '@xh/hoist/desktop/register'; import {HoistInputModel, HoistInputProps, useHoistInputModel} from '@xh/hoist/cmp/input'; import {hoistCmp} from '@xh/hoist/core'; import {Icon} from '@xh/hoist/icon'; import {button, ButtonProps} from '@xh/hoist/desktop/cmp/button'; import {withDefault} from '@xh/hoist/utils/js'; import {ReactElement} from 'react'; import './CheckboxButton.scss'; export interface CheckboxButtonProps extends Omit, HoistInputProps { value?: boolean; /** Icon to display when checked. Defaults to a solid check-square icon with primary intent. */ checkedIcon?: ReactElement; /** Icon to display when unchecked. Defaults to a light outlined square icon. */ uncheckedIcon?: ReactElement; /** Side of the button on which to render the checkbox icon. Default 'left'. */ iconSide?: 'left' | 'right'; } /** * A button-based input to represent and toggle a boolean value. * Renders with a solid "checked" checkbox icon when true and an empty checkbox square when false. * If rendered within a FormField, will use its bound field's displayName for its text by default. */ export const [CheckboxButton, checkboxButton] = hoistCmp.withFactory({ displayName: 'CheckboxButton', className: 'xh-checkbox-button', render(props, ref) { return useHoistInputModel(cmp, props, ref, CheckboxButtonInputModel); } }); class CheckboxButtonInputModel extends HoistInputModel { override xhImpl = true; } //---------------------------------- // Implementation //---------------------------------- const cmp = hoistCmp.factory( ( { // HoistInput props - exclude from passthrough to BP bind, value, commitOnChange, onChange, onCommit, // Consumed by this component model, text, icon, rightIcon, checkedIcon, uncheckedIcon, iconSide, // Remainder passed to hoist button & BP button ...props }, ref ) => { const checked = !!model.renderValue, toggleIcon = checked ? withDefault(checkedIcon, Icon.checkSquare({prefix: 'fas', intent: 'primary'})) : withDefault(uncheckedIcon, Icon.square({prefix: 'fal'})), onRight = iconSide === 'right'; return button({ text: withDefault(text, model.getField()?.displayName), icon: onRight ? icon : toggleIcon, rightIcon: onRight ? toggleIcon : rightIcon, outlined: true, onClick: () => model.noteValueChange(!checked), ...props, ref }); } );