lemmy-ui/src/shared/components/common/language-select.tsx

150 lines
4.1 KiB
TypeScript
Raw Normal View History

import { selectableLanguages } from "@utils/app";
import { randomStr } from "@utils/helpers";
import classNames from "classnames";
import { Component, linkEvent } from "inferno";
import { Language } from "lemmy-js-client";
2023-06-22 00:54:35 +00:00
import { I18NextService, UserService } from "../../services";
import { Icon } from "./icon";
interface LanguageSelectProps {
allLanguages: Language[];
siteLanguages: number[];
selectedLanguageIds?: number[];
multiple?: boolean;
onChange(val: number[]): any;
showAll?: boolean;
showSite?: boolean;
iconVersion?: boolean;
disabled?: boolean;
showLanguageWarning?: boolean;
}
export class LanguageSelect extends Component<LanguageSelectProps, any> {
private id = `language-select-${randomStr()}`;
constructor(props: any, context: any) {
super(props, context);
}
componentDidMount() {
this.setSelectedValues();
}
// Necessary because there is no HTML way to set selected for multiple in value=
setSelectedValues() {
2023-06-05 21:31:12 +00:00
const ids = this.props.selectedLanguageIds?.map(toString);
if (ids) {
2023-06-05 21:31:12 +00:00
const select = (document.getElementById(this.id) as HTMLSelectElement)
.options;
for (let i = 0; i < select.length; i++) {
2023-06-05 21:31:12 +00:00
const o = select[i];
if (ids.includes(o.value)) {
o.selected = true;
}
}
}
}
render() {
return this.props.iconVersion ? (
this.selectBtn
) : (
<div className="language-select mb-3">
<label
className={classNames(
"col-form-label",
`col-sm-${this.props.multiple ? 3 : 2}`
)}
htmlFor={this.id}
>
{I18NextService.i18n.t(
this.props.multiple ? "language_plural" : "language"
)}
</label>
{this.props.multiple && this.props.showLanguageWarning && (
<div
id="lang-warning"
className="alert small alert-warning"
role="alert"
>
{I18NextService.i18n.t("undetermined_language_warning")}
</div>
)}
<div
className={classNames(`col-sm-${this.props.multiple ? 9 : 10}`, {
"input-group": this.props.multiple,
})}
>
{this.selectBtn}
{this.props.multiple && (
<button
className="btn btn-outline-secondary"
onClick={linkEvent(this, this.handleDeselectAll)}
>
<Icon icon="x" />
</button>
)}
</div>
</div>
);
}
get selectBtn() {
const selectedLangs = this.props.selectedLanguageIds;
const filteredLangs = selectableLanguages(
this.props.allLanguages,
this.props.siteLanguages,
this.props.showAll,
this.props.showSite,
UserService.Instance.myUserInfo
);
return (
<select
feat: Bootstrap 5 (#1378) * feat: Use Bootstrap 5; remove Bootstrap 4 * feat: Add link decoration override global var * fix: Change sr-only to visually-hidden * fix: Fix missing toggle button classes * fix: Use darker green to pass 3:1 contrast and allow foreground color generation * fix: Replace all mr- and ml- classes with me- (end) and ms- (start) classes * fix: Replace all pr- and pl- classes with pe- (end) and ps- (start) classes * fix: Replace custom-select with form-select d-inline-block * fix: Change max-width to Bootstrap 4's max-width * fix: Fix badge colors * fix: Replace deprecated btn-block class with d-block * fix: Temporary fix for missing btn-block styles * fix: Fix margin-left auto and margin-right auto * fix: Fix default border color * fix: Fix some button widths * fix: Fix form row margins * fix: Remove theme color maps; no longer necessary in Bootstrap 5 * fix: Remove unused gray * test commit * fix: Fix deprecated input-group-append usage * fix: Add missing col-form-label classes * fix: Fix some column widths * fix: Fix language dropdown style regression * fix: Fix toast background color * fix: Fix missing colors in red themes * fix: Fix default radio button appearance for toggles * fix: Fix missing margin in search form * fix: Fix search form widths * fix: Fix rate limit form columns * fix: Fix search filters layout * fix: Fix weird table background issue; re-compile from main updates * fix: Fix modlog filter layout * fix: Fix some horizontal margins * fix: Fix incorrect usage of input-group * chore: Empty commit to re-trigger Woodpecker job * fix: Fix incorrect Bootstrap 5 padding class * fix: Tighten up the home filter bars for the hell of it * fix: Fix home filter bar gap --------- Co-authored-by: SleeplessOne1917 <abias1122@gmail.com> Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
2023-06-20 12:01:29 +00:00
className={classNames("form-select w-auto", {
"d-inline-block": !this.props.iconVersion,
})}
id={this.id}
onChange={linkEvent(this, this.handleLanguageChange)}
2023-06-22 00:54:35 +00:00
aria-label={I18NextService.i18n.t("language_select_placeholder")}
aria-describedby={
this.props.multiple && this.props.showLanguageWarning
? "lang-warning"
: ""
}
multiple={this.props.multiple}
disabled={this.props.disabled}
>
{!this.props.multiple && (
<option selected disabled hidden>
2023-06-22 00:54:35 +00:00
{I18NextService.i18n.t("language_select_placeholder")}
</option>
)}
{filteredLangs.map(l => (
<option
key={l.id}
value={l.id}
selected={selectedLangs?.includes(l.id)}
>
{l.name}
</option>
))}
</select>
);
}
handleLanguageChange(i: LanguageSelect, event: any) {
2023-06-05 21:31:12 +00:00
const options: HTMLOptionElement[] = Array.from(event.target.options);
const selected: number[] = options
.filter(o => o.selected)
.map(o => Number(o.value));
i.props.onChange(selected);
}
handleDeselectAll(i: LanguageSelect, event: any) {
event.preventDefault();
i.props.onChange([]);
}
}