diff --git a/apps/client/src/widgets/note_icon.tsx b/apps/client/src/widgets/note_icon.tsx index af20a69d0..76d8cbed0 100644 --- a/apps/client/src/widgets/note_icon.tsx +++ b/apps/client/src/widgets/note_icon.tsx @@ -3,9 +3,10 @@ import "./note_icon.css"; import { IconRegistry } from "@triliumnext/commons"; import { Dropdown as BootstrapDropdown } from "bootstrap"; import clsx from "clsx"; -import { t, use } from "i18next"; -import { RefObject } from "preact"; +import { t } from "i18next"; +import { CSSProperties, RefObject } from "preact"; import { useEffect, useMemo, useRef, useState } from "preact/hooks"; +import { CellComponentProps, Grid } from "react-window"; import FNote from "../entities/fnote"; import attributes from "../services/attributes"; @@ -132,13 +133,16 @@ function NoteIconList({ note, dropdownRef }: { }} > {filteredIcons.length ? ( - (filteredIcons ?? []).map(({ id, terms, iconPack }) => ( - - )) + ) : (
{t("note_icon.no_results")}
)} @@ -147,6 +151,22 @@ function NoteIconList({ note, dropdownRef }: { ); } +function IconItemCell({ rowIndex, columnIndex, style, filteredIcons }: CellComponentProps<{ + filteredIcons: IconWithName[]; +}>): React.JSX.Element { + const iconIndex = rowIndex * 12 + columnIndex; + const iconData = filteredIcons[iconIndex]; + const { id, terms, iconPack } = iconData; + return ( + + ); +} + function IconFilterContent({ filterByPrefix, setFilterByPrefix }: { filterByPrefix: string | null; setFilterByPrefix: (value: string | null) => void; @@ -212,7 +232,7 @@ function useFilteredIcons(allIcons: IconWithName[] | undefined, search: string | if (processedSearch || filterByPrefix !== null) { icons = icons.filter((icon) => { if (filterByPrefix) { - if (!icon.id?.startsWith(`${filterByPrefix}-`)) { + if (!icon.id?.startsWith(`${filterByPrefix} `)) { return false; } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b11794447..3758f174c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -292,6 +292,9 @@ importers: react-i18next: specifier: 16.5.0 version: 16.5.0(i18next@25.7.3(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + react-window: + specifier: 2.2.3 + version: 2.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) reveal.js: specifier: 5.2.1 version: 5.2.1 @@ -483,11 +486,7 @@ importers: specifier: 11.3.3 version: 11.3.3 - apps/icon-pack-builder: - devDependencies: - '@phosphor-icons/web': - specifier: 2.1.2 - version: 2.1.2 + apps/icon-pack-builder: {} apps/server: dependencies: @@ -4035,9 +4034,6 @@ packages: resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} engines: {node: '>= 10.0.0'} - '@phosphor-icons/web@2.1.2': - resolution: {integrity: sha512-rPAR9o/bEcp4Cw4DEeZHXf+nlGCMNGkNDRizYHM47NLxz9vvEHp/Tt6FMK1NcWadzw/pFDPnRBGi/ofRya958A==} - '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -12010,6 +12006,12 @@ packages: peerDependencies: react: ^18.0.0 || ^19.0.0 + react-window@2.2.3: + resolution: {integrity: sha512-gTRqQYC8ojbiXyd9duYFiSn2TJw0ROXCgYjenOvNKITWzK0m0eCvkUsEUM08xvydkMh7ncp+LE0uS3DeNGZxnQ==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + react@16.14.0: resolution: {integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==} engines: {node: '>=0.10.0'} @@ -18460,8 +18462,6 @@ snapshots: '@parcel/watcher-win32-x64': 2.5.1 optional: true - '@phosphor-icons/web@2.1.2': {} - '@pkgjs/parseargs@0.11.0': optional: true @@ -28213,6 +28213,11 @@ snapshots: prop-types: 15.8.1 react: 19.2.3 + react-window@2.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + react@16.14.0: dependencies: loose-envify: 1.4.0