chore(react/ribbon): add note types

This commit is contained in:
Elian Doran
2025-08-21 20:30:12 +03:00
parent e2e9721d5f
commit cabeb13adb
5 changed files with 44 additions and 26 deletions

View File

@@ -13,18 +13,10 @@ const NOT_SELECTABLE_NOTE_TYPES = NOTE_TYPES.filter((nt) => nt.reserved || nt.st
const TPL = /*html*/` const TPL = /*html*/`
<div class="dropdown note-type-widget"> <div class="dropdown note-type-widget">
<style>
.note-type-dropdown {
max-height: 500px;
overflow-y: auto;
overflow-x: hidden;
}
</style>
<button type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle select-button note-type-button"> <button type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle select-button note-type-button">
<span class="note-type-desc"></span> <span class="note-type-desc"></span>
<span class="caret"></span> <span class="caret"></span>
</button> </button>
<div class="note-type-dropdown dropdown-menu dropdown-menu-left tn-dropdown-list"></div>
</div> </div>
`; `;
@@ -83,7 +75,7 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
}); });
} else { } else {
this.$noteTypeDropdown.append('<div class="dropdown-divider"></div>'); this.$noteTypeDropdown.append('<div class="dropdown-divider"></div>');
$typeLink = $('<a class="dropdown-item disabled">').attr("data-note-type", noteType.type).append('<span class="check">&check;</span> ').append($("<strong>").text(noteType.title)); $typeLink = $('<a class="dropdown-item disabled">').attr("data-note-type", noteType.type).append('<span class="check">&check;</span> ').append($("<strong>").text());
} }
if (this.note.type === noteType.type) { if (this.note.type === noteType.type) {
@@ -93,15 +85,10 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
this.$noteTypeDropdown.append($typeLink); this.$noteTypeDropdown.append($typeLink);
} }
for (const mimeType of mimeTypesService.getMimeTypes()) { for (const mimeType of ) {
if (!mimeType.enabled) {
continue;
}
const $mimeLink = $('<a class="dropdown-item">') const $mimeLink = $('<a class="dropdown-item">')
.attr("data-mime-type", mimeType.mime) .attr("data-mime-type", mimeType.mime)
.append('<span class="check">&check;</span> ') .append('<span class="check">&check;</span> ')
.append($("<span>").text(mimeType.title))
.on("click", (e) => { .on("click", (e) => {
const $link = $(e.target).closest(".dropdown-item"); const $link = $(e.target).closest(".dropdown-item");

View File

@@ -11,11 +11,12 @@ interface DropdownProps {
children: ComponentChildren; children: ComponentChildren;
title?: string; title?: string;
dropdownContainerStyle?: CSSProperties; dropdownContainerStyle?: CSSProperties;
dropdownContainerClassName?: string;
hideToggleArrow?: boolean; hideToggleArrow?: boolean;
disabled?: boolean; disabled?: boolean;
} }
export default function Dropdown({ className, buttonClassName, isStatic, children, title, dropdownContainerStyle, hideToggleArrow, disabled }: DropdownProps) { export default function Dropdown({ className, buttonClassName, isStatic, children, title, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, disabled }: DropdownProps) {
const dropdownRef = useRef<HTMLDivElement | null>(null); const dropdownRef = useRef<HTMLDivElement | null>(null);
const triggerRef = useRef<HTMLButtonElement | null>(null); const triggerRef = useRef<HTMLButtonElement | null>(null);
@@ -68,7 +69,7 @@ export default function Dropdown({ className, buttonClassName, isStatic, childre
/> />
<div <div
class={`dropdown-menu ${isStatic ? "static" : undefined}`} class={`dropdown-menu ${isStatic ? "static" : ""} ${dropdownContainerClassName ?? ""} tn-dropdown-list`}
style={dropdownContainerStyle} style={dropdownContainerStyle}
aria-labelledby={ariaId} aria-labelledby={ariaId}
> >

View File

@@ -75,12 +75,13 @@ interface FormListItemOpts {
title?: string; title?: string;
active?: boolean; active?: boolean;
badges?: FormListBadge[]; badges?: FormListBadge[];
disabled?: boolean;
} }
export function FormListItem({ children, icon, value, title, active, badges }: FormListItemOpts) { export function FormListItem({ children, icon, value, title, active, badges, disabled }: FormListItemOpts) {
return ( return (
<a <a
class={`dropdown-item ${active ? "active" : ""}`} class={`dropdown-item ${active ? "active" : ""} ${disabled ? "disabled" : ""}`}
data-value={value} title={title} data-value={value} title={title}
tabIndex={0} tabIndex={0}
> >
@@ -104,3 +105,7 @@ export function FormListHeader({ text }: FormListHeaderOpts) {
</li> </li>
) )
} }
export function FormDivider() {
return <div className="dropdown-divider" />;
}

View File

@@ -1,8 +1,10 @@
import { useCallback, useMemo } from "preact/hooks"; import { useCallback, useMemo } from "preact/hooks";
import Dropdown from "../react/Dropdown"; import Dropdown from "../react/Dropdown";
import { NOTE_TYPES } from "../../services/note_types"; import { NOTE_TYPES } from "../../services/note_types";
import { FormListBadge, FormListItem } from "../react/FormList"; import { FormDivider, FormListBadge, FormListItem } from "../react/FormList";
import { t } from "../../services/i18n"; import { t } from "../../services/i18n";
import { useTriliumOption } from "../react/hooks";
import mime_types from "../../services/mime_types";
export default function BasicPropertiesTab() { export default function BasicPropertiesTab() {
return ( return (
@@ -14,9 +16,11 @@ export default function BasicPropertiesTab() {
function NoteTypeWidget() { function NoteTypeWidget() {
const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []); const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []);
const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes");
const mimeTypes = useMemo(() => mime_types.getMimeTypes().filter(mimeType => mimeType.enabled), [ codeNotesMimeTypes ]);
return ( return (
<Dropdown> <Dropdown dropdownContainerClassName="note-type-dropdown">
{noteTypes.map(noteType => { {noteTypes.map(noteType => {
const badges: FormListBadge[] = []; const badges: FormListBadge[] = [];
if (noteType.isNew) { if (noteType.isNew) {
@@ -31,12 +35,27 @@ function NoteTypeWidget() {
}); });
} }
return ( if (noteType.type !== "code") {
<FormListItem return (
badges={badges} <FormListItem
>{noteType.title}</FormListItem> badges={badges}
); >{noteType.title}</FormListItem>
);
} else {
return (
<>
<FormDivider />
<FormListItem disabled>
<strong>{noteType.title}</strong>
</FormListItem>
</>
)
}
})} })}
{mimeTypes.map(mimeType => (
<FormListItem>{mimeType.title}</FormListItem>
))}
</Dropdown> </Dropdown>
) )
} }

View File

@@ -114,4 +114,10 @@
.note-language-container { .note-language-container {
display: flex; display: flex;
align-items: center; align-items: center;
}
.note-type-dropdown {
max-height: 500px;
overflow-y: auto;
overflow-x: hidden;
} }