|
1 | 1 | 'use client'; |
2 | 2 |
|
3 | | -import {Badge, Content, Heading, IllustratedMessage, pressScale, Skeleton, Text} from '@react-spectrum/s2'; |
| 3 | +import {Badge, Content, Heading, IllustratedMessage, pressScale, Text} from '@react-spectrum/s2'; |
4 | 4 | import Checkmark from '@react-spectrum/s2/icons/Checkmark'; |
5 | 5 | import CheckmarkCircle from '@react-spectrum/s2/icons/CheckmarkCircle'; |
6 | | -import {colorSwatch, getColorHexMap, getColorScale} from './color.macro' with {type: 'macro'}; |
| 6 | +import {colorSwatch, getColorScale} from './color.macro' with {type: 'macro'}; |
7 | 7 | import {focusRing, iconStyle, style} from '@react-spectrum/s2/style' with {type: 'macro'}; |
8 | 8 | import {Header, ListBox, ListBoxItem, ListBoxSection} from 'react-aria-components'; |
9 | 9 | import InfoCircle from '@react-spectrum/s2/icons/InfoCircle'; |
10 | 10 | // eslint-disable-next-line monorepo/no-internal-import |
11 | 11 | import NoSearchResults from '@react-spectrum/s2/illustrations/linear/NoSearchResults'; |
12 | | -import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; |
| 12 | +import React, {useCallback, useEffect, useRef, useState} from 'react'; |
13 | 13 | import Similar from '@react-spectrum/s2/icons/Similar'; |
14 | 14 |
|
15 | | -export const colorHexMaps = getColorHexMap(); |
16 | | - |
17 | | -const backgroundColors = [ |
18 | | - 'base', 'layer-1', 'layer-2', 'pasteboard', 'elevated', |
19 | | - 'accent', 'accent-subtle', 'neutral', 'neutral-subdued', 'neutral-subtle', |
20 | | - 'negative', 'negative-subtle', 'informative', 'informative-subtle', |
21 | | - 'positive', 'positive-subtle', 'notice', 'notice-subtle', |
22 | | - 'gray', 'gray-subtle', 'red', 'red-subtle', 'orange', 'orange-subtle', |
23 | | - 'yellow', 'yellow-subtle', 'chartreuse', 'chartreuse-subtle', |
24 | | - 'celery', 'celery-subtle', 'green', 'green-subtle', 'seafoam', 'seafoam-subtle', |
25 | | - 'cyan', 'cyan-subtle', 'blue', 'blue-subtle', 'indigo', 'indigo-subtle', |
26 | | - 'purple', 'purple-subtle', 'fuchsia', 'fuchsia-subtle', 'magenta', 'magenta-subtle', |
27 | | - 'pink', 'pink-subtle', 'turquoise', 'turquoise-subtle', |
28 | | - 'cinnamon', 'cinnamon-subtle', 'brown', 'brown-subtle', |
29 | | - 'silver', 'silver-subtle', 'disabled' |
30 | | -]; |
31 | | - |
32 | | -const textColors = [ |
33 | | - 'accent', 'neutral', 'neutral-subdued', 'negative', 'disabled', |
34 | | - 'heading', 'title', 'body', 'detail', 'code' |
35 | | -]; |
36 | | - |
37 | | -const semanticColorRanges: Record<string, number[]> = { |
38 | | - 'accent-color': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
39 | | - 'informative-color': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
40 | | - 'negative-color': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
41 | | - 'notice-color': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
42 | | - 'positive-color': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600] |
43 | | -}; |
44 | | - |
45 | | -const globalColorRanges: Record<string, number[]> = { |
46 | | - 'gray': [25, 50, 75, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000], |
47 | | - 'blue': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
48 | | - 'red': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
49 | | - 'orange': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
50 | | - 'yellow': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
51 | | - 'chartreuse': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
52 | | - 'celery': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
53 | | - 'green': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
54 | | - 'seafoam': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
55 | | - 'cyan': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
56 | | - 'indigo': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
57 | | - 'purple': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
58 | | - 'fuchsia': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
59 | | - 'magenta': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
60 | | - 'pink': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
61 | | - 'turquoise': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
62 | | - 'brown': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
63 | | - 'silver': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600], |
64 | | - 'cinnamon': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600] |
65 | | -}; |
66 | | - |
67 | | -const semanticColors = Object.entries(semanticColorRanges).flatMap(([scale, ranges]) => |
68 | | - ranges.map(value => ({name: `${scale.replace('-color', '')}-${value}`, section: 'Semantic colors', type: 'backgroundColor'})) |
69 | | -); |
70 | | - |
71 | | -const globalColors = Object.entries(globalColorRanges).flatMap(([scale, ranges]) => |
72 | | - ranges.map(value => ({name: `${scale}-${value}`, section: 'Global colors', type: 'backgroundColor'})) |
73 | | -); |
74 | | - |
75 | | -export const colorSections = [ |
76 | | - { |
77 | | - id: 'background', |
78 | | - name: 'Background colors', |
79 | | - items: backgroundColors.map(name => ({name, section: 'Background colors', type: 'backgroundColor'})) |
80 | | - }, |
81 | | - { |
82 | | - id: 'text', |
83 | | - name: 'Text colors', |
84 | | - items: textColors.map(name => ({name, section: 'Text colors', type: 'color'})) |
85 | | - }, |
86 | | - { |
87 | | - id: 'semantic', |
88 | | - name: 'Semantic colors', |
89 | | - items: semanticColors |
90 | | - }, |
91 | | - { |
92 | | - id: 'global', |
93 | | - name: 'Global colors', |
94 | | - items: globalColors |
95 | | - } |
96 | | -]; |
97 | | - |
98 | 15 | const itemStyle = style({ |
99 | 16 | ...focusRing(), |
100 | 17 | display: 'flex', |
@@ -151,7 +68,7 @@ const headerStyle = style({ |
151 | 68 | marginBottom: 4 |
152 | 69 | }); |
153 | 70 |
|
154 | | -const backgroundSwatches = { |
| 71 | +const backgroundSwatches: Record<string, string> = { |
155 | 72 | 'base': colorSwatch('base'), |
156 | 73 | 'layer-1': colorSwatch('layer-1'), |
157 | 74 | 'layer-2': colorSwatch('layer-2'), |
@@ -211,7 +128,7 @@ const backgroundSwatches = { |
211 | 128 | 'disabled': colorSwatch('disabled') |
212 | 129 | }; |
213 | 130 |
|
214 | | -const textSwatches = { |
| 131 | +const textSwatches: Record<string, string> = { |
215 | 132 | 'accent': colorSwatch('accent', 'color'), |
216 | 133 | 'neutral': colorSwatch('neutral', 'color'), |
217 | 134 | 'neutral-subdued': colorSwatch('neutral-subdued', 'color'), |
@@ -249,7 +166,7 @@ const brownScale = getColorScale('brown'); |
249 | 166 | const silverScale = getColorScale('silver'); |
250 | 167 | const cinnamonScale = getColorScale('cinnamon'); |
251 | 168 |
|
252 | | -const scaleSwatches = { |
| 169 | +const scaleSwatches: Record<string, string> = { |
253 | 170 | ...Object.fromEntries(accentScale), |
254 | 171 | ...Object.fromEntries(informativeScale), |
255 | 172 | ...Object.fromEntries(negativeScale), |
@@ -287,7 +204,11 @@ function CopyInfoMessage() { |
287 | 204 | } |
288 | 205 |
|
289 | 206 | interface ColorSearchViewProps { |
290 | | - filteredItems: typeof colorSections, |
| 207 | + filteredItems: Array<{ |
| 208 | + id: string, |
| 209 | + name: string, |
| 210 | + items: Array<{name: string, section: string, type: string}> |
| 211 | + }>, |
291 | 212 | /** Names of colors that exactly match the searched hex value. */ |
292 | 213 | exactMatches?: Set<string>, |
293 | 214 | /** Names of the closest matching colors when no exact matches exist. */ |
@@ -439,80 +360,3 @@ function ColorItem({item, sectionId, isCopied = false, isBestMatch = false, isEx |
439 | 360 | </ListBoxItem> |
440 | 361 | ); |
441 | 362 | } |
442 | | - |
443 | | -function SkeletonColorItem({item}: {item: {id: string}}) { |
444 | | - const ref = useRef(null); |
445 | | - |
446 | | - return ( |
447 | | - <ListBoxItem |
448 | | - id={item.id} |
449 | | - value={item} |
450 | | - textValue="skeleton" |
451 | | - className={itemStyle} |
452 | | - ref={ref}> |
453 | | - <div |
454 | | - className={swatchStyle} |
455 | | - style={{ |
456 | | - width: '32px', |
457 | | - height: '32px', |
458 | | - backgroundColor: 'var(--s2-gray-200)' |
459 | | - } as React.CSSProperties} /> |
460 | | - <div |
461 | | - className={style({ |
462 | | - maxWidth: 'full', |
463 | | - textOverflow: 'ellipsis', |
464 | | - overflow: 'hidden', |
465 | | - whiteSpace: 'nowrap', |
466 | | - textAlign: 'center' |
467 | | - })}> |
468 | | - <Text styles={style({font: 'ui-sm'})}>Name</Text> |
469 | | - </div> |
470 | | - </ListBoxItem> |
471 | | - ); |
472 | | -} |
473 | | - |
474 | | -export function ColorSearchSkeleton() { |
475 | | - const mockSections = useMemo(() => [ |
476 | | - { |
477 | | - id: 'background', |
478 | | - name: 'Background colors', |
479 | | - items: Array.from({length: 20}, (_, i) => ({id: `skeleton-background-${i}`})) |
480 | | - }, |
481 | | - { |
482 | | - id: 'text', |
483 | | - name: 'Text colors', |
484 | | - items: Array.from({length: 10}, (_, i) => ({id: `skeleton-text-${i}`})) |
485 | | - }, |
486 | | - { |
487 | | - id: 'semantic', |
488 | | - name: 'Semantic colors', |
489 | | - items: Array.from({length: 30}, (_, i) => ({id: `skeleton-semantic-${i}`})) |
490 | | - }, |
491 | | - { |
492 | | - id: 'global', |
493 | | - name: 'Global colors', |
494 | | - items: Array.from({length: 40}, (_, i) => ({id: `skeleton-global-${i}`})) |
495 | | - } |
496 | | - ], []); |
497 | | - |
498 | | - return ( |
499 | | - <Skeleton isLoading> |
500 | | - <div className={style({display: 'flex', flexDirection: 'column', gap: 8})}> |
501 | | - <ListBox |
502 | | - aria-label="Colors loading" |
503 | | - layout="grid" |
504 | | - className={listBoxStyle} |
505 | | - items={mockSections}> |
506 | | - {section => ( |
507 | | - <ListBoxSection id={section.id} className={sectionStyle}> |
508 | | - <Header className={headerStyle}>{section.name}</Header> |
509 | | - {section.items.map(item => ( |
510 | | - <SkeletonColorItem key={item.id} item={item} /> |
511 | | - ))} |
512 | | - </ListBoxSection> |
513 | | - )} |
514 | | - </ListBox> |
515 | | - </div> |
516 | | - </Skeleton> |
517 | | - ); |
518 | | -} |
0 commit comments