diff --git a/.eslintrc.js b/.eslintrc.js
index 786a3229d1e..837b7082e9a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -317,6 +317,66 @@ module.exports = {
'func-names': 'off',
},
},
+ {
+ files: ['ts/axo/**/*.tsx'],
+ plugins: ['better-tailwindcss'],
+ settings: {
+ 'better-tailwindcss': {
+ entryPoint: './ts/axo/tailwind.css',
+ callees: ['css'],
+ },
+ },
+ rules: {
+ // stylistic: Enforce consistent line wrapping for tailwind classes. (recommended, autofix)
+ 'better-tailwindcss/enforce-consistent-line-wrapping': 'off',
+ // stylistic: Enforce a consistent order for tailwind classes. (recommended, autofix)
+ 'better-tailwindcss/enforce-consistent-class-order': 'error',
+ // stylistic: Enforce consistent variable syntax. (autofix)
+ 'better-tailwindcss/enforce-consistent-variable-syntax': 'error',
+ // stylistic: Enforce consistent position of the important modifier. (autofix)
+ 'better-tailwindcss/enforce-consistent-important-position': 'error',
+ // stylistic: Enforce shorthand class names. (autofix)
+ 'better-tailwindcss/enforce-shorthand-classes': 'error',
+ // stylistic: Remove duplicate classes. (autofix)
+ 'better-tailwindcss/no-duplicate-classes': 'error',
+ // stylistic: Remove deprecated classes. (autofix)
+ 'better-tailwindcss/no-deprecated-classes': 'off',
+ // stylistic: Disallow unnecessary whitespace in tailwind classes. (autofix)
+ 'better-tailwindcss/no-unnecessary-whitespace': 'error',
+ // correctness: Report classes not registered with tailwindcss. (recommended)
+ 'better-tailwindcss/no-unregistered-classes': 'error',
+ // correctness: Report classes that produce conflicting styles.
+ 'better-tailwindcss/no-conflicting-classes': 'error',
+ // correctness: Disallow restricted classes. (autofix)
+ 'better-tailwindcss/no-restricted-classes': [
+ 'error',
+ {
+ restrict: [
+ {
+ pattern: '\\[#[a-fA-F0-9]{3,8}?\\]', // ex: "text-[#fff]"
+ message: 'No arbitrary hex values',
+ },
+ {
+ pattern: '\\[rgba?\\(.*\\)\\]', // ex: "text-[rgb(255,255,255)]"
+ message: 'No arbitrary rgb values',
+ },
+ {
+ pattern: '\\[hsla?\\(.*\\)\\]', // ex: "text-[hsl(255,255,255)]"
+ message: 'No arbitrary hsl values',
+ },
+ {
+ pattern: '^.*!$', // ex: "p-4!"
+ message: 'No !important modifiers',
+ },
+ {
+ pattern: '^\\*+:.*', // ex: "*:mx-0",
+ message: 'No child variants',
+ },
+ ],
+ },
+ ],
+ },
+ },
],
rules: {
diff --git a/.prettierignore b/.prettierignore
index 7b2441866ac..20e1689d1c9 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -17,6 +17,7 @@ ts/**/*.js
ts/protobuf/*.d.ts
ts/protobuf/*.js
stylesheets/manifest.css
+stylesheets/tailwind.css
ts/util/lint/exceptions.json
storybook-static
build/locale-display-names.json
diff --git a/.prettierrc.js b/.prettierrc.js
index 124e59afb9f..d2c896f89f3 100644
--- a/.prettierrc.js
+++ b/.prettierrc.js
@@ -1,8 +1,19 @@
// Copyright 2018 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
+/** @type {import("prettier").Config} */
module.exports = {
singleQuote: true,
arrowParens: 'avoid',
trailingComma: 'es5',
+ overrides: [
+ {
+ files: ['./ts/axo/**.tsx'],
+ plugins: ['prettier-plugin-tailwindcss'],
+ options: {
+ tailwindStylesheet: './ts/axo/tailwind.css',
+ tailwindFunctions: ['css'],
+ },
+ },
+ ],
};
diff --git a/.storybook/main.ts b/.storybook/main.ts
index 61e647389f0..02b54337840 100644
--- a/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -9,7 +9,7 @@ const config: StorybookConfig = {
reactDocgen: false,
},
- stories: ['../ts/components/**/*.stories.tsx'],
+ stories: ['../ts/axo/**/*.stories.tsx', '../ts/components/**/*.stories.tsx'],
addons: [
'@storybook/addon-a11y',
@@ -69,6 +69,23 @@ const config: StorybookConfig = {
],
});
+ config.module!.rules!.push({
+ test: /tailwind\.css$/,
+ use: [
+ {
+ loader: 'postcss-loader',
+ options: {
+ postcssOptions: {
+ config: false,
+ plugins: {
+ '@tailwindcss/postcss': {},
+ },
+ },
+ },
+ },
+ ],
+ });
+
config.node = { global: true };
config.externals = {
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
index a801cb51893..51cdbc3c185 100644
--- a/.storybook/preview.tsx
+++ b/.storybook/preview.tsx
@@ -5,8 +5,8 @@ import '../ts/window.d.ts';
import React, { StrictMode } from 'react';
-import 'sanitize.css';
import '../stylesheets/manifest.scss';
+import '../ts/axo/tailwind.css';
import * as styles from './styles.scss';
import messages from '../_locales/en/messages.json';
diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md
index 4ef2eee45ea..cc85c3245a9 100644
--- a/ACKNOWLEDGMENTS.md
+++ b/ACKNOWLEDGMENTS.md
@@ -4818,6 +4818,30 @@ Signal Desktop makes use of the following open source projects.
License: MIT
+## radix-ui
+
+ MIT License
+
+ Copyright (c) 2022 WorkOS
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
## react
MIT License
@@ -5546,117 +5570,6 @@ Signal Desktop makes use of the following open source projects.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-## sanitize.css
-
- # CC0 1.0 Universal
-
- ## Statement of Purpose
-
- The laws of most jurisdictions throughout the world automatically confer
- exclusive Copyright and Related Rights (defined below) upon the creator and
- subsequent owner(s) (each and all, an “owner”) of an original work of
- authorship and/or a database (each, a “Work”).
-
- Certain owners wish to permanently relinquish those rights to a Work for the
- purpose of contributing to a commons of creative, cultural and scientific works
- (“Commons”) that the public can reliably and without fear of later claims of
- infringement build upon, modify, incorporate in other works, reuse and
- redistribute as freely as possible in any form whatsoever and for any purposes,
- including without limitation commercial purposes. These owners may contribute
- to the Commons to promote the ideal of a free culture and the further
- production of creative, cultural and scientific works, or to gain reputation or
- greater distribution for their Work in part through the use and efforts of
- others.
-
- For these and/or other purposes and motivations, and without any expectation of
- additional consideration or compensation, the person associating CC0 with a
- Work (the “Affirmer”), to the extent that he or she is an owner of Copyright
- and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and
- publicly distribute the Work under its terms, with knowledge of his or her
- Copyright and Related Rights in the Work and the meaning and intended legal
- effect of CC0 on those rights.
-
- 1. Copyright and Related Rights. A Work made available under CC0 may be
- protected by copyright and related or neighboring rights (“Copyright and
- Related Rights”). Copyright and Related Rights include, but are not limited
- to, the following:
- 1. the right to reproduce, adapt, distribute, perform, display, communicate,
- and translate a Work;
- 2. moral rights retained by the original author(s) and/or performer(s);
- 3. publicity and privacy rights pertaining to a person’s image or likeness
- depicted in a Work;
- 4. rights protecting against unfair competition in regards to a Work,
- subject to the limitations in paragraph 4(i), below;
- 5. rights protecting the extraction, dissemination, use and reuse of data in
- a Work;
- 6. database rights (such as those arising under Directive 96/9/EC of the
- European Parliament and of the Council of 11 March 1996 on the legal
- protection of databases, and under any national implementation thereof,
- including any amended or successor version of such directive); and
- 7. other similar, equivalent or corresponding rights throughout the world
- based on applicable law or treaty, and any national implementations
- thereof.
-
- 2. Waiver. To the greatest extent permitted by, but not in contravention of,
- applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
- unconditionally waives, abandons, and surrenders all of Affirmer’s Copyright
- and Related Rights and associated claims and causes of action, whether now
- known or unknown (including existing as well as future claims and causes of
- action), in the Work (i) in all territories worldwide, (ii) for the maximum
- duration provided by applicable law or treaty (including future time
- extensions), (iii) in any current or future medium and for any number of
- copies, and (iv) for any purpose whatsoever, including without limitation
- commercial, advertising or promotional purposes (the “Waiver”). Affirmer
- makes the Waiver for the benefit of each member of the public at large and
- to the detriment of Affirmer’s heirs and successors, fully intending that
- such Waiver shall not be subject to revocation, rescission, cancellation,
- termination, or any other legal or equitable action to disrupt the quiet
- enjoyment of the Work by the public as contemplated by Affirmer’s express
- Statement of Purpose.
-
- 3. Public License Fallback. Should any part of the Waiver for any reason be
- judged legally invalid or ineffective under applicable law, then the Waiver
- shall be preserved to the maximum extent permitted taking into account
- Affirmer’s express Statement of Purpose. In addition, to the extent the
- Waiver is so judged Affirmer hereby grants to each affected person a
- royalty-free, non transferable, non sublicensable, non exclusive,
- irrevocable and unconditional license to exercise Affirmer’s Copyright and
- Related Rights in the Work (i) in all territories worldwide, (ii) for the
- maximum duration provided by applicable law or treaty (including future time
- extensions), (iii) in any current or future medium and for any number of
- copies, and (iv) for any purpose whatsoever, including without limitation
- commercial, advertising or promotional purposes (the “License”). The License
- shall be deemed effective as of the date CC0 was applied by Affirmer to the
- Work. Should any part of the License for any reason be judged legally
- invalid or ineffective under applicable law, such partial invalidity or
- ineffectiveness shall not invalidate the remainder of the License, and in
- such case Affirmer hereby affirms that he or she will not (i) exercise any
- of his or her remaining Copyright and Related Rights in the Work or (ii)
- assert any associated claims and causes of action with respect to the Work,
- in either case contrary to Affirmer’s express Statement of Purpose.
-
- 4. Limitations and Disclaimers.
- 1. No trademark or patent rights held by Affirmer are waived, abandoned,
- surrendered, licensed or otherwise affected by this document.
- 2. Affirmer offers the Work as-is and makes no representations or warranties
- of any kind concerning the Work, express, implied, statutory or
- otherwise, including without limitation warranties of title,
- merchantability, fitness for a particular purpose, non infringement, or
- the absence of latent or other defects, accuracy, or the present or
- absence of errors, whether or not discoverable, all to the greatest
- extent permissible under applicable law.
- 3. Affirmer disclaims responsibility for clearing rights of other persons
- that may apply to the Work or any use thereof, including without
- limitation any person’s Copyright and Related Rights in the Work.
- Further, Affirmer disclaims responsibility for obtaining any necessary
- consents, permissions or other rights required for any use of the Work.
- 4. Affirmer understands and acknowledges that Creative Commons is not a
- party to this document and has no duty or obligation with respect to this
- CC0 or use of the Work.
-
- For more information, please see
- http://creativecommons.org/publicdomain/zero/1.0/.
-
## semver
The ISC License
diff --git a/about.html b/about.html
index 32eafe56b0b..d6ea6b7c6e0 100644
--- a/about.html
+++ b/about.html
@@ -15,12 +15,8 @@
script-src 'self';
style-src 'self' 'unsafe-inline';"
/>
-
+
diff --git a/background.html b/background.html
index d1aaa17fc02..deddd89e6b8 100644
--- a/background.html
+++ b/background.html
@@ -76,6 +76,13 @@
type="font/woff2"
crossorigin
/>
+
-
-
+
diff --git a/debug_log.html b/debug_log.html
index bf23592ab3d..111a4bb0a60 100644
--- a/debug_log.html
+++ b/debug_log.html
@@ -15,12 +15,8 @@
script-src 'self';
style-src 'self' 'unsafe-inline';"
/>
-
+
diff --git a/fonts/signal-symbols/SignalSymbolsVariable.woff2 b/fonts/signal-symbols/SignalSymbolsVariable.woff2
new file mode 100644
index 00000000000..24f696573c6
Binary files /dev/null and b/fonts/signal-symbols/SignalSymbolsVariable.woff2 differ
diff --git a/loading.html b/loading.html
index 7e0e0295e3a..89743e64701 100644
--- a/loading.html
+++ b/loading.html
@@ -16,12 +16,8 @@
script-src 'self';
style-src 'self' 'unsafe-inline';"
/>
-
+
diff --git a/package.json b/package.json
index cfbb26817b9..1eb4f47508d 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
"postinstall": "pnpm run build:acknowledgments && pnpm run electron:install-app-deps",
"postuninstall": "pnpm run build:acknowledgments",
"start": "electron .",
- "generate": "npm-run-all build-protobuf build:esbuild build:icu-types build:compact-locales sass get-expire-time copy-components",
+ "generate": "npm-run-all build-protobuf build:esbuild build:icu-types build:compact-locales build:styles get-expire-time copy-components",
"build-release": "pnpm run build",
"sign-release": "node ts/updater/generateSignature.js",
"notarize": "echo 'No longer necessary'",
@@ -30,7 +30,6 @@
"mark-unusued-strings-deleted": "ts-node ./ts/scripts/mark-unused-strings-deleted.ts",
"get-expire-time": "node ts/scripts/get-expire-time.js",
"copy-components": "node ts/scripts/copy.js",
- "sass": "sass stylesheets/manifest.scss:stylesheets/manifest.css stylesheets/manifest_bridge.scss:stylesheets/manifest_bridge.css --fatal-deprecation=1.80.7",
"build-module-protobuf": "pbjs --root='signal-desktop' --target static-module --force-long --no-typeurl --no-verify --no-create --no-convert --wrap commonjs --out ts/protobuf/compiled.js protos/*.proto && pbts --no-comments --out ts/protobuf/compiled.d.ts ts/protobuf/compiled.js",
"clean-module-protobuf": "rm -f ts/protobuf/compiled.d.ts ts/protobuf/compiled.js",
"build-protobuf": "pnpm run build-module-protobuf",
@@ -69,7 +68,9 @@
"dev": "pnpm run build-protobuf && cross-env SIGNAL_ENV=storybook storybook dev --port 6006",
"dev:transpile": "run-p \"check:types --watch\" dev:esbuild dev:icu-types dev:protobuf",
"dev:esbuild": "node scripts/esbuild.js --watch",
- "dev:sass": "pnpm run sass --watch",
+ "dev:styles": "pnpm run '/^dev:styles:(sass|tailwind)$/'",
+ "dev:styles:sass": "pnpm run build:styles:sass --watch",
+ "dev:styles:tailwind": "pnpm run build:styles:tailwind --watch",
"dev:icu-types": "chokidar ./_locales/en/messages.json --initial --command \"pnpm run build:icu-types\"",
"dev:protobuf": "chokidar ./protos/**/*.proto --command \"pnpm run build-protobuf\"",
"build:storybook": "pnpm run build-protobuf && cross-env SIGNAL_ENV=storybook storybook build",
@@ -87,6 +88,9 @@
"build:dev": "run-s --print-label generate build:esbuild:prod",
"build:esbuild": "node scripts/esbuild.js",
"build:esbuild:prod": "node scripts/esbuild.js --prod",
+ "build:styles": "pnpm run \"/^build:styles:.*/\"",
+ "build:styles:sass": "sass stylesheets/manifest.scss:stylesheets/manifest.css stylesheets/manifest_bridge.scss:stylesheets/manifest_bridge.css --fatal-deprecation=1.80.7",
+ "build:styles:tailwind": "tailwindcss -i ./ts/axo/tailwind.css -o ./stylesheets/tailwind.css",
"build:electron": "electron-builder --config.extraMetadata.environment=$SIGNAL_ENV",
"build:release": "cross-env SIGNAL_ENV=production pnpm run build:electron --config.directories.output=release",
"build:release-win32-all": "pnpm run build:release --arm64 --x64",
@@ -183,6 +187,7 @@
"protobufjs": "7.3.2",
"proxy-agent": "6.4.0",
"qrcode-generator": "1.4.4",
+ "radix-ui": "1.4.2",
"react": "18.3.1",
"react-aria": "3.35.1",
"react-aria-components": "1.4.1",
@@ -199,7 +204,6 @@
"redux-promise-middleware": "6.2.0",
"redux-thunk": "3.1.0",
"reselect": "5.1.1",
- "sanitize.css": "13.0.0",
"semver": "7.6.3",
"split2": "4.2.0",
"tinykeys": "3.0.0",
@@ -244,6 +248,8 @@
"@storybook/test": "8.4.4",
"@storybook/test-runner": "0.22.0",
"@storybook/types": "8.1.11",
+ "@tailwindcss/cli": "4.1.7",
+ "@tailwindcss/postcss": "4.1.7",
"@types/backbone": "1.4.22",
"@types/blueimp-load-image": "5.16.6",
"@types/chai": "4.3.16",
@@ -305,6 +311,7 @@
"eslint": "8.56.0",
"eslint-config-airbnb-typescript-prettier": "5.0.0",
"eslint-config-prettier": "8.5.0",
+ "eslint-plugin-better-tailwindcss": "3.7.2",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-local-rules": "1.3.2",
"eslint-plugin-mocha": "10.1.0",
@@ -324,7 +331,10 @@
"pixelmatch": "5.3.0",
"playwright": "1.45.0",
"pngjs": "7.0.0",
+ "postcss": "8.5.3",
+ "postcss-loader": "8.1.1",
"prettier": "3.3.3",
+ "prettier-plugin-tailwindcss": "0.6.11",
"protobufjs-cli": "1.1.1",
"react-devtools": "6.0.1",
"react-devtools-core": "6.0.1",
@@ -340,6 +350,7 @@
"stylelint-config-recommended-scss": "14.1.0",
"stylelint-use-logical-spec": "5.0.1",
"svgo": "3.3.2",
+ "tailwindcss": "4.1.7",
"terser-webpack-plugin": "5.3.10",
"ts-node": "10.9.2",
"typescript": "5.6.3",
@@ -379,7 +390,8 @@
"node-fetch@2.6.7": "patches/node-fetch+2.6.7.patch",
"zod@3.23.8": "patches/zod+3.23.8.patch",
"app-builder-lib": "patches/app-builder-lib.patch",
- "dmg-builder": "patches/dmg-builder.patch"
+ "dmg-builder": "patches/dmg-builder.patch",
+ "eslint-plugin-better-tailwindcss": "patches/eslint-plugin-better-tailwindcss.patch"
},
"onlyBuiltDependencies": [
"@indutny/mac-screen-share",
@@ -390,6 +402,7 @@
"@signalapp/ringrtc",
"@signalapp/windows-ucv",
"@swc/core",
+ "@tailwindcss/oxide",
"bufferutil",
"electron",
"esbuild",
diff --git a/patches/eslint-plugin-better-tailwindcss.patch b/patches/eslint-plugin-better-tailwindcss.patch
new file mode 100644
index 00000000000..d8e0d2072d6
--- /dev/null
+++ b/patches/eslint-plugin-better-tailwindcss.patch
@@ -0,0 +1,13 @@
+diff --git a/lib/cjs/tailwindcss/context.async.v4.js b/lib/cjs/tailwindcss/context.async.v4.js
+index 8464d9d949a0d82a53f3c6683c617b56770e5fba..ac392e6e8139f33650fc1691e5593660f87912cf 100644
+--- a/lib/cjs/tailwindcss/context.async.v4.js
++++ b/lib/cjs/tailwindcss/context.async.v4.js
+@@ -59,7 +59,7 @@ const createTailwindContext = async (ctx) => (0, cache_js_1.withCache)("tailwind
+ }
+ const tailwindUrl = (0, platform_js_1.isWindows)() && (0, module_js_1.isESModule)() ? (0, node_url_1.pathToFileURL)(tailwindPath).toString() : tailwindPath;
+ // eslint-disable-next-line eslint-plugin-typescript/naming-convention
+- const { __unstable__loadDesignSystem } = await Promise.resolve(`${tailwindUrl}`).then(s => __importStar(require(s)));
++ const { __unstable__loadDesignSystem } = await import(`${tailwindUrl}`);
+ let css = await (0, promises_1.readFile)(ctx.tailwindConfigPath, "utf-8");
+ // Determine if the v4 API supports resolving `@import`
+ let supportsImports = false;
diff --git a/permissions_popup.html b/permissions_popup.html
index 831233bcac3..323dc5827b9 100644
--- a/permissions_popup.html
+++ b/permissions_popup.html
@@ -15,12 +15,8 @@
script-src 'self';
style-src 'self' 'unsafe-inline';"
/>
-
+
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9026548b741..38822e8498a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,6 +45,9 @@ patchedDependencies:
dmg-builder:
hash: cb72ed47fa8d45513a36db33fcb41cb75c30cada4737da067bf3fa1f063725f2
path: patches/dmg-builder.patch
+ eslint-plugin-better-tailwindcss:
+ hash: a94affa4d170a27c4cfd44f7ac30ea11ae285cb4e270a5d930dd28cc79901b4f
+ path: patches/eslint-plugin-better-tailwindcss.patch
fabric@4.6.0:
hash: 259e6eff3d60c4a453f7815fca6aa0d3a81842f4efdc4051836812fc1e711e00
path: patches/fabric+4.6.0.patch
@@ -314,6 +317,9 @@ importers:
qrcode-generator:
specifier: 1.4.4
version: 1.4.4(patch_hash=1f10c592d849ed4cfc9f81301196d39857b79240997ef5772138218cb3717e80)
+ radix-ui:
+ specifier: 1.4.2
+ version: 1.4.2(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react:
specifier: 18.3.1
version: 18.3.1
@@ -362,9 +368,6 @@ importers:
reselect:
specifier: 5.1.1
version: 5.1.1
- sanitize.css:
- specifier: 13.0.0
- version: 13.0.0
semver:
specifier: 7.6.3
version: 7.6.3
@@ -492,6 +495,12 @@ importers:
'@storybook/types':
specifier: 8.1.11
version: 8.1.11
+ '@tailwindcss/cli':
+ specifier: 4.1.7
+ version: 4.1.7
+ '@tailwindcss/postcss':
+ specifier: 4.1.7
+ version: 4.1.7
'@types/backbone':
specifier: 1.4.22
version: 1.4.22(patch_hash=9dace206a9f53e0e3b0203051b26aec1e92ad49744b156ad8076946356c6c8e7)
@@ -675,6 +684,9 @@ importers:
eslint-config-prettier:
specifier: 8.5.0
version: 8.5.0(eslint@8.56.0)
+ eslint-plugin-better-tailwindcss:
+ specifier: 3.7.2
+ version: 3.7.2(patch_hash=a94affa4d170a27c4cfd44f7ac30ea11ae285cb4e270a5d930dd28cc79901b4f)(eslint@8.56.0)(tailwindcss@4.1.7)
eslint-plugin-import:
specifier: 2.26.0
version: 2.26.0(@typescript-eslint/parser@6.18.1(eslint@8.56.0)(typescript@5.6.3))(eslint@8.56.0)
@@ -732,9 +744,18 @@ importers:
pngjs:
specifier: 7.0.0
version: 7.0.0
+ postcss:
+ specifier: 8.5.3
+ version: 8.5.3
+ postcss-loader:
+ specifier: 8.1.1
+ version: 8.1.1(postcss@8.5.3)(typescript@5.6.3)(webpack@5.96.1)
prettier:
specifier: 3.3.3
version: 3.3.3
+ prettier-plugin-tailwindcss:
+ specifier: 0.6.11
+ version: 0.6.11(prettier@3.3.3)
protobufjs-cli:
specifier: 1.1.1
version: 1.1.1(patch_hash=178ca99a7e71f1cce7aadae6118e2c4c3b2478d3bfb787c00a661c3b02c09923)(protobufjs@7.3.2(patch_hash=0ae0fcb7c2b673e67231536164cc4841642d16c8a26578de4d43637e2a6f1774))
@@ -773,13 +794,16 @@ importers:
version: 4.4.0(stylelint@16.10.0(typescript@5.6.3))
stylelint-config-recommended-scss:
specifier: 14.1.0
- version: 14.1.0(postcss@8.5.2)(stylelint@16.10.0(typescript@5.6.3))
+ version: 14.1.0(postcss@8.5.3)(stylelint@16.10.0(typescript@5.6.3))
stylelint-use-logical-spec:
specifier: 5.0.1
version: 5.0.1(stylelint@16.10.0(typescript@5.6.3))
svgo:
specifier: 3.3.2
version: 3.3.2
+ tailwindcss:
+ specifier: 4.1.7
+ version: 4.1.7
terser-webpack-plugin:
specifier: 5.3.10
version: 5.3.10(@swc/core@1.10.16(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1)
@@ -814,6 +838,10 @@ packages:
'@adobe/css-tools@4.4.2':
resolution: {integrity: sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==}
+ '@alloc/quick-lru@5.2.0':
+ resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+ engines: {node: '>=10'}
+
'@ampproject/remapping@2.3.0':
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
@@ -1343,6 +1371,10 @@ packages:
resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+ '@eslint/css-tree@3.6.3':
+ resolution: {integrity: sha512-M9iq4Brt/MG+5/B4Jrla5XZqaCgaHjfZyMSUJM3KNpBU61u8gMYg4TTaNTP/mUGR/rnRrVV7RXmh5qI4pIk0Yw==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+
'@eslint/eslintrc@2.1.4':
resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -1918,6 +1950,10 @@ packages:
resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ '@pkgr/core@0.2.9':
+ resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
@@ -1951,9 +1987,51 @@ packages:
'@protobufjs/utf8@1.1.0':
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
+ '@radix-ui/number@1.1.1':
+ resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
+
'@radix-ui/primitive@1.1.2':
resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==}
+ '@radix-ui/react-accessible-icon@1.1.7':
+ resolution: {integrity: sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-accordion@1.2.11':
+ resolution: {integrity: sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-alert-dialog@1.1.14':
+ resolution: {integrity: sha512-IOZfZ3nPvN6lXpJTBCunFQPRSvK8MDgSc1FB85xnIpUKOw9en0dJj8JmCAxV7BiZdtYlUpmrQjoTFkVYtdoWzQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-arrow@1.1.7':
resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
peerDependencies:
@@ -1967,6 +2045,71 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-aspect-ratio@1.1.7':
+ resolution: {integrity: sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-avatar@1.1.10':
+ resolution: {integrity: sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-checkbox@1.3.2':
+ resolution: {integrity: sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-collapsible@1.1.11':
+ resolution: {integrity: sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-collection@1.1.7':
+ resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-compose-refs@1.1.2':
resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
peerDependencies:
@@ -1976,6 +2119,19 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-context-menu@2.2.15':
+ resolution: {integrity: sha512-UsQUMjcYTsBjTSXw0P3GO0werEQvUY2plgRQuKoCTtkNr45q1DiL51j4m7gxhABzZ0BadoXNsIbg7F3KwiUBbw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-context@1.1.2':
resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==}
peerDependencies:
@@ -1985,6 +2141,28 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-dialog@1.1.14':
+ resolution: {integrity: sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-direction@1.1.1':
+ resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
'@radix-ui/react-dismissable-layer@1.1.10':
resolution: {integrity: sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==}
peerDependencies:
@@ -1998,6 +2176,67 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-dropdown-menu@2.1.15':
+ resolution: {integrity: sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-focus-guards@1.1.2':
+ resolution: {integrity: sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-focus-scope@1.1.7':
+ resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-form@0.1.7':
+ resolution: {integrity: sha512-IXLKFnaYvFg/KkeV5QfOX7tRnwHXp127koOFUjLWMTrRv5Rny3DQcAtIFFeA/Cli4HHM8DuJCXAUsgnFVJndlw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-hover-card@1.1.14':
+ resolution: {integrity: sha512-CPYZ24Mhirm+g6D8jArmLzjYu4Eyg3TTUHswR26QgzXBHBe64BO/RHOJKzmF/Dxb4y4f9PKyJdwm/O/AhNkb+Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-id@1.1.1':
resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==}
peerDependencies:
@@ -2007,6 +2246,97 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-label@2.1.7':
+ resolution: {integrity: sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-menu@2.1.15':
+ resolution: {integrity: sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-menubar@1.1.15':
+ resolution: {integrity: sha512-Z71C7LGD+YDYo3TV81paUs8f3Zbmkvg6VLRQpKYfzioOE6n7fOhA3ApK/V/2Odolxjoc4ENk8AYCjohCNayd5A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-navigation-menu@1.2.13':
+ resolution: {integrity: sha512-WG8wWfDiJlSF5hELjwfjSGOXcBR/ZMhBFCGYe8vERpC39CQYZeq1PQ2kaYHdye3V95d06H89KGMsVCIE4LWo3g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-one-time-password-field@0.1.7':
+ resolution: {integrity: sha512-w1vm7AGI8tNXVovOK7TYQHrAGpRF7qQL+ENpT1a743De5Zmay2RbWGKAiYDKIyIuqptns+znCKwNztE2xl1n0Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-password-toggle-field@0.1.2':
+ resolution: {integrity: sha512-F90uYnlBsLPU1UbSLciLsWQmk8+hdWa6SFw4GXaIdNWxFxI5ITKVdAG64f+Twaa9ic6xE7pqxPyUmodrGjT4pQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-popover@1.1.14':
+ resolution: {integrity: sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-popper@1.2.7':
resolution: {integrity: sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==}
peerDependencies:
@@ -2059,6 +2389,97 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-progress@1.1.7':
+ resolution: {integrity: sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-radio-group@1.3.7':
+ resolution: {integrity: sha512-9w5XhD0KPOrm92OTTE0SysH3sYzHsSTHNvZgUBo/VZ80VdYyB5RneDbc0dKpURS24IxkoFRu/hI0i4XyfFwY6g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-roving-focus@1.1.10':
+ resolution: {integrity: sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-scroll-area@1.2.9':
+ resolution: {integrity: sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-select@2.2.5':
+ resolution: {integrity: sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-separator@1.1.7':
+ resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-slider@1.3.5':
+ resolution: {integrity: sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-slot@1.2.3':
resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==}
peerDependencies:
@@ -2068,6 +2489,84 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-switch@1.2.5':
+ resolution: {integrity: sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-tabs@1.1.12':
+ resolution: {integrity: sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toast@1.2.14':
+ resolution: {integrity: sha512-nAP5FBxBJGQ/YfUB+r+O6USFVkWq3gAInkxyEnmvEV5jtSbfDhfa4hwX8CraCnbjMLsE7XSf/K75l9xXY7joWg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toggle-group@1.1.10':
+ resolution: {integrity: sha512-kiU694Km3WFLTC75DdqgM/3Jauf3rD9wxeS9XtyWFKsBUeZA337lC+6uUazT7I1DhanZ5gyD5Stf8uf2dbQxOQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toggle@1.1.9':
+ resolution: {integrity: sha512-ZoFkBBz9zv9GWer7wIjvdRxmh2wyc2oKWw6C6CseWd6/yq1DK/l5lJ+wnsmFwJZbBYqr02mrf8A2q/CVCuM3ZA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toolbar@1.1.10':
+ resolution: {integrity: sha512-jiwQsduEL++M4YBIurjSa+voD86OIytCod0/dbIxFZDLD8NfO1//keXYMfsW8BPcfqwoNjt+y06XcJqAb4KR7A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-tooltip@1.2.7':
resolution: {integrity: sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==}
peerDependencies:
@@ -2117,6 +2616,15 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-use-is-hydrated@0.1.0':
+ resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
'@radix-ui/react-use-layout-effect@1.1.1':
resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==}
peerDependencies:
@@ -2126,6 +2634,15 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-use-previous@1.1.1':
+ resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
'@radix-ui/react-use-rect@1.1.1':
resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==}
peerDependencies:
@@ -3092,6 +3609,98 @@ packages:
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
engines: {node: '>=10'}
+ '@tailwindcss/cli@4.1.7':
+ resolution: {integrity: sha512-hJNjpov/UiJc9ZWH4j/eEQxqklADrD/71s+t8Y0wbyQVAwtLkSp+MeC/sHTb03X+28rfbe0fRXkiBsf73/IwPg==}
+ hasBin: true
+
+ '@tailwindcss/node@4.1.7':
+ resolution: {integrity: sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==}
+
+ '@tailwindcss/oxide-android-arm64@4.1.7':
+ resolution: {integrity: sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@tailwindcss/oxide-darwin-arm64@4.1.7':
+ resolution: {integrity: sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-darwin-x64@4.1.7':
+ resolution: {integrity: sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-freebsd-x64@4.1.7':
+ resolution: {integrity: sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.7':
+ resolution: {integrity: sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.7':
+ resolution: {integrity: sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.7':
+ resolution: {integrity: sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.7':
+ resolution: {integrity: sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-musl@4.1.7':
+ resolution: {integrity: sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-wasm32-wasi@4.1.7':
+ resolution: {integrity: sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+ bundledDependencies:
+ - '@napi-rs/wasm-runtime'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@tybys/wasm-util'
+ - '@emnapi/wasi-threads'
+ - tslib
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.7':
+ resolution: {integrity: sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.7':
+ resolution: {integrity: sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@tailwindcss/oxide@4.1.7':
+ resolution: {integrity: sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==}
+ engines: {node: '>= 10'}
+
+ '@tailwindcss/postcss@4.1.7':
+ resolution: {integrity: sha512-88g3qmNZn7jDgrrcp3ZXEQfp9CVox7xjP1HN2TFKI03CltPVd/c61ydn5qJJL8FYunn0OqBaW5HNUga0kmPVvw==}
+
'@tanstack/react-virtual@3.11.2':
resolution: {integrity: sha512-OuFzMXPF4+xZgx8UzJha0AieuMihhhaWG0tCqpp6tDzlFwOmNBPYMuLOtMJ1Tr4pXLHmgjcWhG6RlknY2oNTdQ==}
peerDependencies:
@@ -3842,6 +4451,10 @@ packages:
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ aria-hidden@1.2.6:
+ resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
+ engines: {node: '>=10'}
+
aria-query@5.3.0:
resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
@@ -4844,14 +5457,17 @@ packages:
engines: {node: '>=0.10'}
hasBin: true
- detect-libc@2.0.3:
- resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
+ detect-libc@2.0.4:
+ resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
engines: {node: '>=8'}
detect-newline@3.1.0:
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
engines: {node: '>=8'}
+ detect-node-es@1.1.0:
+ resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
+
detect-node@2.1.0:
resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
@@ -5080,6 +5696,10 @@ packages:
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
engines: {node: '>=10.13.0'}
+ enhanced-resolve@5.18.2:
+ resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==}
+ engines: {node: '>=10.13.0'}
+
enquirer@2.4.1:
resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
engines: {node: '>=8.6'}
@@ -5257,6 +5877,13 @@ packages:
eslint-import-resolver-webpack:
optional: true
+ eslint-plugin-better-tailwindcss@3.7.2:
+ resolution: {integrity: sha512-uJnoDGmUPtxHHcIW5njEoh1CYlq39E4J2pWq+D7REDGhW41arSCeeaiiwAT4Ok04kXNvmFBiYmC6Jdd6Bz7o2Q==}
+ engines: {node: ^20.11.0 || >=21.2.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
+ tailwindcss: ^3.3.0 || ^4.1.6
+
eslint-plugin-import@2.26.0:
resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==}
engines: {node: '>=4'}
@@ -5741,6 +6368,10 @@ packages:
resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==}
engines: {node: '>= 0.4'}
+ get-nonce@1.0.1:
+ resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
+ engines: {node: '>=6'}
+
get-package-type@0.1.0:
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
engines: {node: '>=8.0.0'}
@@ -6685,6 +7316,14 @@ packages:
node-notifier:
optional: true
+ jiti@1.21.7:
+ resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
+ hasBin: true
+
+ jiti@2.4.2:
+ resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
+ hasBin: true
+
joi@17.13.3:
resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==}
@@ -6839,6 +7478,70 @@ packages:
resolution: {integrity: sha512-4Nk0dKhhRfVS4mECcX2jSDpNU6gcHQLneJjkGQq61N8COGtjSpSA3CI+1Q3kUYv5Vf+SwIqUtaDSdU6JO37c6w==}
engines: {node: '>=8.0.0'}
+ lightningcss-darwin-arm64@1.30.1:
+ resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.30.1:
+ resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.30.1:
+ resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.30.1:
+ resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.30.1:
+ resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-arm64-musl@1.30.1:
+ resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-x64-gnu@1.30.1:
+ resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-linux-x64-musl@1.30.1:
+ resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-win32-arm64-msvc@1.30.1:
+ resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.30.1:
+ resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.30.1:
+ resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
+ engines: {node: '>= 12.0.0'}
+
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
@@ -7107,6 +7810,9 @@ packages:
mdn-data@2.15.0:
resolution: {integrity: sha512-KIrS0lFPOqA4DgeO16vI5fkAsy8p++WBlbXtB5P1EQs8ubBgguAInNd1DnrCeTRfGchY0kgThgDOOIPyOLH2dQ==}
+ mdn-data@2.21.0:
+ resolution: {integrity: sha512-+ZKPQezM5vYJIkCxaC+4DTnRrVZR1CgsKLu5zsQERQx6Tea8Y+wMx5A24rq8A8NepCeatIQufVAekKNgiBMsGQ==}
+
mdurl@2.0.0:
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
@@ -7336,6 +8042,10 @@ packages:
mp4box@0.5.3:
resolution: {integrity: sha512-RIvyFZdPDIg3+mL6vUdPBSyQRrEfKO3ryAeJ4xJJV7HBHQUH3KfLlZRzfSpBHCd/HqR63HfbrWQI/CwXDvYENQ==}
+ mri@1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+
ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
@@ -7349,6 +8059,11 @@ packages:
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
nanoid@3.3.8:
resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -7811,6 +8526,10 @@ packages:
engines: {node: '>=0.10'}
hasBin: true
+ pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+
pify@3.0.0:
resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==}
engines: {node: '>=4'}
@@ -7886,6 +8605,25 @@ packages:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
+ postcss-import@16.1.1:
+ resolution: {integrity: sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+
+ postcss-loader@8.1.1:
+ resolution: {integrity: sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==}
+ engines: {node: '>= 18.12.0'}
+ peerDependencies:
+ '@rspack/core': 0.x || 1.x
+ postcss: ^7.0.0 || ^8.0.1
+ webpack: ^5.0.0
+ peerDependenciesMeta:
+ '@rspack/core':
+ optional: true
+ webpack:
+ optional: true
+
postcss-media-query-parser@0.2.3:
resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==}
@@ -7939,8 +8677,12 @@ packages:
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
- postcss@8.5.2:
- resolution: {integrity: sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==}
+ postcss@8.5.3:
+ resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
postject@1.0.0-alpha.6:
@@ -7964,6 +8706,61 @@ packages:
resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
engines: {node: '>=6.0.0'}
+ prettier-plugin-tailwindcss@0.6.11:
+ resolution: {integrity: sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==}
+ engines: {node: '>=14.21.3'}
+ peerDependencies:
+ '@ianvs/prettier-plugin-sort-imports': '*'
+ '@prettier/plugin-pug': '*'
+ '@shopify/prettier-plugin-liquid': '*'
+ '@trivago/prettier-plugin-sort-imports': '*'
+ '@zackad/prettier-plugin-twig': '*'
+ prettier: ^3.0
+ prettier-plugin-astro: '*'
+ prettier-plugin-css-order: '*'
+ prettier-plugin-import-sort: '*'
+ prettier-plugin-jsdoc: '*'
+ prettier-plugin-marko: '*'
+ prettier-plugin-multiline-arrays: '*'
+ prettier-plugin-organize-attributes: '*'
+ prettier-plugin-organize-imports: '*'
+ prettier-plugin-sort-imports: '*'
+ prettier-plugin-style-order: '*'
+ prettier-plugin-svelte: '*'
+ peerDependenciesMeta:
+ '@ianvs/prettier-plugin-sort-imports':
+ optional: true
+ '@prettier/plugin-pug':
+ optional: true
+ '@shopify/prettier-plugin-liquid':
+ optional: true
+ '@trivago/prettier-plugin-sort-imports':
+ optional: true
+ '@zackad/prettier-plugin-twig':
+ optional: true
+ prettier-plugin-astro:
+ optional: true
+ prettier-plugin-css-order:
+ optional: true
+ prettier-plugin-import-sort:
+ optional: true
+ prettier-plugin-jsdoc:
+ optional: true
+ prettier-plugin-marko:
+ optional: true
+ prettier-plugin-multiline-arrays:
+ optional: true
+ prettier-plugin-organize-attributes:
+ optional: true
+ prettier-plugin-organize-imports:
+ optional: true
+ prettier-plugin-sort-imports:
+ optional: true
+ prettier-plugin-style-order:
+ optional: true
+ prettier-plugin-svelte:
+ optional: true
+
prettier@3.3.3:
resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
engines: {node: '>=14'}
@@ -8099,6 +8896,19 @@ packages:
resolution: {integrity: sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==}
engines: {node: '>= 12.0.0'}
+ radix-ui@1.4.2:
+ resolution: {integrity: sha512-fT/3YFPJzf2WUpqDoQi005GS8EpCi+53VhcLaHUj5fwkPYiZAjk1mSxFvbMA8Uq71L03n+WysuYC+mlKkXxt/Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
rambda@7.5.0:
resolution: {integrity: sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==}
@@ -8213,11 +9023,41 @@ packages:
redux:
optional: true
+ react-remove-scroll-bar@2.3.8:
+ resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-remove-scroll@2.7.1:
+ resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
react-stately@3.35.0:
resolution: {integrity: sha512-1BH21J/TOHpyZe7c+f1BU2bnRWaBDTjLH0WdBuzNfPOXu7RBG3ebPIRvqd7UkPaVfIcol2QJnxe8S0a314JWKA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
+ react-style-singleton@2.2.3:
+ resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
react-virtualized@9.22.6:
resolution: {integrity: sha512-U5j7KuUQt3AaMatlMJ0UJddqSiX+Km0YJxSqbAzIiGw5EmNz0khMyqP2hzgu4+QUtm+QPIrxzUX4raJxmVJnHg==}
peerDependencies:
@@ -8232,6 +9072,9 @@ packages:
resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==}
hasBin: true
+ read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+
read-last-lines@1.8.0:
resolution: {integrity: sha512-oPL0cnZkhsO2xF7DBrdzVhXSNajPP5TzzCim/2IAjeGb17ArLLTRriI/ceV6Rook3L27mvbrOvLlf9xYYnaftQ==}
@@ -8502,9 +9345,6 @@ packages:
sanitize-filename@1.6.3:
resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==}
- sanitize.css@13.0.0:
- resolution: {integrity: sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==}
-
sass-loader@16.0.3:
resolution: {integrity: sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==}
engines: {node: '>= 18.12.0'}
@@ -9003,6 +9843,10 @@ packages:
'@swc/core': ^1.2.147
webpack: '>=2'
+ synckit@0.11.11:
+ resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+
synckit@0.9.2:
resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -9014,6 +9858,13 @@ packages:
resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==}
engines: {node: '>=10.0.0'}
+ tailwind-csstree@0.1.2:
+ resolution: {integrity: sha512-SP36MjhkSGa0Yux/B863QyxljQku+WbGH5f+dqyFJXvdexemcC0Fwj/2du2DoXVkboO5Rc1Pd4i45EmFJual6w==}
+ engines: {node: '>=18.18'}
+
+ tailwindcss@4.1.7:
+ resolution: {integrity: sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==}
+
tapable@2.2.1:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
@@ -9187,6 +10038,10 @@ packages:
'@swc/wasm':
optional: true
+ tsconfig-paths-webpack-plugin@4.2.0:
+ resolution: {integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==}
+ engines: {node: '>=10.13.0'}
+
tsconfig-paths@3.15.0:
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
@@ -9401,11 +10256,36 @@ packages:
urlpattern-polyfill@10.0.0:
resolution: {integrity: sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==}
+ use-callback-ref@1.3.3:
+ resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ use-sidecar@1.1.3:
+ resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
use-sync-external-store@1.4.0:
resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ use-sync-external-store@1.5.0:
+ resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
utf-8-validate@5.0.10:
resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==}
engines: {node: '>=6.14.2'}
@@ -9815,6 +10695,8 @@ snapshots:
'@adobe/css-tools@4.4.2': {}
+ '@alloc/quick-lru@5.2.0': {}
+
'@ampproject/remapping@2.3.0':
dependencies:
'@jridgewell/gen-mapping': 0.3.8
@@ -10281,7 +11163,7 @@ snapshots:
'@malept/cross-spawn-promise': 2.0.0
chalk: 4.1.2
debug: 4.3.7(supports-color@8.1.1)
- detect-libc: 2.0.3
+ detect-libc: 2.0.4
fs-extra: 10.1.0
got: 11.8.5(patch_hash=cfe393dc1cca8970377087e9555a285d1121f75d57223ddd872b1a8d3f8c909b)
node-abi: 3.75.0
@@ -10412,6 +11294,11 @@ snapshots:
'@eslint-community/regexpp@4.12.1': {}
+ '@eslint/css-tree@3.6.3':
+ dependencies:
+ mdn-data: 2.21.0
+ source-map-js: 1.2.1
+
'@eslint/eslintrc@2.1.4':
dependencies:
ajv: 6.12.6
@@ -11188,13 +12075,14 @@ snapshots:
'@parcel/watcher-win32-arm64': 2.5.1
'@parcel/watcher-win32-ia32': 2.5.1
'@parcel/watcher-win32-x64': 2.5.1
- optional: true
'@pkgjs/parseargs@0.11.0':
optional: true
'@pkgr/core@0.1.1': {}
+ '@pkgr/core@0.2.9': {}
+
'@popperjs/core@2.11.8': {}
'@protobufjs/aspromise@1.1.2': {}
@@ -11220,8 +12108,50 @@ snapshots:
'@protobufjs/utf8@1.1.0': {}
+ '@radix-ui/number@1.1.1': {}
+
'@radix-ui/primitive@1.1.2': {}
+ '@radix-ui/react-accessible-icon@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-accordion@1.2.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collapsible': 1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-alert-dialog@1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dialog': 1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
'@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -11231,18 +12161,126 @@ snapshots:
'@types/react': 18.3.20
'@types/react-dom': 18.3.6(@types/react@18.3.20)
+ '@radix-ui/react-aspect-ratio@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-avatar@1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-checkbox@1.3.2(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-collapsible@1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-collection@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
'@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.20)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.20
+ '@radix-ui/react-context-menu@2.2.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-menu': 2.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
'@radix-ui/react-context@1.1.2(@types/react@18.3.20)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.20
+ '@radix-ui/react-dialog@1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ aria-hidden: 1.2.6
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-remove-scroll: 2.7.1(@types/react@18.3.20)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-direction@1.1.1(@types/react@18.3.20)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.20
+
'@radix-ui/react-dismissable-layer@1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
@@ -11256,6 +12294,69 @@ snapshots:
'@types/react': 18.3.20
'@types/react-dom': 18.3.6(@types/react@18.3.20)
+ '@radix-ui/react-dropdown-menu@2.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-menu': 2.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-focus-guards@1.1.2(@types/react@18.3.20)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.20
+
+ '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-form@0.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-label': 2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-hover-card@1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
'@radix-ui/react-id@1.1.1(@types/react@18.3.20)(react@18.3.1)':
dependencies:
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
@@ -11263,6 +12364,140 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.20
+ '@radix-ui/react-label@2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-menu@2.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ aria-hidden: 1.2.6
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-remove-scroll: 2.7.1(@types/react@18.3.20)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-menubar@1.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-menu': 2.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-navigation-menu@1.2.13(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-one-time-password-field@0.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/number': 1.1.1
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-password-toggle-field@0.1.2(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-popover@1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ aria-hidden: 1.2.6
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-remove-scroll: 2.7.1(@types/react@18.3.20)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
'@radix-ui/react-popper@1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -11310,6 +12545,125 @@ snapshots:
'@types/react': 18.3.20
'@types/react-dom': 18.3.6(@types/react@18.3.20)
+ '@radix-ui/react-progress@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-radio-group@1.3.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-roving-focus@1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-scroll-area@1.2.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/number': 1.1.1
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-select@2.2.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/number': 1.1.1
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ aria-hidden: 1.2.6
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-remove-scroll: 2.7.1(@types/react@18.3.20)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-separator@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-slider@1.3.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/number': 1.1.1
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
'@radix-ui/react-slot@1.2.3(@types/react@18.3.20)(react@18.3.1)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
@@ -11317,6 +12671,98 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.20
+ '@radix-ui/react-switch@1.2.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-tabs@1.1.12(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-toast@1.2.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-toggle-group@1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-toggle': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-toggle@1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
+ '@radix-ui/react-toolbar@1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-separator': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-toggle-group': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
'@radix-ui/react-tooltip@1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.2
@@ -11365,12 +12811,25 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.20
+ '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@18.3.20)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ use-sync-external-store: 1.5.0(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+
'@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.20)(react@18.3.1)':
dependencies:
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.20
+ '@radix-ui/react-use-previous@1.1.1(@types/react@18.3.20)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.20
+
'@radix-ui/react-use-rect@1.1.1(@types/react@18.3.20)(react@18.3.1)':
dependencies:
'@radix-ui/rect': 1.1.1
@@ -12939,6 +14398,88 @@ snapshots:
dependencies:
defer-to-connect: 2.0.1
+ '@tailwindcss/cli@4.1.7':
+ dependencies:
+ '@parcel/watcher': 2.5.1
+ '@tailwindcss/node': 4.1.7
+ '@tailwindcss/oxide': 4.1.7
+ enhanced-resolve: 5.18.1
+ mri: 1.2.0
+ picocolors: 1.1.1
+ tailwindcss: 4.1.7
+
+ '@tailwindcss/node@4.1.7':
+ dependencies:
+ '@ampproject/remapping': 2.3.0
+ enhanced-resolve: 5.18.1
+ jiti: 2.4.2
+ lightningcss: 1.30.1
+ magic-string: 0.30.17
+ source-map-js: 1.2.1
+ tailwindcss: 4.1.7
+
+ '@tailwindcss/oxide-android-arm64@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-arm64@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-x64@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-freebsd-x64@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-musl@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-wasm32-wasi@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.7':
+ optional: true
+
+ '@tailwindcss/oxide@4.1.7':
+ dependencies:
+ detect-libc: 2.0.4
+ tar: 7.4.3
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.1.7
+ '@tailwindcss/oxide-darwin-arm64': 4.1.7
+ '@tailwindcss/oxide-darwin-x64': 4.1.7
+ '@tailwindcss/oxide-freebsd-x64': 4.1.7
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.7
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.1.7
+ '@tailwindcss/oxide-linux-arm64-musl': 4.1.7
+ '@tailwindcss/oxide-linux-x64-gnu': 4.1.7
+ '@tailwindcss/oxide-linux-x64-musl': 4.1.7
+ '@tailwindcss/oxide-wasm32-wasi': 4.1.7
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.1.7
+ '@tailwindcss/oxide-win32-x64-msvc': 4.1.7
+
+ '@tailwindcss/postcss@4.1.7':
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ '@tailwindcss/node': 4.1.7
+ '@tailwindcss/oxide': 4.1.7
+ postcss: 8.5.3
+ tailwindcss: 4.1.7
+
'@tanstack/react-virtual@3.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/virtual-core': 3.11.2
@@ -13843,6 +15384,10 @@ snapshots:
argparse@2.0.1: {}
+ aria-hidden@1.2.6:
+ dependencies:
+ tslib: 2.8.1
+
aria-query@5.3.0:
dependencies:
dequal: 2.0.3
@@ -14696,12 +16241,12 @@ snapshots:
css-loader@6.11.0(webpack@5.96.1):
dependencies:
- icss-utils: 5.1.0(postcss@8.5.2)
- postcss: 8.5.2
- postcss-modules-extract-imports: 3.1.0(postcss@8.5.2)
- postcss-modules-local-by-default: 4.2.0(postcss@8.5.2)
- postcss-modules-scope: 3.2.1(postcss@8.5.2)
- postcss-modules-values: 4.0.0(postcss@8.5.2)
+ icss-utils: 5.1.0(postcss@8.5.3)
+ postcss: 8.5.3
+ postcss-modules-extract-imports: 3.1.0(postcss@8.5.3)
+ postcss-modules-local-by-default: 4.2.0(postcss@8.5.3)
+ postcss-modules-scope: 3.2.1(postcss@8.5.3)
+ postcss-modules-values: 4.0.0(postcss@8.5.3)
postcss-value-parser: 4.2.0
semver: 7.6.3
optionalDependencies:
@@ -14709,12 +16254,12 @@ snapshots:
css-loader@7.1.2(webpack@5.96.1):
dependencies:
- icss-utils: 5.1.0(postcss@8.5.2)
- postcss: 8.5.2
- postcss-modules-extract-imports: 3.1.0(postcss@8.5.2)
- postcss-modules-local-by-default: 4.2.0(postcss@8.5.2)
- postcss-modules-scope: 3.2.1(postcss@8.5.2)
- postcss-modules-values: 4.0.0(postcss@8.5.2)
+ icss-utils: 5.1.0(postcss@8.5.3)
+ postcss: 8.5.3
+ postcss-modules-extract-imports: 3.1.0(postcss@8.5.3)
+ postcss-modules-local-by-default: 4.2.0(postcss@8.5.3)
+ postcss-modules-scope: 3.2.1(postcss@8.5.3)
+ postcss-modules-values: 4.0.0(postcss@8.5.3)
postcss-value-parser: 4.2.0
semver: 7.6.3
optionalDependencies:
@@ -14944,13 +16489,14 @@ snapshots:
destroy@1.2.0: {}
- detect-libc@1.0.3:
- optional: true
+ detect-libc@1.0.3: {}
- detect-libc@2.0.3: {}
+ detect-libc@2.0.4: {}
detect-newline@3.1.0: {}
+ detect-node-es@1.1.0: {}
+
detect-node@2.1.0: {}
diff-sequences@29.6.3: {}
@@ -15259,6 +16805,11 @@ snapshots:
graceful-fs: 4.2.11
tapable: 2.2.1
+ enhanced-resolve@5.18.2:
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.2.1
+
enquirer@2.4.1:
dependencies:
ansi-colors: 4.1.3
@@ -15526,6 +17077,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ eslint-plugin-better-tailwindcss@3.7.2(patch_hash=a94affa4d170a27c4cfd44f7ac30ea11ae285cb4e270a5d930dd28cc79901b4f)(eslint@8.56.0)(tailwindcss@4.1.7):
+ dependencies:
+ '@eslint/css-tree': 3.6.3
+ enhanced-resolve: 5.18.2
+ eslint: 8.56.0
+ jiti: 2.4.2
+ postcss: 8.5.6
+ postcss-import: 16.1.1(postcss@8.5.6)
+ synckit: 0.11.11
+ tailwind-csstree: 0.1.2
+ tailwindcss: 4.1.7
+ tsconfig-paths-webpack-plugin: 4.2.0
+
eslint-plugin-import@2.26.0(@typescript-eslint/parser@5.62.0(eslint@8.56.0)(typescript@5.6.3))(eslint@8.56.0):
dependencies:
array-includes: 3.1.8
@@ -16166,6 +17730,8 @@ snapshots:
hasown: 2.0.2
math-intrinsics: 1.1.0
+ get-nonce@1.0.1: {}
+
get-package-type@0.1.0: {}
get-proto@1.0.1:
@@ -16598,9 +18164,9 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
- icss-utils@5.1.0(postcss@8.5.2):
+ icss-utils@5.1.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
ieee754@1.2.1: {}
@@ -17400,6 +18966,10 @@ snapshots:
- supports-color
- ts-node
+ jiti@1.21.7: {}
+
+ jiti@2.4.2: {}
+
joi@17.13.3:
dependencies:
'@hapi/hoek': 9.3.0
@@ -17569,6 +19139,51 @@ snapshots:
libheif-js@1.18.2: {}
+ lightningcss-darwin-arm64@1.30.1:
+ optional: true
+
+ lightningcss-darwin-x64@1.30.1:
+ optional: true
+
+ lightningcss-freebsd-x64@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.30.1:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.30.1:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.30.1:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.30.1:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.30.1:
+ optional: true
+
+ lightningcss@1.30.1:
+ dependencies:
+ detect-libc: 2.0.4
+ optionalDependencies:
+ lightningcss-darwin-arm64: 1.30.1
+ lightningcss-darwin-x64: 1.30.1
+ lightningcss-freebsd-x64: 1.30.1
+ lightningcss-linux-arm-gnueabihf: 1.30.1
+ lightningcss-linux-arm64-gnu: 1.30.1
+ lightningcss-linux-arm64-musl: 1.30.1
+ lightningcss-linux-x64-gnu: 1.30.1
+ lightningcss-linux-x64-musl: 1.30.1
+ lightningcss-win32-arm64-msvc: 1.30.1
+ lightningcss-win32-x64-msvc: 1.30.1
+
lines-and-columns@1.2.4: {}
linkify-it@5.0.0:
@@ -17866,6 +19481,8 @@ snapshots:
mdn-data@2.15.0: {}
+ mdn-data@2.21.0: {}
+
mdurl@2.0.0: {}
media-typer@0.3.0: {}
@@ -18116,6 +19733,8 @@ snapshots:
mp4box@0.5.3: {}
+ mri@1.2.0: {}
+
ms@2.0.0: {}
ms@2.1.3: {}
@@ -18131,6 +19750,8 @@ snapshots:
object-assign: 4.1.1
thenify-all: 1.6.0
+ nanoid@3.3.11: {}
+
nanoid@3.3.8: {}
natural-compare-lite@1.4.0: {}
@@ -18173,8 +19794,7 @@ snapshots:
node-addon-api@1.7.2:
optional: true
- node-addon-api@7.1.1:
- optional: true
+ node-addon-api@7.1.1: {}
node-addon-api@8.3.0: {}
@@ -18619,6 +20239,8 @@ snapshots:
pidtree@0.3.1: {}
+ pify@2.3.0: {}
+
pify@3.0.0: {}
pino-abstract-transport@2.0.0:
@@ -18698,38 +20320,56 @@ snapshots:
possible-typed-array-names@1.1.0: {}
+ postcss-import@16.1.1(postcss@8.5.6):
+ dependencies:
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.10
+
+ postcss-loader@8.1.1(postcss@8.5.3)(typescript@5.6.3)(webpack@5.96.1):
+ dependencies:
+ cosmiconfig: 9.0.0(typescript@5.6.3)
+ jiti: 1.21.7
+ postcss: 8.5.3
+ semver: 7.6.3
+ optionalDependencies:
+ webpack: 5.96.1(@swc/core@1.10.16(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)
+ transitivePeerDependencies:
+ - typescript
+
postcss-media-query-parser@0.2.3: {}
- postcss-modules-extract-imports@3.1.0(postcss@8.5.2):
+ postcss-modules-extract-imports@3.1.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
- postcss-modules-local-by-default@4.2.0(postcss@8.5.2):
+ postcss-modules-local-by-default@4.2.0(postcss@8.5.3):
dependencies:
- icss-utils: 5.1.0(postcss@8.5.2)
- postcss: 8.5.2
+ icss-utils: 5.1.0(postcss@8.5.3)
+ postcss: 8.5.3
postcss-selector-parser: 7.1.0
postcss-value-parser: 4.2.0
- postcss-modules-scope@3.2.1(postcss@8.5.2):
+ postcss-modules-scope@3.2.1(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-selector-parser: 7.1.0
- postcss-modules-values@4.0.0(postcss@8.5.2):
+ postcss-modules-values@4.0.0(postcss@8.5.3):
dependencies:
- icss-utils: 5.1.0(postcss@8.5.2)
- postcss: 8.5.2
+ icss-utils: 5.1.0(postcss@8.5.3)
+ postcss: 8.5.3
postcss-resolve-nested-selector@0.1.6: {}
- postcss-safe-parser@7.0.1(postcss@8.5.2):
+ postcss-safe-parser@7.0.1(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
- postcss-scss@4.0.9(postcss@8.5.2):
+ postcss-scss@4.0.9(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-selector-parser@6.1.2:
dependencies:
@@ -18743,12 +20383,18 @@ snapshots:
postcss-value-parser@4.2.0: {}
- postcss@8.5.2:
+ postcss@8.5.3:
dependencies:
nanoid: 3.3.8
picocolors: 1.1.1
source-map-js: 1.2.1
+ postcss@8.5.6:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
postject@1.0.0-alpha.6:
dependencies:
commander: 9.5.0
@@ -18764,6 +20410,10 @@ snapshots:
dependencies:
fast-diff: 1.3.0
+ prettier-plugin-tailwindcss@0.6.11(prettier@3.3.3):
+ dependencies:
+ prettier: 3.3.3
+
prettier@3.3.3: {}
pretty-error@4.0.0:
@@ -18914,6 +20564,69 @@ snapshots:
lodash.clonedeep: 4.5.0
lodash.isequal: 4.5.0
+ radix-ui@1.4.2(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@radix-ui/primitive': 1.1.2
+ '@radix-ui/react-accessible-icon': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-accordion': 1.2.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-alert-dialog': 1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-aspect-ratio': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-avatar': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-checkbox': 1.3.2(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-collapsible': 1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-context-menu': 2.2.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-dialog': 1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-dropdown-menu': 2.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-form': 0.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-hover-card': 1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-label': 2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-menu': 2.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-menubar': 1.1.15(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-navigation-menu': 1.2.13(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-one-time-password-field': 0.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-password-toggle-field': 0.1.2(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-popover': 1.1.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-progress': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-radio-group': 1.3.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-scroll-area': 1.2.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-select': 2.2.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-separator': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slider': 1.3.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-switch': 1.2.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-tabs': 1.1.12(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-toast': 1.2.14(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-toggle': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-toggle-group': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-toolbar': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-tooltip': 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+ '@types/react-dom': 18.3.6(@types/react@18.3.20)
+
rambda@7.5.0: {}
ramda@0.29.0: {}
@@ -19125,6 +20838,25 @@ snapshots:
'@types/react': 18.3.20
redux: 5.0.1
+ react-remove-scroll-bar@2.3.8(@types/react@18.3.20)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-style-singleton: 2.2.3(@types/react@18.3.20)(react@18.3.1)
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 18.3.20
+
+ react-remove-scroll@2.7.1(@types/react@18.3.20)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-remove-scroll-bar: 2.3.8(@types/react@18.3.20)(react@18.3.1)
+ react-style-singleton: 2.2.3(@types/react@18.3.20)(react@18.3.1)
+ tslib: 2.8.1
+ use-callback-ref: 1.3.3(@types/react@18.3.20)(react@18.3.1)
+ use-sidecar: 1.1.3(@types/react@18.3.20)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.20
+
react-stately@3.35.0(react@18.3.1):
dependencies:
'@react-stately/calendar': 3.7.0(react@18.3.1)
@@ -19154,6 +20886,14 @@ snapshots:
'@react-types/shared': 3.27.0(react@18.3.1)
react: 18.3.1
+ react-style-singleton@2.2.3(@types/react@18.3.20)(react@18.3.1):
+ dependencies:
+ get-nonce: 1.0.1
+ react: 18.3.1
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 18.3.20
+
react-virtualized@9.22.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@babel/runtime': 7.26.7
@@ -19175,6 +20915,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ read-cache@1.0.0:
+ dependencies:
+ pify: 2.3.0
+
read-last-lines@1.8.0:
dependencies:
mz: 2.7.0
@@ -19376,7 +21120,7 @@ snapshots:
adjust-sourcemap-loader: 4.0.0
convert-source-map: 1.9.0
loader-utils: 2.0.4
- postcss: 8.5.2
+ postcss: 8.5.3
source-map: 0.6.1
resolve.exports@2.0.3: {}
@@ -19475,8 +21219,6 @@ snapshots:
dependencies:
truncate-utf8-bytes: 1.0.2
- sanitize.css@13.0.0: {}
-
sass-loader@16.0.3(sass@1.80.7)(webpack@5.96.1):
dependencies:
neo-async: 2.6.2
@@ -19982,14 +21724,14 @@ snapshots:
optionalDependencies:
stylelint-scss: 6.11.0(stylelint@16.10.0(typescript@5.6.3))
- stylelint-config-recommended-scss@14.1.0(postcss@8.5.2)(stylelint@16.10.0(typescript@5.6.3)):
+ stylelint-config-recommended-scss@14.1.0(postcss@8.5.3)(stylelint@16.10.0(typescript@5.6.3)):
dependencies:
- postcss-scss: 4.0.9(postcss@8.5.2)
+ postcss-scss: 4.0.9(postcss@8.5.3)
stylelint: 16.10.0(typescript@5.6.3)
stylelint-config-recommended: 14.0.1(stylelint@16.10.0(typescript@5.6.3))
stylelint-scss: 6.11.0(stylelint@16.10.0(typescript@5.6.3))
optionalDependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
stylelint-config-recommended@14.0.1(stylelint@16.10.0(typescript@5.6.3)):
dependencies:
@@ -20040,9 +21782,9 @@ snapshots:
micromatch: 4.0.8
normalize-path: 3.0.0
picocolors: 1.1.1
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-resolve-nested-selector: 0.1.6
- postcss-safe-parser: 7.0.1(postcss@8.5.2)
+ postcss-safe-parser: 7.0.1(postcss@8.5.3)
postcss-selector-parser: 6.1.2
postcss-value-parser: 4.2.0
resolve-from: 5.0.0
@@ -20103,6 +21845,10 @@ snapshots:
'@swc/counter': 0.1.3
webpack: 5.96.1(@swc/core@1.10.16(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)
+ synckit@0.11.11:
+ dependencies:
+ '@pkgr/core': 0.2.9
+
synckit@0.9.2:
dependencies:
'@pkgr/core': 0.1.1
@@ -20118,6 +21864,10 @@ snapshots:
string-width: 4.2.3
strip-ansi: 6.0.1
+ tailwind-csstree@0.1.2: {}
+
+ tailwindcss@4.1.7: {}
+
tapable@2.2.1: {}
tar@6.2.1:
@@ -20291,6 +22041,13 @@ snapshots:
optionalDependencies:
'@swc/core': 1.10.16(@swc/helpers@0.5.15)
+ tsconfig-paths-webpack-plugin@4.2.0:
+ dependencies:
+ chalk: 4.1.2
+ enhanced-resolve: 5.18.2
+ tapable: 2.2.1
+ tsconfig-paths: 4.2.0
+
tsconfig-paths@3.15.0:
dependencies:
'@types/json5': 0.0.29
@@ -20511,10 +22268,29 @@ snapshots:
urlpattern-polyfill@10.0.0: {}
+ use-callback-ref@1.3.3(@types/react@18.3.20)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 18.3.20
+
+ use-sidecar@1.1.3(@types/react@18.3.20)(react@18.3.1):
+ dependencies:
+ detect-node-es: 1.1.0
+ react: 18.3.1
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 18.3.20
+
use-sync-external-store@1.4.0(react@18.3.1):
dependencies:
react: 18.3.1
+ use-sync-external-store@1.5.0(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
utf-8-validate@5.0.10:
dependencies:
node-gyp-build: 4.8.4
diff --git a/screenShare.html b/screenShare.html
index 606175d7684..5dc56396e9a 100644
--- a/screenShare.html
+++ b/screenShare.html
@@ -15,12 +15,8 @@
script-src 'self';
style-src 'self' 'unsafe-inline';"
/>
-
+
diff --git a/settings.html b/settings.html
index fe6f8d8ce85..69e0e344d66 100644
--- a/settings.html
+++ b/settings.html
@@ -15,12 +15,8 @@
script-src 'self';
style-src 'self' 'unsafe-inline';"
/>
-
+
diff --git a/stylesheets/_global.scss b/stylesheets/_global.scss
index 6ac0d2a48d5..421ae96641b 100644
--- a/stylesheets/_global.scss
+++ b/stylesheets/_global.scss
@@ -7,6 +7,8 @@
html {
height: 100%;
cursor: inherit;
+ // Legacy style from sanitize.css:
+ overflow-wrap: break-word;
}
.light-theme {
@@ -157,10 +159,13 @@ audio {
}
button {
- cursor: pointer;
font-size: inherit;
-webkit-app-region: no-drag;
}
+button:not(:disabled) {
+ cursor: pointer;
+}
+
button.grey {
border-radius: 5px;
border: solid 1px variables.$color-gray-25;
diff --git a/stylesheets/components/Select.scss b/stylesheets/components/Select.scss
index dcdb70342e4..c8d2cc464b3 100644
--- a/stylesheets/components/Select.scss
+++ b/stylesheets/components/Select.scss
@@ -20,6 +20,7 @@
padding-inline: 12px 32px;
text-overflow: ellipsis;
width: 100%;
+ color: variables.$color-black;
@include mixins.dark-theme {
background-color: variables.$color-gray-90;
diff --git a/stylesheets/components/fun/FunSearch.scss b/stylesheets/components/fun/FunSearch.scss
index 12c429199e2..3d8f93a7537 100644
--- a/stylesheets/components/fun/FunSearch.scss
+++ b/stylesheets/components/fun/FunSearch.scss
@@ -43,6 +43,7 @@ $input-padding-inline: 12px;
$input-padding-inline + $icon-actual-size + $icon-margin-inline-start
);
@include mixins.font-body-1;
+ color: light-dark(variables.$color-black, variables.$color-white);
background: light-dark(variables.$color-gray-05, variables.$color-gray-80);
&:focus {
diff --git a/test/index.html b/test/index.html
index fa21a42418a..65b1c07e741 100644
--- a/test/index.html
+++ b/test/index.html
@@ -7,6 +7,7 @@
TextSecure test runner
+
diff --git a/ts/axo/AxoButton.stories.tsx b/ts/axo/AxoButton.stories.tsx
new file mode 100644
index 00000000000..f638af85634
--- /dev/null
+++ b/ts/axo/AxoButton.stories.tsx
@@ -0,0 +1,90 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React from 'react';
+import type { Meta } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import {
+ _getAllAxoButtonVariants,
+ _getAllAxoButtonSizes,
+ AxoButton,
+} from './AxoButton';
+
+export default {
+ title: 'Axo/AxoButton',
+} satisfies Meta;
+
+export function Basic(): JSX.Element {
+ const variants = _getAllAxoButtonVariants();
+ const sizes = _getAllAxoButtonSizes();
+ return (
+
+ {sizes.map(size => {
+ return (
+
+
Size: {size}
+ {variants.map(variant => {
+ return (
+
+
+ {variant}
+
+
+
+ Disabled
+
+
+
+ Icon
+
+
+
+ Disabled
+
+
+
+ Arrow
+
+
+
+ Disabled
+
+
+ );
+ })}
+
+ );
+ })}
+
+ );
+}
diff --git a/ts/axo/AxoButton.tsx b/ts/axo/AxoButton.tsx
new file mode 100644
index 00000000000..0641e6dfa6e
--- /dev/null
+++ b/ts/axo/AxoButton.tsx
@@ -0,0 +1,195 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React, { memo, forwardRef } from 'react';
+import type { ButtonHTMLAttributes, FC, ForwardedRef, ReactNode } from 'react';
+import type { Styles } from './_internal/css';
+import { css } from './_internal/css';
+import { AxoSymbol, type AxoSymbolName } from './AxoSymbol';
+import { assert } from './_internal/assert';
+
+const Namespace = 'AxoButton';
+
+const baseAxoButtonStyles = css(
+ 'flex items-center-safe justify-center-safe gap-1 truncate rounded-full select-none',
+ 'outline-0 outline-border-focused focused:outline-[2.5px]'
+);
+
+const AxoButtonTypes = {
+ default: css(baseAxoButtonStyles),
+ subtle: css(
+ baseAxoButtonStyles,
+ 'bg-fill-secondary',
+ 'pressed:bg-fill-secondary-pressed'
+ ),
+ floating: css(
+ baseAxoButtonStyles,
+ 'bg-fill-floating',
+ 'shadow-elevation-1',
+ 'pressed:bg-fill-floating-pressed'
+ ),
+ borderless: css(
+ baseAxoButtonStyles,
+ 'bg-transparent',
+ 'hovered:bg-fill-secondary',
+ 'pressed:bg-fill-secondary-pressed'
+ ),
+} as const satisfies Record
;
+
+const AxoButtonVariants = {
+ // default
+ secondary: css(
+ AxoButtonTypes.default,
+ 'bg-fill-secondary text-label-primary',
+ 'pressed:bg-fill-secondary-pressed',
+ 'disabled:text-label-disabled'
+ ),
+ primary: css(
+ AxoButtonTypes.default,
+ 'bg-color-fill-primary text-label-primary-on-color',
+ 'pressed:bg-color-fill-primary-pressed',
+ 'disabled:text-label-disabled-on-color'
+ ),
+ affirmative: css(
+ AxoButtonTypes.default,
+ 'bg-color-fill-affirmative text-label-primary-on-color',
+ 'pressed:bg-color-fill-affirmative-pressed',
+ 'disabled:text-label-disabled-on-color'
+ ),
+ destructive: css(
+ AxoButtonTypes.default,
+ 'bg-color-fill-destructive text-label-primary-on-color',
+ 'pressed:bg-color-fill-destructive-pressed',
+ 'disabled:text-label-disabled-on-color'
+ ),
+
+ // subtle
+ 'subtle-primary': css(
+ AxoButtonTypes.subtle,
+ 'text-color-label-primary',
+ 'disabled:text-color-label-primary-disabled'
+ ),
+ 'subtle-affirmative': css(
+ AxoButtonTypes.subtle,
+ 'text-color-label-affirmative',
+ 'disabled:text-color-label-affirmative-disabled'
+ ),
+ 'subtle-destructive': css(
+ AxoButtonTypes.subtle,
+ 'text-color-label-destructive',
+ 'disabled:text-color-label-destructive-disabled'
+ ),
+
+ // floating
+ 'floating-secondary': css(
+ AxoButtonTypes.floating,
+ 'text-label-primary',
+ 'disabled:text-label-disabled'
+ ),
+ 'floating-primary': css(
+ AxoButtonTypes.floating,
+ 'text-color-label-primary',
+ 'disabled:text-color-label-primary-disabled'
+ ),
+ 'floating-affirmative': css(
+ AxoButtonTypes.floating,
+ 'text-color-label-affirmative',
+ 'disabled:text-color-label-affirmative-disabled'
+ ),
+ 'floating-destructive': css(
+ AxoButtonTypes.floating,
+ 'text-color-label-destructive',
+ 'disabled:text-color-label-destructive-disabled'
+ ),
+
+ // borderless
+ 'borderless-secondary': css(
+ AxoButtonTypes.borderless,
+ 'text-label-primary',
+ 'disabled:text-label-disabled'
+ ),
+ 'borderless-primary': css(
+ AxoButtonTypes.borderless,
+ 'text-color-label-primary',
+ 'disabled:text-color-label-primary-disabled'
+ ),
+ 'borderless-affirmative': css(
+ AxoButtonTypes.borderless,
+ 'text-color-label-affirmative',
+ 'disabled:text-color-label-affirmative-disabled'
+ ),
+ 'borderless-destructive': css(
+ AxoButtonTypes.borderless,
+ 'text-color-label-destructive',
+ 'disabled:text-color-label-destructive-disabled'
+ ),
+};
+
+const AxoButtonSizes = {
+ large: css('px-4 py-2 type-body-medium font-medium'),
+ medium: css('px-3 py-1.5 type-body-medium font-medium'),
+ small: css('px-2 py-1 type-body-small font-medium'),
+} as const satisfies Record;
+
+type BaseButtonAttrs = Omit<
+ ButtonHTMLAttributes,
+ 'className' | 'style' | 'children'
+>;
+
+type AxoButtonVariant = keyof typeof AxoButtonVariants;
+type AxoButtonSize = keyof typeof AxoButtonSizes;
+
+type AxoButtonProps = BaseButtonAttrs &
+ Readonly<{
+ variant: AxoButtonVariant;
+ size: AxoButtonSize;
+ symbol?: AxoSymbolName;
+ arrow?: boolean;
+ children: ReactNode;
+ }>;
+
+export function _getAllAxoButtonVariants(): ReadonlyArray {
+ return Object.keys(AxoButtonVariants) as Array;
+}
+
+export function _getAllAxoButtonSizes(): ReadonlyArray {
+ return Object.keys(AxoButtonSizes) as Array;
+}
+
+// eslint-disable-next-line import/export
+export const AxoButton: FC = memo(
+ forwardRef((props, ref: ForwardedRef) => {
+ const { variant, size, symbol, arrow, children, ...rest } = props;
+ const variantStyles = assert(
+ AxoButtonVariants[variant],
+ `${Namespace}: Invalid variant ${variant}`
+ );
+ const sizeStyles = assert(
+ AxoButtonSizes[size],
+ `${Namespace}: Invalid size ${size}`
+ );
+ return (
+
+ {symbol != null && (
+
+ )}
+ {children}
+ {arrow && }
+
+ );
+ })
+);
+
+AxoButton.displayName = `${Namespace}`;
+
+// eslint-disable-next-line max-len
+// eslint-disable-next-line @typescript-eslint/no-namespace, @typescript-eslint/no-redeclare, import/export
+export namespace AxoButton {
+ export type Variant = AxoButtonVariant;
+ export type Size = AxoButtonSize;
+ export type Props = AxoButtonProps;
+}
diff --git a/ts/axo/AxoContextMenu.stories.tsx b/ts/axo/AxoContextMenu.stories.tsx
new file mode 100644
index 00000000000..924eeebf3d1
--- /dev/null
+++ b/ts/axo/AxoContextMenu.stories.tsx
@@ -0,0 +1,99 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React, { useState } from 'react';
+import type { Meta } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { AxoContextMenu } from './AxoContextMenu';
+
+export default {
+ title: 'Axo/AxoContextMenu',
+} satisfies Meta;
+
+export function Basic(): JSX.Element {
+ const [showBookmarks, setShowBookmarks] = useState(true);
+ const [showFullUrls, setShowFullUrls] = useState(false);
+ const [selectedPerson, setSelectedPerson] = useState('jamie');
+ return (
+
+
+
+
+ Right-Click
+
+
+
+
+ Back
+
+
+ Forward
+
+
+ Reload
+
+
+ More Tools
+
+
+ Save Page As...
+
+
+ Create Shortcut...
+
+
+ Name Window...
+
+
+
+ Developer Tools
+
+
+
+
+
+ Show Bookmarks
+
+
+ Show Full URLs
+
+
+ People
+
+
+ Jamie
+
+
+ Tyler
+
+
+
+
+
+ );
+}
diff --git a/ts/axo/AxoContextMenu.tsx b/ts/axo/AxoContextMenu.tsx
new file mode 100644
index 00000000000..b7d7791fdca
--- /dev/null
+++ b/ts/axo/AxoContextMenu.tsx
@@ -0,0 +1,388 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React, { memo } from 'react';
+import { ContextMenu } from 'radix-ui';
+import type { FC } from 'react';
+import { AxoSymbol } from './AxoSymbol';
+import { AxoBaseMenu } from './_internal/AxoBaseMenu';
+
+const Namespace = 'AxoContextMenu';
+
+/**
+ * Displays a menu located at the pointer, triggered by a right click or a long press.
+ *
+ * Note: For menus that are triggered by a normal button press, you should use
+ * `AxoDropdownMenu`.
+ *
+ * @example Anatomy
+ * ```tsx
+ * import { AxoContextMenu } from "./axo/ContextMenu/AxoContentMenu.tsx";
+ *
+ * export default () => (
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * )
+ * ```
+ */
+// eslint-disable-next-line @typescript-eslint/no-namespace
+export namespace AxoContextMenu {
+ /**
+ * Component:
+ * --------------------------------
+ */
+
+ export type RootProps = AxoBaseMenu.MenuRootProps;
+
+ export const Root: FC = memo(props => {
+ return {props.children} ;
+ });
+
+ Root.displayName = `${Namespace}.Root`;
+
+ /**
+ * Component:
+ * -----------------------------------
+ */
+
+ export type TriggerProps = AxoBaseMenu.MenuTriggerProps;
+
+ export const Trigger: FC = memo(props => {
+ return {props.children} ;
+ });
+
+ Trigger.displayName = `${Namespace}.Trigger`;
+
+ /**
+ * Component:
+ * -----------------------------------
+ */
+
+ export type ContentProps = AxoBaseMenu.MenuContentProps;
+
+ /**
+ * The component that pops out in an open context menu.
+ * Uses a portal to render the content part into the `body`.
+ */
+ export const Content: FC = memo(props => {
+ return (
+
+
+ {props.children}
+
+
+ );
+ });
+
+ Content.displayName = `${Namespace}.Content`;
+
+ /**
+ * Component:
+ * --------------------------------
+ */
+
+ export type ItemProps = AxoBaseMenu.MenuItemProps;
+
+ /**
+ * The component that contains the context menu items.
+ * @example
+ * ```tsx
+ * }>
+ * {i18n("myContextMenuText")}
+ *
+ * ````
+ */
+ export const Item: FC = memo(props => {
+ return (
+
+ {props.symbol && (
+
+
+
+ )}
+
+ {props.children}
+ {props.keyboardShortcut && (
+
+ )}
+
+
+ );
+ });
+
+ Item.displayName = `${Namespace}.Item`;
+
+ /**
+ * Component:
+ * ---------------------------------
+ */
+
+ export type GroupProps = AxoBaseMenu.MenuGroupProps;
+
+ /**
+ * Used to group multiple {@link AxoContextMenu.Item}'s.
+ */
+ export const Group: FC = memo(props => {
+ return (
+
+ {props.children}
+
+ );
+ });
+
+ Group.displayName = `${Namespace}.Group`;
+
+ /**
+ * Component:
+ * ---------------------------------
+ */
+
+ export type LabelProps = AxoBaseMenu.MenuLabelProps;
+
+ /**
+ * Used to render a label. It won't be focusable using arrow keys.
+ */
+ export const Label: FC = memo(props => {
+ return (
+
+
+ {props.children}
+
+
+ );
+ });
+
+ Label.displayName = `${Namespace}.Label`;
+
+ /**
+ * Component:
+ * ----------------------------------------
+ */
+
+ export type CheckboxItemProps = AxoBaseMenu.MenuCheckboxItemProps;
+
+ /**
+ * An item that can be controlled and rendered like a checkbox.
+ */
+ export const CheckboxItem: FC = memo(props => {
+ return (
+
+
+
+
+
+
+
+
+
+ {props.symbol && (
+
+
+
+ )}
+ {props.children}
+ {props.keyboardShortcut && (
+
+ )}
+
+
+ );
+ });
+
+ CheckboxItem.displayName = `${Namespace}.CheckboxItem`;
+
+ /**
+ * Component:
+ * --------------------------------------
+ */
+
+ export type RadioGroupProps = AxoBaseMenu.MenuRadioGroupProps;
+
+ /**
+ * Used to group multiple {@link AxoContextMenu.RadioItem}'s.
+ */
+ export const RadioGroup: FC = memo(props => {
+ return (
+
+ {props.children}
+
+ );
+ });
+
+ RadioGroup.displayName = `${Namespace}.RadioGroup`;
+
+ /**
+ * Component:
+ * -------------------------------------
+ */
+
+ export type RadioItemProps = AxoBaseMenu.MenuRadioItemProps;
+
+ /**
+ * An item that can be controlled and rendered like a radio.
+ */
+ export const RadioItem: FC = memo(props => {
+ return (
+
+
+
+
+
+
+
+
+
+ {props.symbol && }
+ {props.children}
+ {props.keyboardShortcut && (
+
+ )}
+
+
+ );
+ });
+
+ RadioItem.displayName = `${Namespace}.RadioItem`;
+
+ /**
+ * Component:
+ * -------------------------------------
+ */
+
+ export type SeparatorProps = AxoBaseMenu.MenuSeparatorProps;
+
+ /**
+ * Used to visually separate items in the context menu.
+ */
+ export const Separator: FC = memo(() => {
+ return (
+
+ );
+ });
+
+ Separator.displayName = `${Namespace}.Separator`;
+
+ /**
+ * Component:
+ * -------------------------------
+ */
+
+ export type SubProps = AxoBaseMenu.MenuSubProps;
+
+ /**
+ * Contains all the parts of a submenu.
+ */
+ export const Sub: FC = memo(props => {
+ return {props.children} ;
+ });
+
+ Sub.displayName = `${Namespace}.Sub`;
+
+ /**
+ * Component:
+ * --------------------------------------
+ */
+
+ export type SubTriggerProps = AxoBaseMenu.MenuSubTriggerProps;
+
+ /**
+ * An item that opens a submenu. Must be rendered inside
+ * {@link ContextMenu.Sub}.
+ */
+ export const SubTrigger: FC = memo(props => {
+ return (
+
+ {props.symbol && (
+
+
+
+ )}
+
+ {props.children}
+
+
+
+
+
+ );
+ });
+
+ SubTrigger.displayName = `${Namespace}.SubTrigger`;
+
+ /**
+ * Component:
+ * --------------------------------------
+ */
+
+ export type SubContentProps = AxoBaseMenu.MenuSubContentProps;
+
+ /**
+ * The component that pops out when a submenu is open. Must be rendered
+ * inside {@link AxoContextMenu.Sub}.
+ */
+ export const SubContent: FC = memo(props => {
+ return (
+
+ {props.children}
+
+ );
+ });
+
+ SubContent.displayName = `${Namespace}.SubContent`;
+}
diff --git a/ts/axo/AxoDropdownMenu.stories.tsx b/ts/axo/AxoDropdownMenu.stories.tsx
new file mode 100644
index 00000000000..d28e6c6aaaa
--- /dev/null
+++ b/ts/axo/AxoDropdownMenu.stories.tsx
@@ -0,0 +1,100 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React, { useState } from 'react';
+import type { Meta } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { AxoDropdownMenu } from './AxoDropdownMenu';
+import { AxoButton } from './AxoButton';
+
+export default {
+ title: 'Axo/AxoDropdownMenu',
+} satisfies Meta;
+
+export function Basic(): JSX.Element {
+ const [showBookmarks, setShowBookmarks] = useState(true);
+ const [showFullUrls, setShowFullUrls] = useState(false);
+ const [selectedPerson, setSelectedPerson] = useState('jamie');
+ return (
+
+
+
+
+ Open Dropdown Menu
+
+
+
+
+ Back
+
+
+ Forward
+
+
+ Reload
+
+
+ More Tools
+
+
+ Save Page As...
+
+
+ Create Shortcut...
+
+
+ Name Window...
+
+
+
+ Developer Tools
+
+
+
+
+
+ Show Bookmarks
+
+
+ Show Full URLs
+
+
+ People
+
+
+ Jamie
+
+
+ Tyler
+
+
+
+
+
+ );
+}
diff --git a/ts/axo/AxoDropdownMenu.tsx b/ts/axo/AxoDropdownMenu.tsx
new file mode 100644
index 00000000000..4917832e5ca
--- /dev/null
+++ b/ts/axo/AxoDropdownMenu.tsx
@@ -0,0 +1,402 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React, { memo } from 'react';
+import { DropdownMenu } from 'radix-ui';
+import type { FC } from 'react';
+import { AxoSymbol } from './AxoSymbol';
+import { AxoBaseMenu } from './_internal/AxoBaseMenu';
+
+const Namespace = 'AxoDropdownMenu';
+
+/**
+ * Displays a menu to the user—such as a set of actions or functions—triggered
+ * by a button.
+ *
+ * Note: For menus that are triggered by a right-click, you should use
+ * `AxoContextMenu`.
+ *
+ * @example Anatomy
+ * ```tsx
+ * import { AxoDropdownMenu } from "./axo/DropdownMenu/AxoDropdownMenu.tsx";
+ *
+ * export default () => (
+ *
+ *
+ * Click Me
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * )
+ * ```
+ */
+// eslint-disable-next-line @typescript-eslint/no-namespace
+export namespace AxoDropdownMenu {
+ /**
+ * Component:
+ * ---------------------------------
+ */
+
+ export type RootProps = AxoBaseMenu.MenuRootProps;
+
+ /**
+ * Contains all the parts of a dropdown menu.
+ */
+ export const Root: FC = memo(props => {
+ return {props.children} ;
+ });
+
+ Root.displayName = `${Namespace}.Root`;
+
+ /**
+ * Component:
+ * ------------------------------------
+ */
+
+ export type TriggerProps = AxoBaseMenu.MenuTriggerProps;
+
+ /**
+ * The button that toggles the dropdown menu.
+ * By default, the {@link AxoDropdownMenu.Content} will position itself
+ * against the trigger.
+ */
+ export const Trigger: FC = memo(props => {
+ return (
+ {props.children}
+ );
+ });
+
+ Trigger.displayName = `${Namespace}.Trigger`;
+
+ /**
+ * Component:
+ * ------------------------------------
+ */
+
+ export type ContentProps = AxoBaseMenu.MenuContentProps;
+
+ /**
+ * The component that pops out when the dropdown menu is open.
+ * Uses a portal to render the content part into the `body`.
+ */
+ export const Content: FC = memo(props => {
+ return (
+
+
+ {props.children}
+
+
+ );
+ });
+
+ Content.displayName = `${Namespace}.Content`;
+
+ /**
+ * Component:
+ * ---------------------------------
+ */
+
+ export type ItemProps = AxoBaseMenu.MenuItemProps;
+
+ /**
+ * The component that contains the dropdown menu items.
+ * @example
+ * ```tsx
+ * }>
+ * {i18n("myContextMenuText")}
+ *
+ * ````
+ */
+ export const Item: FC = memo(props => {
+ return (
+
+ {props.symbol && (
+
+
+
+ )}
+
+ {props.children}
+ {props.keyboardShortcut && (
+
+ )}
+
+
+ );
+ });
+
+ Item.displayName = `${Namespace}.Item`;
+
+ /**
+ * Component:
+ * ----------------------------------
+ */
+
+ export type GroupProps = AxoBaseMenu.MenuGroupProps;
+
+ /**
+ * Used to group multiple {@link AxoDropdownMenu.Item}'s.
+ */
+ export const Group: FC = memo(props => {
+ return (
+
+ {props.children}
+
+ );
+ });
+
+ Group.displayName = `${Namespace}.Group`;
+
+ /**
+ * Component:
+ * ----------------------------------
+ */
+
+ export type LabelProps = AxoBaseMenu.MenuLabelProps;
+
+ /**
+ * Used to render a label. It won't be focusable using arrow keys.
+ */
+ export const Label: FC = memo(props => {
+ return (
+
+
+ {props.children}
+
+
+ );
+ });
+
+ Label.displayName = `${Namespace}.Label`;
+
+ /**
+ * Component:
+ * -----------------------------------------
+ */
+
+ export type CheckboxItemProps = AxoBaseMenu.MenuCheckboxItemProps;
+
+ /**
+ * An item that can be controlled and rendered like a checkbox.
+ */
+ export const CheckboxItem: FC = memo(props => {
+ return (
+
+
+
+
+
+
+
+
+
+ {props.symbol && (
+
+
+
+ )}
+ {props.children}
+ {props.keyboardShortcut && (
+
+ )}
+
+
+ );
+ });
+
+ CheckboxItem.displayName = `${Namespace}.CheckboxItem`;
+
+ /**
+ * Component:
+ * ---------------------------------------
+ */
+
+ export type RadioGroupProps = AxoBaseMenu.MenuRadioGroupProps;
+
+ /**
+ * Used to group multiple {@link AxoDropdownMenu.RadioItem}'s.
+ */
+ export const RadioGroup: FC = memo(props => {
+ return (
+
+ {props.children}
+
+ );
+ });
+
+ RadioGroup.displayName = `${Namespace}.RadioGroup`;
+
+ /**
+ * Component:
+ * --------------------------------------
+ */
+
+ export type RadioItemProps = AxoBaseMenu.MenuRadioItemProps;
+
+ /**
+ * An item that can be controlled and rendered like a radio.
+ */
+ export const RadioItem: FC = memo(props => {
+ return (
+
+
+
+
+
+
+
+
+
+ {props.symbol && }
+ {props.children}
+ {props.keyboardShortcut && (
+
+ )}
+
+
+ );
+ });
+
+ RadioItem.displayName = `${Namespace}.RadioItem`;
+
+ /**
+ * Component:
+ * --------------------------------------
+ */
+
+ export type SeparatorProps = AxoBaseMenu.MenuSeparatorProps;
+
+ /**
+ * Used to visually separate items in the dropdown menu.
+ */
+ export const Separator: FC = memo(() => {
+ return (
+
+ );
+ });
+
+ Separator.displayName = `${Namespace}.Separator`;
+
+ /**
+ * Component:
+ * -------------------------------
+ */
+
+ export type SubProps = AxoBaseMenu.MenuSubProps;
+
+ /**
+ * Contains all the parts of a submenu.
+ */
+ export const Sub: FC = memo(props => {
+ return {props.children} ;
+ });
+
+ Sub.displayName = `${Namespace}.Sub`;
+
+ /**
+ * Component:
+ * ---------------------------------------
+ */
+
+ export type SubTriggerProps = AxoBaseMenu.MenuSubTriggerProps;
+
+ /**
+ * An item that opens a submenu. Must be rendered inside
+ * {@link ContextMenu.Sub}.
+ */
+ export const SubTrigger: FC = memo(props => {
+ return (
+
+ {props.symbol && (
+
+
+
+ )}
+
+ {props.children}
+
+
+
+
+
+ );
+ });
+
+ SubTrigger.displayName = `${Namespace}.SubTrigger`;
+
+ /**
+ * Component:
+ * ---------------------------------------
+ */
+
+ export type SubContentProps = AxoBaseMenu.MenuSubContentProps;
+
+ /**
+ * The component that pops out when a submenu is open. Must be rendered
+ * inside {@link AxoDropdownMenu.Sub}.
+ */
+ export const SubContent: FC = memo(props => {
+ return (
+
+ {props.children}
+
+ );
+ });
+
+ SubContent.displayName = `${Namespace}.SubContent`;
+}
diff --git a/ts/axo/AxoSelect.stories.tsx b/ts/axo/AxoSelect.stories.tsx
new file mode 100644
index 00000000000..c85d21eecac
--- /dev/null
+++ b/ts/axo/AxoSelect.stories.tsx
@@ -0,0 +1,90 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React, { useState } from 'react';
+import type { Meta } from '@storybook/react';
+import { AxoSelect } from './AxoSelect';
+
+export default {
+ title: 'Axo/AxoSelect',
+} satisfies Meta;
+
+function Template(props: {
+ disabled?: boolean;
+ triggerWidth?: AxoSelect.TriggerWidth;
+ triggerVariant: AxoSelect.TriggerVariant;
+}) {
+ const [value, setValue] = useState(null);
+ return (
+
+
+
+
+ Fruits
+ Apple
+ Banana
+ Blueberry
+ Grapes
+ Pineapple
+
+
+
+ Vegetables
+ Aubergine
+ Broccoli
+
+ Carrot
+
+ Leek
+
+
+
+ Meat
+ Beef
+ Chicken
+ Lamb
+ Pork
+
+
+
+ );
+}
+
+export function Basic(): JSX.Element {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/ts/axo/AxoSelect.tsx b/ts/axo/AxoSelect.tsx
new file mode 100644
index 00000000000..ed29dc18c11
--- /dev/null
+++ b/ts/axo/AxoSelect.tsx
@@ -0,0 +1,288 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React, { memo } from 'react';
+import type { FC, ReactNode } from 'react';
+import { Select } from 'radix-ui';
+import { AxoBaseMenu } from './_internal/AxoBaseMenu';
+import { AxoSymbol } from './AxoSymbol';
+import type { Styles } from './_internal/css';
+import { css } from './_internal/css';
+
+const Namespace = 'AxoSelect';
+
+/**
+ * Displays a list of options for the user to pick from—triggered by a button.
+ *
+ * @example Anatomy
+ * ```tsx
+ * export default () => (
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * );
+ * ```
+ */
+// eslint-disable-next-line @typescript-eslint/no-namespace
+export namespace AxoSelect {
+ /**
+ * Component:
+ * ---------------------------
+ */
+
+ export type RootProps = Readonly<{
+ name?: string;
+ form?: string;
+ autoComplete?: string;
+ disabled?: boolean;
+ required?: boolean;
+ open?: boolean;
+ onOpenChange?: (open: boolean) => void;
+ value: string | null;
+ onValueChange: (value: string) => void;
+ children: ReactNode;
+ }>;
+
+ /**
+ * Contains all the parts of a select.
+ */
+ export const Root: FC = memo(props => {
+ return (
+
+ {props.children}
+
+ );
+ });
+
+ Root.displayName = `${Namespace}.Root`;
+
+ /**
+ * Component:
+ * ---------------------------
+ */
+
+ const baseTriggerStyles = css(
+ 'flex',
+ 'rounded-full py-[5px] ps-3 pe-2.5 text-label-primary',
+ 'disabled:text-label-disabled',
+ 'outline-0 outline-border-focused focused:outline-[2.5px]'
+ );
+
+ const TriggerVariants = {
+ default: css(
+ baseTriggerStyles,
+ 'bg-fill-secondary',
+ 'pressed:bg-fill-secondary-pressed'
+ ),
+ floating: css(
+ baseTriggerStyles,
+ 'bg-fill-floating',
+ 'shadow-elevation-1',
+ 'pressed:bg-fill-floating-pressed'
+ ),
+ borderless: css(
+ baseTriggerStyles,
+ 'bg-transparent',
+ 'hovered:bg-fill-secondary',
+ 'pressed:bg-fill-secondary-pressed'
+ ),
+ } as const satisfies Record;
+
+ const TriggerWidths = {
+ hug: css(),
+ fixed: css('w-[120px]'),
+ };
+
+ export type TriggerVariant = keyof typeof TriggerVariants;
+ export type TriggerWidth = keyof typeof TriggerWidths;
+
+ export type TriggerProps = Readonly<{
+ variant?: TriggerVariant;
+ width?: TriggerWidth;
+ placeholder: string;
+ children?: ReactNode;
+ }>;
+
+ /**
+ * The button that toggles the select.
+ * The {@link AxoSelect.Content} will position itself by aligning over the
+ * trigger.
+ */
+ export const Trigger: FC = memo(props => {
+ const variant = props.variant ?? 'default';
+ const width = props.width ?? 'hug';
+ const variantStyles = TriggerVariants[variant];
+ const widthStyles = TriggerWidths[width];
+ return (
+
+
+
+ {props.children}
+
+
+
+
+
+
+ );
+ });
+
+ Trigger.displayName = `${Namespace}.Trigger`;
+
+ /**
+ * Component:
+ * ------------------------------
+ */
+
+ export type ContentProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ /**
+ * The component that pops out when the select is open.
+ * Uses a portal to render the content part into the `body`.
+ */
+ export const Content: FC = memo(props => {
+ return (
+
+
+
+
+
+
+ {props.children}
+
+
+
+
+
+
+ );
+ });
+
+ Content.displayName = `${Namespace}.Content`;
+
+ /**
+ * Component:
+ * ---------------------------
+ */
+
+ export type ItemProps = Readonly<{
+ value: string;
+ disabled?: boolean;
+ textValue?: string;
+ children: ReactNode;
+ }>;
+
+ /**
+ * The component that contains the select items.
+ */
+ export const Item: FC = memo(props => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ {props.children}
+
+
+
+ );
+ });
+
+ Item.displayName = `${Namespace}.Content`;
+
+ /**
+ * Component:
+ * ---------------------------
+ */
+
+ export type GroupProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ /**
+ * Used to group multiple items.
+ * Use in conjunction with {@link AxoSelect.Label to ensure good accessibility
+ * via automatic labelling.
+ */
+ export const Group: FC = memo(props => {
+ return (
+
+ {props.children}
+
+ );
+ });
+
+ Group.displayName = `${Namespace}.Group`;
+
+ /**
+ * Component:
+ * ---------------------------
+ */
+
+ export type LabelProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ /**
+ * Used to render the label of a group. It won't be focusable using arrow keys.
+ */
+ export const Label: FC = memo(props => {
+ return (
+
+
+ {props.children}
+
+
+ );
+ });
+
+ Label.displayName = `${Namespace}.Label`;
+
+ /**
+ * Component:
+ * ---------------------------
+ */
+
+ export type SeparatorProps = Readonly<{
+ // N/A
+ }>;
+
+ /**
+ * Used to visually separate items in the select.
+ */
+ export const Separator: FC = memo(() => {
+ return ;
+ });
+
+ Separator.displayName = `${Namespace}.Separator`;
+}
diff --git a/ts/axo/AxoSymbol.stories.tsx b/ts/axo/AxoSymbol.stories.tsx
new file mode 100644
index 00000000000..ea0dd4bf119
--- /dev/null
+++ b/ts/axo/AxoSymbol.stories.tsx
@@ -0,0 +1,102 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React, { memo, useMemo, useState } from 'react';
+import type { Meta } from '@storybook/react';
+import { Direction } from 'radix-ui';
+import Fuse from 'fuse.js';
+import type { AxoSymbolName } from './AxoSymbol';
+import { AxoSymbol, _getAllAxoSymbolNames, _getAxoSymbol } from './AxoSymbol';
+
+export default {
+ title: 'Axo/AxoSymbol',
+} satisfies Meta;
+
+const SymbolInfo = memo(function SymbolInfo(props: {
+ symbolName: AxoSymbolName;
+}): JSX.Element {
+ const ltr = _getAxoSymbol(props.symbolName, 'ltr');
+ const rtl = _getAxoSymbol(props.symbolName, 'rtl');
+
+ const variants =
+ ltr === rtl
+ ? ([
+ // same
+ { title: 'LTR/RTL', dir: 'ltr', text: ltr },
+ ] as const)
+ : ([
+ { title: 'LTR', dir: 'ltr', text: ltr },
+ { title: 'RTL', dir: 'rtl', text: rtl },
+ ] as const);
+
+ return (
+
+
+ {variants.map(variant => {
+ return (
+
+
+ {variant.title}
+
+
+
+
+
+
+
+ {Array.from(variant.text, char => {
+ const codePoint = char.codePointAt(0) ?? -1;
+ return `U+${codePoint.toString(16).toUpperCase()}`;
+ }).join(' ')}
+
+
+ );
+ })}
+
+
+ {props.symbolName}
+
+
+ );
+});
+
+const allAxoSymbolNames = _getAllAxoSymbolNames()
+ .slice()
+ .sort((a, b) => a.localeCompare(b));
+const fuse = new Fuse(allAxoSymbolNames);
+
+export function All(): JSX.Element {
+ const [input, setInput] = useState('');
+
+ const results = useMemo(() => {
+ if (input.trim() !== '') {
+ return fuse.search(input).map(result => {
+ return result.item;
+ });
+ }
+ return allAxoSymbolNames;
+ }, [input]);
+
+ return (
+ <>
+
+ {
+ setInput(event.currentTarget.value);
+ }}
+ className="w-full rounded bg-elevated-background-secondary p-3 type-body-medium"
+ />
+
+
+ {results.map(result => {
+ return ;
+ })}
+
+ >
+ );
+}
diff --git a/ts/axo/AxoSymbol.tsx b/ts/axo/AxoSymbol.tsx
new file mode 100644
index 00000000000..a3d04d1eed5
--- /dev/null
+++ b/ts/axo/AxoSymbol.tsx
@@ -0,0 +1,263 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import type { FC } from 'react';
+import React, { memo } from 'react';
+import { Direction } from 'radix-ui';
+import { VisuallyHidden } from 'react-aria';
+import { assert } from './_internal/assert';
+
+const { useDirection } = Direction;
+
+const Namespace = 'AxoSymbol';
+
+type AxoSymbolDef = string | { ltr: string; rtl: string };
+
+const AllAxoSymbolDefs = {
+ logo: '\u{E000}',
+ album: '\u{E001}',
+ appearance: '\u{E031}',
+ 'arrow-[start]': { ltr: '\u{2190}', rtl: '\u{2192}' },
+ 'arrow-[end]': { ltr: '\u{2192}', rtl: '\u{2190}' },
+ 'arrow-up': '\u{2191}',
+ 'arrow-down': '\u{2193}',
+ 'arrow-up_[start]': { ltr: '\u{2196}', rtl: '\u{2197}' },
+ 'arrow-up_[end]': { ltr: '\u{2197}', rtl: '\u{2196}' },
+ 'arrow-down_[start]': { ltr: '\u{2199}', rtl: '\u{2198}' },
+ 'arrow-down_[end]': { ltr: '\u{2198}', rtl: '\u{2199}' },
+ 'arrow-circle-[start]': { ltr: '\u{E00B}', rtl: '\u{E00C}' },
+ 'arrow-circle-[end]': { ltr: '\u{E00C}', rtl: '\u{E00B}' },
+ 'arrow-circle-up': '\u{E00D}',
+ 'arrow-circle-down': '\u{E00E}',
+ 'arrow-circle-up_[start]': { ltr: '\u{E00F}', rtl: '\u{E010}' },
+ 'arrow-circle-up_[end]': { ltr: '\u{E010}', rtl: '\u{E00F}' },
+ 'arrow-circle-down_[start]': { ltr: '\u{E011}', rtl: '\u{E012}' },
+ 'arrow-circle-down_[end]': { ltr: '\u{E012}', rtl: '\u{E011}' },
+ 'arrow-square-[start]': { ltr: '\u{E013}', rtl: '\u{E014}' },
+ 'arrow-square-[end]': { ltr: '\u{E014}', rtl: '\u{E013}' },
+ 'arrow-square-up': '\u{E015}',
+ 'arrow-square-down': '\u{E016}',
+ 'arrow-square-up_[start]': { ltr: '\u{E017}', rtl: '\u{E018}' },
+ 'arrow-square-up_[end]': { ltr: '\u{E018}', rtl: '\u{E017}' },
+ 'arrow-square-down_[start]': { ltr: '\u{E019}', rtl: '\u{E01A}' },
+ 'arrow-square-down_[end]': { ltr: '\u{E01A}', rtl: '\u{E019}' },
+ 'arrow-dash-down': '\u{E021}',
+ 'arrow-circle-[start]-fill': { ltr: '\u{E003}', rtl: '\u{E004}' },
+ 'arrow-circle-[end]-fill': { ltr: '\u{E004}', rtl: '\u{E003}' },
+ 'arrow-circle-up-fill': '\u{E005}',
+ 'arrow-circle-down-fill': '\u{E006}',
+ 'arrow-circle-up_[start]-fill': { ltr: '\u{E007}', rtl: '\u{E008}' },
+ 'arrow-circle-up_[end]-fill': { ltr: '\u{E008}', rtl: '\u{E007}' },
+ 'arrow-circle-down_[start]-fill': { ltr: '\u{E009}', rtl: '\u{E00A}' },
+ 'arrow-circle-down_[end]-fill': { ltr: '\u{E00A}', rtl: '\u{E009}' },
+ 'arrow-square-[start]-fill': { ltr: '\u{E08A}', rtl: '\u{E08B}' },
+ 'arrow-square-[end]-fill': { ltr: '\u{E08B}', rtl: '\u{E08A}' },
+ 'arrow-square-up-fill': '\u{E08C}',
+ 'arrow-square-down-fill': '\u{E08D}',
+ 'arrow-square-up_[start]-fill': { ltr: '\u{E08E}', rtl: '\u{E08F}' },
+ 'arrow-square-up_[end]-fill': { ltr: '\u{E08F}', rtl: '\u{E08E}' },
+ 'arrow-square-down_[start]-fill': { ltr: '\u{E090}', rtl: '\u{E091}' },
+ 'arrow-square-down_[end]-fill': { ltr: '\u{E091}', rtl: '\u{E090}' },
+ at: '\u{E01B}',
+ attach: '\u{E058}',
+ audio: '\u{E01C}',
+ 'audio-rectangle': '\u{E01D}',
+ badge: '\u{E099}',
+ 'badge-fill': '\u{E09A}',
+ bell: '\u{E01E}',
+ 'bell-slash': '\u{E01F}',
+ 'bell-ring': '\u{E020}',
+ block: '\u{E002}',
+ calender: '\u{E0A2}',
+ 'calender-blank': '\u{E0A3}',
+ check: '\u{2713}',
+ 'check-circle': '\u{E022}',
+ 'check-square': '\u{E023}',
+ 'chevron-[start]': { ltr: '\u{E024}', rtl: '\u{E025}' },
+ 'chevron-[end]': { ltr: '\u{E025}', rtl: '\u{E024}' },
+ 'chevron-up': '\u{E026}',
+ 'chevron-down': '\u{E027}',
+ 'chevron-circle-[start]': { ltr: '\u{E028}', rtl: '\u{E029}' },
+ 'chevron-circle-[end]': { ltr: '\u{E029}', rtl: '\u{E028}' },
+ 'chevron-circle-up': '\u{E02A}',
+ 'chevron-circle-down': '\u{E02B}',
+ 'chevron-square-[start]': { ltr: '\u{E02C}', rtl: '\u{E02D}' },
+ 'chevron-square-[end]': { ltr: '\u{E02D}', rtl: '\u{E02C}' },
+ 'chevron-square-up': '\u{E02E}',
+ 'chevron-square-down': '\u{E02F}',
+ 'dropdown-down': '\u{E07F}',
+ 'dropdown-up': '\u{E080}',
+ 'dropdown-triangle-down': '\u{E082}',
+ 'dropdown-triangle-up': '\u{E083}',
+ 'dropdown-double': '\u{E081}',
+ edit: '\u{E030}',
+ emoji: '\u{263A}',
+ error: '\u{E032}',
+ 'error-triangle': '\u{E092}',
+ 'error-fill': '\u{E093}',
+ 'error-triangle-fill': '\u{E094}',
+ file: '\u{E034}',
+ forward: '\u{E035}',
+ 'forward-fill': '\u{E036}',
+ gif: '\u{E037}',
+ 'gif-rectangle': '\u{E097}',
+ 'gif-rectangle-fill': '\u{E098}',
+ gift: '\u{E0B5}',
+ globe: '\u{E0B6}',
+ group: '\u{E038}',
+ 'group-x': '\u{E0AE}',
+ heart: '\u{E039}',
+ help: '\u{E0D8}',
+ incoming: '\u{E03A}',
+ info: '\u{E03B}',
+ leave: { ltr: '\u{E03C}', rtl: '\u{E03D}' },
+ link: '\u{E03E}',
+ 'link-android': '\u{E03F}',
+ 'link-broken': '\u{E057}',
+ 'link-slash': '\u{E040}',
+ lock: '\u{E041}',
+ 'lock-open': '\u{E07D}',
+ megaphone: '\u{E042}',
+ merge: '\u{E043}',
+ message: '\u{E0A6}',
+ 'message_status-sending': '\u{E044}',
+ 'message_status-sent': '\u{E045}',
+ 'message_status-read': '\u{E047}',
+ 'message_status-delivered': '\u{E046}',
+ 'message_timer-00': '\u{E048}',
+ 'message_timer-05': '\u{E049}',
+ 'message_timer-10': '\u{E04A}',
+ 'message_timer-15': '\u{E04B}',
+ 'message_timer-20': '\u{E04C}',
+ 'message_timer-25': '\u{E04D}',
+ 'message_timer-30': '\u{E04E}',
+ 'message_timer-35': '\u{E04F}',
+ 'message_timer-40': '\u{E050}',
+ 'message_timer-45': '\u{E051}',
+ 'message_timer-50': '\u{E052}',
+ 'message_timer-55': '\u{E053}',
+ 'message_timer-60': '\u{E054}',
+ mic: '\u{E055}',
+ 'mic-slash': '\u{E056}',
+ minus: '\u{2212}',
+ 'minus-circle': '\u{2296}',
+ 'minus-square': '\u{E059}',
+ 'missed-incoming': '\u{E05A}',
+ 'missed-outgoing': '\u{E05B}',
+ note: { ltr: '\u{E095}', rtl: '\u{E096}' },
+ official_badge: '\u{E086}',
+ 'official_badge-fill': '\u{E087}',
+ outgoing: '\u{E05C}',
+ person: '\u{E05D}',
+ 'person-circle': '\u{E05E}',
+ 'person-check': '\u{E05F}',
+ 'person-x': '\u{E060}',
+ 'person-plus': '\u{E061}',
+ 'person-minus': '\u{E062}',
+ 'person-question': '\u{E06A}',
+ phone: '\u{E063}',
+ 'phone-fill': '\u{E064}',
+ photo: '\u{E065}',
+ 'photo-slash': '\u{E066}',
+ play: '\u{E067}',
+ 'play-circle': '\u{E068}',
+ 'play-square': '\u{E069}',
+ plus: '\u{002B}',
+ 'plus-circle': '\u{2295}',
+ 'plus-square': '\u{E06C}',
+ raise_hand: '\u{E07E}',
+ 'raise_hand-fill': '\u{E084}',
+ refresh: '\u{E0C4}',
+ reply: '\u{E06D}',
+ 'reply-fill': '\u{E06E}',
+ safety_number: '\u{E06F}',
+ spam: '\u{E033}',
+ sticker: '\u{E070}',
+ thread: '\u{E071}',
+ 'thread-fill': '\u{E072}',
+ timer: '\u{E073}',
+ 'timer-slash': '\u{E074}',
+ video_camera: '\u{E075}',
+ 'video_camera-slash': '\u{E076}',
+ 'video_camera-fill': '\u{E077}',
+ video: '\u{E088}',
+ 'video-slash': '\u{E089}',
+ view_once: '\u{E078}',
+ 'view_once-dash': '\u{E079}',
+ 'view_once-viewed': '\u{E07A}',
+ x: '\u{00D7}',
+ 'x-circle': '\u{2297}',
+ 'x-square': '\u{2327}',
+ space: '\u{0020}',
+} as const satisfies Record;
+
+export type AxoSymbolName = keyof typeof AllAxoSymbolDefs;
+
+export function _getAllAxoSymbolNames(): ReadonlyArray {
+ return Object.keys(AllAxoSymbolDefs) as Array;
+}
+
+export function _getAxoSymbol(
+ symbolName: AxoSymbolName,
+ dir: 'ltr' | 'rtl'
+): string {
+ const symbolDef = assert(
+ AllAxoSymbolDefs[symbolName],
+ `${Namespace}:Invalid name: ${symbolName}`
+ );
+ const symbol = typeof symbolDef === 'string' ? symbolDef : symbolDef[dir];
+ return symbol;
+}
+
+// eslint-disable-next-line @typescript-eslint/no-namespace
+export namespace AxoSymbol {
+ /**
+ * Component:
+ * --------------------------------------
+ */
+
+ export type InlineGlyphProps = Readonly<{
+ symbol: AxoSymbolName;
+ label: string | null;
+ }>;
+
+ export const InlineGlyph: FC = memo(props => {
+ const direction = useDirection();
+ const symbol = _getAxoSymbol(props.symbol, direction);
+ return (
+ <>
+
+ {symbol}
+
+ {props.label != null && (
+ {props.label}
+ )}
+ >
+ );
+ });
+
+ InlineGlyph.displayName = `${Namespace}.InlineGlyph`;
+
+ /**
+ * Component:
+ * --------------------------------------
+ */
+
+ export type IconProps = Readonly<{
+ size: 14 | 16 | 20;
+ symbol: AxoSymbolName;
+ label: string | null;
+ }>;
+
+ export const Icon: FC = memo(props => {
+ return (
+
+
+
+ );
+ });
+
+ Icon.displayName = `${Namespace}.Icon`;
+}
diff --git a/ts/axo/_internal/AxoBaseMenu.tsx b/ts/axo/_internal/AxoBaseMenu.tsx
new file mode 100644
index 00000000000..7c1216287d4
--- /dev/null
+++ b/ts/axo/_internal/AxoBaseMenu.tsx
@@ -0,0 +1,348 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import React from 'react';
+import type { ReactNode } from 'react';
+import { css } from './css';
+import { AxoSymbol, type AxoSymbolName } from '../AxoSymbol';
+
+// eslint-disable-next-line @typescript-eslint/no-namespace
+export namespace AxoBaseMenu {
+ //
+ const baseContentStyles = css(
+ 'max-w-[300px] min-w-[200px] p-1.5',
+ 'select-none',
+ 'rounded-xl bg-elevated-background-tertiary shadow-elevation-3',
+ 'data-[state=closed]:animate-fade-out'
+ );
+
+ const baseContentGridStyles = css('grid grid-cols-[min-content_auto]');
+
+ //
+ const baseGroupStyles = css('col-span-full grid grid-cols-subgrid');
+
+ // -
+ const baseItemStyles = css(
+ 'col-span-full grid grid-cols-subgrid items-center'
+ );
+
+ //
- (not Separator)
+ const labeledItemStyles = css(baseItemStyles, 'truncate p-1.5');
+
+ //
- (not Label/Separator)
+ const navigableItemStyles = css(
+ labeledItemStyles,
+ 'rounded-md type-body-medium',
+ 'outline-0 data-[highlighted]:bg-fill-secondary-pressed',
+ 'data-[disabled]:text-label-disabled',
+ 'outline-0 outline-border-focused focused:outline-[2.5px]'
+ );
+
+ /**
+ *
- (not Label/Separator)
+ */
+ type BaseNavigableItemProps = Readonly<{
+ /**
+ * When true, prevents the user from interacting with the item.
+ */
+ disabled?: boolean;
+ /**
+ * Optional text used for typeahead purposes. By default the typeahead
+ * behavior will use the .textContent of the item. Use this when the
+ * content is complex, or you have non-textual content inside.
+ */
+ textValue?: string;
+ /**
+ * An icon that should be rendered before the text.
+ */
+ symbol?: AxoSymbolName;
+ }>;
+
+ //
- (not SubTrigger/Label/Separator)
+ const selectableItemStyles = css(navigableItemStyles);
+
+ /**
+ * Used for any selectable content node such as Item, CheckboxItem, or RadioItem,
+ * But not nodes like SubTrigger, Separator, Group, etc.
+ */
+ type BaseSelectableItemProps = BaseNavigableItemProps &
+ Readonly<{
+ keyboardShortcut?: string;
+ onSelect?: (event: Event) => void;
+ }>;
+
+ /**
+ * AxoBaseMenu: Item Slots
+ * -----------------------
+ */
+
+ export type ItemLeadingSlotProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ export function ItemLeadingSlot(props: ItemLeadingSlotProps): JSX.Element {
+ return (
+
+ {props.children}
+
+ );
+ }
+
+ export type ItemContentSlotProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ export function ItemContentSlot(props: ItemContentSlotProps): JSX.Element {
+ return (
+
+ {props.children}
+
+ );
+ }
+
+ /**
+ * AxoBaseMenu: Item Parts
+ * -----------------------
+ */
+
+ export const itemTextStyles = css('flex-1 truncate text-start');
+
+ export type ItemTextProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ export function ItemText(props: ItemTextProps): JSX.Element {
+ return {props.children} ;
+ }
+
+ export type ItemCheckPlaceholderProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ export function ItemCheckPlaceholder(
+ props: ItemCheckPlaceholderProps
+ ): JSX.Element {
+ return {props.children} ;
+ }
+
+ export function ItemCheck(): JSX.Element {
+ return ;
+ }
+
+ export function ItemSymbol(props: { symbol: AxoSymbolName }): JSX.Element {
+ return ;
+ }
+
+ export type ItemKeyboardShortcutProps = Readonly<{
+ keyboardShortcut: string;
+ }>;
+
+ export function ItemKeyboardShortcut(
+ props: ItemKeyboardShortcutProps
+ ): JSX.Element {
+ return (
+
+ {props.keyboardShortcut}
+
+ );
+ }
+
+ /**
+ * AxoBaseMenu: Root
+ * -----------------
+ */
+
+ export type MenuRootProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ /**
+ * AxoBaseMenu: Trigger
+ * --------------------
+ */
+
+ export type MenuTriggerProps = Readonly<{
+ /**
+ * When true, the context menu won't open when right-clicking.
+ * Note that this will also restore the native context menu.
+ */
+ disabled?: boolean;
+ children: ReactNode;
+ }>;
+
+ /**
+ * AxoBaseMenu: Content
+ * --------------------
+ */
+
+ export type MenuContentProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ export const menuContentStyles = css(
+ baseContentStyles,
+ baseContentGridStyles,
+ 'max-h-(--radix-popper-available-height) overflow-auto [scrollbar-width:none]',
+ 'overflow-auto [scrollbar-width:none]'
+ );
+
+ export const selectContentStyles = css(baseContentStyles);
+ export const selectContentViewportStyles = css(baseContentGridStyles);
+
+ /**
+ * AxoBaseMenu: Item
+ * -----------------
+ */
+
+ export type MenuItemProps = BaseSelectableItemProps &
+ Readonly<{
+ /**
+ * Event handler called when the user selects an item (via mouse or
+ * keyboard). Calling event.preventDefault in this handler will prevent the
+ * context menu from closing when selecting that item.
+ */
+ onSelect: (event: Event) => void;
+ children: ReactNode;
+ }>;
+
+ export const menuItemStyles = css(selectableItemStyles);
+ export const selectItemStyles = css(selectableItemStyles);
+
+ /**
+ * AxoBaseMenu: Group
+ * ------------------
+ */
+
+ export type MenuGroupProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ export const menuGroupStyles = css(baseGroupStyles);
+ export const selectGroupStyles = css(baseGroupStyles);
+
+ /**
+ * AxoBaseMenu: Label
+ * ------------------
+ */
+
+ export type MenuLabelProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ const baseLabelStyles = css(
+ labeledItemStyles,
+ 'type-body-small text-label-secondary'
+ );
+
+ export const menuLabelStyles = css(baseLabelStyles);
+ export const selectLabelStyles = css(baseLabelStyles);
+
+ /**
+ * AxoBaseMenu: CheckboxItem
+ * -------------------------
+ */
+
+ export type MenuCheckboxItemProps = BaseSelectableItemProps &
+ Readonly<{
+ /**
+ * The controlled checked state of the item. Must be used in conjunction
+ * with `onCheckedChange`.
+ */
+ checked: boolean;
+ /**
+ * Event handler called when the checked state changes.
+ */
+ onCheckedChange: (checked: boolean) => void;
+ children: ReactNode;
+ }>;
+
+ export const menuCheckboxItemStyles = css(selectableItemStyles);
+
+ /**
+ * AxoBaseMenu: RadioGroup
+ * -----------------------
+ */
+
+ export type MenuRadioGroupProps = Readonly<{
+ /**
+ * The value of the selected item in the group.
+ */
+ value: string;
+
+ /**
+ * Event handler called when the value changes.
+ */
+ onValueChange: (value: string) => void;
+ children: ReactNode;
+ }>;
+
+ export const menuRadioGroupStyles = css(baseGroupStyles);
+
+ /**
+ * AxoBaseMenu: RadioItem
+ * ----------------------
+ */
+
+ export type MenuRadioItemProps = BaseSelectableItemProps &
+ Readonly<{
+ value: string;
+ children: ReactNode;
+ }>;
+
+ export const menuRadioItemStyles = css(selectableItemStyles);
+
+ /**
+ * AxoBaseMenu: Separator
+ * ----------------------
+ */
+
+ export type MenuSeparatorProps = Readonly<{
+ // N/A
+ }>;
+
+ const baseSeparatorStyles = css(
+ baseItemStyles,
+ 'mx-0.5 my-1 border-t-[0.5px] border-border-primary'
+ );
+
+ export const menuSeparatorStyles = css(baseSeparatorStyles);
+ export const selectSeperatorStyles = css(baseSeparatorStyles);
+
+ /**
+ * AxoBaseMenu: Sub
+ * ----------------
+ */
+
+ export type MenuSubProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ /**
+ * AxoBaseMenu: SubTrigger
+ * -----------------------
+ */
+
+ export type MenuSubTriggerProps = BaseNavigableItemProps &
+ Readonly<{
+ children: ReactNode;
+ }>;
+
+ export const menuSubTriggerStyles = css(
+ navigableItemStyles,
+ 'data-[state=open]:not-data-[highlighted]:bg-fill-secondary'
+ );
+
+ /**
+ * AxoBaseMenu: SubContent
+ * -----------------------
+ */
+
+ export type MenuSubContentProps = Readonly<{
+ children: ReactNode;
+ }>;
+
+ export const menuSubContentStyles = css(
+ baseContentStyles,
+ 'max-h-(--radix-popper-available-height) overflow-auto [scrollbar-width:none]',
+ baseContentGridStyles
+ );
+}
diff --git a/ts/axo/_internal/assert.tsx b/ts/axo/_internal/assert.tsx
new file mode 100644
index 00000000000..99b3f7d51d6
--- /dev/null
+++ b/ts/axo/_internal/assert.tsx
@@ -0,0 +1,17 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+export class AssertionError extends TypeError {
+ override name = 'AssertionError';
+}
+
+export function assert(condition: boolean, message?: string): asserts condition;
+export function assert(input: T, message?: string): NonNullable;
+export function assert(input: T, message?: string): NonNullable {
+ if (input === false || input == null) {
+ // eslint-disable-next-line no-debugger
+ debugger;
+ throw new AssertionError(message ?? `input is ${input}`);
+ }
+ return input;
+}
diff --git a/ts/axo/_internal/css.tsx b/ts/axo/_internal/css.tsx
new file mode 100644
index 00000000000..c3293c62dff
--- /dev/null
+++ b/ts/axo/_internal/css.tsx
@@ -0,0 +1,27 @@
+// Copyright 2025 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+export type Styles = string & { __Styles: never };
+
+export function css(
+ ...classNames: ReadonlyArray
+): Styles {
+ const { length } = classNames;
+
+ let result = '';
+ let first = true;
+
+ for (let index = 0; index < length; index += 1) {
+ const className = classNames[index];
+ if (typeof className === 'string') {
+ if (first) {
+ first = false;
+ } else {
+ result += ' ';
+ }
+ result += className;
+ }
+ }
+
+ return result as Styles;
+}
diff --git a/ts/axo/tailwind.css b/ts/axo/tailwind.css
new file mode 100644
index 00000000000..d43508958ba
--- /dev/null
+++ b/ts/axo/tailwind.css
@@ -0,0 +1,376 @@
+@import 'tailwindcss';
+
+/**
+ * Custom Variants
+ * ----------------------------------------------------------------------------
+ */
+@custom-variant dark (&:where(.dark-theme, .dark-theme *));
+
+@custom-variant hovered (&:hover:not(:disabled));
+@custom-variant pressed (&:active:not(:disabled));
+@custom-variant focused (.keyboard-mode &:focus);
+
+/**
+ * Color
+ * ----------------------------------------------------------------------------
+ */
+
+/* prettier-ignore */
+@theme {
+ --color-*: initial; /* reset defaults */
+
+ /* Colors/Labels */
+ --color-label-primary: light-dark(--alpha(#000 / 85%), --alpha(#FFF / 85%));
+ --color-label-secondary: light-dark(--alpha(#000 / 55%), --alpha(#FFF / 55%));
+ --color-label-placeholder: light-dark(--alpha(#000 / 30%), --alpha(#FFF / 30%));
+ --color-label-disabled: light-dark(--alpha(#000 / 20%), --alpha(#FFF / 20%));
+
+ --color-label-primary-inverted: light-dark(--alpha(#FFF / 85%), /* */ #000 /* */);
+ --color-label-secondary-inverted: light-dark(--alpha(#FFF / 55%), --alpha(#000 / 55%));
+ --color-label-placeholder-inverted: light-dark(--alpha(#FFF / 30%), --alpha(#000 / 30%));
+ --color-label-disabled-inverted: light-dark(--alpha(#FFF / 20%), --alpha(#000 / 20%));
+
+ --color-label-primary-on-color: light-dark(/* */ #FFF /* */, --alpha(#FFF / 90%));
+ --color-label-secondary-on-color: light-dark(--alpha(#FFF / 80%), --alpha(#FFF / 70%));
+ --color-label-placeholder-on-color: light-dark(--alpha(#FFF / 45%), --alpha(#FFF / 45%));
+ --color-label-disabled-on-color: light-dark(--alpha(#FFF / 35%), --alpha(#FFF / 30%));
+
+ /* Colors/Color Label */
+ --color-color-label-primary: light-dark(/* */ #030FFC /* */, /* */ #99A1FF /* */);
+ --color-color-label-primary-disabled: light-dark(--alpha(#030FFC / 25%), --alpha(#99A1FF / 25%));
+ --color-color-label-light: light-dark(/* */ #99A1FF /* */, /* */ #99A1FF /* */);
+ --color-color-label-light-disabled: light-dark(--alpha(#99A1FF / 25%), --alpha(#99A1FF / 25%));
+ --color-color-label-affirmative: light-dark(/* */ #00AD17 /* */, /* */ #30D150 /* */);
+ --color-color-label-affirmative-disabled: light-dark(--alpha(#00AD17 / 25%), --alpha(#30D150 / 25%));
+ --color-color-label-destructive: light-dark(/* */ #F21602 /* */, /* */ #FF4A3A /* */);
+ --color-color-label-destructive-disabled: light-dark(--alpha(#F21602 / 25%), --alpha(#FF4A3A / 25%));
+
+ /* Colors/Background */
+ --color-background-primary: light-dark(/* */ #FFFFFF /* */, /* */ #1A1A1A /* */);
+ --color-background-secondary: light-dark(/* */ #F6F6F6 /* */, /* */ #262626 /* */);
+ --color-background-overlay: light-dark(--alpha(#000000 / 20%), --alpha(#000000 / 40%));
+
+ /* Colors/Elevated Background */
+ --color-elevated-background-primary: light-dark(#FAFAFA, #2A2A2A);
+ --color-elevated-background-secondary: light-dark(#F2F2F2, #323232);
+ --color-elevated-background-tertiary: light-dark(#EAEAEA, #3A3A3A);
+ --color-elevated-background-quaternary: light-dark(#2A2A2A, #424242);
+
+ /* Colors/Fill */
+ --color-fill-primary: light-dark(/* */ #FFFFFF /* */, --alpha(#808080 / 20%));
+ --color-fill-primary-pressed: light-dark(/* */ #F6F6F6 /* */, --alpha(#808080 / 28%));
+ --color-fill-secondary: light-dark(--alpha(#808080 / 12%), --alpha(#808080 / 20%));
+ --color-fill-secondary-pressed: light-dark(--alpha(#808080 / 20%), --alpha(#808080 / 28%));
+ --color-fill-selected: light-dark(--alpha(#808080 / 25%), --alpha(#808080 / 32%));
+ --color-fill-inverted: light-dark(/* */ #424242 /* */, /* */ #DEDEDE /* */);
+ --color-fill-inverted-pressed: light-dark(/* */ #4E4E4E /* */, /* */ #CACACA /* */);
+ --color-fill-floating: light-dark(/* */ #FFFFFF /* */, /* */ #2A2A2A /* */);
+ --color-fill-floating-pressed: light-dark(/* */ #F6F6F6 /* */, /* */ #323232 /* */);
+ --color-fill-on-media: light-dark(--alpha(#000000 / 75%), --alpha(#000000 / 75%));
+ --color-fill-on-media-pressed: light-dark(--alpha(#000000 / 83%), --alpha(#000000 / 83%));
+
+ /* Colors/Message Fill */
+ --color-message-fill-incoming-primary: light-dark(/* */ #EAEAEA /* */, /* */ #3A3A3A /* */);
+ --color-message-fill-incoming-secondary: light-dark(--alpha(#FFFFFF / 80%), --alpha(#FFFFFF / 20%));
+ --color-message-fill-incoming-tertiary: light-dark(--alpha(#FFFFFF / 60%), --alpha(#FFFFFF / 12%));
+ --color-message-fill-outgoing-primary: light-dark(/* */ #2267F5 /* */, /* */ #2267F5 /* */);
+ --color-message-fill-outgoing-secondary: light-dark(--alpha(#FFFFFF / 60%), --alpha(#FFFFFF / 60%));
+ --color-message-fill-outgoing-tertiary: light-dark(--alpha(#FFFFFF / 20%), --alpha(#FFFFFF / 20%));
+
+ /* Colors/Color Fill */
+ --color-color-fill-primary: light-dark(#4655FF, #5563FF);
+ --color-color-fill-primary-pressed: light-dark(#3B4AF4, #4856F2);
+ --color-color-fill-affirmative: light-dark(#02C028, #02C529);
+ --color-color-fill-affirmative-pressed: light-dark(#00B324, #00B725);
+ --color-color-fill-warning: light-dark(#FFCC00, #FFD60A);
+ --color-color-fill-warning-pressed: light-dark(#FFCC00, #F1C900);
+ --color-color-fill-destructive: light-dark(#FD2512, #FB4332);
+ --color-color-fill-destructive-pressed: light-dark(#EB1300, #E93120);
+
+ /* Colors/Border */
+ --color-border-primary: light-dark(--alpha(#000000 / 16%), --alpha(#FFFFFF / 16%));
+ --color-border-secondary: light-dark(--alpha(#000000 / 08%), --alpha(#FFFFFF / 08%));
+ --color-border-focused: light-dark(/* */ #C1C7FE /* */, /* */ #C1C7FE /* */);
+ --color-border-selected: light-dark(/* */ #4655FF /* */, /* */ #5563FF /* */);
+ --color-border-selected-on-color: light-dark(/* */ #FFFFFF /* */, --alpha(#FFFFFF / 90%));
+ --color-border-error: light-dark(/* */ #FD2512 /* */, /* */ #FB4332 /* */);
+
+ /* Colors/Shadow */
+ --color-shadow-elevation-1: light-dark(--alpha(#000 / 08%), --alpha(#000 / 16%));
+ --color-shadow-elevation-2: light-dark(--alpha(#000 / 08%), --alpha(#000 / 16%));
+ --color-shadow-elevation-3: light-dark(--alpha(#000 / 10%), --alpha(#000 / 20%));
+ --color-shadow-elevation-4: light-dark(--alpha(#000 / 12%), --alpha(#000 / 24%));
+ --color-shadow-elevation-5: light-dark(--alpha(#000 / 20%), --alpha(#000 / 40%));
+ --color-shadow-outline: light-dark(--alpha(#000 / 12%), /* */ transparent);
+ --color-shadow-highlight: light-dark(/* */ transparent, --alpha(#FFF / 08%));
+}
+
+@layer base {
+ /* High Contrast Mode */
+ /* prettier-ignore */
+ @media (prefers-contrast: more) {
+ /* Colors/Labels */
+ --color-label-primary: light-dark(/* */ #000 /* */, /* */ #FFF /* */);
+ --color-label-secondary: light-dark(--alpha(#000 / 70%), --alpha(#FFF / 70%));
+ --color-label-placeholder: light-dark(--alpha(#000 / 50%), --alpha(#FFF / 50%));
+ --color-label-disabled: light-dark(--alpha(#000 / 40%), --alpha(#FFF / 40%));
+
+ --color-label-primary-inverted: light-dark(/* */ #FFF /* */, /* */ #000 /* */);
+ --color-label-secondary-inverted: light-dark(--alpha(#FFF / 70%), --alpha(#000 / 70%));
+ --color-label-placeholder-inverted: light-dark(--alpha(#FFF / 50%), --alpha(#000 / 50%));
+ --color-label-disabled-inverted: light-dark(--alpha(#FFF / 40%), --alpha(#000 / 40%));
+
+ --color-label-primary-on-color: light-dark(/* */ #FFF /* */, /* */ #FFF /* */);
+ --color-label-secondary-on-color: light-dark(--alpha(#FFF / 90%), --alpha(#FFF / 90%));
+ --color-label-placeholder-on-color: light-dark(--alpha(#FFF / 60%), --alpha(#FFF / 60%));
+ --color-label-disabled-on-color: light-dark(--alpha(#FFF / 50%), --alpha(#FFF / 50%));
+
+ /* Colors/Color Label */
+ --color-color-label-primary: light-dark(/* */ #000ECC /* */, /* */ #D5D9FF /* */);
+ --color-color-label-primary-disabled: light-dark(--alpha(#000ECC / 40%), --alpha(#D5D9FF / 40%));
+ --color-color-label-light: light-dark(/* */ #D5D9FF /* */, /* */ #D5D9FF /* */);
+ --color-color-label-light-disabled: light-dark(--alpha(#D5D9FF / 40%), --alpha(#D5D9FF / 40%));
+ --color-color-label-affirmative: light-dark(/* */ #004D0F /* */, /* */ #4CEF6D /* */);
+ --color-color-label-affirmative-disabled: light-dark(--alpha(#004D0F / 40%), --alpha(#4CEF6D / 40%));
+ --color-color-label-destructive: light-dark(/* */ #8A0B00 /* */, /* */ #FFC5C2 /* */);
+ --color-color-label-destructive-disabled: light-dark(--alpha(#8A0B00 / 40%), --alpha(#FFC5C2 / 40%));
+
+ /* Colors/Background */
+ --color-background-primary: light-dark(/* */ #FFFFFF /* */, /* */ #121212 /* */);
+ --color-background-secondary: light-dark(/* */ #F6F6F6 /* */, /* */ #1E1E1E /* */);
+ --color-background-overlay: light-dark(--alpha(#000000 / 40%), --alpha(#000000 / 60%));
+
+ /* Colors/Elevated Background */
+ --color-elevated-background-primary: light-dark(#FFFFFF, #222222);
+ --color-elevated-background-secondary: light-dark(#F2F2F2, #2A2A2A);
+ --color-elevated-background-tertiary: light-dark(#EAEAEA, #323232);
+ --color-elevated-background-quaternary: light-dark(#262626, #3A3A3A);
+
+ /* Colors/Fill */
+ --color-fill-primary: light-dark(/* */ #FFFFFF /* */, --alpha(#808080 / 30%));
+ --color-fill-primary-pressed: light-dark(/* */ #EAEAEA /* */, --alpha(#808080 / 38%));
+ --color-fill-secondary: light-dark(--alpha(#808080 / 22%), --alpha(#808080 / 30%));
+ --color-fill-secondary-pressed: light-dark(--alpha(#808080 / 30%), --alpha(#808080 / 38%));
+ --color-fill-selected: light-dark(--alpha(#808080 / 34%), --alpha(#808080 / 42%));
+ --color-fill-inverted: light-dark(/* */ #2A2A2A /* */, /* */ #F6F6F6 /* */);
+ --color-fill-inverted-pressed: light-dark(/* */ #363636 /* */, /* */ #E2E2E2 /* */);
+ --color-fill-floating: light-dark(/* */ #FFFFFF /* */, /* */ #323232 /* */);
+ --color-fill-floating-pressed: light-dark(/* */ #EAEAEA /* */, /* */ #3A3A3A /* */);
+ --color-fill-on-media: light-dark(--alpha(#000000 / 85%), --alpha(#000000 / 85%));
+ --color-fill-on-media-pressed: light-dark(--alpha(#000000 / 93%), --alpha(#000000 / 93%));
+
+ /* Colors/Message Fill */
+ --color-message-fill-incoming-primary: light-dark(/* */ #E0E0E0 /* */, /* */ #424242 /* */);
+ --color-message-fill-incoming-secondary: light-dark(--alpha(#FFFFFF / 90%), --alpha(#FFFFFF / 30%));
+ --color-message-fill-incoming-tertiary: light-dark(--alpha(#FFFFFF / 70%), --alpha(#FFFFFF / 22%));
+ --color-message-fill-outgoing-primary: light-dark(/* */ #0842B9 /* */, /* */ #0842B9 /* */);
+ --color-message-fill-outgoing-secondary: light-dark(--alpha(#FFFFFF / 70%), --alpha(#FFFFFF / 70%));
+ --color-message-fill-outgoing-tertiary: light-dark(--alpha(#FFFFFF / 30%), --alpha(#FFFFFF / 30%));
+
+ /* Colors/Color Fill */
+ --color-color-fill-primary: light-dark(#2B3BED, #2B3BED);
+ --color-color-fill-primary-pressed: light-dark(#1E2EE0, #1E2EE0);
+ --color-color-fill-affirmative: light-dark(#1D7A2F, #1D7A2F);
+ --color-color-fill-affirmative-pressed: light-dark(#115E23, #116E23);
+ --color-color-fill-warning: light-dark(#F0C000, #F0C000);
+ --color-color-fill-warning-pressed: light-dark(#E4B600, #E4B600);
+ --color-color-fill-destructive: light-dark(#B7271A, #B7271A);
+ --color-color-fill-destructive-pressed: light-dark(#A61609, #A61609);
+
+ /* Colors/Border */
+ --color-border-primary: light-dark(--alpha(#000000 / 32%), --alpha(#FFFFFF / 32%));
+ --color-border-secondary: light-dark(--alpha(#000000 / 16%), --alpha(#FFFFFF / 16%));
+ --color-border-focused: light-dark(/* */ #A0A7FE /* */, /* */ #A0A7FE /* */);
+ --color-border-selected: light-dark(/* */ #2B3BED /* */, /* */ #5563FF /* */);
+ --color-border-selected-on-color: light-dark(/* */ #FFFFFF /* */, /* */ #FFFFFF /* */);
+ --color-border-error: light-dark(/* */ #B7271A /* */, /* */ #FB4332 /* */);
+
+ /* Colors/Shadow */
+ --color-shadow-elevation-1: light-dark(--alpha(#000 / 08%), --alpha(#000 / 16%));
+ --color-shadow-elevation-2: light-dark(--alpha(#000 / 08%), --alpha(#000 / 16%));
+ --color-shadow-elevation-3: light-dark(--alpha(#000 / 10%), --alpha(#000 / 20%));
+ --color-shadow-elevation-4: light-dark(--alpha(#000 / 12%), --alpha(#000 / 24%));
+ --color-shadow-elevation-5: light-dark(--alpha(#000 / 20%), --alpha(#000 / 40%));
+ --color-shadow-outline: light-dark(--alpha(#000 / 32%), /* */ transparent);
+ --color-shadow-highlight: light-dark(/* */ transparent, --alpha(#FFF / 32%));
+ }
+}
+
+/**
+ * Font Family
+ * ----------------------------------------------------------------------------
+ */
+@theme {
+ --font-*: initial; /* reset defaults */
+ /* Note: --font-sans also has language */
+ --font-sans: Inter, 'Source Sans Pro', 'Source Han Sans', -apple-system,
+ system-ui, 'Segoe UI', 'Noto Sans', 'Helvetica Neue', Helvetica, Arial,
+ sans-serif;
+ /* Note: This font-family is checked for in matchMonospace, to support paste scenarios */
+ --font-mono: 'SF Mono', SFMono-Regular, ui-monospace, 'DejaVu Sans Mono',
+ Menlo, Consolas, monospace;
+ --font-symbols: 'SignalSymbols';
+}
+
+@font-face {
+ font-family: 'SignalSymbols';
+ font-style: normal;
+ font-weight: 300 400 700;
+ font-display: block;
+ src: url('../../fonts/signal-symbols/SignalSymbolsVariable.woff2');
+}
+
+@layer base {
+ /* Japanese */
+ :lang(ja) {
+ --font-sans: Inter, 'SF Pro', 'SF Pro JP', 'BIZ UDGothic',
+ 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3', メイリオ, Meiryo,
+ 'MS Pゴシック', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ }
+ /* Farsi (Persian) */
+ :lang(fa) {
+ --font-sans: 'Vazirmatn', -apple-system, system-ui, BlinkMacSystemFont,
+ 'Segoe UI', Tahoma, 'Noto Sans Arabic', Helvetica, Arial, sans-serif;
+ }
+ /* Urdu */
+ :lang(ur) {
+ --font-sans: 'Noto Nastaliq Urdu', Gulzar, 'Jameel Noori Nastaleeq',
+ 'Faiz Lahori Nastaleeq', 'Urdu Typesetting', Helvetica, Arial, sans-serif;
+ }
+}
+
+/**
+ * Typography
+ * ----------------------------------------------------------------------------
+ * Should prefer to use the `type-*` utility when possible.
+ */
+@theme {
+ /* text-size */
+ --text-*: initial; /* reset defaults */
+ --type-text-title-large: 1.5rem /* 24px */;
+ --type-text-title-medium: 1.125rem /* 18px */;
+ --type-text-title-small: 0.875rem /* 14px */;
+ --type-text-body-large: 0.875rem /* 14px */;
+ --type-text-body-medium: 0.8125rem /* 13px */;
+ --type-text-body-small: 0.75rem /* 12px */;
+ --type-text-caption: 0.6825rem /* 11px */;
+ /* font-weight */
+ --font-weight-*: initial; /* reset defaults */
+ --font-weight-semibold: 600;
+ --font-weight-medium: 500;
+ --font-weight-regular: 400;
+ --type-font-weight-title-large: var(--font-weight-semibold);
+ --type-font-weight-title-medium: var(--font-weight-semibold);
+ --type-font-weight-title-small: var(--font-weight-semibold);
+ --type-font-weight-body-large: var(--font-weight-regular);
+ --type-font-weight-body-medium: var(--font-weight-regular);
+ --type-font-weight-body-small: var(--font-weight-medium);
+ --type-font-weight-caption: var(--font-weight-regular);
+ /* letter-spacing */
+ --tracking-*: initial; /* reset defaults */
+ --type-tracking-title-large: -0.019em /* (@ 24px) -0.46px */;
+ --type-tracking-title-medium: -0.014em /* (@ 18px) -0.25px */;
+ --type-tracking-title-small: -0.006em /* (@ 14px) -0.08px */;
+ --type-tracking-body-large: -0.006em /* (@ 14px) -0.08px */;
+ --type-tracking-body-medium: -0.003em /* (@ 13px) -0.04px */;
+ --type-tracking-body-small: 0em /* (@ 12px) 0px */;
+ --type-tracking-caption: 0.005em /* (@ 11px) 0.05px */;
+ /* line-height */
+ --leading-*: initial; /* reset defaults */
+ --leading-none: 1;
+ --type-leading-title-large: 2rem /* 32px */;
+ --type-leading-title-medium: 1.5rem /* 24px */;
+ --type-leading-title-small: 1.25rem /* 20px */;
+ --type-leading-body-large: 1.25rem /* 20px */;
+ --type-leading-body-medium: 1.125rem /* 18px */;
+ --type-leading-body-small: 1rem /* 16px */;
+ --type-leading-caption: 0.875rem /* 14px */;
+}
+
+/* prettier-ignore */
+@utility type-* {
+ font-size: --value(--type-text-*);
+ font-weight: --value(--type-font-weight-*);
+ letter-spacing: --value(--type-tracking-*);
+ line-height: --value(--type-leading-*);
+}
+
+/**
+ * Shadow
+ * ----------------------------------------------------------------------------
+ */
+/* prettier-ignore */
+@theme {
+ /* box-shadow */
+ --shadow-*: initial; /* reset defaults */
+ --shadow-elevation-0:
+ 0 1px 2px 0 var(--color-shadow-elevation-1);
+ --shadow-elevation-1:
+ 0 0 0 0.5px var(--color-shadow-highlight) inset,
+ 0 0 0 0.5px var(--color-shadow-outline),
+ 0 2px 8px 0 var(--color-shadow-elevation-2);
+ --shadow-elevation-2:
+ 0 0 0 0.5px var(--color-shadow-highlight) inset,
+ 0 0 0 0.5px var(--color-shadow-outline),
+ 0 4px 12px 0 var(--color-shadow-elevation-3);
+ --shadow-elevation-3:
+ 0 0 0 0.5px var(--color-shadow-highlight) inset,
+ 0 0 0 0.5px var(--color-shadow-outline),
+ 0 6px 16px 0 var(--color-shadow-elevation-4);
+ --shadow-elevation-4:
+ 0 0 0 0.5px var(--color-shadow-highlight) inset,
+ 0 0 0 0.5px var(--color-shadow-outline),
+ 0 12px 56px 0 var(--color-shadow-elevation-5);
+
+ /* box-shadow: inset */
+ --inset-shadow-*: initial; /* reset defaults */
+
+ /* filter: drop-shadow() */
+ --drop-shadow-*: initial; /* reset defaults */
+ --drop-shadow-elevation-0: var(--shadow-elevation-0);
+ --drop-shadow-elevation-1: var(--shadow-elevation-1);
+ --drop-shadow-elevation-2: var(--shadow-elevation-2);
+ --drop-shadow-elevation-3: var(--shadow-elevation-3);
+ --drop-shadow-elevation-4: var(--shadow-elevation-4);
+}
+
+/**
+ * Blur
+ * ----------------------------------------------------------------------------
+ */
+
+@theme {
+ /* filter/backdrop-filter: blur() */
+ --blur-*: initial; /* reset defaults */
+ --blur-thin: 10px;
+ --blur-regular: 40px;
+ --blur-thick: 80px;
+}
+
+/**
+ * Easing
+ * ----------------------------------------------------------------------------
+ */
+@theme {
+ --ease-*: initial; /* reset defaults */
+ --ease-in-cubic: cubic-bezier(0.32, 0, 0.67, 0);
+ --ease-out-cubic: cubic-bezier(0.33, 1, 0.68, 1);
+ --east-in-out-cubic: cubic-bezier(0.65, 0, 0.35, 1);
+}
+
+/**
+ * Animations
+ * ----------------------------------------------------------------------------
+ */
+@theme {
+ --animate-*: initial; /* reset defaults */
+ --animate-fade-out: animate-fade-out 120ms var(--ease-out-cubic);
+}
+
+@layer base {
+ @keyframes animate-fade-out {
+ to {
+ opacity: 0;
+ }
+ }
+}