mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-01 04:34:50 -04:00
Create a select component for the web
This commit is contained in:
parent
7f6da9d79e
commit
b406ea6088
@ -19,6 +19,7 @@
|
|||||||
"@kyoo/ui": "workspace:^",
|
"@kyoo/ui": "workspace:^",
|
||||||
"@material-symbols/svg-400": "^0.14.1",
|
"@material-symbols/svg-400": "^0.14.1",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"@tanstack/react-query": "^5.12.1",
|
"@tanstack/react-query": "^5.12.1",
|
||||||
"@tanstack/react-query-devtools": "^5.12.2",
|
"@tanstack/react-query-devtools": "^5.12.2",
|
||||||
"array-shuffle": "^3.0.0",
|
"array-shuffle": "^3.0.0",
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"@gorhom/portal": "*",
|
"@gorhom/portal": "*",
|
||||||
"@material-symbols/svg-400": "*",
|
"@material-symbols/svg-400": "*",
|
||||||
"@radix-ui/react-dropdown-menu": "*",
|
"@radix-ui/react-dropdown-menu": "*",
|
||||||
|
"@radix-ui/react-select": "*",
|
||||||
"blurhash": "*",
|
"blurhash": "*",
|
||||||
"expo-linear-gradient": "*",
|
"expo-linear-gradient": "*",
|
||||||
"moti": "*",
|
"moti": "*",
|
||||||
@ -32,6 +33,9 @@
|
|||||||
"@radix-ui/react-dropdown-menu": {
|
"@radix-ui/react-dropdown-menu": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"@radix-ui/react-select": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"blurhash": {
|
"blurhash": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -54,6 +58,7 @@
|
|||||||
"solito": "^4.1.3"
|
"solito": "^4.1.3"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"blurhash": "^2.0.5",
|
"blurhash": "^2.0.5",
|
||||||
"react-native-blurhash": "^1.1.11",
|
"react-native-blurhash": "^1.1.11",
|
||||||
"react-native-fast-image": "^8.6.3",
|
"react-native-fast-image": "^8.6.3",
|
||||||
|
@ -33,6 +33,7 @@ export * from "./progress";
|
|||||||
export * from "./slider";
|
export * from "./slider";
|
||||||
export * from "./alert";
|
export * from "./alert";
|
||||||
export * from "./menu";
|
export * from "./menu";
|
||||||
|
export * from "./select";
|
||||||
export * from "./input";
|
export * from "./input";
|
||||||
export * from "./button";
|
export * from "./button";
|
||||||
export * from "./chip";
|
export * from "./chip";
|
||||||
|
@ -32,11 +32,11 @@ import { focusReset, ts } from "./utils";
|
|||||||
import { SvgProps } from "react-native-svg";
|
import { SvgProps } from "react-native-svg";
|
||||||
|
|
||||||
type YoshikiFunc<T> = (props: ReturnType<typeof useYoshiki>) => T;
|
type YoshikiFunc<T> = (props: ReturnType<typeof useYoshiki>) => T;
|
||||||
const YoshikiProvider = ({ children }: { children: YoshikiFunc<ReactNode> }) => {
|
export const YoshikiProvider = ({ children }: { children: YoshikiFunc<ReactNode> }) => {
|
||||||
const yoshiki = useYoshiki();
|
const yoshiki = useYoshiki();
|
||||||
return <>{children(yoshiki)}</>;
|
return <>{children(yoshiki)}</>;
|
||||||
};
|
};
|
||||||
const InternalTriger = forwardRef<unknown, any>(function _Triger(
|
export const InternalTriger = forwardRef<unknown, any>(function _Triger(
|
||||||
{ Component, ComponentProps, ...props },
|
{ Component, ComponentProps, ...props },
|
||||||
ref,
|
ref,
|
||||||
) {
|
) {
|
||||||
|
159
front/packages/primitives/src/select.web.tsx
Normal file
159
front/packages/primitives/src/select.web.tsx
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Kyoo - A portable and vast media library solution.
|
||||||
|
* Copyright (c) Kyoo.
|
||||||
|
*
|
||||||
|
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||||
|
*
|
||||||
|
* Kyoo is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* Kyoo is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as RSelect from "@radix-ui/react-select";
|
||||||
|
import { ReactNode, forwardRef } from "react";
|
||||||
|
import { Icon } from "./icons";
|
||||||
|
import Check from "@material-symbols/svg-400/rounded/check-fill.svg";
|
||||||
|
import ExpandMore from "@material-symbols/svg-400/rounded/expand_more-fill.svg";
|
||||||
|
import ExpandLess from "@material-symbols/svg-400/rounded/expand_less-fill.svg";
|
||||||
|
import { ContrastArea, SwitchVariant } from "./themes";
|
||||||
|
import { InternalTriger, YoshikiProvider } from "./menu.web";
|
||||||
|
import { Theme, px, useYoshiki as useNativeYoshiki } from "yoshiki/native";
|
||||||
|
import { useYoshiki } from "yoshiki";
|
||||||
|
import { PressableFeedback } from "./links";
|
||||||
|
import { P } from "./text";
|
||||||
|
import { focusReset, ts } from "./utils";
|
||||||
|
|
||||||
|
export const Select = ({
|
||||||
|
children,
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
onValueChange,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
onValueChange: (v: string) => void;
|
||||||
|
}) => {
|
||||||
|
const { css } = useNativeYoshiki();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RSelect.Root value={value} onValueChange={onValueChange}>
|
||||||
|
<RSelect.Trigger aria-label={label} asChild>
|
||||||
|
<InternalTriger
|
||||||
|
Component={PressableFeedback}
|
||||||
|
ComponentProps={css({
|
||||||
|
flexGrow: 0,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
overflow: "hidden",
|
||||||
|
p: ts(0.5),
|
||||||
|
borderRadius: ts(5),
|
||||||
|
borderColor: (theme) => theme.accent,
|
||||||
|
borderWidth: ts(0.5),
|
||||||
|
fover: {
|
||||||
|
self: { bg: (theme: Theme) => theme.accent },
|
||||||
|
text: { color: (theme: Theme) => theme.colors.white },
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<P {...css({ textAlign: "center" }, "text")}>{<RSelect.Value />}</P>
|
||||||
|
<RSelect.Icon asChild>
|
||||||
|
<Icon icon={ExpandMore} />
|
||||||
|
</RSelect.Icon>
|
||||||
|
</InternalTriger>
|
||||||
|
</RSelect.Trigger>
|
||||||
|
<ContrastArea mode="user">
|
||||||
|
<SwitchVariant>
|
||||||
|
<YoshikiProvider>
|
||||||
|
{({ css }) => (
|
||||||
|
<RSelect.Portal>
|
||||||
|
<RSelect.Content
|
||||||
|
{...css({
|
||||||
|
bg: (theme) => theme.background,
|
||||||
|
overflow: "auto",
|
||||||
|
minWidth: "220px",
|
||||||
|
borderRadius: "8px",
|
||||||
|
boxShadow:
|
||||||
|
"0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2)",
|
||||||
|
zIndex: 2,
|
||||||
|
maxHeight: "calc(var(--radix-dropdown-menu-content-available-height) * 0.8)",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<RSelect.ScrollUpButton asChild>
|
||||||
|
<Icon icon={ExpandLess} />
|
||||||
|
</RSelect.ScrollUpButton>
|
||||||
|
<RSelect.Viewport>{children}</RSelect.Viewport>
|
||||||
|
<RSelect.ScrollDownButton asChild>
|
||||||
|
<Icon icon={ExpandMore} />
|
||||||
|
</RSelect.ScrollDownButton>
|
||||||
|
</RSelect.Content>
|
||||||
|
</RSelect.Portal>
|
||||||
|
)}
|
||||||
|
</YoshikiProvider>
|
||||||
|
</SwitchVariant>
|
||||||
|
</ContrastArea>
|
||||||
|
</RSelect.Root>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Item = forwardRef<HTMLDivElement, { label: string; value: string }>(function Item(
|
||||||
|
{ label, value, ...props },
|
||||||
|
ref,
|
||||||
|
) {
|
||||||
|
const { css, theme } = useYoshiki();
|
||||||
|
const { css: nCss } = useNativeYoshiki();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<style jsx global>{`
|
||||||
|
[data-highlighted] {
|
||||||
|
background: ${theme.variant.accent};
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
<RSelect.Item
|
||||||
|
ref={ref}
|
||||||
|
value={value}
|
||||||
|
{...css(
|
||||||
|
{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingLeft: "35px",
|
||||||
|
paddingRight: "25px",
|
||||||
|
height: "32px",
|
||||||
|
color: (theme) => theme.paragraph,
|
||||||
|
borderRadius: "4px",
|
||||||
|
position: "relative",
|
||||||
|
userSelect: "none",
|
||||||
|
...focusReset,
|
||||||
|
},
|
||||||
|
props as any,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<RSelect.ItemText {...css({ color: (theme) => theme.paragraph })}>{label}</RSelect.ItemText>
|
||||||
|
<RSelect.ItemIndicator asChild>
|
||||||
|
<InternalTriger
|
||||||
|
Component={Icon}
|
||||||
|
icon={Check}
|
||||||
|
ComponentProps={nCss({
|
||||||
|
position: "absolute",
|
||||||
|
left: 0,
|
||||||
|
width: px(25),
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</RSelect.ItemIndicator>
|
||||||
|
</RSelect.Item>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
Select.Item = Item;
|
@ -2890,6 +2890,7 @@ __metadata:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@expo/html-elements": ^0.5.1
|
"@expo/html-elements": ^0.5.1
|
||||||
"@gorhom/portal": ^1.0.14
|
"@gorhom/portal": ^1.0.14
|
||||||
|
"@radix-ui/react-select": ^2.0.0
|
||||||
"@tanstack/react-query": ^5.12.1
|
"@tanstack/react-query": ^5.12.1
|
||||||
"@types/react": 18.2.39
|
"@types/react": 18.2.39
|
||||||
blurhash: ^2.0.5
|
blurhash: ^2.0.5
|
||||||
@ -2902,6 +2903,7 @@ __metadata:
|
|||||||
"@gorhom/portal": "*"
|
"@gorhom/portal": "*"
|
||||||
"@material-symbols/svg-400": "*"
|
"@material-symbols/svg-400": "*"
|
||||||
"@radix-ui/react-dropdown-menu": "*"
|
"@radix-ui/react-dropdown-menu": "*"
|
||||||
|
"@radix-ui/react-select": "*"
|
||||||
blurhash: "*"
|
blurhash: "*"
|
||||||
expo-linear-gradient: "*"
|
expo-linear-gradient: "*"
|
||||||
moti: "*"
|
moti: "*"
|
||||||
@ -2914,6 +2916,8 @@ __metadata:
|
|||||||
react-native-svg: "*"
|
react-native-svg: "*"
|
||||||
yoshiki: "*"
|
yoshiki: "*"
|
||||||
dependenciesMeta:
|
dependenciesMeta:
|
||||||
|
"@radix-ui/react-select":
|
||||||
|
optional: true
|
||||||
blurhash:
|
blurhash:
|
||||||
optional: true
|
optional: true
|
||||||
react-native-blurhash:
|
react-native-blurhash:
|
||||||
@ -2927,6 +2931,8 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
"@radix-ui/react-dropdown-menu":
|
"@radix-ui/react-dropdown-menu":
|
||||||
optional: true
|
optional: true
|
||||||
|
"@radix-ui/react-select":
|
||||||
|
optional: true
|
||||||
blurhash:
|
blurhash:
|
||||||
optional: true
|
optional: true
|
||||||
react-native-blurhash:
|
react-native-blurhash:
|
||||||
@ -3212,6 +3218,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@radix-ui/number@npm:1.0.1":
|
||||||
|
version: 1.0.1
|
||||||
|
resolution: "@radix-ui/number@npm:1.0.1"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": ^7.13.10
|
||||||
|
checksum: 621ea8b7d4195d1a65a9c0aee918e8335e7f198088eec91577512c89c2ba3a3bab4a767cfb872a2b9c3092a78ff41cad9a924845a939f6bb87fe9356241ea0ea
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@radix-ui/primitive@npm:1.0.1":
|
"@radix-ui/primitive@npm:1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "@radix-ui/primitive@npm:1.0.1"
|
resolution: "@radix-ui/primitive@npm:1.0.1"
|
||||||
@ -3578,6 +3593,46 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@radix-ui/react-select@npm:^2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "@radix-ui/react-select@npm:2.0.0"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": ^7.13.10
|
||||||
|
"@radix-ui/number": 1.0.1
|
||||||
|
"@radix-ui/primitive": 1.0.1
|
||||||
|
"@radix-ui/react-collection": 1.0.3
|
||||||
|
"@radix-ui/react-compose-refs": 1.0.1
|
||||||
|
"@radix-ui/react-context": 1.0.1
|
||||||
|
"@radix-ui/react-direction": 1.0.1
|
||||||
|
"@radix-ui/react-dismissable-layer": 1.0.5
|
||||||
|
"@radix-ui/react-focus-guards": 1.0.1
|
||||||
|
"@radix-ui/react-focus-scope": 1.0.4
|
||||||
|
"@radix-ui/react-id": 1.0.1
|
||||||
|
"@radix-ui/react-popper": 1.1.3
|
||||||
|
"@radix-ui/react-portal": 1.0.4
|
||||||
|
"@radix-ui/react-primitive": 1.0.3
|
||||||
|
"@radix-ui/react-slot": 1.0.2
|
||||||
|
"@radix-ui/react-use-callback-ref": 1.0.1
|
||||||
|
"@radix-ui/react-use-controllable-state": 1.0.1
|
||||||
|
"@radix-ui/react-use-layout-effect": 1.0.1
|
||||||
|
"@radix-ui/react-use-previous": 1.0.1
|
||||||
|
"@radix-ui/react-visually-hidden": 1.0.3
|
||||||
|
aria-hidden: ^1.1.1
|
||||||
|
react-remove-scroll: 2.5.5
|
||||||
|
peerDependencies:
|
||||||
|
"@types/react": "*"
|
||||||
|
"@types/react-dom": "*"
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@types/react":
|
||||||
|
optional: true
|
||||||
|
"@types/react-dom":
|
||||||
|
optional: true
|
||||||
|
checksum: 9ebf4a3e70fd5f583cf468e432ff04768b3442c44788eaf415e044f19c900b886e92eb46e19e138c4994d8a361f5e31f93d13b5bcf413469f21899bbe1112d1d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@radix-ui/react-slot@npm:1.0.1":
|
"@radix-ui/react-slot@npm:1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "@radix-ui/react-slot@npm:1.0.1"
|
resolution: "@radix-ui/react-slot@npm:1.0.1"
|
||||||
@ -3668,6 +3723,21 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@radix-ui/react-use-previous@npm:1.0.1":
|
||||||
|
version: 1.0.1
|
||||||
|
resolution: "@radix-ui/react-use-previous@npm:1.0.1"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": ^7.13.10
|
||||||
|
peerDependencies:
|
||||||
|
"@types/react": "*"
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@types/react":
|
||||||
|
optional: true
|
||||||
|
checksum: 66b4312e857c58b75f3bf62a2048ef090b79a159e9da06c19a468c93e62336969c33dbef60ff16969f00b20386cc25d138f6a353f1658b35baac0a6eff4761b9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@radix-ui/react-use-rect@npm:1.0.1":
|
"@radix-ui/react-use-rect@npm:1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "@radix-ui/react-use-rect@npm:1.0.1"
|
resolution: "@radix-ui/react-use-rect@npm:1.0.1"
|
||||||
@ -3700,6 +3770,26 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@radix-ui/react-visually-hidden@npm:1.0.3":
|
||||||
|
version: 1.0.3
|
||||||
|
resolution: "@radix-ui/react-visually-hidden@npm:1.0.3"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": ^7.13.10
|
||||||
|
"@radix-ui/react-primitive": 1.0.3
|
||||||
|
peerDependencies:
|
||||||
|
"@types/react": "*"
|
||||||
|
"@types/react-dom": "*"
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@types/react":
|
||||||
|
optional: true
|
||||||
|
"@types/react-dom":
|
||||||
|
optional: true
|
||||||
|
checksum: 2e9d0c8253f97e7d6ffb2e52a5cfd40ba719f813b39c3e2e42c496d54408abd09ef66b5aec4af9b8ab0553215e32452a5d0934597a49c51dd90dc39181ed0d57
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@radix-ui/rect@npm:1.0.1":
|
"@radix-ui/rect@npm:1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "@radix-ui/rect@npm:1.0.1"
|
resolution: "@radix-ui/rect@npm:1.0.1"
|
||||||
@ -15245,6 +15335,7 @@ __metadata:
|
|||||||
"@kyoo/ui": "workspace:^"
|
"@kyoo/ui": "workspace:^"
|
||||||
"@material-symbols/svg-400": ^0.14.1
|
"@material-symbols/svg-400": ^0.14.1
|
||||||
"@radix-ui/react-dropdown-menu": ^2.0.6
|
"@radix-ui/react-dropdown-menu": ^2.0.6
|
||||||
|
"@radix-ui/react-select": ^2.0.0
|
||||||
"@svgr/webpack": ^8.1.0
|
"@svgr/webpack": ^8.1.0
|
||||||
"@tanstack/react-query": ^5.12.1
|
"@tanstack/react-query": ^5.12.1
|
||||||
"@tanstack/react-query-devtools": ^5.12.2
|
"@tanstack/react-query-devtools": ^5.12.2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user