diff --git a/webui/package.json b/webui/package.json index 3ecf9a0..8147c84 100644 --- a/webui/package.json +++ b/webui/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@jaames/iro": "^5.5.1", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", @@ -15,6 +16,7 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "4.0.3", + "react-semantic-ui-range": "^0.7.1", "typescript": "^4.1.2", "web-vitals": "^1.0.1" }, diff --git a/webui/src/App.tsx b/webui/src/App.tsx index e137f40..c6a00d1 100644 --- a/webui/src/App.tsx +++ b/webui/src/App.tsx @@ -1,9 +1,14 @@ import React from 'react'; import {HookRouter, navigate, usePath, useRoutes} from "hookrouter"; import {Tabs} from "./primitives/Layout"; +import {HSColorPicker} from "./primitives/Forms"; const routeObj: HookRouter.RouteObject = { - "/": () =>
1
, + "/": () => ( +
+ void(0)}/> +
+ ), "/devices": () =>
2
, "/settings": () =>
3
, } diff --git a/webui/src/primitives/Forms.tsx b/webui/src/primitives/Forms.tsx new file mode 100644 index 0000000..1a512d6 --- /dev/null +++ b/webui/src/primitives/Forms.tsx @@ -0,0 +1,43 @@ +import React, {useLayoutEffect, useState} from 'react'; +// @ts-ignore +import iro from "@jaames/iro"; + +interface ColorPickerProps { + h: number + s: number + onChange: (h: number, v: number) => void +} + +const randomId = () => Math.floor(Math.random() * 100000); + +export const HSColorPicker: React.FC = ({h, s, onChange}) => { + const [random] = useState(() => `color-picker-${randomId()}`); + + useLayoutEffect(() => { + // @ts-ignore + const colorPicker = new iro.ColorPicker(`#${random}`, { + color: {h, s: s * 100, v: 255}, + layout: [ + { + component: iro.ui.Wheel, + options: {} + } + ], + }); + + colorPicker.on("input:end", (color: { hsv: { h: number, s: number } }) => { + onChange(color.hsv.h || 0, (color.hsv.s || 0) / 100); + }); + + return () => { + const elem = document.getElementById(`color-picker-${random}`); + if (elem === null) { + return; + } + + elem.innerHTML = ""; + }; + }, [h, s, onChange, random]); + + return
; +}; diff --git a/webui/src/primitives/Layout.tsx b/webui/src/primitives/Layout.tsx index c6a700e..a243f65 100644 --- a/webui/src/primitives/Layout.tsx +++ b/webui/src/primitives/Layout.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useEffect, useMemo} from "react"; +import React, {useCallback, useEffect} from "react"; import "./Layout.sass"; interface TabsProps { diff --git a/webui/yarn.lock b/webui/yarn.lock index 2cf11df..0007f81 100644 --- a/webui/yarn.lock +++ b/webui/yarn.lock @@ -1209,6 +1209,11 @@ dependencies: "@hapi/hoek" "^8.3.0" +"@irojs/iro-core@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@irojs/iro-core/-/iro-core-1.2.0.tgz#3587c2db7a6de09f76dbf75b94605ac251039ca8" + integrity sha512-RVxd4lEx3KPXRBYo7urLSr9C3PJsm3t9AgPQppP5LDqQcMrXCXcZoeneMtQndMk60k72NziNiPpbZlZIvcT4VQ== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1225,6 +1230,14 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== +"@jaames/iro@^5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@jaames/iro/-/iro-5.5.1.tgz#1935713fe3cca8c4eadcfc6013b6f846ac8be097" + integrity sha512-HR2phfXjEINFKXxEdbGqp9/MfHfQ/xP+nLi2gjNV4RHB3tBOgHMpS1WFMU7fp1vl//vWXxKxVKa91D+5JoFgMA== + dependencies: + "@irojs/iro-core" "^1.2.0" + preact "^10.0.0" + "@jest/console@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" @@ -9070,6 +9083,11 @@ postcss@^8.1.0: nanoid "^3.1.20" source-map "^0.6.1" +preact@^10.0.0: + version "10.5.13" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.5.13.tgz#85f6c9197ecd736ce8e3bec044d08fd1330fa019" + integrity sha512-q/vlKIGNwzTLu+jCcvywgGrt+H/1P/oIRSD6mV4ln3hmlC+Aa34C7yfPI4+5bzW8pONyVXYS7SvXosy2dKKtWQ== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -9449,6 +9467,11 @@ react-scripts@4.0.3: optionalDependencies: fsevents "^2.1.3" +react-semantic-ui-range@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/react-semantic-ui-range/-/react-semantic-ui-range-0.7.1.tgz#bc552f889e4243d500d4673dd7966752664935fe" + integrity sha512-6AQLuFeARHcIO7yl4Pd0BBIB9sJyeNK1mku7luK6aTXrj9EGaqr1fWS7w4b0+GUP7CvkixmcyYqykxzpKS4Lcw== + react@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"