diff --git a/packages/graphic-walker/package.json b/packages/graphic-walker/package.json index 282e425ef..52cd857e8 100644 --- a/packages/graphic-walker/package.json +++ b/packages/graphic-walker/package.json @@ -100,7 +100,7 @@ "postinstall-postinstall": "^2.1.0", "rbush": "^3.0.1", "re-resizable": "^6.9.8", - "react-color": "^2.19.3", + "react-colorful": "^5.6.1", "react-dropzone": "^14.2.3", "react-error-boundary": "^4.0.11", "react-i18next": "^11.18.6", @@ -131,13 +131,10 @@ "@types/rbush": "^3.0.3", "@types/react": "*", "@types/react-beautiful-dnd": "^13.1.2", - "@types/react-color": "^3.0.6", "@types/react-dom": "*", - "@types/styled-components": "^5.1.26", "@types/topojson-client": "^3.1.1", "@vercel/analytics": "^0.1.8", "@vitejs/plugin-react": "^3.1.0", - "styled-components": "^5.3.6", "ts-json-schema-generator": "^1.5.0", "ts-patch": "^3.1.2", "ts-xor": "^1.3.0", @@ -147,7 +144,6 @@ }, "peerDependencies": { "react": ">=17.0.0 <19.0.0", - "react-dom": ">=17.0.0 <19.0.0", - "styled-components": "^5.3.6" + "react-dom": ">=17.0.0 <19.0.0" } } diff --git a/packages/graphic-walker/src/components/actionMenu/list.tsx b/packages/graphic-walker/src/components/actionMenu/list.tsx index 62548d07c..a18f2af8f 100644 --- a/packages/graphic-walker/src/components/actionMenu/list.tsx +++ b/packages/graphic-walker/src/components/actionMenu/list.tsx @@ -1,12 +1,8 @@ import React, { Fragment, memo, type ComponentProps, type ReactElement, createContext, useState, useContext, useMemo, useEffect } from 'react'; import { ChevronRightIcon } from '@heroicons/react/24/outline'; -import styled from 'styled-components'; import { Transition } from '@headlessui/react'; import { Separator } from '../ui/separator'; - -function classNames(...classes: string[]) { - return classes.filter(Boolean).join(' '); -} +import { cn } from '@/utils'; export interface IActionMenuItem { icon?: ReactElement; @@ -16,41 +12,6 @@ export interface IActionMenuItem { onPress?: () => void; } -const List = styled.div` - display: grid; - grid-template-columns: max-content 1fr max-content; - & > div { - /* row */ - display: contents; - > * { - background: inherit; - cursor: pointer; - width: 100%; - height: 100%; - display: flex; - align-items: center; - overflow: hidden; - padding-block: 0.2rem; - padding-inline: 0.2rem; - &:first-child { - padding-left: 0.4rem; - } - } - > *:first-child { - border-top-left-radius: calc(var(--radius) - 4px); - border-bottom-left-radius: calc(var(--radius) - 4px); - } - > *:last-child { - border-top-right-radius: calc(var(--radius) - 4px); - border-bottom-right-radius: calc(var(--radius) - 4px); - } - &[aria-disabled='true'] > * { - opacity: 0.5; - cursor: default; - } - } -`; - interface IActionMenuRootContext { path: number[]; setPath: (path: number[]) => void; @@ -92,62 +53,119 @@ const ActionMenuItem = memo(function ActionMenuItem({ item }, [children.length, hover, focus, ctx, basePath]); return ( -
{ - if (disabled || children.length) { - e.stopPropagation(); - e.preventDefault(); - return; - } - if (!disabled) { - onPress?.(); - ctx.onDismiss(); - } - }} - onFocus={() => { - if (!disabled) { - setFocus(true); - } - if (children.length && !expanded) { - ctx.setPath(path); - } - }} - onBlur={() => { - setFocus(false); - }} - onMouseEnter={() => { - setHover(true); - if (children.length && !expanded && !disabled) { - ctx.setPath(path); - } - }} - onMouseLeave={() => { - setHover(false); - }} - onKeyDown={(e) => { - if (disabled || children.length) { - return; - } - if (e.key === 'Enter' || e.key === 'Space') { - onPress?.(); - ctx.onDismiss(); - } - }} - > - -
+ <> +
{ + if (disabled || children.length) { + e.stopPropagation(); + e.preventDefault(); + return; + } + if (!disabled) { + onPress?.(); + ctx.onDismiss(); + } + }} + onFocus={() => { + if (!disabled) { + setFocus(true); + } + if (children.length && !expanded) { + ctx.setPath(path); + } + }} + onBlur={() => { + setFocus(false); + }} + onMouseEnter={() => { + setHover(true); + if (children.length && !expanded && !disabled) { + ctx.setPath(path); + } + }} + onMouseLeave={() => { + setHover(false); + }} + onKeyDown={(e) => { + if (disabled || children.length) { + return; + } + if (e.key === 'Enter' || e.key === 'Space') { + onPress?.(); + ctx.onDismiss(); + } + }} + > + {icon} +
+
{ + if (disabled || children.length) { + e.stopPropagation(); + e.preventDefault(); + return; + } + if (!disabled) { + onPress?.(); + ctx.onDismiss(); + } + }} + onMouseEnter={() => { + setHover(true); + if (children.length && !expanded && !disabled) { + ctx.setPath(path); + } + }} + onMouseLeave={() => { + setHover(false); + }} + > {label}
- + ); }); @@ -186,11 +204,11 @@ const MenuItemList = memo(function ActionMenuItemList(
{title &&
{title}
} {title && } - +
{items.map((item, index) => ( ))} - +
); }); diff --git a/packages/graphic-walker/src/components/clickMenu.tsx b/packages/graphic-walker/src/components/clickMenu.tsx index 9a72c5daf..acbde96fd 100644 --- a/packages/graphic-walker/src/components/clickMenu.tsx +++ b/packages/graphic-walker/src/components/clickMenu.tsx @@ -1,14 +1,5 @@ -import React, { useCallback, useMemo, useRef, useState } from 'react'; -import styled from 'styled-components'; -import { Transition } from '@headlessui/react'; +import React, { useCallback, useState } from 'react'; -const MenuContainer = styled.div` - min-width: 100px; - position: absolute; - z-index: 99; - cursor: pointer; - padding: 4px; -`; interface ClickMenuProps { x: number; y: number; @@ -27,9 +18,12 @@ const ClickMenu: React.FC = (props) => { const top = y - (rect?.top ?? 0); return (
- +
{children} - +
); }; diff --git a/packages/graphic-walker/src/components/color-picker.ts b/packages/graphic-walker/src/components/color-picker.ts deleted file mode 100644 index 2ca8d7b6f..000000000 --- a/packages/graphic-walker/src/components/color-picker.ts +++ /dev/null @@ -1,26 +0,0 @@ -import styled from 'styled-components'; -import { SketchPicker } from 'react-color'; - -export const StyledPicker = styled(SketchPicker)<{ noShadow?: boolean; noBorder?: boolean }>` - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: ${({ noShadow }) => - noShadow ? 'none' : 'var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)'} !important; - border-color: hsl(var(--border)) !important; - border-width: ${({ noBorder }) => (noBorder ? '0' : '1px')} !important; - background: hsl(var(--popover)) !important; - color: hsl(var(--popover-foreground)) !important; - .flexbox-fix { - border-color: hsl(var(--border)) !important; - } - label { - color: hsl(var(--popover-foreground)) !important; - } - input { - box-shadow: none !important; - border-radius: calc(var(--radius) - 2px) !important; - border: 1px solid hsl(var(--input)) !important; - background-color: transparent !important; - width: 100% !important; - } -`; diff --git a/packages/graphic-walker/src/components/color-picker.tsx b/packages/graphic-walker/src/components/color-picker.tsx new file mode 100644 index 000000000..b5cc451dd --- /dev/null +++ b/packages/graphic-walker/src/components/color-picker.tsx @@ -0,0 +1,29 @@ +import { HexColorPicker, HexColorInput } from 'react-colorful'; +import React from 'react'; + +export const StyledPicker = (props: { color: string; onChange: (color: string) => void; presetColors?: string[] }) => { + return ( +
+
+ +
+ + {props.presetColors && ( +
+ {props.presetColors.map((color) => ( +
props.onChange(color)} + /> + ))} +
+ )} +
+ ); +}; diff --git a/packages/graphic-walker/src/components/dataTable/index.tsx b/packages/graphic-walker/src/components/dataTable/index.tsx index f2f1ca0ec..306acc4f3 100644 --- a/packages/graphic-walker/src/components/dataTable/index.tsx +++ b/packages/graphic-walker/src/components/dataTable/index.tsx @@ -1,5 +1,4 @@ import React, { useMemo, useState, useRef, useEffect, useCallback, forwardRef, useImperativeHandle, ForwardedRef } from 'react'; -import styled from 'styled-components'; import type { IMutField, IRow, IComputationFunction, IFilterFiledSimple, IFilterRule, IFilterField, IFilterWorkflowStep, IField, IVisFilter } from '../../interfaces'; import { useTranslation } from 'react-i18next'; import LoadingLayer from '../loadingLayer'; @@ -31,34 +30,14 @@ interface DataTableProps { hidePaginationAtOnepage?: boolean; displayOffset?: number; } -const Container = styled.div` - overflow-x: auto; - height: 100%; - display: flex; - flex-direction: column; - table { - box-sizing: content-box; - border-collapse: collapse; - font-size: 12px; - tbody { - td { - } - td.number { - text-align: right; - } - td.text { - text-align: left; - } - } - } -`; + // const ANALYTIC_TYPE_LIST = ['dimension', 'measure']; const SEMANTIC_TYPE_LIST = ['nominal', 'ordinal', 'quantitative', 'temporal']; // function getCellType(field: IMutField): 'number' | 'text' { // return field.dataType === 'number' || field.dataType === 'integer' ? 'number' : 'text'; // } -function getHeaderType(field: IMutField): 'number' | 'text' { - return field.analyticType === 'dimension' ? 'text' : 'number'; +function getHeaderType(field: IMutField): string { + return field.analyticType === 'dimension' ? 'text-left' : 'text-right'; } function getHeaderClassNames(field: IMutField) { @@ -378,7 +357,7 @@ const DataTable = forwardRef( } }, []); return ( - +
{!disableFilter && filters.length > 0 && (
Filters: @@ -415,7 +394,7 @@ const DataTable = forwardRef( )}
- +
{headers.map((row) => ( @@ -566,7 +545,7 @@ const DataTable = forwardRef( )} - + ); }); diff --git a/packages/graphic-walker/src/components/explainData/index.tsx b/packages/graphic-walker/src/components/explainData/index.tsx index dcf0676c8..4f20a3393 100644 --- a/packages/graphic-walker/src/components/explainData/index.tsx +++ b/packages/graphic-walker/src/components/explainData/index.tsx @@ -3,7 +3,6 @@ import { observer } from 'mobx-react-lite'; import { useCompututaion, useVizStore } from '../../store'; import { useTranslation } from 'react-i18next'; import { getMeaAggKey } from '../../utils'; -import styled from 'styled-components'; import embed from 'vega-embed'; import { VegaGlobalConfig, IDarkMode, IThemeKey, IField, IRow, IPredicate } from '../../interfaces'; import { builtInThemes } from '../../vis/theme'; @@ -12,27 +11,6 @@ import { Dialog, DialogContent } from '../ui/dialog'; import LoadingLayer from '../loadingLayer'; import { themeContext } from '@/store/theme'; -const Container = styled.div` - height: 50vh; - overflow-y: hidden; -`; -const TabsList = styled.div` - display: flex; - flex-direction: column; - align-items: stretch; - justify-content: stretch; - height: 100%; - overflow-y: scroll; -`; - -const Tab = styled.div` - margin-block: 0.2em; - margin-inline: 0.2em; - padding: 0.5em; - border-width: 2px; - cursor: pointer; -`; - const getCategoryName = (row: IRow, field: IField) => { if (field.semanticType === 'quantitative') { let id = field.fid; @@ -193,20 +171,24 @@ const ExplainData: React.FC<{ > {explainDataInfoList.length === 0 && } - - +
+
{explainDataInfoList.map((option, i) => { return ( - setSelectedInfoIndex(i)}> +
setSelectedInfoIndex(i)} + > {option.targetField.name} {option.score.toFixed(2)} - +
); })} - +
- +
); diff --git a/packages/graphic-walker/src/components/painter/components.tsx b/packages/graphic-walker/src/components/painter/components.tsx index 80faeca9d..79c2f23bc 100644 --- a/packages/graphic-walker/src/components/painter/components.tsx +++ b/packages/graphic-walker/src/components/painter/components.tsx @@ -245,10 +245,8 @@ export const ColorEditor = (props: { color: string; onChangeColor: (color: strin color={color} onChange={(color) => { setColorEdited(true); - setColor(color.hex); + setColor(color); }} - noShadow - noBorder />
@@ -62,12 +109,13 @@ export const ColorPickerComponent = ({ defaultColor, setDefaultColor, setPrimary {displayColorPicker && ( { + color={rgbaToHex(defaultColor.r, defaultColor.g, defaultColor.b, defaultColor.a)} + onChange={(hexColor) => { setPrimaryColorEdited(true); + const rgbaColor = hexToRgba(hexColor); setDefaultColor({ - ...color.rgb, - a: color.rgb.a ?? 1, + ...rgbaColor, + a: defaultColor.a, // preserve alpha }); }} /> diff --git a/packages/graphic-walker/src/fields/components.tsx b/packages/graphic-walker/src/fields/components.tsx index f7dcc1a26..134cfe1e3 100644 --- a/packages/graphic-walker/src/fields/components.tsx +++ b/packages/graphic-walker/src/fields/components.tsx @@ -1,5 +1,4 @@ import React, { CSSProperties } from 'react'; -import styled from 'styled-components'; import { useTranslation } from 'react-i18next'; import { GLOBAL_CONFIG } from '../config'; @@ -11,12 +10,12 @@ export const FieldListContainer: React.FC<{ const { t } = useTranslation('translation', { keyPrefix: 'constant.draggable_key' }); return ( - -
-

{t(props.name)}

+
+
+

{t(props.name)}

-
{props.children}
- +
{props.children}
+
); }; @@ -46,100 +45,53 @@ export const FilterFieldContainer: React.FC<{ children?: React.ReactNode | Itera ); }; -export const FieldsContainer = styled.div` - display: flex; - padding: 0.2em; - min-height: 2.4em; - flex-wrap: wrap; - > div { - margin: 1px; - } - touch-action: none; -`; +export const FieldsContainer = React.forwardRef(({ children, className = '', ...props }, ref) => ( +
div]:m-px ${className}`} {...props}> + {children} +
+)); -export const FilterFieldsContainer = styled.div({ - display: 'flex', - flexDirection: 'column', - paddingBlock: '0.5em 0.8em', - paddingInline: '0.2em', - minHeight: '4em', - '> div': { - marginBlock: '0.3em', - marginInline: '1px', - }, -}); +FieldsContainer.displayName = 'FieldsContainer'; -export const FieldListSegment = styled.div` - display: flex; - font-size: 12px; - div.fl-header { - /* flex-basis: 100px; */ - width: 100px; - flex-shrink: 0; - h4 { - margin: 0.6em; - font-weight: 400; - } - } - div.fl-container { - flex-grow: 10; - position: relative; - } -`; +export const FilterFieldsContainer = React.forwardRef(({ children, className = '', ...props }, ref) => ( +
div]:my-1.5 [&>div]:mx-px ${className}`} {...props}> + {children} +
+)); -export const FilterFieldSegment = styled.div` - border: 1px solid #e5e7eb; - @media (prefers-color-scheme: dark) { - border: 1px solid #2d3748; - } - font-size: 12px; - margin: 0.2em; +FilterFieldsContainer.displayName = 'FilterFieldsContainer'; - .flt-header { - border-bottom: 1px solid #e5e7eb; - @media (prefers-color-scheme: dark) { - border-bottom: 1px solid #2d3748; - } - padding: 0.6em; - > h4 { - font-weight: 400; - } - } +export const FilterFieldSegment: React.FC<{ children?: React.ReactNode; className?: string }> = ({ children, className = '' }) => ( +
+ {children} +
+); - .flt-container { - } -`; +export const Pill = React.forwardRef(({ colType, children, className = '', ...props }, ref) => { + const baseClasses = "flex items-center rounded-sm border box-border cursor-default text-xs h-5 min-w-[150px] max-w-[300px] px-2.5 select-none truncate whitespace-nowrap"; + const typeClasses = colType === 'continuous' + ? "bg-background border-muted-foreground text-foreground" + : "bg-primary border-background text-primary-foreground"; + + return ( +
+ {children} +
+ ); +}); -export const Pill = styled.div<{ colType: 'discrete' | 'continuous' }>` - background-color: ${(props) => (props.colType === 'continuous' ? 'hsl(var(--background))' : 'hsl(var(--primary))')}; - border-color: ${(props) => (props.colType === 'continuous' ? 'hsl(var(--muted-foreground))' : 'hsl(var(--background))')}; - color: ${(props) => (props.colType === 'continuous' ? 'hsl(var(--foreground))' : 'hsl(var(--primary-foreground))')}; - -moz-user-select: none; - -ms-user-select: none; - -webkit-align-items: center; - -webkit-user-select: none; - align-items: center; - border-radius: calc(var(--radius) - 2px); - border-style: solid; - border-width: 1px; - box-sizing: border-box; - cursor: default; - display: -webkit-flex; - display: flex; - font-size: 12px; - height: 20px; - min-width: 150px; - max-width: 300px; - /* overflow-y: hidden; */ - padding: 0 10px; - user-select: none; - text-overflow: ellipsis; - white-space: nowrap; - /* --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow-color: rgb(6 182 212/0.5); - --tw-shadow: var(--tw-shadow-colored); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow); */ -`; +Pill.displayName = 'Pill'; diff --git a/packages/graphic-walker/src/fields/datasetFields/dimFields.tsx b/packages/graphic-walker/src/fields/datasetFields/dimFields.tsx index d49b18763..2037a1301 100644 --- a/packages/graphic-walker/src/fields/datasetFields/dimFields.tsx +++ b/packages/graphic-walker/src/fields/datasetFields/dimFields.tsx @@ -23,7 +23,7 @@ const DimFields: React.FC = (props) => { ` - transform: ${props => !props.isDragging && 'translate(0px, 0px) !important'}; - user-select: none; - align-items: center; - overflow: hidden; - > *:not(span) { - flex: 0 0 unset; +export const FieldPill = React.forwardRef< + HTMLDivElement, + { + isDragging: boolean; + children?: React.ReactNode; + className?: string; + [key: string]: any; } - > span { - flex: 1; - display: inline-block; - padding-inline: 0.1em; - /* truncate */ - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - :has([role="button"]:hover) { - background-color: unset; - } -` \ No newline at end of file +>(({ isDragging, children, className = '', ...props }, ref) => { + const baseClasses = + "select-none items-center overflow-hidden [&>*:not(span)]:flex-none [&>span]:flex-1 [&>span]:inline-block [&>span]:px-0.5 [&>span]:overflow-hidden [&>span]:text-ellipsis [&>span]:whitespace-nowrap has-[[role='button']:hover]:bg-transparent"; + const transformClass = !isDragging ? '[transform:translate(0px,0px)!important]' : ''; + + return ( +
+ {children} +
+ ); +}); + +FieldPill.displayName = 'FieldPill'; diff --git a/packages/graphic-walker/src/fields/encodeFields/multiEncodeEditor.tsx b/packages/graphic-walker/src/fields/encodeFields/multiEncodeEditor.tsx index ac0f47cec..247f96e36 100644 --- a/packages/graphic-walker/src/fields/encodeFields/multiEncodeEditor.tsx +++ b/packages/graphic-walker/src/fields/encodeFields/multiEncodeEditor.tsx @@ -9,16 +9,10 @@ import { COUNT_FIELD_ID, MEA_KEY_ID, MEA_VAL_ID } from '../../constants'; import DropdownContext from '../../components/dropdownContext'; import { GLOBAL_CONFIG } from '../../config'; import { Draggable, DroppableStateSnapshot } from '@kanaries/react-beautiful-dnd'; -import styled from 'styled-components'; import SelectContext, { type ISelectContextOption } from '../../components/selectContext'; import { refMapper } from '../fieldsContext'; import { getFieldIdentifier } from '@/utils'; -const PillActions = styled.div` - overflow: visible !important; - width: calc(100% - 1.875rem); -`; - interface MultiEncodeEditorProps { dkey: { id: keyof Omit; @@ -74,7 +68,7 @@ const SingleEncodeEditor: React.FC = (props) => { >
- +
{channelItem.fid === MEA_KEY_ID && ( = (props) => { )} - +
); }} diff --git a/packages/graphic-walker/src/fields/encodeFields/singleEncodeEditor.tsx b/packages/graphic-walker/src/fields/encodeFields/singleEncodeEditor.tsx index f2531a3b2..c05eea69f 100644 --- a/packages/graphic-walker/src/fields/encodeFields/singleEncodeEditor.tsx +++ b/packages/graphic-walker/src/fields/encodeFields/singleEncodeEditor.tsx @@ -9,16 +9,10 @@ import { COUNT_FIELD_ID, MEA_KEY_ID, MEA_VAL_ID } from '../../constants'; import DropdownContext from '../../components/dropdownContext'; import { GLOBAL_CONFIG } from '../../config'; import { Draggable, DroppableStateSnapshot } from '@kanaries/react-beautiful-dnd'; -import styled from 'styled-components'; import SelectContext, { type ISelectContextOption } from '../../components/selectContext'; import { refMapper } from '../fieldsContext'; import { getFieldIdentifier } from '@/utils'; -const PillActions = styled.div` - overflow: visible !important; - width: calc(100% - 1.875rem); -`; - interface SingleEncodeEditorProps { dkey: { id: keyof Omit; @@ -80,7 +74,7 @@ const SingleEncodeEditor: React.FC = (props) => { > - +
{channelItem.fid === MEA_KEY_ID && ( = (props) => { )} - +
); }} diff --git a/packages/graphic-walker/src/fields/filterField/filterPill.tsx b/packages/graphic-walker/src/fields/filterField/filterPill.tsx index a53bcc2cd..31379c0a5 100644 --- a/packages/graphic-walker/src/fields/filterField/filterPill.tsx +++ b/packages/graphic-walker/src/fields/filterField/filterPill.tsx @@ -2,7 +2,6 @@ import { observer } from 'mobx-react-lite'; import React from 'react'; import { DraggableProvided } from '@kanaries/react-beautiful-dnd'; import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; import { PencilSquareIcon } from '@heroicons/react/24/solid'; import { useVizStore } from '../../store'; import { refMapper } from '../fieldsContext'; @@ -14,49 +13,6 @@ interface FilterPillProps { fIndex: number; } -const Pill = styled.div` - user-select: none; - align-items: stretch; - border-style: solid; - border-width: 1px; - box-sizing: border-box; - cursor: default; - display: flex; - flex-direction: column; - font-size: 12px; - min-width: 150px; - overflow-y: hidden; - padding: 0; - - > * { - flex-grow: 1; - padding-block: 0.2em; - padding-inline: 0.5em; - } - - > header { - height: 20px; - border-bottom-width: 1px; - } - - > div.output { - min-height: 20px; - - > span { - overflow-y: hidden; - max-height: 4em; - } - - .icon { - display: none; - - &:hover { - display: unset; - } - } - } -`; - const FilterPill: React.FC = observer((props) => { const { provided, fIndex } = props; const vizStore = useVizStore(); @@ -71,7 +27,12 @@ const FilterPill: React.FC = observer((props) => { const fieldName = field.enableAgg ? `${field.aggName}(${field.name})` : field.name; return ( - +
{fieldName}
= observer((props) => { height="1.4em" />
- +
); }); diff --git a/packages/graphic-walker/src/fields/filterField/slider.tsx b/packages/graphic-walker/src/fields/filterField/slider.tsx index 9e347e2b3..8cbde6f88 100644 --- a/packages/graphic-walker/src/fields/filterField/slider.tsx +++ b/packages/graphic-walker/src/fields/filterField/slider.tsx @@ -1,33 +1,7 @@ import React, { useEffect, useState } from 'react'; -import styled from 'styled-components'; import { useTranslation } from 'react-i18next'; import { Slider as RangeSlider } from '@/components/rangeslider'; import { Input } from '@/components/ui/input'; -const SliderContainer = styled.div` - display: flex; - flex-direction: column; - align-items: stretch; - justify-content: stretch; - padding-block: 1em; - - > .output { - display: flex; - justify-content: space-between; - margin-top: 1em; - - > output { - width: 100%; - } - - > output:first-child { - margin-right: 0.5em; - } - - > output:last-child { - margin-left: 0.5em; - } - } -`; interface ValueInputProps { min: number; @@ -88,10 +62,10 @@ const Slider: React.FC = React.memo(function Slider({ min, max, val const stepDigit = 10 ** Math.floor(Math.log10((max - min) / 100)); return ( - +
onChange([min, max])} /> -
- +
+
{t('filters.range.start_value')}
{ = React.memo(function Slider({ min, max, val /> }
- +
{t('filters.range.end_value')}
{ = React.memo(function Slider({ min, max, val }
- +
); }); diff --git a/packages/graphic-walker/src/fields/filterField/tabs.tsx b/packages/graphic-walker/src/fields/filterField/tabs.tsx index a0683b767..49d816440 100644 --- a/packages/graphic-walker/src/fields/filterField/tabs.tsx +++ b/packages/graphic-walker/src/fields/filterField/tabs.tsx @@ -1,6 +1,5 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline'; import type { IFilterField, IFilterRule, IFieldStats, IMutField, IComputationFunction, IKeyWord } from '../../interfaces'; @@ -31,87 +30,6 @@ export type RuleFormProps = { displayOffset?: number; }; -const Container = styled.div` - margin-block: 1em; - - > .btn-grp { - display: flex; - flex-direction: row; - margin-block: 1em; - - > * { - margin-inline-start: 0.6em; - - &:first-child { - margin-inline-start: 0; - } - } - } -`; - -const Table = styled.div` - display: flex; - flex-direction: column; - max-height: 30vh; - overflow-y: scroll; -`; - -const TableRow = styled.div` - display: flex; - & > input, - & > *[for] { - cursor: pointer; - } - & > * { - padding-block: 0.6em; - padding-inline: 0.2em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - user-select: none; - border-bottom: 0.8px solid hsl(var(--border)); - flex-shink: 0; - } - & > *:first-child { - width: 4em; - } - & > *:last-child { - width: max-content; - } - & > *:first-child + * { - flex: 1; - } -`; - -const TabsContainer = styled.div` - display: flex; - flex-direction: column; - align-items: stretch; - justify-content: stretch; -`; - -const CalendarInputContainer = styled.div` - display: flex; - padding-block: 1em; - width: 100%; - - > .calendar-input { - width: 100%; - } - - > .calendar-input:first-child { - margin-right: 0.5em; - } - - > .calendar-input:last-child { - margin-left: 0.5em; - } -`; - -const TabPanel = styled.div``; - -const TabItem = styled.div``; - const StatusCheckbox: React.FC<{ currentNum: number; totalNum: number; onChange: () => void; disabled?: boolean; loading?: boolean }> = (props) => { const { currentNum, totalNum, onChange } = props; @@ -548,10 +466,10 @@ export const FilterOneOfRule: React.FC = ({ ); return field.rule?.type === 'one of' || field.rule?.type === 'not in' ? ( - +
{t('constant.filter_type.one_of')}
{t('constant.filter_type.one_of_desc')}
-
+
@@ -601,8 +519,8 @@ export const FilterOneOfRule: React.FC = ({
)}
-
- +
+
= ({
- -
+
+
{loading && (
@@ -628,7 +546,7 @@ export const FilterOneOfRule: React.FC = ({ )} {/*
*/} {!loading && ( - +
{showLoadingList && rowVirtualizer.getTotalSize() === 0 && } {showLoadingList && (
= ({ }} > {rowVirtualizer.getVirtualItems().map((vItem) => ( - = ({
-
+
))}
)} @@ -677,9 +595,9 @@ export const FilterOneOfRule: React.FC = ({ const item = data?.get(idx); if (!item) { return ( - = ({ effect={() => loadData(idx)} effectId={`${field.fid}_${sortConfig.key}${sortConfig.ascending ? '' : '_dsc'}_${idx}`} /> - + ); } const { value, count } = item; @@ -713,8 +631,9 @@ export const FilterOneOfRule: React.FC = ({ const displayValue = field.semanticType === 'temporal' ? formatDate(parsedOffsetDate(displayOffset, field.offset)(value)) : `${value}`; return ( - = ({ {displayValue} - + ); })} )} -
+
)} {isNotEmpty(distinctTotal) && ( - - +
+
- -
+
+
)}
- +
) : null; }; @@ -845,10 +764,10 @@ export const FilterTemporalRangeRule: React.FC +
{t('constant.filter_type.temporal_range')}
{t('constant.filter_type.temporal_range_desc')}
- +
{t('filters.range.start_value')}
handleChange([field.rule?.value[0], value])} />
- - +
+
) : null; }; @@ -906,11 +825,11 @@ export const FilterRangeRule: React.FC = ({ } return field.rule?.type === 'range' ? ( - +
{t('range')}
{t('range_desc')}
- +
) : null; }; @@ -956,7 +875,7 @@ const Tabs: React.FC = ({ allFields, field, onChange, tabs, displayOf }, [tabs]); return ( - +
setWhich(s as (typeof tabs)[number])}> {tabs.map((option) => { return ( @@ -973,13 +892,13 @@ const Tabs: React.FC = ({ allFields, field, onChange, tabs, displayOf })}
- +
{tabs.map((tab, i) => { const Component = filterTabs[tab]; if (!Component) return null; return ( - = ({ allFields, field, onChange, tabs, displayOf tabIndex={0} > - +
); })} -
- +
+ ); }; diff --git a/packages/graphic-walker/src/index.css b/packages/graphic-walker/src/index.css index 49e38986f..66d11d85c 100644 --- a/packages/graphic-walker/src/index.css +++ b/packages/graphic-walker/src/index.css @@ -73,3 +73,101 @@ code { .dark .leaflet-tooltip-left:before { border-left-color: hsl(var(--popover)); } + +.react-colorful { + position: relative; + display: flex; + flex-direction: column; + width: 200px; + height: 200px; + user-select: none; + cursor: default; +} + +.react-colorful__saturation { + position: relative; + flex-grow: 1; + border-color: transparent; /* Fixes https://github.com/omgovich/react-colorful/issues/139 */ + border-bottom: 12px solid #000; + border-radius: 8px 8px 0 0; + background-image: linear-gradient(to top, #000, rgba(0, 0, 0, 0)), linear-gradient(to right, #fff, rgba(255, 255, 255, 0)); +} + +.react-colorful__pointer-fill, +.react-colorful__alpha-gradient { + content: ''; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + pointer-events: none; + border-radius: inherit; +} + +/* Improve elements rendering on light backgrounds */ +.react-colorful__alpha-gradient, +.react-colorful__saturation { + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05); +} + +.react-colorful__hue, +.react-colorful__alpha { + position: relative; + height: 24px; +} + +.react-colorful__hue { + background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%); +} + +/* Round bottom corners of the last element: `Hue` for `ColorPicker` or `Alpha` for `AlphaColorPicker` */ +.react-colorful__last-control { + border-radius: 0 0 8px 8px; +} + +.react-colorful__interactive { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + border-radius: inherit; + outline: none; + /* Don't trigger the default scrolling behavior when the event is originating from this element */ + touch-action: none; +} + +.react-colorful__pointer { + position: absolute; + z-index: 1; + box-sizing: border-box; + width: 28px; + height: 28px; + transform: translate(-50%, -50%); + background-color: #fff; + border: 2px solid #fff; + border-radius: 50%; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +.react-colorful__interactive:focus .react-colorful__pointer { + transform: translate(-50%, -50%) scale(1.1); +} + +/* Chessboard-like pattern for alpha related elements */ +.react-colorful__alpha, +.react-colorful__alpha-pointer { + background-color: #fff; + background-image: url('data:image/svg+xml,'); +} + +/* Display the saturation pointer over the hue one */ +.react-colorful__saturation-pointer { + z-index: 3; +} + +/* Display the hue pointer over the alpha one */ +.react-colorful__hue-pointer { + z-index: 2; +} diff --git a/packages/graphic-walker/src/shadow-dom.tsx b/packages/graphic-walker/src/shadow-dom.tsx index f3c0c23d0..603290e74 100644 --- a/packages/graphic-walker/src/shadow-dom.tsx +++ b/packages/graphic-walker/src/shadow-dom.tsx @@ -1,5 +1,4 @@ import React, { HTMLAttributes, createContext, useEffect, useMemo, useRef, useState } from 'react'; -import { StyleSheetManager } from 'styled-components'; import root from 'react-shadow'; import tailwindStyle from 'tailwindcss/tailwind.css?inline'; @@ -51,11 +50,7 @@ export const ShadowDom: React.FC = function ShadowDom({ onMount integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossOrigin="" /> - {shadowRoot && ( - - {children} - - )} + {shadowRoot && {children}} ); diff --git a/packages/graphic-walker/src/vis/observable-plot-renderer.tsx b/packages/graphic-walker/src/vis/observable-plot-renderer.tsx index 29173e5b9..f2b5b4c71 100644 --- a/packages/graphic-walker/src/vis/observable-plot-renderer.tsx +++ b/packages/graphic-walker/src/vis/observable-plot-renderer.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState, useMemo, useRef, useContext, forwardRef, MutableRefObject } from 'react'; import * as Plot from '@observablehq/plot'; -import styled from 'styled-components'; import { useResizeDetector } from 'react-resize-detector'; import { Subject } from 'rxjs'; @@ -22,13 +21,6 @@ import canvasSize from 'canvas-size'; import { startTask } from '../utils'; import { toObservablePlotSpec } from '@/lib/observablePlot'; -// Example container styled similarly to your Vega-Lite container: -const CanvasContainer = styled.div<{ rowSize: number; colSize: number }>` - display: grid; - grid-template-columns: repeat(${(props) => props.colSize}, auto); - grid-template-rows: repeat(${(props) => props.rowSize}, 1fr); -`; - // For referencing selection events: const SELECTION_NAME = 'geom'; const click$ = new Subject(); @@ -206,7 +198,7 @@ const ObservablePlotRenderer = forwardRef { let specsArr: any[] = []; if (rowRepeatFields.length === 0 && colRepeatFields.length === 0) { - return [] + return []; } const count = rowRepeatFields.length * colRepeatFields.length; @@ -234,7 +226,7 @@ const ObservablePlotRenderer = forwardRef
- {plotPlaceholders.map((plotRef, i) => (
))} -
+
); }); diff --git a/packages/graphic-walker/src/vis/react-vega.tsx b/packages/graphic-walker/src/vis/react-vega.tsx index 2223a7966..c1e72f92f 100644 --- a/packages/graphic-walker/src/vis/react-vega.tsx +++ b/packages/graphic-walker/src/vis/react-vega.tsx @@ -3,7 +3,6 @@ import embed from 'vega-embed'; import { Subject, Subscription } from 'rxjs'; import * as op from 'rxjs/operators'; import { expressionFunction, type ScenegraphEvent } from 'vega'; -import styled from 'styled-components'; import { useVegaExportApi } from '../utils/vegaApiExport'; import { IViewField, IRow, IStackMode, VegaGlobalConfig, IVegaChartRef, IChannelScales, IDarkMode, IConfigScaleSet } from '../interfaces'; import { getVegaTimeFormatRules } from './temporalFormat'; @@ -30,12 +29,6 @@ expressionFunction('formatBin', (datum: [number, number] | number, formatString? return `[${formatter(Number(min.toFixed(beaStep)))},${formatter(Number(max.toFixed(beaStep)))}]`; }); -const CanvaContainer = styled.div<{ rowSize: number; colSize: number }>` - display: grid; - grid-template-columns: repeat(${(props) => props.colSize}, auto); - grid-template-rows: repeat(${(props) => props.rowSize}, 1fr); -`; - function parseRect(el: HTMLCanvasElement | SVGSVGElement) { if (el instanceof HTMLCanvasElement) { return { @@ -541,19 +534,20 @@ const ReactVega = forwardRef(function ReactVe style={{ overflow: layoutMode === 'auto' ? 'visible' : 'hidden' }} >
- {/*
*/} {viewPlaceholders.map((view, i) => (
))} -
+
); }); diff --git a/packages/graphic-walker/vite.config.ts b/packages/graphic-walker/vite.config.ts index 3665dee9f..619e141da 100644 --- a/packages/graphic-walker/vite.config.ts +++ b/packages/graphic-walker/vite.config.ts @@ -41,7 +41,6 @@ export default defineConfig({ globals: { 'react': 'React', 'react-dom': 'ReactDOM', - 'styled-components': 'styled', }, }, }, diff --git a/packages/playground/package.json b/packages/playground/package.json index a32d96b8b..b6b499b95 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -24,7 +24,7 @@ "@vercel/analytics": "^1.1.1", "color-space": "^2.0.1", "react": "^18.2.0", - "react-color": "^2.19.3", + "react-colorful": "^5.6.1", "react-dom": "^18.2.0", "react-router": "^6.20.0", "react-router-dom": "^6.20.0", diff --git a/packages/playground/src/examples/components/colorPicker.tsx b/packages/playground/src/examples/components/colorPicker.tsx index 53fa16e99..61209d972 100644 --- a/packages/playground/src/examples/components/colorPicker.tsx +++ b/packages/playground/src/examples/components/colorPicker.tsx @@ -1,39 +1,166 @@ -import styled from 'styled-components'; -import { SketchPicker } from 'react-color'; -import { useState, useEffect, useRef } from 'react'; -import { extractRGB } from '../util'; +import { HexColorPicker, HexColorInput } from 'react-colorful'; +import { ErrorBoundary } from 'react-error-boundary'; +import React from 'react'; -const StyledPicker = styled(SketchPicker)<{ noShadow?: boolean; noBorder?: boolean }>` - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: ${({ noShadow }) => - noShadow ? 'none' : 'var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)'} !important; - border-color: hsl(var(--border)) !important; - border-width: ${({ noBorder }) => (noBorder ? '0' : '1px')} !important; - background: hsl(var(--popover)) !important; - color: hsl(var(--popover-foreground)) !important; - .flexbox-fix { - border-color: hsl(var(--border)) !important; - } - label { - color: hsl(var(--popover-foreground)) !important; - } - input { - box-shadow: none !important; - border-radius: calc(var(--radius) - 2px) !important; - border: 1px solid hsl(var(--input)) !important; - background-color: transparent !important; - width: 100% !important; +const DEFAULT_COLOR_SCHEME = ['#5B8FF9', '#FF6900', '#FCB900', '#7BDCB5', '#00D084', '#8ED1FC', '#0693E3', '#ABB8C3', '#EB144C', '#F78DA7', '#9900EF']; + +const StyledPicker = (props: { color: string; onChange: (color: string) => void; presetColors?: string[] }) => { + return ( +
+
+ +
+ + {props.presetColors && ( +
+ {props.presetColors.map((color) => ( +
props.onChange(color)} + /> + ))} +
+ )} +
+ ); +}; + +// Utility functions for color conversion +const rgbaToHex = (r: number, g: number, b: number): string => { + const toHex = (n: number) => { + const hex = Math.round(Math.max(0, Math.min(255, n))).toString(16); + return hex.length === 1 ? '0' + hex : hex; + }; + return `#${toHex(r)}${toHex(g)}${toHex(b)}`; +}; + +const hexToRgba = (hex: string): { r: number; g: number; b: number; a: number } => { + // Remove # if present + hex = hex.replace('#', ''); + + // Handle short hex format (e.g., #fff) + if (hex.length === 3) { + hex = hex + .split('') + .map((char) => char + char) + .join(''); } -`; -const DEFAULT_COLOR_SCHEME = ['#5B8FF9', '#FF6900', '#FCB900', '#7BDCB5', '#00D084', '#8ED1FC', '#0693E3', '#ABB8C3', '#EB144C', '#F78DA7', '#9900EF']; + const r = parseInt(hex.substr(0, 2), 16); + const g = parseInt(hex.substr(2, 2), 16); + const b = parseInt(hex.substr(4, 2), 16); + + return { r, g, b, a: 1 }; +}; + +export const ColorPickerComponent = ({ + defaultColor, + setDefaultColor, + setPrimaryColorEdited, + displayColorPicker, + setDisplayColorPicker, +}: { + defaultColor: { r: number; g: number; b: number; a: number }; + setDefaultColor: (color: { r: number; g: number; b: number; a: number }) => void; + setPrimaryColorEdited: (edited: boolean) => void; + displayColorPicker: boolean; + setDisplayColorPicker: (display: boolean) => void; +}) => { + return ( + +
+ { + setPrimaryColorEdited(true); + setDefaultColor({ + ...defaultColor, + r: Number(e.target.value), + }); + }} + /> + { + setPrimaryColorEdited(true); + setDefaultColor({ + ...defaultColor, + g: Number(e.target.value), + }); + }} + /> + { + setPrimaryColorEdited(true); + setDefaultColor({ + ...defaultColor, + b: Number(e.target.value), + }); + }} + /> +
+ } + > +
{ + e.stopPropagation(); + e.preventDefault(); + }} + > +
{ + e.stopPropagation(); + e.preventDefault(); + setDisplayColorPicker(true); + }} + >
+
+ {displayColorPicker && ( + { + setPrimaryColorEdited(true); + const rgbaColor = hexToRgba(hexColor); + setDefaultColor({ + ...rgbaColor, + a: defaultColor.a, // preserve alpha + }); + }} + /> + )} +
+
+
+ ); +}; +// Simple Picker component for backward compatibility export function Picker(props: { value: string; onChange: (v: string) => void; disabled?: boolean }) { - const [displayColorPicker, setDisplayColorPicker] = useState(false); - const pickerRef = useRef(null); + const [displayColorPicker, setDisplayColorPicker] = React.useState(false); + const pickerRef = React.useRef(null); - useEffect(() => { + React.useEffect(() => { if (displayColorPicker) { const listener = (event: MouseEvent) => { if (pickerRef.current && !pickerRef.current.contains(event.target as Node)) { @@ -44,34 +171,38 @@ export function Picker(props: { value: string; onChange: (v: string) => void; di return () => document.removeEventListener('click', listener); } }, [displayColorPicker]); + + // Convert hex to RGBA for the new color picker + const hexToRgbaColor = (hex: string) => { + const rgba = hexToRgba(hex); + return rgba; + }; + + // Convert RGBA back to hex + const rgbaToHexColor = (color: { r: number; g: number; b: number; a: number }) => { + return rgbaToHex(color.r, color.g, color.b); + }; + + const [colorState, setColorState] = React.useState(() => hexToRgbaColor(props.value)); + + React.useEffect(() => { + setColorState(hexToRgbaColor(props.value)); + }, [props.value]); + return ( -
{ - e.stopPropagation(); - e.preventDefault(); + { + setColorState(color); + props.onChange(rgbaToHexColor(color)); }} - > -
{ - e.stopPropagation(); - e.preventDefault(); - !props.disabled && setDisplayColorPicker(true); - }} - >
-
- {displayColorPicker && !props.disabled && ( - { - props.onChange(color.hex); - }} - /> - )} -
-
+ setPrimaryColorEdited={() => {}} + displayColorPicker={displayColorPicker && !props.disabled} + setDisplayColorPicker={(display) => { + if (!props.disabled) { + setDisplayColorPicker(display); + } + }} + /> ); } diff --git a/yarn.lock b/yarn.lock index 65e227190..758e8f052 100644 --- a/yarn.lock +++ b/yarn.lock @@ -72,13 +72,6 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" - integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== - dependencies: - "@babel/types" "^7.22.5" - "@babel/helper-compilation-targets@^7.22.15": version "7.22.15" resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" @@ -110,7 +103,7 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.22.5": +"@babel/helper-module-imports@^7.22.15": version "7.22.15" resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== @@ -220,7 +213,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.22.5", "@babel/plugin-syntax-jsx@^7.7.2": +"@babel/plugin-syntax-jsx@^7.7.2": version "7.23.3" resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== @@ -341,7 +334,7 @@ "@babel/parser" "^7.22.15" "@babel/types" "^7.22.15" -"@babel/traverse@^7.23.2", "@babel/traverse@^7.23.3", "@babel/traverse@^7.4.5": +"@babel/traverse@^7.23.2", "@babel/traverse@^7.23.3": version "7.23.3" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz#26ee5f252e725aa7aca3474aa5b324eaf7908b5b" integrity sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ== @@ -378,28 +371,6 @@ dependencies: apache-arrow "^13.0.0" -"@emotion/is-prop-valid@^1.1.0": - version "1.2.1" - resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc" - integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw== - dependencies: - "@emotion/memoize" "^0.8.1" - -"@emotion/memoize@^0.8.1": - version "0.8.1" - resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" - integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== - -"@emotion/stylis@^0.8.4": - version "0.8.5" - resolved "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" - integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== - -"@emotion/unitless@^0.7.4": - version "0.7.5" - resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" - integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== - "@esbuild/android-arm64@0.18.20": version "0.18.20" resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" @@ -755,11 +726,6 @@ resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== -"@icons/material@^0.2.4": - version "0.2.4" - resolved "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" - integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1970,7 +1936,7 @@ dependencies: "@types/unist" "^2" -"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.1": +"@types/hoist-non-react-statics@^3.3.1": version "3.3.5" resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz#dab7867ef789d87e2b4b0003c9d65c49cc44a494" integrity sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg== @@ -2087,7 +2053,7 @@ "@types/react-dom@*", "@types/react-dom@^18.2.15", "@types/react-dom@^18.x": version "18.3.7" - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz#b89ddf2cd83b4feafcc4e2ea41afdfb95a0d194f" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.7.tgz#b89ddf2cd83b4feafcc4e2ea41afdfb95a0d194f" integrity sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ== "@types/react-syntax-highlighter@^15.5.10": @@ -2099,7 +2065,7 @@ "@types/react@*", "@types/react@^18.2.37", "@types/react@^18.x": version "18.3.23" - resolved "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz#86ae6f6b95a48c418fecdaccc8069e0fbb63696a" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.23.tgz#86ae6f6b95a48c418fecdaccc8069e0fbb63696a" integrity sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w== dependencies: "@types/prop-types" "*" @@ -2122,15 +2088,6 @@ resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== -"@types/styled-components@^5.1.26": - version "5.1.30" - resolved "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.30.tgz#7f2b2c01245e3274083091517c7205c9ce9dd420" - integrity sha512-xxJqw0s1myRTgrzHgG5tKHS9hK+KNhjbKMXDWlHRo9eDNVVUqf147QUGYUqwyCDkFyGr2pi1qJKFMEy0ACZb0A== - dependencies: - "@types/hoist-non-react-statics" "*" - "@types/react" "*" - csstype "^3.0.2" - "@types/topojson-client@^3.1.1": version "3.1.4" resolved "https://registry.npmjs.org/@types/topojson-client/-/topojson-client-3.1.4.tgz#81b83f9ecd6542dc5c3df21967f992e3fe192c33" @@ -2492,17 +2449,6 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -"babel-plugin-styled-components@>= 1.12.0": - version "2.1.4" - resolved "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz#9a1f37c7f32ef927b4b008b529feb4a2c82b1092" - integrity sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-module-imports" "^7.22.5" - "@babel/plugin-syntax-jsx" "^7.22.5" - lodash "^4.17.21" - picomatch "^2.3.1" - babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -2615,11 +2561,6 @@ camelcase@^6.2.0: resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -camelize@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" - integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== - caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541: version "1.0.30001563" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz#aa68a64188903e98f36eb9c56e48fba0c1fe2a32" @@ -2868,20 +2809,6 @@ css-box-model@^1.2.0: dependencies: tiny-invariant "^1.0.6" -css-color-keywords@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" - integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== - -css-to-react-native@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" - integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== - dependencies: - camelize "^1.0.0" - css-color-keywords "^1.0.0" - postcss-value-parser "^4.0.2" - cssesc@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -3783,7 +3710,7 @@ highlight.js@^10.4.1, highlight.js@~10.7.0: resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -4560,7 +4487,7 @@ lodash.merge@^4.6.2: resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.0.1, lodash@^4.17.15, lodash@^4.17.21: +lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4620,11 +4547,6 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" -material-colors@^1.2.1: - version "1.2.6" - resolved "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46" - integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg== - memoize-one@^5.1.1: version "5.2.1" resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" @@ -4996,7 +4918,7 @@ postcss-selector-parser@^6.0.11: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== @@ -5047,7 +4969,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.5.10, prop-types@^15.8.1: +prop-types@^15.8.1: version "15.8.1" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -5113,18 +5035,10 @@ re-resizable@^6.9.8: resolved "https://registry.npmjs.org/re-resizable/-/re-resizable-6.9.11.tgz#f356e27877f12d926d076ab9ad9ff0b95912b475" integrity sha512-a3hiLWck/NkmyLvGWUuvkAmN1VhwAz4yOhS6FdMTaxCUVN9joIWkT11wsO68coG/iEYuwn+p/7qAmfQzRhiPLQ== -react-color@^2.19.3: - version "2.19.3" - resolved "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz#ec6c6b4568312a3c6a18420ab0472e146aa5683d" - integrity sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA== - dependencies: - "@icons/material" "^0.2.4" - lodash "^4.17.15" - lodash-es "^4.17.15" - material-colors "^1.2.1" - prop-types "^15.5.10" - reactcss "^1.2.0" - tinycolor2 "^1.4.1" +react-colorful@^5.6.1: + version "5.6.1" + resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.6.1.tgz#7dc2aed2d7c72fac89694e834d179e32f3da563b" + integrity sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw== react-dom@^18.2.0: version "18.2.0" @@ -5283,13 +5197,6 @@ react@^18.2.0: dependencies: loose-envify "^1.1.0" -reactcss@^1.2.0: - version "1.2.3" - resolved "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd" - integrity sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A== - dependencies: - lodash "^4.0.1" - read-cache@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" @@ -5467,11 +5374,6 @@ server-only@^0.0.1: resolved "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz#0f366bb6afb618c37c9255a314535dc412cd1c9e" integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA== -shallowequal@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" - integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -5590,22 +5492,6 @@ strip-json-comments@^3.1.1: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -styled-components@^5.3.6: - version "5.3.11" - resolved "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz#9fda7bf1108e39bf3f3e612fcc18170dedcd57a8" - integrity sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/traverse" "^7.4.5" - "@emotion/is-prop-valid" "^1.1.0" - "@emotion/stylis" "^0.8.4" - "@emotion/unitless" "^0.7.4" - babel-plugin-styled-components ">= 1.12.0" - css-to-react-native "^3.0.0" - hoist-non-react-statics "^3.0.0" - shallowequal "^1.1.0" - supports-color "^5.5.0" - sucrase@^3.32.0: version "3.34.0" resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f" @@ -5619,7 +5505,7 @@ sucrase@^3.32.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" -supports-color@^5.3.0, supports-color@^5.5.0: +supports-color@^5.3.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -5751,11 +5637,6 @@ tiny-invariant@^1.0.6: resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== -tinycolor2@^1.4.1: - version "1.6.0" - resolved "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" - integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== - tmpl@1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"