diff --git a/frontend/components/FrontmatterInput.js b/frontend/components/FrontmatterInput.js
index b0d8061a96..e6f1869833 100644
--- a/frontend/components/FrontmatterInput.js
+++ b/frontend/components/FrontmatterInput.js
@@ -3,6 +3,7 @@ import { has_ctrl_or_cmd_pressed } from "../common/KeyboardShortcuts.js"
import _ from "../imports/lodash.js"
import "https://cdn.jsdelivr.net/gh/fonsp/rebel-tag-input@1.0.6/lib/rebel-tag-input.mjs"
+import "https://esm.sh/bcp47-picker@1.0.16?pin=v134&target=es2020"
//@ts-ignore
import immer from "../imports/immer.js"
@@ -179,7 +180,7 @@ const clean_data = (obj) => {
return _.isEmpty(a) ? null : a
}
-const special_field_names = ["tags", "date", "license", "url", "color"]
+const special_field_names = ["tags", "date", "language", "license", "url", "color"]
const field_type = (name) => {
for (const t of special_field_names) {
@@ -195,8 +196,12 @@ const Input = ({ value, on_value, type, id }) => {
useLayoutEffect(() => {
if (!input_ref.current) return
- input_ref.current.value = value
- }, [input_ref.current, value])
+ if (type === "language") {
+ input_ref.current.setAttribute("value", value)
+ } else {
+ input_ref.current.value = value
+ }
+ }, [input_ref.current, value, type])
useLayoutEffect(() => {
if (!input_ref.current) return
@@ -205,11 +210,12 @@ const Input = ({ value, on_value, type, id }) => {
on_value(input_ref.current.value)
}
- input_ref.current.addEventListener("input", listener)
+ let event_name = type === "language" ? "change" : "input"
+ input_ref.current.addEventListener(event_name, listener)
return () => {
- input_ref.current?.removeEventListener("input", listener)
+ input_ref.current?.removeEventListener(event_name, listener)
}
- }, [input_ref.current])
+ }, [input_ref.current, type])
const placeholder = type === "url" ? "https://..." : undefined
@@ -217,6 +223,8 @@ const Input = ({ value, on_value, type, id }) => {
? html``
: type === "license"
? LicenseInput({ ref: input_ref, id })
+ : type === "language"
+ ? LanguageInput({ ref: input_ref, id })
: html``
}
@@ -236,3 +244,7 @@ const LicenseInput = ({ ref, id }) => {
`
}
+
+const LanguageInput = ({ ref, id }) => {
+ return html``
+}
diff --git a/frontend/editor.css b/frontend/editor.css
index f97b297873..0b287a9b8b 100644
--- a/frontend/editor.css
+++ b/frontend/editor.css
@@ -1,4 +1,6 @@
@import url("https://cdn.jsdelivr.net/npm/dialog-polyfill@0.5.6/dist/dialog-polyfill.css");
+@import url("https://cdn.jsdelivr.net/npm/bcp47-picker@1.0.16/dist/bcp47-picker.css");
+@import url("https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css");
/* @import url("https://fonts.googleapis.com/css?family=Roboto+Mono:400,400i,500,700&display=swap&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext"); */
@import url("https://cdn.jsdelivr.net/npm/@fontsource/roboto-mono@4.4.5/400.css");
@@ -25,6 +27,52 @@
@import url("./featured-card.css");
+.bootstrap .input-group {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: stretch;
+ width: 100%;
+}
+
+.bootstrap .list-group {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ border-radius: 0.25rem;
+}
+.bootstrap .list-group-item.active {
+ z-index: 2;
+ color: #fff;
+ background-color: #0d6efd;
+ border-color: #0d6efd;
+}
+
+.bootstrap .gap-2 {
+ gap: 0.5rem !important;
+}
+.bootstrap .d-flex {
+ display: flex !important;
+}
+.bootstrap .form-control {
+ display: block;
+ width: 100%;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #212529;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #ced4da;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ border-radius: 0.25rem;
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+
/* VARIABLES */
:root {