shoelace/src/internal/form-control.ts

102 wiersze
2.9 KiB
TypeScript
Czysty Zwykły widok Historia

import { html, TemplateResult } from 'lit';
2021-09-21 02:01:21 +00:00
import { classMap } from 'lit-html/directives/class-map.js';
import { ifDefined } from 'lit-html/directives/if-defined.js';
2020-12-23 20:47:13 +00:00
export const renderFormControl = (
props: {
/** The input id, used to map the input to the label */
inputId: string;
2020-12-23 20:47:13 +00:00
/** The size of the form control */
size: 'small' | 'medium' | 'large';
2020-12-23 20:47:13 +00:00
/** The label id, used to map the label to the input */
labelId?: string;
2020-12-23 20:47:13 +00:00
/** The label text (if the label slot isn't used) */
label?: string;
2020-12-23 20:47:13 +00:00
/** Whether or not a label slot has been provided. */
hasLabelSlot?: boolean;
2020-12-23 20:47:13 +00:00
/** The help text id, used to map the input to the help text */
helpTextId?: string;
2020-12-23 20:47:13 +00:00
/** The help text (if the help-text slot isn't used) */
helpText?: string;
2020-12-23 20:47:13 +00:00
/** Whether or not a help text slot has been provided. */
hasHelpTextSlot?: boolean;
2020-12-23 20:47:13 +00:00
/** A function that gets called when the label is clicked. */
onLabelClick?: (event: MouseEvent) => void;
},
input: TemplateResult
) => {
2021-03-06 17:01:39 +00:00
const hasLabel = props.label ? true : !!props.hasLabelSlot;
const hasHelpText = props.helpText ? true : !!props.hasHelpTextSlot;
2020-12-23 20:47:13 +00:00
2021-02-26 14:09:13 +00:00
return html`
2020-12-23 20:47:13 +00:00
<div
part="form-control"
2021-02-26 14:09:13 +00:00
class=${classMap({
2020-12-23 20:47:13 +00:00
'form-control': true,
'form-control--small': props.size === 'small',
'form-control--medium': props.size === 'medium',
'form-control--large': props.size === 'large',
'form-control--has-label': hasLabel,
'form-control--has-help-text': hasHelpText
2021-02-26 14:09:13 +00:00
})}
2020-12-23 20:47:13 +00:00
>
<label
part="label"
id=${ifDefined(props.labelId)}
2020-12-23 20:47:13 +00:00
class="form-control__label"
2021-02-26 14:09:13 +00:00
for=${props.inputId}
aria-hidden=${hasLabel ? 'false' : 'true'}
2021-03-06 17:01:39 +00:00
@click=${(event: MouseEvent) => (props.onLabelClick ? props.onLabelClick(event) : null)}
2020-12-23 20:47:13 +00:00
>
2021-02-26 14:09:13 +00:00
<slot name="label">${props.label}</slot>
2020-12-23 20:47:13 +00:00
</label>
2021-02-26 14:09:13 +00:00
<div class="form-control__input">${html`${input}`}</div>
2020-12-23 20:47:13 +00:00
<div
part="help-text"
id=${ifDefined(props.helpTextId)}
2020-12-23 20:47:13 +00:00
class="form-control__help-text"
2021-02-26 14:09:13 +00:00
aria-hidden=${hasHelpText ? 'false' : 'true'}
2020-12-23 20:47:13 +00:00
>
2021-02-26 14:09:13 +00:00
<slot name="help-text">${props.helpText}</slot>
2020-12-23 20:47:13 +00:00
</div>
</div>
2021-02-26 14:09:13 +00:00
`;
2020-12-23 20:47:13 +00:00
};
export function getLabelledBy(props: {
/** The label id, used to map the label to the input */
labelId: string;
/** The label text (if the label slot isn't used) */
label: string;
/** Whether or not a label slot has been provided. */
hasLabelSlot: boolean;
/** The help text id, used to map the input to the help text */
helpTextId: string;
/** The help text (if the help-text slot isn't used) */
helpText: string;
/** Whether or not a help text slot has been provided. */
hasHelpTextSlot: boolean;
}) {
const labelledBy = [
props.label || props.hasLabelSlot ? props.labelId : '',
props.helpText || props.hasHelpTextSlot ? props.helpTextId : ''
].filter(val => val);
return labelledBy.join(' ') || undefined;
}