11'use client' ;
22
33import { Autocomplete , GridLayout , ListBox , ListBoxItem , Size , useFilter , Virtualizer } from 'react-aria-components' ;
4+ // eslint-disable-next-line monorepo/no-internal-import
5+ import Checkmark from '@react-spectrum/s2/illustrations/gradient/generic1/Checkmark' ;
46import { Content , Heading , IllustratedMessage , pressScale , ProgressCircle , Radio , RadioGroup , SearchField , SegmentedControl , SegmentedControlItem , Text , UNSTABLE_ToastQueue as ToastQueue } from '@react-spectrum/s2' ;
5- import { focusRing , style } from '@react-spectrum/s2/style' with { type : 'macro' } ;
7+ import { focusRing , iconStyle , style } from '@react-spectrum/s2/style' with { type : 'macro' } ;
68// @ts -ignore
79import Gradient from '@react-spectrum/s2/icons/Gradient' ;
810import { illustrationAliases } from './illustrationAliases.js' ;
11+ import InfoCircle from '@react-spectrum/s2/icons/InfoCircle' ;
912// eslint-disable-next-line monorepo/no-internal-import
1013import NoSearchResults from '@react-spectrum/s2/illustrations/linear/NoSearchResults' ;
1114import Polygon4 from '@react-spectrum/s2/icons/Polygon4' ;
12- import React , { Suspense , use , useCallback , useRef , useState } from 'react' ;
15+ import React , { Suspense , use , useCallback , useEffect , useRef , useState } from 'react' ;
1316
1417type IllustrationItemType = {
1518 id : string ,
@@ -22,7 +25,7 @@ const itemStyle = style({
2225 backgroundColor : {
2326 default : 'gray-50' ,
2427 isHovered : 'gray-100' ,
25- isFocused : 'gray-100' ,
28+ isFocusVisible : 'gray-100' ,
2629 isSelected : 'neutral'
2730 } ,
2831 font : 'ui-sm' ,
@@ -77,6 +80,7 @@ export function IllustrationCards() {
7780 < Radio value = "generic2" > Generic 2</ Radio >
7881 </ RadioGroup >
7982 ) }
83+ < CopyInfoMessage />
8084 < Suspense fallback = { < Loading /> } >
8185 < IllustrationList variant = { variant } gradientStyle = { gradientStyle } />
8286 </ Suspense >
@@ -93,19 +97,48 @@ function Loading() {
9397 ) ;
9498}
9599
96- let handleCopyImport = ( id : string , variant : string , gradientStyle : string ) => {
97- let importText = variant === 'gradient' ?
98- `import ${ id } from '@react-spectrum/s2/illustrations/gradient/${ gradientStyle } /${ id } ';` :
99- `import ${ id } from '@react-spectrum/s2/illustrations/linear/${ id } ';` ;
100- navigator . clipboard . writeText ( importText ) . then ( ( ) => {
101- // noop
102- } ) . catch ( ( ) => {
103- ToastQueue . negative ( 'Failed to copy import statement.' ) ;
104- } ) ;
105- } ;
100+ function CopyInfoMessage ( ) {
101+ return (
102+ < div className = { style ( { display : 'flex' , alignItems : 'center' , justifyContent : 'center' , gap : 4 } ) } >
103+ < InfoCircle styles = { iconStyle ( { size : 'XS' } ) } />
104+ < span className = { style ( { font : 'ui' } ) } > Press an item to copy its import statement</ span >
105+ </ div >
106+ ) ;
107+ }
108+
109+ function useCopyImport ( variant : string , gradientStyle : string ) {
110+ let [ copiedId , setCopiedId ] = useState < string | null > ( null ) ;
111+ let timeout = useRef < ReturnType < typeof setTimeout > | null > ( null ) ;
112+
113+ useEffect ( ( ) => {
114+ return ( ) => {
115+ if ( timeout . current ) {
116+ clearTimeout ( timeout . current ) ;
117+ }
118+ } ;
119+ } , [ ] ) ;
120+
121+ let handleCopyImport = useCallback ( ( id : string ) => {
122+ if ( timeout . current ) {
123+ clearTimeout ( timeout . current ) ;
124+ }
125+ let importText = variant === 'gradient' ?
126+ `import ${ id } from '@react-spectrum/s2/illustrations/gradient/${ gradientStyle } /${ id } ';` :
127+ `import ${ id } from '@react-spectrum/s2/illustrations/linear/${ id } ';` ;
128+ navigator . clipboard . writeText ( importText ) . then ( ( ) => {
129+ setCopiedId ( id ) ;
130+ timeout . current = setTimeout ( ( ) => setCopiedId ( null ) , 2000 ) ;
131+ } ) . catch ( ( ) => {
132+ ToastQueue . negative ( 'Failed to copy import statement.' ) ;
133+ } ) ;
134+ } , [ variant , gradientStyle ] ) ;
135+
136+ return { copiedId, handleCopyImport} ;
137+ }
106138
107139function IllustrationList ( { variant, gradientStyle} ) {
108140 let items = use ( loadIllustrations ( variant , gradientStyle ) ) ;
141+ let { copiedId, handleCopyImport} = useCopyImport ( variant , gradientStyle ) ;
109142 return (
110143 < Virtualizer
111144 layout = { GridLayout }
@@ -119,7 +152,8 @@ function IllustrationList({variant, gradientStyle}) {
119152 aria-label = "Illustrations"
120153 items = { items }
121154 layout = "grid"
122- onAction = { ( item ) => handleCopyImport ( item . toString ( ) , variant , gradientStyle ) }
155+ onAction = { ( item ) => handleCopyImport ( item . toString ( ) ) }
156+ dependencies = { [ copiedId ] }
123157 className = { style ( { height : 560 , width : '100%' , maxHeight : '100%' , overflow : 'auto' , scrollPaddingY : 4 } ) }
124158 renderEmptyState = { ( ) => (
125159 < IllustratedMessage styles = { style ( { marginX : 'auto' , marginY : 32 } ) } >
@@ -132,25 +166,25 @@ function IllustrationList({variant, gradientStyle}) {
132166 </ Content >
133167 </ IllustratedMessage >
134168 ) } >
135- { ( item : IllustrationItemType ) => < IllustrationItem item = { item } /> }
169+ { ( item : IllustrationItemType ) => < IllustrationItem item = { item } isCopied = { copiedId === item . id } /> }
136170 </ ListBox >
137171 </ Virtualizer >
138172 ) ;
139173}
140174
141- function IllustrationItem ( { item} : { item : IllustrationItemType } ) {
175+ function IllustrationItem ( { item, isCopied = false } : { item : IllustrationItemType , isCopied ?: boolean } ) {
142176 let Illustration = item . Component ;
143177 let ref = useRef ( null ) ;
144178 return (
145179 < ListBoxItem id = { item . id } value = { item } textValue = { item . id } className = { itemStyle } ref = { ref } style = { pressScale ( ref ) } >
146- < Illustration />
180+ { isCopied ? < Checkmark /> : < Illustration /> }
147181 < div
148182 className = { style ( {
149183 display : 'flex' ,
150184 alignItems : 'center' ,
151185 padding : 4
152186 } ) } >
153- { item . id }
187+ { isCopied ? 'Copied!' : item . id }
154188 </ div >
155189 </ ListBoxItem >
156190 ) ;
0 commit comments