@@ -186,6 +186,7 @@ var Anchor = Anchor || (() => {
186186 ...Object . keys ( ALIAS_MAP ) ,
187187 'remove' , 'lock' , 'unlock' , 'center' , 'update' , 'info' ,
188188 'track' , 'untrack' , 'retrack' ,
189+ 'chain' ,
189190 'ignore-selected' , 'persist' ,
190191 'config' ,
191192 '--help' ,
@@ -1132,6 +1133,9 @@ var Anchor = Anchor || (() => {
11321133 `<b>${ CMD_TOKEN } center [ignore-selected] [child_id...]</b>` ,
11331134 'Snap child(ren) to anchor centre (0 offset, 0 rotation, 1:1 scale).' ,
11341135 '' ,
1136+ `<b>${ CMD_TOKEN } chain [component flags] [ignore-selected] [child_id...]</b>` ,
1137+ 'Mutually anchor tokens in a ring (A\u2192B, B\u2192C, C\u2192A). Move any one, all follow.' ,
1138+ '' ,
11351139 `<b>${ CMD_TOKEN } update [ignore-selected] [child_id...]</b>` ,
11361140 'Force immediate transform sync.' ,
11371141 '' ,
@@ -1507,7 +1511,7 @@ var Anchor = Anchor || (() => {
15071511 // Only skip the first otherArg as a potential anchor ID when we're
15081512 // establishing a new anchor relationship AND it's actually a valid graphic.
15091513 // If there's no valid graphic as the first arg, all otherArgs are child IDs.
1510- const ACTION_FLAGS = [ 'remove' , 'lock' , 'unlock' , 'center' , 'update' , 'info' , 'track' , 'untrack' , 'retrack' ] ;
1514+ const ACTION_FLAGS = [ 'remove' , 'lock' , 'unlock' , 'center' , 'update' , 'info' , 'track' , 'untrack' , 'retrack' , 'chain' ] ;
15111515 const hasAction = ACTION_FLAGS . some ( f => flags . has ( f ) ) ;
15121516 const isNewAnchor = ! hasAction && ( Object . keys ( FLAG_EXPANSIONS ) . some ( f => flags . has ( f ) ) || flags . size === 0 ) ;
15131517 const firstArgIsAnchor = isNewAnchor &&
@@ -1640,6 +1644,21 @@ var Anchor = Anchor || (() => {
16401644 } ) ;
16411645 }
16421646
1647+ // Chain — circular anchor ring: A→B, B→C, C→A
1648+ if ( flags . has ( 'chain' ) ) {
1649+ const comps = resolveComponents ( flags ) ;
1650+ const ids = resolveChildIds ( msg , flags , otherArgs ) ;
1651+ if ( ids . length < 2 ) {
1652+ reply ( msg , 'Error' , 'Chain requires at least 2 tokens.' ) ;
1653+ } else {
1654+ for ( var i = 0 ; i < ids . length ; i ++ ) {
1655+ var nextIdx = ( i + 1 ) % ids . length ;
1656+ anchorObj ( ids [ i ] , ids [ nextIdx ] , comps ) ;
1657+ }
1658+ reply ( msg , 'Info' , 'Chain-linked ' + ids . length + ' tokens in a ring.' ) ;
1659+ }
1660+ }
1661+
16431662 // Info
16441663 if ( flags . has ( 'info' ) ) {
16451664 if ( childIds . length > 0 ) {
0 commit comments