@funnest/charts-ui 0.6.15 → 0.6.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +38 -5
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1821,6 +1821,8 @@ var DEBOUNCE_MS = 150;
1821
1821
  var RECENT_KEY2 = "recent-symbols";
1822
1822
  var FAVORITE_KEY = "favorite-symbols";
1823
1823
  var MAX_RECENT = 8;
1824
+ var FIRST_ROWS = 40;
1825
+ var MORE_ROWS = 80;
1824
1826
  var displayCode = (symbol) => symbol.slice(symbol.lastIndexOf(":") + 1);
1825
1827
  var toStored = (info) => JSON.parse(JSON.stringify({ ...info, tickSize: 0, price: void 0, changePercent: void 0, sparkline: void 0 }));
1826
1828
  function Highlight({ text, query }) {
@@ -1896,8 +1898,10 @@ function SymbolSearch({ ctx }) {
1896
1898
  const [recent, setRecent] = d2(() => ctx.storage.get(RECENT_KEY2, []));
1897
1899
  const [favorites, setFavorites] = d2(() => ctx.storage.get(FAVORITE_KEY, []));
1898
1900
  const [active, setActive] = d2(0);
1901
+ const [limit, setLimit] = d2(FIRST_ROWS);
1899
1902
  const inputRef = T2(null);
1900
1903
  const listRef = T2(null);
1904
+ const endRef = T2(null);
1901
1905
  A2(() => inputRef.current?.focus(), []);
1902
1906
  A2(() => {
1903
1907
  let alive = true;
@@ -1923,7 +1927,8 @@ function SymbolSearch({ ctx }) {
1923
1927
  }, [query]);
1924
1928
  const matchCategory = ctx.searchCategories.find((c3) => c3.id === category)?.match ?? (() => true);
1925
1929
  const categoryOf = (info) => ctx.searchCategories.find((c3) => c3.id !== "all" && c3.match(info));
1926
- const isFavorite = (info) => favorites.some((f4) => f4.symbol === info.symbol);
1930
+ const favoriteSet = w2(() => new Set(favorites.map((f4) => f4.symbol)), [favorites]);
1931
+ const isFavorite = (info) => favoriteSet.has(info.symbol);
1927
1932
  const filter = (list) => list.filter((i3) => matchCategory(i3) && (!exchange || i3.exchange === exchange));
1928
1933
  const exchanges = w2(() => {
1929
1934
  const counts = /* @__PURE__ */ new Map();
@@ -1954,11 +1959,36 @@ function SymbolSearch({ ctx }) {
1954
1959
  }
1955
1960
  }
1956
1961
  const rows = [...recentRows, ...resultRows];
1962
+ const shownRows = resultRows.length > limit ? resultRows.slice(0, limit) : resultRows;
1957
1963
  const exchangeLabel = (name) => ctx.searchExchanges.find((e3) => e3.name === name)?.label?.[locale] ?? name;
1958
1964
  A2(() => setActive(0), [query, category, exchange, view, results]);
1959
1965
  A2(() => {
1960
- listRef.current?.querySelector(`[data-index="${active}"]`)?.scrollIntoView({ block: "nearest" });
1966
+ setLimit(FIRST_ROWS);
1967
+ if (listRef.current) listRef.current.scrollTop = 0;
1968
+ }, [query, category, exchange, view]);
1969
+ const hasMore = resultRows.length > limit;
1970
+ A2(() => {
1971
+ const end = endRef.current;
1972
+ if (!hasMore || !end) return;
1973
+ const io = new IntersectionObserver((entries) => entries.some((e3) => e3.isIntersecting) && setLimit((l3) => l3 + MORE_ROWS), {
1974
+ root: listRef.current,
1975
+ rootMargin: "0px 0px 600px 0px"
1976
+ });
1977
+ io.observe(end);
1978
+ return () => io.disconnect();
1979
+ }, [hasMore, limit]);
1980
+ const scrollToActive = T2(false);
1981
+ A2(() => {
1982
+ if (active - recentRows.length >= limit - 1) {
1983
+ scrollToActive.current = true;
1984
+ setLimit(active - recentRows.length + MORE_ROWS);
1985
+ } else listRef.current?.querySelector(`[data-index="${active}"]`)?.scrollIntoView({ block: "nearest" });
1961
1986
  }, [active]);
1987
+ A2(() => {
1988
+ if (!scrollToActive.current) return;
1989
+ scrollToActive.current = false;
1990
+ listRef.current?.querySelector(`[data-index="${active}"]`)?.scrollIntoView({ block: "nearest" });
1991
+ }, [limit]);
1962
1992
  const close = () => ctx.setSearchOpen(false);
1963
1993
  const save = (key, next, set) => {
1964
1994
  set(next);
@@ -2048,7 +2078,8 @@ function SymbolSearch({ ctx }) {
2048
2078
  }
2049
2079
  )
2050
2080
  ]
2051
- }
2081
+ },
2082
+ (isRecent ? "recent:" : "") + info.symbol
2052
2083
  );
2053
2084
  };
2054
2085
  const sideItem = (label, selected, onClick, extra, logoUrl) => /* @__PURE__ */ a3("button", { class: "fnc-sr-side-item", "aria-pressed": selected, onClick, children: [
@@ -2104,13 +2135,14 @@ function SymbolSearch({ ctx }) {
2104
2135
  ] }),
2105
2136
  recentRows.map((info, i3) => row2(info, i3, true)),
2106
2137
  (recentRows.length > 0 || view.kind === "favorites") && /* @__PURE__ */ a3("div", { class: "fnc-sr-section", children: view.kind === "favorites" ? t3.favorites : t3.symbols }),
2107
- loading && !results && view.kind === "all" ? Array.from({ length: 6 }, () => /* @__PURE__ */ a3("div", { class: "fnc-sr-skeleton", "aria-hidden": "true" })) : resultRows.map((info, i3) => {
2138
+ loading && !results && view.kind === "all" ? Array.from({ length: 6 }, () => /* @__PURE__ */ a3("div", { class: "fnc-sr-skeleton", "aria-hidden": "true" })) : shownRows.map((info, i3) => {
2108
2139
  const m3 = more.get(i3);
2109
2140
  return m3 ? /* @__PURE__ */ a3($, { children: [
2110
2141
  row2(info, recentRows.length + i3, false),
2111
2142
  /* @__PURE__ */ a3("button", { class: "fnc-sr-more", onClick: () => (setView({ kind: "all" }), setExchange(m3.exchange)), children: t3.showAllIn.replace("{exchange}", exchangeLabel(m3.exchange)).replace("{n}", m3.count.toLocaleString(locale === "ko" ? "ko-KR" : "en-US")) })
2112
- ] }) : row2(info, recentRows.length + i3, false);
2143
+ ] }, info.symbol) : row2(info, recentRows.length + i3, false);
2113
2144
  }),
2145
+ hasMore && /* @__PURE__ */ a3("div", { ref: endRef, class: "fnc-sr-end", "aria-hidden": "true" }),
2114
2146
  !loading && rows.length === 0 && /* @__PURE__ */ a3("div", { class: "fnc-empty", children: view.kind === "favorites" && favorites.length === 0 ? t3.noFavorites : t3.noResults })
2115
2147
  ] })
2116
2148
  ] }),
@@ -3255,6 +3287,7 @@ var CSS = (
3255
3287
  .fnc-sr-spark-slot { display: inline-flex; flex: none; width: 72px; height: 24px; }
3256
3288
  .fnc-sr-more { display: block; width: calc(100% - 16px); margin: 2px 8px 8px; padding: 8px 12px; border-radius: var(--fnc-radius); background: var(--fnc-surface); color: var(--fnc-text-2); font-size: 13px; font-weight: 600; text-align: left; }
3257
3289
  .fnc-sr-more:hover { color: var(--fnc-text); }
3290
+ .fnc-sr-end { height: 1px; }
3258
3291
  .fnc-sr-side-item:hover { background: var(--fnc-surface); }
3259
3292
  .fnc-sr-side-item[aria-pressed='true'] { background: var(--fnc-surface); font-weight: 700; }
3260
3293
  .fnc-chip-token {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnest/charts-ui",
3
- "version": "0.6.15",
3
+ "version": "0.6.16",
4
4
  "description": "Pro trading UI (toolbar, drawing tools, sheets) for Funnest Charts. Framework-agnostic.",
5
5
  "keywords": [
6
6
  "chart",
@@ -42,7 +42,7 @@
42
42
  "NOTICE"
43
43
  ],
44
44
  "dependencies": {
45
- "@funnest/charts": "0.6.15"
45
+ "@funnest/charts": "0.6.16"
46
46
  },
47
47
  "devDependencies": {
48
48
  "preact": "^11.2.0"