@@ -100,6 +100,7 @@ const ANCHOR_SIDES: AnchorSideKeyword[] = [
100
100
'center' ,
101
101
] ;
102
102
103
+ const POSITION_ANCHOR_DATASET_KEY = 'polyfillPositionAnchorName' ;
103
104
export type AnchorSide = AnchorSideKeyword | number ;
104
105
105
106
export type AnchorSize =
@@ -221,6 +222,10 @@ function isIdentifier(node: csstree.CssNode): node is csstree.Identifier {
221
222
return Boolean ( node . type === 'Identifier' && node . name ) ;
222
223
}
223
224
225
+ function getDeclarationValue ( node : DeclarationWithValue ) {
226
+ return ( node . value . children . first as csstree . Identifier ) . name ;
227
+ }
228
+
224
229
function isPercentage ( node : csstree . CssNode ) : node is csstree . Percentage {
225
230
return Boolean ( node . type === 'Percentage' && node . value ) ;
226
231
}
@@ -249,6 +254,12 @@ export function isBoxAlignmentProp(
249
254
return BOX_ALIGNMENT_PROPS . includes ( property as BoxAlignmentProperty ) ;
250
255
}
251
256
257
+ function isPositionAnchorDeclaration (
258
+ node : csstree . CssNode ,
259
+ ) : node is DeclarationWithValue {
260
+ return node . type === 'Declaration' && node . property === 'position-anchor' ;
261
+ }
262
+
252
263
function parseAnchorFn (
253
264
node : csstree . FunctionNode ,
254
265
replaceCss ?: boolean ,
@@ -338,7 +349,7 @@ function getAnchorNameData(node: csstree.CssNode, rule?: csstree.Raw) {
338
349
node . value . children . first &&
339
350
rule ?. value
340
351
) {
341
- const name = ( node . value . children . first as csstree . Identifier ) . name ;
352
+ const name = getDeclarationValue ( node ) ;
342
353
return { name, selector : rule . value } ;
343
354
}
344
355
return { } ;
@@ -394,12 +405,25 @@ function getAnchorFunctionData(
394
405
return { } ;
395
406
}
396
407
408
+ function getPositionAnchorData ( node : csstree . CssNode , rule ?: csstree . Raw ) {
409
+ if ( isPositionAnchorDeclaration ( node ) && rule ?. value ) {
410
+ const targets = document . querySelectorAll ( rule . value ) ;
411
+ const name = getDeclarationValue ( node ) ;
412
+
413
+ for ( const targetEl of targets ) {
414
+ ( targetEl as HTMLElement ) . dataset [ POSITION_ANCHOR_DATASET_KEY ] = name ;
415
+ }
416
+ return { name, selector : rule . value } ;
417
+ }
418
+ return { } ;
419
+ }
420
+
397
421
function getPositionFallbackDeclaration (
398
422
node : csstree . Declaration ,
399
423
rule ?: csstree . Raw ,
400
424
) {
401
425
if ( isFallbackDeclaration ( node ) && node . value . children . first && rule ?. value ) {
402
- const name = ( node . value . children . first as csstree . Identifier ) . name ;
426
+ const name = getDeclarationValue ( node ) ;
403
427
return { name, selector : rule . value } ;
404
428
}
405
429
return { } ;
@@ -452,6 +476,8 @@ async function getAnchorEl(
452
476
return await validatedForPositioning ( targetEl , [
453
477
`#${ CSS . escape ( anchorAttr ) } ` ,
454
478
] ) ;
479
+ } else if ( targetEl . dataset [ POSITION_ANCHOR_DATASET_KEY ] ) {
480
+ anchorName = targetEl . dataset [ POSITION_ANCHOR_DATASET_KEY ] ;
455
481
}
456
482
}
457
483
const anchorSelectors = anchorName ? anchorNames [ anchorName ] ?? [ ] : [ ] ;
@@ -571,6 +597,17 @@ export async function parseCSS(styleData: StyleData[]) {
571
597
}
572
598
}
573
599
600
+ // Parse `position-anchor` data
601
+ const { name : positionAnchorName , selector : positionAnchorSelector } =
602
+ getPositionAnchorData ( node , rule ) ;
603
+ if ( positionAnchorName && positionAnchorSelector ) {
604
+ if ( anchorNames [ positionAnchorName ] ) {
605
+ anchorNames [ positionAnchorName ] . push ( positionAnchorSelector ) ;
606
+ } else {
607
+ anchorNames [ positionAnchorName ] = [ positionAnchorSelector ] ;
608
+ }
609
+ }
610
+
574
611
// Parse `anchor()` function
575
612
const {
576
613
prop,
0 commit comments