From 2c8a44dfa128264023e106498498ca5a19b771e8 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Mon, 25 Nov 2024 15:11:54 +0100 Subject: [PATCH] :sparkles: new combobox component to the ds with component testing --- frontend/.storybook/main.js | 2 +- frontend/package.json | 14 +- frontend/src/app/main/ui/ds.cljs | 2 + .../src/app/main/ui/ds/controls/combobox.cljs | 252 ++++++++ .../src/app/main/ui/ds/controls/combobox.mdx | 62 ++ .../src/app/main/ui/ds/controls/combobox.scss | 87 +++ .../main/ui/ds/controls/combobox.stories.jsx | 216 +++++++ .../src/app/main/ui/ds/controls/select.cljs | 58 +- .../src/app/main/ui/ds/controls/select.scss | 65 -- .../ds/controls/shared/options_dropdown.cljs | 69 ++ .../ds/controls/shared/options_dropdown.scss | 74 +++ frontend/yarn.lock | 605 ++++++++++++------ 12 files changed, 1191 insertions(+), 315 deletions(-) create mode 100644 frontend/src/app/main/ui/ds/controls/combobox.cljs create mode 100644 frontend/src/app/main/ui/ds/controls/combobox.mdx create mode 100644 frontend/src/app/main/ui/ds/controls/combobox.scss create mode 100644 frontend/src/app/main/ui/ds/controls/combobox.stories.jsx create mode 100644 frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs create mode 100644 frontend/src/app/main/ui/ds/controls/shared/options_dropdown.scss diff --git a/frontend/.storybook/main.js b/frontend/.storybook/main.js index cd48f83bc..3c975df2e 100644 --- a/frontend/.storybook/main.js +++ b/frontend/.storybook/main.js @@ -2,7 +2,7 @@ const config = { stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], staticDirs: ["../resources/public"], - addons: ["@storybook/addon-essentials", "@storybook/addon-themes"], + addons: ["@storybook/addon-essentials", "@storybook/addon-themes", "@storybook/addon-interactions"], core: { builder: "@storybook/builder-vite", options: { diff --git a/frontend/package.json b/frontend/package.json index 8d5760f3b..0f85bf1b2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -48,11 +48,13 @@ }, "devDependencies": { "@playwright/test": "1.48.1", - "@storybook/addon-essentials": "^8.3.6", - "@storybook/addon-themes": "^8.3.6", - "@storybook/blocks": "^8.3.6", - "@storybook/react": "^8.3.6", - "@storybook/react-vite": "^8.3.6", + "@storybook/addon-essentials": "^8.4.6", + "@storybook/addon-interactions": "^8.4.6", + "@storybook/addon-themes": "^8.4.6", + "@storybook/blocks": "^8.4.6", + "@storybook/react": "^8.4.6", + "@storybook/react-vite": "^8.4.6", + "@storybook/test": "^8.4.6", "@types/node": "^22.7.7", "autoprefixer": "^10.4.20", "concurrently": "^9.0.1", @@ -86,7 +88,7 @@ "sass": "^1.80.3", "sass-embedded": "^1.80.3", "shadow-cljs": "2.28.18", - "storybook": "^8.3.6", + "storybook": "^8.4.6", "svg-sprite": "^2.0.4", "typescript": "^5.6.3", "vite": "^5.4.9", diff --git a/frontend/src/app/main/ui/ds.cljs b/frontend/src/app/main/ui/ds.cljs index 89f8a4961..435dd91b3 100644 --- a/frontend/src/app/main/ui/ds.cljs +++ b/frontend/src/app/main/ui/ds.cljs @@ -9,6 +9,7 @@ [app.config :as cf] [app.main.ui.ds.buttons.button :refer [button*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] + [app.main.ui.ds.controls.combobox :refer [combobox*]] [app.main.ui.ds.controls.input :refer [input*]] [app.main.ui.ds.controls.select :refer [select*]] [app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]] @@ -37,6 +38,7 @@ :Loader loader* :RawSvg raw-svg* :Select select* + :Combobox combobox* :Text text* :TabSwitcher tab-switcher* :Toast toast* diff --git a/frontend/src/app/main/ui/ds/controls/combobox.cljs b/frontend/src/app/main/ui/ds/controls/combobox.cljs new file mode 100644 index 000000000..e39efedb1 --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/combobox.cljs @@ -0,0 +1,252 @@ +;; 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 app.main.ui.ds.controls.combobox + (:require-macros + [app.common.data.macros :as dm] + [app.main.style :as stl]) + (:require + [app.main.ui.ds.controls.shared.options-dropdown :refer [options-dropdown*]] + [app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list] :as i] + [app.util.array :as array] + [app.util.dom :as dom] + [app.util.keyboard :as kbd] + [app.util.object :as obj] + [rumext.v2 :as mf])) + +(def listbox-id-index (atom 0)) + +(defn- get-option + [options id] + (array/find #(= id (obj/get % "id")) options)) + +(defn- handle-focus-change + [options focused* new-index options-nodes-refs] + (let [option (aget options new-index) + id (obj/get option "id") + nodes (mf/ref-val options-nodes-refs) + node (obj/get nodes id)] + (reset! focused* id) + (dom/scroll-into-view-if-needed! node))) + +(defn- handle-selection + [focused* selected* open*] + (when-let [focused (deref focused*)] + (reset! selected* focused)) + (reset! open* false) + (reset! focused* nil)) + +(def ^:private schema:combobox-option + [:and + [:map {:title "option"} + [:id :string] + [:icon {:optional true} + [:and :string [:fn #(contains? icon-list %)]]] + [:label {:optional true} :string] + [:aria-label {:optional true} :string]] + [:fn {:error/message "invalid data: missing required props"} + (fn [option] + (or (and (contains? option :icon) + (or (contains? option :label) + (contains? option :aria-label))) + (contains? option :label)))]]) + +(def ^:private schema:combobox + [:map + [:options [:vector {:min 1} schema:combobox-option]] + [:class {:optional true} :string] + [:disabled {:optional true} :boolean] + [:default-selected {:optional true} :string] + [:on-change {:optional true} fn?]]) + +(mf/defc combobox* + {::mf/props :obj + ::mf/schema schema:combobox} + [{:keys [options class disabled default-selected on-change] :rest props}] + (let [open* (mf/use-state false) + open (deref open*) + + selected* (mf/use-state default-selected) + selected (deref selected*) + + focused* (mf/use-state nil) + focused (deref focused*) + + has-focus* (mf/use-state false) + has-focus (deref has-focus*) + + dropdown-options + (mf/use-memo + (mf/deps options selected) + (fn [] + (->> options + (array/filter (fn [option] + (let [lower-option (.toLowerCase (obj/get option "id")) + lower-filter (.toLowerCase selected)] + (.includes lower-option lower-filter))))))) + + on-click + (mf/use-fn + (mf/deps disabled) + (fn [event] + (dom/stop-propagation event) + (when-not disabled + (reset! has-focus* true) + (if (= "INPUT" (.-tagName (.-target event))) + (reset! open* true) + (swap! open* not))))) + + on-option-click + (mf/use-fn + (mf/deps on-change) + (fn [event] + (let [node (dom/get-current-target event) + id (dom/get-data node "id")] + (reset! selected* id) + (reset! focused* nil) + (reset! open* false) + (when (fn? on-change) + (on-change id))))) + + options-nodes-refs (mf/use-ref nil) + options-ref (mf/use-ref nil) + listbox-id-ref (mf/use-ref (dm/str "listbox-" (swap! listbox-id-index inc))) + listbox-id (mf/ref-val listbox-id-ref) + combobox-ref (mf/use-ref nil) + + set-ref + (mf/use-fn + (fn [node id] + (let [refs (or (mf/ref-val options-nodes-refs) #js {}) + refs (if node + (obj/set! refs id node) + (obj/unset! refs id))] + (mf/set-ref-val! options-nodes-refs refs)))) + + on-blur + (mf/use-fn + (fn [event] + (let [target (.-relatedTarget event) + outside? (not (.contains (mf/ref-val combobox-ref) target))] + (when outside? + (reset! focused* nil) + (reset! open* false) + (reset! has-focus* false))))) + + on-key-down + (mf/use-fn + (mf/deps open focused disabled dropdown-options) + (fn [event] + (when-not disabled + (let [options dropdown-options + focused (deref focused*) + len (alength options) + index (array/find-index #(= (deref focused*) (obj/get % "id")) options)] + (dom/stop-propagation event) + + (when (< len 0) + (reset! index len)) + + (cond + (and (not open) (kbd/down-arrow? event)) + (reset! open* true) + + open + (cond + (kbd/home? event) + (handle-focus-change options focused* 0 options-nodes-refs) + + (kbd/up-arrow? event) + (let [new-index (if (= index -1) + (dec len) + (mod (- index 1) len))] + (handle-focus-change options focused* new-index options-nodes-refs)) + + + (kbd/down-arrow? event) + (let [new-index (if (= index -1) + 0 + (mod (+ index 1) len))] + (handle-focus-change options focused* new-index options-nodes-refs)) + + (or (kbd/space? event) (kbd/enter? event)) + (when (deref open*) + (dom/prevent-default event) + (handle-selection focused* selected* open*) + (when (fn? on-change) + (on-change focused))) + + (kbd/esc? event) + (do (reset! open* false) + (reset! focused* nil)))))))) + + on-input-change + (mf/use-fn + (fn [event] + (let [value (.-value (.-currentTarget event))] + (reset! selected* value) + (reset! focused* nil) + (when (fn? on-change) + (on-change value))))) + on-focus + (mf/use-fn + (fn [_] (reset! has-focus* true))) + + class (dm/str class " " (stl/css :combobox)) + + selected-option (get-option options selected) + icon (obj/get selected-option "icon")] + + (mf/with-effect [options] + (mf/set-ref-val! options-ref options)) + + [:div {:ref combobox-ref + :class (stl/css-case + :combobox-wrapper true + :focused has-focus)} + + [:div {:class class + :on-click on-click + :on-focus on-focus + :on-blur on-blur} + [:span {:class (stl/css-case :combobox-header true + :header-icon (some? icon))} + (when icon + [:> icon* {:id icon + :size "s" + :aria-hidden true}]) + [:input {:type "text" + :role "combobox" + :aria-autocomplete "both" + :aria-expanded open + :aria-controls listbox-id + :aria-activedescendant focused + :class (stl/css :input) + :data-testid "combobox-input" + :disabled disabled + :value selected + :on-change on-input-change + :on-key-down on-key-down}]] + + [:> :button {:tab-index "-1" + :aria-expanded open + :aria-controls listbox-id + :class (stl/css :button-toggle-list) + :on-click on-click} + [:> icon* {:id i/arrow + :class (stl/css :arrow) + :size "s" + :aria-hidden true + :data-testid "combobox-open-button"}]]] + + (when (and open (seq dropdown-options)) + [:> options-dropdown* {:on-click on-option-click + :options dropdown-options + :selected selected + :focused focused + :set-ref set-ref + :id listbox-id + :data-testid "combobox-options"}])])) diff --git a/frontend/src/app/main/ui/ds/controls/combobox.mdx b/frontend/src/app/main/ui/ds/controls/combobox.mdx new file mode 100644 index 000000000..3d2016a88 --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/combobox.mdx @@ -0,0 +1,62 @@ +import { Canvas, Meta } from "@storybook/blocks"; +import * as ComboboxStories from "./combobox.stories"; + + + +# Combobox + +Combobox lets users choose one option from an options menu or enter a custom value that is not listed in the menu. It combines the functionality of a dropdown menu and an input field, allowing for both selection and free-form input. + +## Variants + +**Text**: We will use this variant when there are enough space and icons don't add any useful context. + + + +**Icon and text**: We will use this variant when there are enough space and icons add any useful context. + + + +## Technical notes + +### Icons + +Each option of `combobox*` may accept an `icon`, which must contain an [icon ID](../foundations/assets/icon.mdx). +These are available in the `app.main.ds.foundations.assets.icon` namespace. + +```clj +(ns app.main.ui.foo + (:require + [app.main.ui.ds.foundations.assets.icon :as i])) +``` + +```clj +[:> combobox* + {:options [{ :label "Code" + :id "option-code" + :icon i/fill-content } + { :label "Design" + :id "option-design" + :icon i/pentool } + { :label "Menu" + :id "option-menu" } + ]}] +``` + + + +## Usage guidelines (design) + +### Where to Use + +Combobox is used in applications where users need to select from a range of text-based options or enter custom input. + +### When to Use + +Consider using a combobox when you have five or more options to present, and users may benefit from the ability to search or input a custom value that is not in the predefined list. + +### Interaction / Behavior + +- **Opening Options**: When the user clicks on the input area, a dropdown menu of options appears. Users can either scroll through the options, type to filter them, or input a new value directly. +- **Selecting an Option**: Once an option is selected or a custom value is entered, the dropdown closes, and the input field displays the chosen value. +- **Keyboard Support**: Combobox supports navigation using keyboard input, including arrow keys to navigate the list and Enter to make a selection. diff --git a/frontend/src/app/main/ui/ds/controls/combobox.scss b/frontend/src/app/main/ui/ds/controls/combobox.scss new file mode 100644 index 000000000..9fad67590 --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/combobox.scss @@ -0,0 +1,87 @@ +// 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 + +@use "../_borders.scss" as *; +@use "../_sizes.scss" as *; +@use "../typography.scss" as *; + +.combobox-wrapper { + --combobox-icon-fg-color: var(--color-foreground-secondary); + --combobox-fg-color: var(--color-foreground-primary); + --combobox-bg-color: var(--color-background-tertiary); + --combobox-outline-color: none; + --combobox-border-color: none; + + @include use-typography("body-small"); + position: relative; + display: grid; + grid-template-rows: auto; + gap: var(--sp-xxs); + width: 100%; + + &:hover { + --combobox-bg-color: var(--color-background-quaternary); + } +} + +.combobox { + display: grid; + grid-template-columns: 1fr auto; + gap: var(--sp-xs); + height: $sz-32; + width: 100%; + padding: var(--sp-s); + border: none; + border-radius: $br-8; + outline: $b-1 solid var(--combobox-outline-color); + border: $b-1 solid var(--combobox-border-color); + background: var(--combobox-bg-color); + color: var(--combobox-fg-color); + appearance: none; + + &:disabled { + --combobox-bg-color: var(--color-background-primary); + --combobox-border-color: var(--color-background-quaternary); + --combobox-fg-color: var(--color-foreground-secondary); + } +} + +.focused { + --combobox-outline-color: var(--color-accent-primary); +} + +.arrow { + color: var(--combobox-icon-fg-color); + transform: rotate(90deg); +} + +.combobox-header { + display: grid; + justify-items: start; + gap: var(--sp-xs); +} + +.input { + all: unset; + + @include use-typography("body-small"); + background-color: transparent; + overflow: hidden; + text-align: left; + inline-size: 100%; + padding-inline-start: var(--sp-xxs); + color: var(--combobox-fg-color); +} + +.header-icon { + grid-template-columns: auto 1fr; + color: var(--combobox-icon-fg-color); +} + +.button-toggle-list { + all: unset; + display: flex; +} diff --git a/frontend/src/app/main/ui/ds/controls/combobox.stories.jsx b/frontend/src/app/main/ui/ds/controls/combobox.stories.jsx new file mode 100644 index 000000000..331863937 --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/combobox.stories.jsx @@ -0,0 +1,216 @@ +// 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 + +import * as React from "react"; +import Components from "@target/components"; + +import { userEvent, within, expect } from "@storybook/test"; + +const { Combobox } = Components; + +let lastValue = null; + +export default { + title: "Controls/Combobox", + component: Combobox, + argTypes: { + disabled: { control: "boolean" }, + }, + args: { + disabled: false, + options: [ + { id: "January", label: "January" }, + { id: "February", label: "February" }, + { id: "March", label: "March" }, + { id: "April", label: "April" }, + { id: "May", label: "May" }, + { id: "June", label: "June" }, + { id: "July", label: "July" }, + { id: "August", label: "August" }, + { id: "September", label: "September" }, + { id: "October", label: "October" }, + { id: "November", label: "November" }, + { id: "December", label: "December" }, + ], + defaultSelected: "February", + onChange: (value) => (lastValue = value), + }, + parameters: { + controls: { + exclude: ["options", "defaultSelected"], + }, + }, + render: ({ ...args }) => ( +
+ +
+ ), +}; + +export const Default = { + parameters: { + docs: { + story: { + height: "450px", + }, + }, + }, +}; + +export const WithIcons = { + args: { + options: [ + { id: "January", label: "January", icon: "fill-content" }, + { id: "February", label: "February", icon: "pentool" }, + { id: "March", label: "March" }, + { id: "April", label: "April" }, + { id: "May", label: "May" }, + { id: "June", label: "June" }, + { id: "July", label: "July" }, + { id: "August", label: "August" }, + { id: "September", label: "September" }, + { id: "October", label: "October" }, + { id: "November", label: "November" }, + { id: "December", label: "December" }, + ], + }, + parameters: { + docs: { + story: { + height: "450px", + }, + }, + }, +}; + +export const TestInteractions = { + ...WithIcons, + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + + const combobox = await canvas.getByRole("combobox"); + const button = await canvas.getByTestId("combobox-open-button"); + const input = await canvas.getByTestId("combobox-input"); + + const waitOptionNotPresent = async () => { + expect(canvas.queryByTestId("combobox-options")).not.toBeInTheDocument(); + }; + + const waitOptionsPresent = async () => { + const options = await canvas.findByTestId("combobox-options"); + expect(options).toBeVisible(); + + return options; + }; + + await userEvent.clear(input); + + await step("Toggle dropdown on click arrow button", async () => { + await userEvent.click(button); + + await waitOptionsPresent(); + expect(combobox).toHaveAttribute("aria-expanded", "true"); + + await userEvent.click(button); + await waitOptionNotPresent(); + expect(combobox).toHaveAttribute("aria-expanded", "false"); + }); + + await step("Aria controls is set correctly", async () => { + await userEvent.click(button); + + const ariaControls = combobox.getAttribute("aria-controls"); + + const options = await canvas.findByTestId("combobox-options"); + + expect(options).toHaveAttribute("id", ariaControls); + }); + + await step("Navigation keys", async () => { + // Arrow down + await userEvent.click(input); + await waitOptionsPresent(); + + await userEvent.keyboard("{ArrowDown}"); + await userEvent.keyboard("{ArrowDown}"); + await userEvent.keyboard("{Enter}"); + + expect(input).toHaveValue("February"); + expect(lastValue).toBe("February"); + await userEvent.clear(input); + + // Arrow up + await userEvent.keyboard("{ArrowDown}"); + await waitOptionsPresent(); + + await userEvent.keyboard("{ArrowUp}"); + await userEvent.keyboard("{ArrowUp}"); + expect(combobox).toHaveAttribute("aria-activedescendant", "November"); + await userEvent.keyboard("{Enter}"); + + expect(input).toHaveValue("November"); + expect(lastValue).toBe("November"); + await userEvent.clear(input); + + // Home + await userEvent.keyboard("{ArrowDown}"); + await waitOptionsPresent(); + + await userEvent.keyboard("{ArrowDown}"); + await userEvent.keyboard("{ArrowDown}"); + await userEvent.keyboard("{Home}"); + expect(combobox).toHaveAttribute("aria-activedescendant", "January"); + await userEvent.keyboard("{Enter}"); + + expect(input).toHaveValue("January"); + expect(lastValue).toBe("January"); + await userEvent.clear(input); + }); + + await step("Toggle dropdown with arrow down and ESC", async () => { + userEvent.click(input); + + await waitOptionsPresent(); + + await userEvent.keyboard("{Escape}"); + expect(combobox).toHaveAttribute("aria-expanded", "false"); + await waitOptionNotPresent(); + + await userEvent.keyboard("{ArrowDown}"); + await waitOptionsPresent(); + expect(combobox).toHaveAttribute("aria-expanded", "true"); + + await userEvent.keyboard("{Escape}"); + await waitOptionNotPresent(); + expect(combobox).toHaveAttribute("aria-expanded", "false"); + }); + + await step("Filter with 'Ju' and select July", async () => { + await userEvent.type(input, "Ju"); + + const options = await canvas.findAllByTestId("dropdown-option"); + expect(options).toHaveLength(2); + + await userEvent.keyboard("{ArrowDown}"); + await userEvent.keyboard("{ArrowDown}"); + + await userEvent.keyboard("{Enter}"); + + expect(input).toHaveValue("July"); + expect(lastValue).toBe("July"); + }); + + await step("Close dropdown when focus out", async () => { + await userEvent.click(button); + + await waitOptionsPresent(); + + await userEvent.tab(); + + await waitOptionNotPresent(); + }); + }, +}; diff --git a/frontend/src/app/main/ui/ds/controls/select.cljs b/frontend/src/app/main/ui/ds/controls/select.cljs index e50e6a45f..0d2730ebb 100644 --- a/frontend/src/app/main/ui/ds/controls/select.cljs +++ b/frontend/src/app/main/ui/ds/controls/select.cljs @@ -9,6 +9,7 @@ [app.common.data.macros :as dm] [app.main.style :as stl]) (:require + [app.main.ui.ds.controls.shared.options-dropdown :refer [options-dropdown*]] [app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list] :as i] [app.util.array :as array] [app.util.dom :as dom] @@ -16,63 +17,6 @@ [app.util.object :as obj] [rumext.v2 :as mf])) -(mf/defc option* - {::mf/props :obj - ::mf/private true} - [{:keys [id label icon aria-label on-click selected set-ref focused] :rest props}] - [:> :li {:value id - :class (stl/css-case :option true - :option-with-icon (some? icon) - :option-current focused) - :aria-selected selected - - :ref (fn [node] - (set-ref node id)) - :role "option" - :id id - :on-click on-click - :data-id id} - - (when (some? icon) - [:> icon* - {:id icon - :size "s" - :class (stl/css :option-icon) - :aria-hidden (when label true) - :aria-label (when (not label) aria-label)}]) - - [:span {:class (stl/css :option-text)} label] - (when selected - [:> icon* - {:id i/tick - :size "s" - :class (stl/css :option-check) - :aria-hidden (when label true)}])]) - -(mf/defc options-dropdown* - {::mf/props :obj - ::mf/private true} - [{:keys [set-ref on-click options selected focused] :rest props}] - (let [props (mf/spread-props props - {:class (stl/css :option-list) - :tab-index "-1" - :role "listbox"})] - [:> "ul" props - (for [option ^js options] - (let [id (obj/get option "id") - label (obj/get option "label") - aria-label (obj/get option "aria-label") - icon (obj/get option "icon")] - [:> option* {:selected (= id selected) - :key id - :id id - :label label - :icon icon - :aria-label aria-label - :set-ref set-ref - :focused (= id focused) - :on-click on-click}]))])) - (def ^:private schema:select-option [:and [:map {:title "option"} diff --git a/frontend/src/app/main/ui/ds/controls/select.scss b/frontend/src/app/main/ui/ds/controls/select.scss index ff2cbe507..072870cd4 100644 --- a/frontend/src/app/main/ui/ds/controls/select.scss +++ b/frontend/src/app/main/ui/ds/controls/select.scss @@ -14,7 +14,6 @@ --select-bg-color: var(--color-background-tertiary); --select-outline-color: none; --select-border-color: none; - --select-dropdown-border-color: var(--color-background-quaternary); &:hover { --select-bg-color: var(--color-background-quaternary); @@ -81,67 +80,3 @@ grid-template-columns: auto 1fr; color: var(--select-icon-fg-color); } - -.option-list { - --options-dropdown-bg-color: var(--color-background-tertiary); - position: absolute; - right: 0; - top: $sz-36; - width: 100%; - background-color: var(--options-dropdown-bg-color); - border-radius: $br-8; - border: $b-1 solid var(--select-dropdown-border-color); - padding-block: var(--sp-xs); - margin-block-end: 0; - max-height: $sz-400; - overflow-y: auto; - overflow-x: hidden; -} - -.option { - --select-option-fg-color: var(--color-foreground-primary); - --select-option-bg-color: unset; - - &:hover { - --select-option-bg-color: var(--color-background-quaternary); - } - - &[aria-selected="true"] { - --select-option-bg-color: var(--color-background-quaternary); - } - - display: grid; - align-items: center; - justify-items: start; - grid-template-columns: 1fr auto; - gap: var(--sp-xs); - width: 100%; - height: $sz-32; - padding: var(--sp-s); - border-radius: $br-8; - outline: $b-1 solid var(--select-outline-color); - outline-offset: -1px; - background-color: var(--select-option-bg-color); -} - -.option-with-icon { - grid-template-columns: auto 1fr auto; -} - -.option-text { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; - min-width: 0; - padding-inline-start: var(--sp-xxs); -} - -.option-icon { - color: var(--select-icon-fg-color); -} - -.option-current { - --select-option-outline-color: var(--color-accent-primary); - outline: $b-1 solid var(--select-option-outline-color); -} diff --git a/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs b/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs new file mode 100644 index 000000000..16ce0240a --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs @@ -0,0 +1,69 @@ +;; 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 app.main.ui.ds.controls.shared.options-dropdown + (:require-macros + [app.main.style :as stl]) + (:require + [app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i] + [app.util.object :as obj] + [rumext.v2 :as mf])) + +(mf/defc option* + {::mf/props :obj + ::mf/private true} + [{:keys [id label icon aria-label on-click selected set-ref focused] :rest props}] + [:> :li {:value id + :class (stl/css-case :option true + :option-with-icon (some? icon) + :option-current focused) + :aria-selected selected + :ref (fn [node] + (set-ref node id)) + :role "option" + :id id + :on-click on-click + :data-id id + :data-testid "dropdown-option"} + + (when (some? icon) + [:> icon* + {:id icon + :size "s" + :class (stl/css :option-icon) + :aria-hidden (when label true) + :aria-label (when (not label) aria-label)}]) + + [:span {:class (stl/css :option-text)} label] + (when selected + [:> icon* + {:id i/tick + :size "s" + :class (stl/css :option-check) + :aria-hidden (when label true)}])]) + +(mf/defc options-dropdown* + {::mf/props :obj} + [{:keys [set-ref on-click options selected focused] :rest props}] + (let [props (mf/spread-props props + {:class (stl/css :option-list) + :tab-index "-1" + :role "listbox"})] + [:> "ul" props + (for [option ^js options] + (let [id (obj/get option "id") + label (obj/get option "label") + aria-label (obj/get option "aria-label") + icon (obj/get option "icon")] + [:> option* {:selected (= id selected) + :key id + :id id + :label label + :icon icon + :aria-label aria-label + :set-ref set-ref + :focused (= id focused) + :on-click on-click}]))])) diff --git a/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.scss b/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.scss new file mode 100644 index 000000000..8b330e30b --- /dev/null +++ b/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.scss @@ -0,0 +1,74 @@ +// 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 + +@use "../../_borders.scss" as *; +@use "../../_sizes.scss" as *; +@use "../../typography.scss" as *; + +.option-list { + --options-dropdown-icon-fg-color: var(--color-foreground-secondary); + --options-dropdown-bg-color: var(--color-background-tertiary); + --options-dropdown-outline-color: none; + --options-dropdown-border-color: var(--color-background-quaternary); + + position: absolute; + right: 0; + top: $sz-36; + width: 100%; + background-color: var(--options-dropdown-bg-color); + border-radius: $br-8; + border: $b-1 solid var(--options-dropdown-dropdown-border-color); + padding-block: var(--sp-xs); + margin-block-end: 0; + max-height: $sz-400; + overflow-y: auto; + overflow-x: hidden; +} + +.option { + --options-dropdown-fg-color: var(--color-foreground-primary); + --options-dropdown-bg-color: unset; + + display: grid; + align-items: center; + justify-items: start; + grid-template-columns: 1fr auto; + gap: var(--sp-xs); + width: 100%; + height: $sz-32; + padding: var(--sp-s); + border-radius: $br-8; + outline: $b-1 solid var(--options-dropdown-outline-color); + outline-offset: -1px; + background-color: var(--options-dropdown-bg-color); + + &:hover, + &[aria-selected="true"] { + --options-dropdown-bg-color: var(--color-background-quaternary); + } +} + +.option-with-icon { + grid-template-columns: auto 1fr auto; +} + +.option-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + min-width: 0; + padding-inline-start: var(--sp-xxs); +} + +.option-icon { + color: var(--options-dropdown-icon-fg-color); +} + +.option-current { + --options-dropdown-outline-color: var(--color-accent-primary); + outline: $b-1 solid var(--options-dropdown-outline-color); +} diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 58b2cbe1e..c9ed1b332 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -5,6 +5,13 @@ __metadata: version: 8 cacheKey: 10c0 +"@adobe/css-tools@npm:^4.4.0": + version: 4.4.1 + resolution: "@adobe/css-tools@npm:4.4.1" + checksum: 10c0/1a68ad9af490f45fce7b6e50dd2d8ac0c546d74431649c0d42ee4ceb1a9fa057fae0a7ef1e148effa12d84ec00ed71869ebfe0fb1dcdcc80bfcb6048c12abcc0 + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" @@ -15,7 +22,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0": +"@babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0": version: 7.26.2 resolution: "@babel/code-frame@npm:7.26.2" dependencies: @@ -633,21 +640,19 @@ __metadata: languageName: node linkType: hard -"@joshwooding/vite-plugin-react-docgen-typescript@npm:0.3.0": - version: 0.3.0 - resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.3.0" +"@joshwooding/vite-plugin-react-docgen-typescript@npm:0.4.2": + version: 0.4.2 + resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.4.2" dependencies: - glob: "npm:^7.2.0" - glob-promise: "npm:^4.2.0" magic-string: "npm:^0.27.0" react-docgen-typescript: "npm:^2.2.2" peerDependencies: typescript: ">= 4.3.x" - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/31098ad8fcc2440437534599c111d9f2951dd74821e8ba46c521b969bae4c918d830b7bb0484efbad29a51711bb62d3bc623d5a1ed5b1695b5b5594ea9dd4ca0 + checksum: 10c0/355d13ad92a9da786b561a25250e6c94a8e51d235ced345e54ebfe709abc45ab60c2a8d06599df6ec0441fba01720f189883429943cb62dff9a4c31b59f0939c languageName: node linkType: hard @@ -1243,9 +1248,9 @@ __metadata: languageName: node linkType: hard -"@storybook/addon-actions@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-actions@npm:8.4.2" +"@storybook/addon-actions@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-actions@npm:8.4.6" dependencies: "@storybook/global": "npm:^5.0.0" "@types/uuid": "npm:^9.0.1" @@ -1253,143 +1258,158 @@ __metadata: polished: "npm:^4.2.2" uuid: "npm:^9.0.0" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/ac89e6e0517efa2f8d6442f8fc0b1c3912bfc1ad50e03cccd06721d3bb52d11f472126a590c746cd565875d8ac11c63457de94e7c1ff6a3f8151b3c6488802d6 + storybook: ^8.4.6 + checksum: 10c0/80b2feceacb4ebe7f2be06b2fe3f49ded5ee08ca8bd036ff47a65d45d8796d29081ccadd0526984c8022bcfa24348e0ad4ce3f37cee4a60a928bae372bfc8afe languageName: node linkType: hard -"@storybook/addon-backgrounds@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-backgrounds@npm:8.4.2" +"@storybook/addon-backgrounds@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-backgrounds@npm:8.4.6" dependencies: "@storybook/global": "npm:^5.0.0" memoizerific: "npm:^1.11.3" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/8fac73fafe7974c1710b0565e0fab56b9a3ee35190a06b63e9ae996c5f5a0d214ec755f7e88de8fb8d7493eb022ad820952dffbfc417f2949c07750faea18e46 + storybook: ^8.4.6 + checksum: 10c0/2125d6905bf44194adf79e92698753d5e4ff75fac1ffbba1fc95ae705ba9ac8dc6ca9249c9a862aa05ea207d916d23142faefa759bb9ce21c6e16f0e329d28d2 languageName: node linkType: hard -"@storybook/addon-controls@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-controls@npm:8.4.2" +"@storybook/addon-controls@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-controls@npm:8.4.6" dependencies: "@storybook/global": "npm:^5.0.0" dequal: "npm:^2.0.2" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/8de00a60c34de7972efc3c882912c1b135d4867045783742515741380750a58f4ce0e98139328804adcf1c2926110ca88e2df1135c3b1b03a05b20c97494ef7a + storybook: ^8.4.6 + checksum: 10c0/f5f0ab2de8de80c8c3726de81802042cc29a6f2ec50de3b8bd463286c9056e87800e4ea9b350c6a41ce4c4175a11cb7d3d490da5cfc20bbf2a2e3549f77a82a7 languageName: node linkType: hard -"@storybook/addon-docs@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-docs@npm:8.4.2" +"@storybook/addon-docs@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-docs@npm:8.4.6" dependencies: "@mdx-js/react": "npm:^3.0.0" - "@storybook/blocks": "npm:8.4.2" - "@storybook/csf-plugin": "npm:8.4.2" - "@storybook/react-dom-shim": "npm:8.4.2" + "@storybook/blocks": "npm:8.4.6" + "@storybook/csf-plugin": "npm:8.4.6" + "@storybook/react-dom-shim": "npm:8.4.6" react: "npm:^16.8.0 || ^17.0.0 || ^18.0.0" react-dom: "npm:^16.8.0 || ^17.0.0 || ^18.0.0" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/ba8046898006b7e0c088ee26e378eff7e9aa315eb0c7ddf6b6d15ad6eea0d544d39674868b2b5ef5c89e64e1dee5501ceceaf2a3854636e88b99f5eaafe4b239 + storybook: ^8.4.6 + checksum: 10c0/ae53bf71048fe7476862ae733f0f765a22d0d1da32457f7ca7e3bdd23bb1cd452c56bc4e1f586cf978599c3f5acb835caeb569ff394eaec09d3259382f4954be languageName: node linkType: hard -"@storybook/addon-essentials@npm:^8.3.6": - version: 8.4.2 - resolution: "@storybook/addon-essentials@npm:8.4.2" +"@storybook/addon-essentials@npm:^8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-essentials@npm:8.4.6" dependencies: - "@storybook/addon-actions": "npm:8.4.2" - "@storybook/addon-backgrounds": "npm:8.4.2" - "@storybook/addon-controls": "npm:8.4.2" - "@storybook/addon-docs": "npm:8.4.2" - "@storybook/addon-highlight": "npm:8.4.2" - "@storybook/addon-measure": "npm:8.4.2" - "@storybook/addon-outline": "npm:8.4.2" - "@storybook/addon-toolbars": "npm:8.4.2" - "@storybook/addon-viewport": "npm:8.4.2" + "@storybook/addon-actions": "npm:8.4.6" + "@storybook/addon-backgrounds": "npm:8.4.6" + "@storybook/addon-controls": "npm:8.4.6" + "@storybook/addon-docs": "npm:8.4.6" + "@storybook/addon-highlight": "npm:8.4.6" + "@storybook/addon-measure": "npm:8.4.6" + "@storybook/addon-outline": "npm:8.4.6" + "@storybook/addon-toolbars": "npm:8.4.6" + "@storybook/addon-viewport": "npm:8.4.6" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/746470edd1f9ebbb9bd4f48461bc24141c215fe146b335efe14fbb289d381faf3935d55e4e25c251777b940caf827c06574062bb18bb1b95e2c9c85b89c8635a + storybook: ^8.4.6 + checksum: 10c0/b8fb83e018fcb1e8cad04b371af5f8ce9933e3a500a78a889715ecfe4efd9faa52acce2d0f97fb04fe9ae0898e661112816c052bfe9b5f01189938b122055a44 languageName: node linkType: hard -"@storybook/addon-highlight@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-highlight@npm:8.4.2" +"@storybook/addon-highlight@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-highlight@npm:8.4.6" dependencies: "@storybook/global": "npm:^5.0.0" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/6838bab4434da65e85de70908f0ca09e9aa93facdb8fa6799100d711a55cbc69744c131f8994e910efd6bf74507bcc035f7ca4f3367c3003fc5799212160fc65 + storybook: ^8.4.6 + checksum: 10c0/67a23a5e3b8f7740c7101e8fa886f3f9c6c61b6db3cb3430d2c805231f7ad170d2d926c12e7c9bfc4af327c5abac5b4155f4c0d70ea423b04704fe3def845acc languageName: node linkType: hard -"@storybook/addon-measure@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-measure@npm:8.4.2" +"@storybook/addon-interactions@npm:^8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-interactions@npm:8.4.6" + dependencies: + "@storybook/global": "npm:^5.0.0" + "@storybook/instrumenter": "npm:8.4.6" + "@storybook/test": "npm:8.4.6" + polished: "npm:^4.2.2" + ts-dedent: "npm:^2.2.0" + peerDependencies: + storybook: ^8.4.6 + checksum: 10c0/42e4bc2df354dba10217385687ac20fb355f4e1a2a7390812081d6b387151b67bca868211794e531c1e112dc4ce50c70dffa55c8f4338b0bd860d59363d58d5b + languageName: node + linkType: hard + +"@storybook/addon-measure@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-measure@npm:8.4.6" dependencies: "@storybook/global": "npm:^5.0.0" tiny-invariant: "npm:^1.3.1" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/3458cce88b41bb54f74f5affc610b07f486db07709ac13a1b84b7b17fb0d9c2b3fce9325b69a9f60a8d446ae0befc530a4de7d5dc133f4d818d438ff4378cf61 + storybook: ^8.4.6 + checksum: 10c0/fd05b49fdb102a991fc696a0f75fde08d372b692778340ab2abc2c73fbd31a07dfa27a7a9d775dda7baaa9bd8a18972ed0bd86e9ce27948afb0305778f7b5a95 languageName: node linkType: hard -"@storybook/addon-outline@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-outline@npm:8.4.2" +"@storybook/addon-outline@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-outline@npm:8.4.6" dependencies: "@storybook/global": "npm:^5.0.0" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/042693756b2d00e9454f544d35d1e6a638e7adc7e165c92a4a0c99578a0ff001357c54826fa0e8fe7dbedcd10e62b60045fd30e1cd2b4e3dff4521aece9e6426 + storybook: ^8.4.6 + checksum: 10c0/62600a9f4164a8d91118d37cd7be4f4dd871e849a156ba7728f463bc2cfc5a8a233df09055dd5e5733a042fde7a63b08616cb3c61b26c363c1e2d4ce20d92584 languageName: node linkType: hard -"@storybook/addon-themes@npm:^8.3.6": - version: 8.4.2 - resolution: "@storybook/addon-themes@npm:8.4.2" +"@storybook/addon-themes@npm:^8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-themes@npm:8.4.6" dependencies: ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/53e93495011dd1c19d65370e3b9ce2b5ab9051558822311b5e03f36a7611210eaaee62c63866788e69ff96532a309d35626dcb02fbcee2f2963f4db1edd3a5d5 + storybook: ^8.4.6 + checksum: 10c0/a20d84f1b8b72935b24a16dd1d859554398f4b391974ef04815e70c644901ff98910b8ed6d7415f939223853e4dfee61f466e7c3041c409195fd97f3176992c1 languageName: node linkType: hard -"@storybook/addon-toolbars@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-toolbars@npm:8.4.2" +"@storybook/addon-toolbars@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-toolbars@npm:8.4.6" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/f5808d3863867295475295423a397108d41b01ac6564b0a18241c2f1e3ecf9e67c4326c663917c72315f6c60f203dc0d0e93b4778af4e7071a047a6001e1eef5 + storybook: ^8.4.6 + checksum: 10c0/6525e71aaa3870ae97d407b662323022ade98859f89975110f5fb4a1d3f34b6c918d47fcc8a6a271f4a77acfcaadc963a846a83ebc6c748b37df50422ad60e7e languageName: node linkType: hard -"@storybook/addon-viewport@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/addon-viewport@npm:8.4.2" +"@storybook/addon-viewport@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/addon-viewport@npm:8.4.6" dependencies: memoizerific: "npm:^1.11.3" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/676dc421781afcb50598172d9a1391604e73b9d35989b23e33674ec81b16c5dbd123a6a43098134927e1d2ffb3353fd32231261025cfc5e50ebb1259329f8ec1 + storybook: ^8.4.6 + checksum: 10c0/824438cc44a45f90748ac5f20ac148a36d975a94fa89504a583e0e1188de8c574e042ad3cd537bc16ddb30d4e44e90f5a63263239b13419aec5334e2ece18cd0 languageName: node linkType: hard -"@storybook/blocks@npm:8.4.2, @storybook/blocks@npm:^8.3.6": - version: 8.4.2 - resolution: "@storybook/blocks@npm:8.4.2" +"@storybook/blocks@npm:8.4.6, @storybook/blocks@npm:^8.4.6": + version: 8.4.6 + resolution: "@storybook/blocks@npm:8.4.6" dependencies: "@storybook/csf": "npm:^0.1.11" "@storybook/icons": "npm:^1.2.12" @@ -1397,42 +1417,42 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.2 + storybook: ^8.4.6 peerDependenciesMeta: react: optional: true react-dom: optional: true - checksum: 10c0/63cb3ed08742409041dca7fea3b476fb16675ddcc11b602ba4b20f61ab92993e15bc020e14e92398d4e2ea3bf62186274f5737c1c88ae26f9e717168f71441d5 + checksum: 10c0/36d79c3aeb3d27f4ba966d62302e13fc17fd7b450dbfbcf538adfc6df3cfecb13c92f9d2542871fa747a77d7c770e413b358623049135355fb01454d6eb52d9a languageName: node linkType: hard -"@storybook/builder-vite@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/builder-vite@npm:8.4.2" +"@storybook/builder-vite@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/builder-vite@npm:8.4.6" dependencies: - "@storybook/csf-plugin": "npm:8.4.2" + "@storybook/csf-plugin": "npm:8.4.6" browser-assert: "npm:^1.2.1" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.4.2 - vite: ^4.0.0 || ^5.0.0 - checksum: 10c0/646f7cfbc77e7aaced8d2f0922e1b54662f6cb3c7602c5db97a419fd724033f8d68a332ebad9bf14641f7e7edec42797685bdfa24c666475f3bbeb23fe20f941 + storybook: ^8.4.6 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + checksum: 10c0/36998ffea04023a9f634ebbafe0d1ab3bd3e7c7fec8e8e6c4caef3ce0c94ce01fa44f332f40d0053edb788548f95096baf8561cd35c23fe3c9bcfd872f74f631 languageName: node linkType: hard -"@storybook/components@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/components@npm:8.4.2" +"@storybook/components@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/components@npm:8.4.6" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10c0/36ffb5f73dceb481e76fa6e006118f382c23c8081cf47500f0eea8566e902a11d3fd219b599a9f622358f17652c445f71bc8d7a80e0d43f28cd85d60f7b4a15f + checksum: 10c0/1622b2f12b6d18e5c495a623deb2930888b3e8b173a271cbe42a7cbd6e14e80b736c57792ea97d5269dff0e6c0db40385d3ea80ab6e46d4cb6e104aee6cac6bc languageName: node linkType: hard -"@storybook/core@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/core@npm:8.4.2" +"@storybook/core@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/core@npm:8.4.6" dependencies: "@storybook/csf": "npm:^0.1.11" better-opn: "npm:^3.0.2" @@ -1450,18 +1470,18 @@ __metadata: peerDependenciesMeta: prettier: optional: true - checksum: 10c0/75a9a9e00d98bb77d171a2738fdc0e9ab1cfbd760410b95c286368c7f25bbb756b61bd23b89d512707a02e450b81ecbdc72bf05e63fb18ea35509a2a806b0e21 + checksum: 10c0/1e30268eec18458dd78ed4b97fb12ac47b2c3cb41ffcbe9e9f5934b3f0c83b0bfcb0c0d508926344779383cc5260f992dcd534ffffab3f05425c7cee8c90687c languageName: node linkType: hard -"@storybook/csf-plugin@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/csf-plugin@npm:8.4.2" +"@storybook/csf-plugin@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/csf-plugin@npm:8.4.6" dependencies: unplugin: "npm:^1.3.1" peerDependencies: - storybook: ^8.4.2 - checksum: 10c0/8fc0db319b8ebe6a445989cc0c5576c7186da086f84d5fad30615e1e527f31bcf562e12b4f31ec85e3fd188aa676116d4023232dcca4441c7c517cda0ac23bf0 + storybook: ^8.4.6 + checksum: 10c0/d771f36ee768c6ff62ecd930c6ff64a4ba45bdbb7f7fb41e5f4ffd02204e3f54b17ed091049b265a6d371922bf599bfe749eb9deabfcd7e2b4fb5a5444655241 languageName: node linkType: hard @@ -1491,43 +1511,55 @@ __metadata: languageName: node linkType: hard -"@storybook/manager-api@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/manager-api@npm:8.4.2" +"@storybook/instrumenter@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/instrumenter@npm:8.4.6" + dependencies: + "@storybook/global": "npm:^5.0.0" + "@vitest/utils": "npm:^2.1.1" peerDependencies: - storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10c0/306e16af4a4babf18d7b32335f974ac969a3f9139534f37e3ce238462f69f1ad52e3091a45bf76b1cbdd8f3cf989836c8433cad6cbb2c3eb4dcbc7ccb0f8ae82 + storybook: ^8.4.6 + checksum: 10c0/602017872236124dc9dfa77d6bc2c5987d540063f15c7ace83bf91060d9343fdbe113a61cba44e17cae2247aeeb69875ebf45ff66ce9c28d364d2d3638eb3ec8 languageName: node linkType: hard -"@storybook/preview-api@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/preview-api@npm:8.4.2" +"@storybook/manager-api@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/manager-api@npm:8.4.6" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10c0/7b54c1962d27d32f29a3839660098ad8995cfcf31d4bde3662cff69d7a06cc4d315dad92f565901e3b0ebd7bf12fa8995cc625a71f13c34d82a4529412d8f83c + checksum: 10c0/5921ec72df0be765bd398aa906186c9b121a8b3415a7e1a10014a8d17c44aec386b59de3d240017bfc925be00c40a4da8d26991b5fa39023f23ba8efe1b0d58e languageName: node linkType: hard -"@storybook/react-dom-shim@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/react-dom-shim@npm:8.4.2" +"@storybook/preview-api@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/preview-api@npm:8.4.6" + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + checksum: 10c0/63967f4813c75e410634bff20189b5a670a061cfeeaa601ec07f0de82e2b4955af292836030d5a8432c3c7e48968285e121ed2bb55d2b5c70d17dbb4ada3c051 + languageName: node + linkType: hard + +"@storybook/react-dom-shim@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/react-dom-shim@npm:8.4.6" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.2 - checksum: 10c0/f4cc8d3cb557c8e84f62047680af926570f170a87aec7775830b91c4793c7afee84092ef6cd9c518dbd0ab9311139a4698f1477f35d21bc4d1462c6bd54105c5 + storybook: ^8.4.6 + checksum: 10c0/b97c6faa3adc3efe1b7b6f5e38476e040c0a988b14db68e368d704c68f3f4d4bf7866b36607c118a0483242921b34944b5f5f72614d9852476476f6ead462e5c languageName: node linkType: hard -"@storybook/react-vite@npm:^8.3.6": - version: 8.4.2 - resolution: "@storybook/react-vite@npm:8.4.2" +"@storybook/react-vite@npm:^8.4.6": + version: 8.4.6 + resolution: "@storybook/react-vite@npm:8.4.6" dependencies: - "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.3.0" + "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.4.2" "@rollup/pluginutils": "npm:^5.0.2" - "@storybook/builder-vite": "npm:8.4.2" - "@storybook/react": "npm:8.4.2" + "@storybook/builder-vite": "npm:8.4.6" + "@storybook/react": "npm:8.4.6" find-up: "npm:^5.0.0" magic-string: "npm:^0.30.0" react-docgen: "npm:^7.0.0" @@ -1536,43 +1568,101 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.2 - vite: ^4.0.0 || ^5.0.0 - checksum: 10c0/7e04112b0678a2bfd9fb913eb9161055fdb30d6ee34983294632eaae72067a16727e84801bede7b76cd7f7e0c6005021011432ea394c1a82fd73de5c6fb7b567 + storybook: ^8.4.6 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + checksum: 10c0/9f81a19461dbbf11932a13f8fb611dbcd95fbfa695ee5536daf7e078bf0feb5ddda2738606073826131e3fee710e230dce9042e3f7f985203392376aa8407643 languageName: node linkType: hard -"@storybook/react@npm:8.4.2, @storybook/react@npm:^8.3.6": - version: 8.4.2 - resolution: "@storybook/react@npm:8.4.2" +"@storybook/react@npm:8.4.6, @storybook/react@npm:^8.4.6": + version: 8.4.6 + resolution: "@storybook/react@npm:8.4.6" dependencies: - "@storybook/components": "npm:8.4.2" + "@storybook/components": "npm:8.4.6" "@storybook/global": "npm:^5.0.0" - "@storybook/manager-api": "npm:8.4.2" - "@storybook/preview-api": "npm:8.4.2" - "@storybook/react-dom-shim": "npm:8.4.2" - "@storybook/theming": "npm:8.4.2" + "@storybook/manager-api": "npm:8.4.6" + "@storybook/preview-api": "npm:8.4.6" + "@storybook/react-dom-shim": "npm:8.4.6" + "@storybook/theming": "npm:8.4.6" peerDependencies: - "@storybook/test": 8.4.2 + "@storybook/test": 8.4.6 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.2 + storybook: ^8.4.6 typescript: ">= 4.2.x" peerDependenciesMeta: "@storybook/test": optional: true typescript: optional: true - checksum: 10c0/a5ce045dae71c2a039c1ac4411c07b4a51574a6f607c6c6f105e87147410b32e7d882b3f225d6fa78ddc29423881aee76727826d2b960a61f913f7d849fdcc1f + checksum: 10c0/1441f8ab3be91757647c6b1a05eb1ef0d78a454ffd14b01a14fdde00e92a8be8fc7c8408c4670b46bc20a5a04995514f0890e98ed6ee35c362ff36141da02f02 languageName: node linkType: hard -"@storybook/theming@npm:8.4.2": - version: 8.4.2 - resolution: "@storybook/theming@npm:8.4.2" +"@storybook/test@npm:8.4.6, @storybook/test@npm:^8.4.6": + version: 8.4.6 + resolution: "@storybook/test@npm:8.4.6" + dependencies: + "@storybook/csf": "npm:^0.1.11" + "@storybook/global": "npm:^5.0.0" + "@storybook/instrumenter": "npm:8.4.6" + "@testing-library/dom": "npm:10.4.0" + "@testing-library/jest-dom": "npm:6.5.0" + "@testing-library/user-event": "npm:14.5.2" + "@vitest/expect": "npm:2.0.5" + "@vitest/spy": "npm:2.0.5" + peerDependencies: + storybook: ^8.4.6 + checksum: 10c0/fbf7c2ac7773a7fe18145876eb67491ce90b000ba5f8e364a319569e56d56e706fdd1c7ef24d3ab2ffa3dfcdb92377d8050c8ffbd457d2d8b613aba2a4845a04 + languageName: node + linkType: hard + +"@storybook/theming@npm:8.4.6": + version: 8.4.6 + resolution: "@storybook/theming@npm:8.4.6" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10c0/8765a25952273f87f65018159228fa448a0bb6fa38486650344ddc076cd895546ab3b88d35a6e7f80d3223635e28d59f82510922c589a36a7c6afc33c5bcc0d7 + checksum: 10c0/7d9c8e5ef2c1d974cd5258301350a2345890326e7be7a5ed6bdd0db70fd1648c0bbb8ee1d905f8e66fa57b75c47aefe7ec9772ec0bfb9691d127dcc19286e4c9 + languageName: node + linkType: hard + +"@testing-library/dom@npm:10.4.0": + version: 10.4.0 + resolution: "@testing-library/dom@npm:10.4.0" + dependencies: + "@babel/code-frame": "npm:^7.10.4" + "@babel/runtime": "npm:^7.12.5" + "@types/aria-query": "npm:^5.0.1" + aria-query: "npm:5.3.0" + chalk: "npm:^4.1.0" + dom-accessibility-api: "npm:^0.5.9" + lz-string: "npm:^1.5.0" + pretty-format: "npm:^27.0.2" + checksum: 10c0/0352487720ecd433400671e773df0b84b8268fb3fe8e527cdfd7c11b1365b398b4e0eddba6e7e0c85e8d615f48257753283fccec41f6b986fd6c85f15eb5f84f + languageName: node + linkType: hard + +"@testing-library/jest-dom@npm:6.5.0": + version: 6.5.0 + resolution: "@testing-library/jest-dom@npm:6.5.0" + dependencies: + "@adobe/css-tools": "npm:^4.4.0" + aria-query: "npm:^5.0.0" + chalk: "npm:^3.0.0" + css.escape: "npm:^1.5.1" + dom-accessibility-api: "npm:^0.6.3" + lodash: "npm:^4.17.21" + redent: "npm:^3.0.0" + checksum: 10c0/fd5936a547f04608d8de15a7de3ae26516f21023f8f45169b10c8c8847015fd20ec259b7309f08aa1031bcbc37c6e5e6f532d1bb85ef8f91bad654193ec66a4c + languageName: node + linkType: hard + +"@testing-library/user-event@npm:14.5.2": + version: 14.5.2 + resolution: "@testing-library/user-event@npm:14.5.2" + peerDependencies: + "@testing-library/dom": ">=7.21.4" + checksum: 10c0/68a0c2aa28a3c8e6eb05cafee29705438d7d8a9427423ce5064d44f19c29e89b5636de46dd2f28620fb10abba75c67130185bbc3aa23ac1163a227a5f36641e1 languageName: node linkType: hard @@ -1607,6 +1697,13 @@ __metadata: languageName: node linkType: hard +"@types/aria-query@npm:^5.0.1": + version: 5.0.4 + resolution: "@types/aria-query@npm:5.0.4" + checksum: 10c0/dc667bc6a3acc7bba2bccf8c23d56cb1f2f4defaa704cfef595437107efaa972d3b3db9ec1d66bc2711bfc35086821edd32c302bffab36f2e79b97f312069f08 + languageName: node + linkType: hard + "@types/babel__core@npm:^7.18.0": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -1662,16 +1759,6 @@ __metadata: languageName: node linkType: hard -"@types/glob@npm:^7.1.3": - version: 7.2.0 - resolution: "@types/glob@npm:7.2.0" - dependencies: - "@types/minimatch": "npm:*" - "@types/node": "npm:*" - checksum: 10c0/a8eb5d5cb5c48fc58c7ca3ff1e1ddf771ee07ca5043da6e4871e6757b4472e2e73b4cfef2644c38983174a4bc728c73f8da02845c28a1212f98cabd293ecae98 - languageName: node - linkType: hard - "@types/mdx@npm:^2.0.0": version: 2.0.13 resolution: "@types/mdx@npm:2.0.13" @@ -1679,14 +1766,7 @@ __metadata: languageName: node linkType: hard -"@types/minimatch@npm:*": - version: 5.1.2 - resolution: "@types/minimatch@npm:5.1.2" - checksum: 10c0/83cf1c11748891b714e129de0585af4c55dd4c2cafb1f1d5233d79246e5e1e19d1b5ad9e8db449667b3ffa2b6c80125c429dbee1054e9efb45758dbc4e118562 - languageName: node - linkType: hard - -"@types/node@npm:*, @types/node@npm:^22.7.7": +"@types/node@npm:^22.7.7": version: 22.9.0 resolution: "@types/node@npm:22.9.0" dependencies: @@ -1716,6 +1796,18 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/expect@npm:2.0.5" + dependencies: + "@vitest/spy": "npm:2.0.5" + "@vitest/utils": "npm:2.0.5" + chai: "npm:^5.1.1" + tinyrainbow: "npm:^1.2.0" + checksum: 10c0/08cb1b0f106d16a5b60db733e3d436fa5eefc68571488eb570dfe4f599f214ab52e4342273b03dbe12331cc6c0cdc325ac6c94f651ad254cd62f3aa0e3d185aa + languageName: node + linkType: hard + "@vitest/expect@npm:2.1.4": version: 2.1.4 resolution: "@vitest/expect@npm:2.1.4" @@ -1747,6 +1839,15 @@ __metadata: languageName: node linkType: hard +"@vitest/pretty-format@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/pretty-format@npm:2.0.5" + dependencies: + tinyrainbow: "npm:^1.2.0" + checksum: 10c0/236c0798c5170a0b5ad5d4bd06118533738e820b4dd30079d8fbcb15baee949d41c60f42a9f769906c4a5ce366d7ef11279546070646c0efc03128c220c31f37 + languageName: node + linkType: hard + "@vitest/pretty-format@npm:2.1.4, @vitest/pretty-format@npm:^2.1.4": version: 2.1.4 resolution: "@vitest/pretty-format@npm:2.1.4" @@ -1756,6 +1857,15 @@ __metadata: languageName: node linkType: hard +"@vitest/pretty-format@npm:2.1.8": + version: 2.1.8 + resolution: "@vitest/pretty-format@npm:2.1.8" + dependencies: + tinyrainbow: "npm:^1.2.0" + checksum: 10c0/1dc5c9b1c7c7e78e46a2a16033b6b20be05958bbebc5a5b78f29e32718c80252034804fccd23f34db6b3583239db47e68fc5a8e41942c54b8047cc3b4133a052 + languageName: node + linkType: hard + "@vitest/runner@npm:2.1.4": version: 2.1.4 resolution: "@vitest/runner@npm:2.1.4" @@ -1777,6 +1887,15 @@ __metadata: languageName: node linkType: hard +"@vitest/spy@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/spy@npm:2.0.5" + dependencies: + tinyspy: "npm:^3.0.0" + checksum: 10c0/70634c21921eb271b54d2986c21d7ab6896a31c0f4f1d266940c9bafb8ac36237846d6736638cbf18b958bd98e5261b158a6944352742accfde50b7818ff655e + languageName: node + linkType: hard + "@vitest/spy@npm:2.1.4": version: 2.1.4 resolution: "@vitest/spy@npm:2.1.4" @@ -1786,6 +1905,18 @@ __metadata: languageName: node linkType: hard +"@vitest/utils@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/utils@npm:2.0.5" + dependencies: + "@vitest/pretty-format": "npm:2.0.5" + estree-walker: "npm:^3.0.3" + loupe: "npm:^3.1.1" + tinyrainbow: "npm:^1.2.0" + checksum: 10c0/0d1de748298f07a50281e1ba058b05dcd58da3280c14e6f016265e950bd79adab6b97822de8f0ea82d3070f585654801a9b1bcf26db4372e51cf7746bf86d73b + languageName: node + linkType: hard + "@vitest/utils@npm:2.1.4": version: 2.1.4 resolution: "@vitest/utils@npm:2.1.4" @@ -1797,6 +1928,17 @@ __metadata: languageName: node linkType: hard +"@vitest/utils@npm:^2.1.1": + version: 2.1.8 + resolution: "@vitest/utils@npm:2.1.8" + dependencies: + "@vitest/pretty-format": "npm:2.1.8" + loupe: "npm:^3.1.2" + tinyrainbow: "npm:^1.2.0" + checksum: 10c0/d4a29ecd8f6c24c790e4c009f313a044d89e664e331bc9c3cfb57fe1380fb1d2999706dbbfc291f067d6c489602e76d00435309fbc906197c0d01f831ca17d64 + languageName: node + linkType: hard + "@xmldom/xmldom@npm:^0.8.10": version: 0.8.10 resolution: "@xmldom/xmldom@npm:0.8.10" @@ -1931,6 +2073,13 @@ __metadata: languageName: node linkType: hard +"ansi-styles@npm:^5.0.0": + version: 5.2.0 + resolution: "ansi-styles@npm:5.2.0" + checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df + languageName: node + linkType: hard + "ansi-styles@npm:^6.1.0": version: 6.2.1 resolution: "ansi-styles@npm:6.2.1" @@ -1969,6 +2118,22 @@ __metadata: languageName: node linkType: hard +"aria-query@npm:5.3.0": + version: 5.3.0 + resolution: "aria-query@npm:5.3.0" + dependencies: + dequal: "npm:^2.0.3" + checksum: 10c0/2bff0d4eba5852a9dd578ecf47eaef0e82cc52569b48469b0aac2db5145db0b17b7a58d9e01237706d1e14b7a1b0ac9b78e9c97027ad97679dd8f91b85da1469 + languageName: node + linkType: hard + +"aria-query@npm:^5.0.0": + version: 5.3.2 + resolution: "aria-query@npm:5.3.2" + checksum: 10c0/003c7e3e2cff5540bf7a7893775fc614de82b0c5dde8ae823d47b7a28a9d4da1f7ed85f340bdb93d5649caa927755f0e31ecc7ab63edfdfc00c8ef07e505e03e + languageName: node + linkType: hard + "arr-diff@npm:^4.0.0": version: 4.0.0 resolution: "arr-diff@npm:4.0.0" @@ -2469,7 +2634,7 @@ __metadata: languageName: node linkType: hard -"chai@npm:^5.1.2": +"chai@npm:^5.1.1, chai@npm:^5.1.2": version: 5.1.2 resolution: "chai@npm:5.1.2" dependencies: @@ -2493,7 +2658,17 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.1.2": +"chalk@npm:^3.0.0": + version: 3.0.0 + resolution: "chalk@npm:3.0.0" + dependencies: + ansi-styles: "npm:^4.1.0" + supports-color: "npm:^7.1.0" + checksum: 10c0/ee650b0a065b3d7a6fda258e75d3a86fc8e4effa55871da730a9e42ccb035bf5fd203525e5a1ef45ec2582ecc4f65b47eb11357c526b84dd29a14fb162c414d2 + languageName: node + linkType: hard + +"chalk@npm:^4.1.0, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -3071,6 +3246,13 @@ __metadata: languageName: node linkType: hard +"css.escape@npm:^1.5.1": + version: 1.5.1 + resolution: "css.escape@npm:1.5.1" + checksum: 10c0/5e09035e5bf6c2c422b40c6df2eb1529657a17df37fda5d0433d722609527ab98090baf25b13970ca754079a0f3161dd3dfc0e743563ded8cfa0749d861c1525 + languageName: node + linkType: hard + "css@npm:^3.0.0": version: 3.0.0 resolution: "css@npm:3.0.0" @@ -3304,7 +3486,7 @@ __metadata: languageName: node linkType: hard -"dequal@npm:^2.0.2": +"dequal@npm:^2.0.2, dequal@npm:^2.0.3": version: 2.0.3 resolution: "dequal@npm:2.0.3" checksum: 10c0/f98860cdf58b64991ae10205137c0e97d384c3a4edc7f807603887b7c4b850af1224a33d88012009f150861cbee4fa2d322c4cc04b9313bee312e47f6ecaa888 @@ -3378,6 +3560,20 @@ __metadata: languageName: node linkType: hard +"dom-accessibility-api@npm:^0.5.9": + version: 0.5.16 + resolution: "dom-accessibility-api@npm:0.5.16" + checksum: 10c0/b2c2eda4fae568977cdac27a9f0c001edf4f95a6a6191dfa611e3721db2478d1badc01db5bb4fa8a848aeee13e442a6c2a4386d65ec65a1436f24715a2f8d053 + languageName: node + linkType: hard + +"dom-accessibility-api@npm:^0.6.3": + version: 0.6.3 + resolution: "dom-accessibility-api@npm:0.6.3" + checksum: 10c0/10bee5aa514b2a9a37c87cd81268db607a2e933a050074abc2f6fa3da9080ebed206a320cbc123567f2c3087d22292853bdfdceaffdd4334ffe2af9510b29360 + languageName: node + linkType: hard + "dom-helpers@npm:^5.1.3": version: 5.2.1 resolution: "dom-helpers@npm:5.2.1" @@ -4301,11 +4497,13 @@ __metadata: "@penpot/svgo": "penpot/svgo#c6fba7a4dcfbc27b643e7fc0c94fc98cf680b77b" "@penpot/text-editor": "portal:./text-editor" "@playwright/test": "npm:1.48.1" - "@storybook/addon-essentials": "npm:^8.3.6" - "@storybook/addon-themes": "npm:^8.3.6" - "@storybook/blocks": "npm:^8.3.6" - "@storybook/react": "npm:^8.3.6" - "@storybook/react-vite": "npm:^8.3.6" + "@storybook/addon-essentials": "npm:^8.4.6" + "@storybook/addon-interactions": "npm:^8.4.6" + "@storybook/addon-themes": "npm:^8.4.6" + "@storybook/blocks": "npm:^8.4.6" + "@storybook/react": "npm:^8.4.6" + "@storybook/react-vite": "npm:^8.4.6" + "@storybook/test": "npm:^8.4.6" "@tokens-studio/sd-transforms": "npm:^0.16.1" "@types/node": "npm:^22.7.7" autoprefixer: "npm:^10.4.20" @@ -4358,7 +4556,7 @@ __metadata: sax: "npm:^1.4.1" shadow-cljs: "npm:2.28.18" source-map-support: "npm:^0.5.21" - storybook: "npm:^8.3.6" + storybook: "npm:^8.4.6" style-dictionary: "npm:4.0.0-prerelease.34" svg-sprite: "npm:^2.0.4" tdigest: "npm:^0.1.2" @@ -4550,17 +4748,6 @@ __metadata: languageName: node linkType: hard -"glob-promise@npm:^4.2.0": - version: 4.2.2 - resolution: "glob-promise@npm:4.2.2" - dependencies: - "@types/glob": "npm:^7.1.3" - peerDependencies: - glob: ^7.1.6 - checksum: 10c0/3eb01bed2901539365df6a4d27800afb8788840647d01f9bf3500b3de756597f2ff4b8c823971ace34db228c83159beca459dc42a70968d4e9c8200ed2cc96bd - languageName: node - linkType: hard - "glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.3, glob@npm:^10.4.2": version: 10.4.5 resolution: "glob@npm:10.4.5" @@ -4593,7 +4780,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3, glob@npm:^7.2.0, glob@npm:^7.2.3": +"glob@npm:^7.1.3, glob@npm:^7.2.3": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -5695,7 +5882,7 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^3.1.0, loupe@npm:^3.1.2": +"loupe@npm:^3.1.0, loupe@npm:^3.1.1, loupe@npm:^3.1.2": version: 3.1.2 resolution: "loupe@npm:3.1.2" checksum: 10c0/b13c02e3ddd6a9d5f8bf84133b3242de556512d824dddeea71cce2dbd6579c8f4d672381c4e742d45cf4423d0701765b4a6e5fbc24701def16bc2b40f8daa96a @@ -5741,6 +5928,15 @@ __metadata: languageName: node linkType: hard +"lz-string@npm:^1.5.0": + version: 1.5.0 + resolution: "lz-string@npm:1.5.0" + bin: + lz-string: bin/bin.js + checksum: 10c0/36128e4de34791838abe979b19927c26e67201ca5acf00880377af7d765b38d1c60847e01c5ec61b1a260c48029084ab3893a3925fd6e48a04011364b089991b + languageName: node + linkType: hard + "magic-string@npm:^0.27.0": version: 0.27.0 resolution: "magic-string@npm:0.27.0" @@ -5953,7 +6149,7 @@ __metadata: languageName: node linkType: hard -"min-indent@npm:^1.0.1": +"min-indent@npm:^1.0.0, min-indent@npm:^1.0.1": version: 1.0.1 resolution: "min-indent@npm:1.0.1" checksum: 10c0/7e207bd5c20401b292de291f02913230cb1163abca162044f7db1d951fa245b174dc00869d40dd9a9f32a885ad6a5f3e767ee104cf278f399cb4e92d3f582d5c @@ -7003,6 +7199,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^27.0.2": + version: 27.5.1 + resolution: "pretty-format@npm:27.5.1" + dependencies: + ansi-regex: "npm:^5.0.1" + ansi-styles: "npm:^5.0.0" + react-is: "npm:^17.0.1" + checksum: 10c0/0cbda1031aa30c659e10921fa94e0dd3f903ecbbbe7184a729ad66f2b6e7f17891e8c7d7654c458fa4ccb1a411ffb695b4f17bbcd3fe075fabe181027c4040ed + languageName: node + linkType: hard + "pretty-time@npm:^1.1.0": version: 1.1.0 resolution: "pretty-time@npm:1.1.0" @@ -7254,6 +7461,13 @@ __metadata: languageName: node linkType: hard +"react-is@npm:^17.0.1": + version: 17.0.2 + resolution: "react-is@npm:17.0.2" + checksum: 10c0/2bdb6b93fbb1820b024b496042cce405c57e2f85e777c9aabd55f9b26d145408f9f74f5934676ffdc46f3dcff656d78413a6e43968e7b3f92eea35b3052e9053 + languageName: node + linkType: hard + "react-lifecycles-compat@npm:^3.0.4": version: 3.0.4 resolution: "react-lifecycles-compat@npm:3.0.4" @@ -7373,6 +7587,16 @@ __metadata: languageName: node linkType: hard +"redent@npm:^3.0.0": + version: 3.0.0 + resolution: "redent@npm:3.0.0" + dependencies: + indent-string: "npm:^4.0.0" + strip-indent: "npm:^3.0.0" + checksum: 10c0/d64a6b5c0b50eb3ddce3ab770f866658a2b9998c678f797919ceb1b586bab9259b311407280bd80b804e2a7c7539b19238ae6a2a20c843f1a7fcff21d48c2eae + languageName: node + linkType: hard + "regenerator-runtime@npm:^0.14.0": version: 0.14.1 resolution: "regenerator-runtime@npm:0.14.1" @@ -8288,11 +8512,11 @@ __metadata: languageName: node linkType: hard -"storybook@npm:^8.3.6": - version: 8.4.2 - resolution: "storybook@npm:8.4.2" +"storybook@npm:^8.4.6": + version: 8.4.6 + resolution: "storybook@npm:8.4.6" dependencies: - "@storybook/core": "npm:8.4.2" + "@storybook/core": "npm:8.4.6" peerDependencies: prettier: ^2 || ^3 peerDependenciesMeta: @@ -8302,7 +8526,7 @@ __metadata: getstorybook: ./bin/index.cjs sb: ./bin/index.cjs storybook: ./bin/index.cjs - checksum: 10c0/54791f44de53d465a74c44ec16255ebe5248156eee54b768fdcc12a7556e1b6e2a23c9c5c5eec0c3fcc71c3820398999ede5042f711a851b0ca9c71e65c8ab19 + checksum: 10c0/e15249718c1efab3d3d05f3152df28fc8f7e2e988bf7414cd4abf2adfb5d6c3b802f05dad5be0521c30d0ba43e55abf516e6f874b0671e0d1e84a7096cb47d3d languageName: node linkType: hard @@ -8479,6 +8703,15 @@ __metadata: languageName: node linkType: hard +"strip-indent@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-indent@npm:3.0.0" + dependencies: + min-indent: "npm:^1.0.0" + checksum: 10c0/ae0deaf41c8d1001c5d4fbe16cb553865c1863da4fae036683b474fa926af9fc121e155cb3fc57a68262b2ae7d5b8420aa752c97a6428c315d00efe2a3875679 + languageName: node + linkType: hard + "strip-indent@npm:^4.0.0": version: 4.0.0 resolution: "strip-indent@npm:4.0.0" @@ -8745,7 +8978,7 @@ __metadata: languageName: node linkType: hard -"tinyspy@npm:^3.0.2": +"tinyspy@npm:^3.0.0, tinyspy@npm:^3.0.2": version: 3.0.2 resolution: "tinyspy@npm:3.0.2" checksum: 10c0/55ffad24e346622b59292e097c2ee30a63919d5acb7ceca87fc0d1c223090089890587b426e20054733f97a58f20af2c349fb7cc193697203868ab7ba00bcea0 @@ -8861,7 +9094,7 @@ __metadata: languageName: node linkType: hard -"ts-dedent@npm:^2.0.0": +"ts-dedent@npm:^2.0.0, ts-dedent@npm:^2.2.0": version: 2.2.0 resolution: "ts-dedent@npm:2.2.0" checksum: 10c0/175adea838468cc2ff7d5e97f970dcb798bbcb623f29c6088cb21aa2880d207c5784be81ab1741f56b9ac37840cbaba0c0d79f7f8b67ffe61c02634cafa5c303