🐛 Fix ICounted error on numeric-input token dropdown keyboard nav (#8803)

The options stored in options-ref is a delay (lazy value). In
on-token-key-down, it was passed raw to next-focus-index without being
dereferenced first, causing count to be called on a JS object that does
not implement ICounted.

Fix: dereference the delay in on-token-key-down (matching the existing
pattern in on-key-down), and make next-focus-index itself also handle
delays defensively. Add unit tests covering the delay case.
This commit is contained in:
Andrey Antukh 2026-04-01 11:21:01 +02:00 committed by GitHub
parent 350cc01b72
commit d3ac824912
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 43 additions and 2 deletions

View File

@ -136,9 +136,10 @@
[options]
(some #(when (focusable-option? %) (:id %)) options))
(defn- next-focus-index
(defn next-focus-index
[options focused-id direction]
(let [len (count options)
(let [options (if (delay? options) @options options)
len (count options)
start-index (or (d/index-of-pred options #(= focused-id (:id %))) -1)
indices (case direction
:down (range (inc start-index) (+ len start-index))
@ -586,6 +587,7 @@
up? (kbd/up-arrow? event)
down? (kbd/down-arrow? event)
options (mf/ref-val options-ref)
options (if (delay? options) @options options)
detach-btn (mf/ref-val token-detach-btn-ref)
target (dom/get-target event)]

View File

@ -21,6 +21,7 @@
[frontend-tests.tokens.style-dictionary-test]
[frontend-tests.tokens.token-errors-test]
[frontend-tests.tokens.workspace-tokens-remap-test]
[frontend-tests.ui.ds-controls-numeric-input-test]
[frontend-tests.util-object-test]
[frontend-tests.util-range-tree-test]
[frontend-tests.util-simple-math-test]
@ -55,6 +56,7 @@
'frontend-tests.tokens.logic.token-remapping-test
'frontend-tests.tokens.style-dictionary-test
'frontend-tests.tokens.token-errors-test
'frontend-tests.ui.ds-controls-numeric-input-test
'frontend-tests.util-object-test
'frontend-tests.util-range-tree-test
'frontend-tests.util-simple-math-test

View File

@ -0,0 +1,37 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns frontend-tests.ui.ds-controls-numeric-input-test
(:require
[app.main.ui.ds.controls.numeric-input :refer [next-focus-index]]
[cljs.test :as t :include-macros true]))
(def ^:private sample-options
[{:id "a" :type :item :name "Alpha"}
{:id "b" :type :group :name "Group"}
{:id "c" :type :item :name "Charlie"}
{:id "d" :type :separator :name "---"}
{:id "e" :type :item :name "Echo"}])
(t/deftest test-next-focus-index
(t/testing "returns index of next focusable item going down"
(t/is (= 2 (next-focus-index sample-options "a" :down))))
(t/testing "returns index of next focusable item going up"
(t/is (= 0 (next-focus-index sample-options "c" :up))))
(t/testing "wraps around going down"
(t/is (= 0 (next-focus-index sample-options "e" :down))))
(t/testing "wraps around going up"
(t/is (= 4 (next-focus-index sample-options "a" :up))))
(t/testing "works when options is a delay"
(let [delayed-options (delay sample-options)]
(t/is (= 2 (next-focus-index delayed-options "a" :down)))))
(t/testing "works with nil focused-id (no current selection)"
(t/is (= 0 (next-focus-index sample-options nil :down)))))