1+ import { colord } from "colord" ;
12import { useEffect , useMemo , useRef , useState , type ReactNode } from "react" ;
3+ import { useStore } from "@nanostores/react" ;
24import { computed } from "nanostores" ;
35import { matchSorter } from "match-sorter" ;
46import { isFeatureEnabled } from "@webstudio-is/feature-flags" ;
@@ -19,9 +21,10 @@ import {
1921 properties as propertiesData ,
2022 propertyDescriptions ,
2123} from "@webstudio-is/css-data" ;
22- import { useStore } from "@nanostores/react " ;
24+ import { ROOT_INSTANCE_ID } from "@webstudio-is/sdk " ;
2325import {
2426 hyphenateProperty ,
27+ toValue ,
2528 type StyleProperty ,
2629} from "@webstudio-is/css-engine" ;
2730import {
@@ -33,12 +36,20 @@ import { styleConfigByName } from "../../shared/configs";
3336import { deleteProperty , setProperty } from "../../shared/use-style-data" ;
3437import {
3538 $definedStyles ,
39+ $matchingBreakpoints ,
40+ getDefinedStyles ,
3641 useComputedStyleDecl ,
3742 useComputedStyles ,
3843} from "../../shared/model" ;
3944import { getDots } from "../../shared/style-section" ;
4045import { PropertyInfo } from "../../property-label" ;
4146import { sections } from "../sections" ;
47+ import { ColorPopover } from "../../shared/color-picker" ;
48+ import {
49+ $selectedInstanceSelector ,
50+ $styles ,
51+ $styleSourceSelections ,
52+ } from "~/shared/nano-states" ;
4253
4354// Only here to keep the same section module interface
4455export const properties = [ ] ;
@@ -165,45 +176,41 @@ const AdvancedPropertyLabel = ({ property }: { property: StyleProperty }) => {
165176 styleDecl . source . name === "default" ? "code" : styleDecl . source . name ;
166177 const [ isOpen , setIsOpen ] = useState ( false ) ;
167178 return (
168- < Flex align = "center" >
169- < Tooltip
170- open = { isOpen }
171- onOpenChange = { setIsOpen }
172- // prevent closing tooltip on content click
173- onPointerDown = { ( event ) => event . preventDefault ( ) }
174- triggerProps = { {
175- onClick : ( event ) => {
176- if ( event . altKey ) {
177- event . preventDefault ( ) ;
178- deleteProperty ( property ) ;
179- return ;
180- }
181- setIsOpen ( true ) ;
182- } ,
183- } }
184- content = {
185- < PropertyInfo
186- title = { label }
187- description = { description }
188- styles = { [ styleDecl ] }
189- onReset = { ( ) => {
190- deleteProperty ( property ) ;
191- setIsOpen ( false ) ;
192- } }
193- />
194- }
195- >
196- < Flex shrink gap = { 1 } align = "center" >
197- < Label color = { color } text = "mono" truncate >
198- { label }
199- </ Label >
200- </ Flex >
201- </ Tooltip >
202- </ Flex >
179+ < Tooltip
180+ open = { isOpen }
181+ onOpenChange = { setIsOpen }
182+ // prevent closing tooltip on content click
183+ onPointerDown = { ( event ) => event . preventDefault ( ) }
184+ triggerProps = { {
185+ onClick : ( event ) => {
186+ if ( event . altKey ) {
187+ event . preventDefault ( ) ;
188+ deleteProperty ( property ) ;
189+ return ;
190+ }
191+ setIsOpen ( true ) ;
192+ } ,
193+ } }
194+ content = {
195+ < PropertyInfo
196+ title = { label }
197+ description = { description }
198+ styles = { [ styleDecl ] }
199+ onReset = { ( ) => {
200+ deleteProperty ( property ) ;
201+ setIsOpen ( false ) ;
202+ } }
203+ />
204+ }
205+ >
206+ < Label color = { color } text = "mono" >
207+ { label }
208+ </ Label >
209+ </ Tooltip >
203210 ) ;
204211} ;
205212
206- const $customProperties = computed ( $definedStyles , ( definedStyles ) => {
213+ const $availableCustomProperties = computed ( $definedStyles , ( definedStyles ) => {
207214 const customProperties = new Set < StyleProperty > ( ) ;
208215 for ( const { property } of definedStyles ) {
209216 if ( property . startsWith ( "--" ) ) {
@@ -221,21 +228,41 @@ const AdvancedPropertyValue = ({
221228 property : StyleProperty ;
222229} ) => {
223230 const styleDecl = useComputedStyleDecl ( property ) ;
224- const customProperties = useStore ( $customProperties ) ;
231+ const availableCustomProperties = useStore ( $availableCustomProperties ) ;
225232 const { items } = styleConfigByName ( property ) ;
226233 const inputRef = useRef < HTMLInputElement > ( null ) ;
227234 useEffect ( ( ) => {
228235 if ( autoFocus ) {
229236 inputRef . current ?. focus ( ) ;
230237 }
231238 } , [ autoFocus ] ) ;
239+ const isColor = colord ( toValue ( styleDecl . usedValue ) ) . isValid ( ) ;
232240 return (
233241 < CssValueInputContainer
234242 inputRef = { inputRef }
235243 variant = "chromeless"
236244 size = "2"
237245 text = "mono"
238246 fieldSizing = "content"
247+ prefix = {
248+ isColor && (
249+ < ColorPopover
250+ size = { 1 }
251+ value = { styleDecl . usedValue }
252+ onChange = { ( styleValue ) => {
253+ const options = { isEphemeral : true , listed : true } ;
254+ if ( styleValue ) {
255+ setProperty ( property ) ( styleValue , options ) ;
256+ } else {
257+ deleteProperty ( property , options ) ;
258+ }
259+ } }
260+ onChangeComplete = { ( styleValue ) => {
261+ setProperty ( property ) ( styleValue ) ;
262+ } }
263+ />
264+ )
265+ }
239266 property = { property }
240267 styleSource = { styleDecl . source . name }
241268 keywords = { [
@@ -244,7 +271,7 @@ const AdvancedPropertyValue = ({
244271 value : item . name ,
245272 } ) ) ,
246273 // very basic custom properties autocomplete
247- ...Array . from ( customProperties ) . map ( ( name ) => ( {
274+ ...Array . from ( availableCustomProperties ) . map ( ( name ) => ( {
248275 type : "keyword" as const ,
249276 value : name ,
250277 } ) ) ,
@@ -276,23 +303,46 @@ const initialProperties = new Set<StyleProperty>([
276303 "opacity" ,
277304] ) ;
278305
279- const $advancedProperties = computed ( $definedStyles , ( definedStyles ) => {
280- // All properties used by the panels except the advanced panel
281- const baseProperties = new Set < StyleProperty > ( [ ] ) ;
282- for ( const { properties } of sections . values ( ) ) {
283- for ( const property of properties ) {
284- baseProperties . add ( property ) ;
306+ const $advancedProperties = computed (
307+ [
308+ $selectedInstanceSelector ,
309+ $styleSourceSelections ,
310+ $matchingBreakpoints ,
311+ $styles ,
312+ ] ,
313+ ( instanceSelector , styleSourceSelections , matchingBreakpoints , styles ) => {
314+ if ( instanceSelector === undefined ) {
315+ return [ ] ;
285316 }
286- }
287- const advancedProperties = new Set < StyleProperty > ( initialProperties ) ;
288- for ( const { property, listed } of definedStyles ) {
289- // exclude properties from style panel UI unless edited in advanced section
290- if ( baseProperties . has ( property ) === false || listed ) {
291- advancedProperties . add ( property ) ;
317+ const instanceAndRootSelector =
318+ instanceSelector [ 0 ] === ROOT_INSTANCE_ID
319+ ? instanceSelector
320+ : // prevent showing properties inherited from root
321+ // to not bloat advanced panel
322+ instanceSelector ;
323+ const definedStyles = getDefinedStyles ( {
324+ instanceSelector : instanceAndRootSelector ,
325+ matchingBreakpoints,
326+ styleSourceSelections,
327+ styles,
328+ } ) ;
329+ // All properties used by the panels except the advanced panel
330+ const baseProperties = new Set < StyleProperty > ( [ ] ) ;
331+ for ( const { properties } of sections . values ( ) ) {
332+ for ( const property of properties ) {
333+ baseProperties . add ( property ) ;
334+ }
292335 }
336+ const advancedProperties = new Set < StyleProperty > ( initialProperties ) ;
337+ for ( const { property, listed } of definedStyles ) {
338+ // exclude properties from style panel UI unless edited in advanced section
339+ if ( baseProperties . has ( property ) === false || listed ) {
340+ advancedProperties . add ( property ) ;
341+ }
342+ }
343+ return Array . from ( advancedProperties ) . reverse ( ) ;
293344 }
294- return Array . from ( advancedProperties ) . reverse ( ) ;
295- } ) ;
345+ ) ;
296346
297347export const Section = ( ) => {
298348 const [ isAdding , setIsAdding ] = useState ( false ) ;
@@ -320,7 +370,7 @@ export const Section = () => {
320370 ) }
321371 < Box >
322372 { advancedProperties . map ( ( property ) => (
323- < Flex key = { property } wrap = "wrap" align = "center" >
373+ < Flex key = { property } wrap = "wrap" align = "center" justify = "start" >
324374 < AdvancedPropertyLabel property = { property } />
325375 < Text > :</ Text >
326376 < AdvancedPropertyValue
0 commit comments