diff --git a/packages/core/src/components/BetaMenu/BetaMenu.module.css b/packages/core/src/components/BetaMenu/BetaMenu.module.css new file mode 100644 index 0000000..466816e --- /dev/null +++ b/packages/core/src/components/BetaMenu/BetaMenu.module.css @@ -0,0 +1,20 @@ +.button { + /* No positioning needed - will be positioned by parent FloatingActions */ +} + +.iconContainer { + display: flex; + gap: calc(var(--spacing) * 0.5); + align-items: center; +} + +.flaskIcon { + width: 16px; + height: 16px; +} + +.caretIcon { + width: 12px; + height: 12px; + opacity: 0.7; +} diff --git a/packages/core/src/components/BetaMenu/BetaMenu.tsx b/packages/core/src/components/BetaMenu/BetaMenu.tsx new file mode 100644 index 0000000..367aa92 --- /dev/null +++ b/packages/core/src/components/BetaMenu/BetaMenu.tsx @@ -0,0 +1,63 @@ +import { useSubscribe } from "@spred/react"; + +import { Button } from "@core/components/Button/Button"; +import { MFlask } from "@core/components/Icon/MFlask"; +import { MTriangleDown } from "@core/components/Icon/MTriangleDown"; +import { Menu } from "@core/components/Menu/Menu"; +import { MenuItemButton } from "@core/components/Menu/MenuItemButton"; +import { MenuItemGroup } from "@core/components/Menu/MenuItemGroup"; +import { MenuItemSeparator } from "@core/components/Menu/MenuItemSeparator"; +import { levelStepsPresets } from "@core/levelStepsPresets"; +import { LEVEL_STEPS_PRESETS, type LevelStepsPreset } from "@core/schemas/brand"; +import { resetToInitialState } from "@core/stores/config"; +import { + applyLevelStepsPreset, + distributeContrastEvenly, + levelStepsPresetStore, +} from "@core/stores/settings"; + +import styles from "./BetaMenu.module.css"; + +export function BetaMenu() { + const currentPreset = useSubscribe(levelStepsPresetStore.$lastValidValue); + + return ( + ( + + )} + > + + {LEVEL_STEPS_PRESETS.map((preset) => ( + applyLevelStepsPreset(preset as LevelStepsPreset)} + > + {levelStepsPresets[preset].label} + + ))} + + + distributeContrastEvenly()}> + Distribute Contrast Evenly + + + + Reset to Initial State + + + ); +} diff --git a/packages/core/src/components/Grid/GridCellHueHeader.tsx b/packages/core/src/components/Grid/GridCellHueHeader.tsx index 3c76d34..a790795 100644 --- a/packages/core/src/components/Grid/GridCellHueHeader.tsx +++ b/packages/core/src/components/Grid/GridCellHueHeader.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback, useRef } from "react"; +import { type ClipboardEvent, memo, useCallback, useRef } from "react"; import { useSubscribe } from "@spred/react"; @@ -19,6 +19,7 @@ import { } from "@core/stores/colors"; import { $bgColorModeLeft } from "@core/stores/settings"; import type { HueId } from "@core/types"; +import { hexToHueAngle } from "@core/utils/colors/hexToHueAngle"; import type { AnyProps } from "@core/utils/react/types"; import { DATA_ATTR_CELL_HUE_ID } from "./constants"; @@ -70,6 +71,20 @@ const NameInput = memo(function NameInput({ hueId }: HueComponentProps) { } }); + const handlePaste = useCallback( + (e: ClipboardEvent) => { + const pastedText = e.clipboardData.getData("text"); + const hueAngle = hexToHueAngle(pastedText); + + if (hueAngle !== null) { + e.preventDefault(); + updateHueAngle(hueId, String(Math.round(hueAngle))); + resetHueName(hueId); + } + }, + [hueId], + ); + return ( updateLevelContrast(levelId, e.target.value)} - /> +
+ updateLevelContrast(levelId, e.target.value)} + /> +
); }); @@ -174,32 +196,47 @@ const ChromaInput = memo(function ChromaInput({ levelId }: LevelComponentProps) const chromaPlaceholder = useSubscribe($chromaPlaceholder); return ( - updateLevelchromaCap(levelId, e.target.value || null)} - /> +
+ updateLevelchromaCap(levelId, e.target.value || null)} + /> + +
); }); diff --git a/packages/core/src/components/Grid/GridLeftTopCell.tsx b/packages/core/src/components/Grid/GridLeftTopCell.tsx index f86619d..907d9e7 100644 --- a/packages/core/src/components/Grid/GridLeftTopCell.tsx +++ b/packages/core/src/components/Grid/GridLeftTopCell.tsx @@ -4,9 +4,12 @@ import { useSubscribe } from "@spred/react"; import clsx from "clsx"; import { Button } from "@core/components/Button/Button"; -import { Select } from "@core/components/Select/Select"; +import { Menu } from "@core/components/Menu/Menu"; +import { MenuItemButton } from "@core/components/Menu/MenuItemButton"; +import { MenuItemSeparator } from "@core/components/Menu/MenuItemSeparator"; import { Text } from "@core/components/Text/Text"; -import { parseChromaMode } from "@core/schemas/settings"; +import { ChromaMode } from "@core/schemas/brand"; +import { $isAnyChromaCapSet, resetAllChroma } from "@core/stores/colors"; import { chromaModeStore, colorSpaceStore, @@ -43,6 +46,7 @@ export const GridLeftTopCell = memo(function GridLeftTopCell() { const chromaModeValue = useSubscribe(chromaModeStore.$lastValidValue); const colorSpace = useSubscribe(colorSpaceStore.$lastValidValue); const isColorSpaceLocked = useSubscribe($isColorSpaceLocked); + const hasChromaCaps = useSubscribe($isAnyChromaCapSet); return ( @@ -79,13 +83,34 @@ export const GridLeftTopCell = memo(function GridLeftTopCell() { colors -