10881088 height : 0 ;
10891089 }
10901090
1091+ .token-beam {
1092+ margin-top : 10vmin ;
1093+ font-size : 1.4em ;
1094+ }
1095+ .token-beam p {
1096+ font-size : .8em ;
1097+ }
1098+ .token-beam__title + .l-sec__controls {
1099+ margin-top : 0 ;
1100+ }
1101+ .token-beam__token {
1102+ cursor : pointer;
1103+ user-select : all;
1104+ text-decoration : underline;
1105+ padding-top : 0.25em ;
1106+ font-size : .9rem ;
1107+ display : block;
1108+ }
1109+ .token-beam__token : hover {
1110+ border-color : var (--c0 );
1111+ text-decoration : none;
1112+ }
1113+ .token-beam__status {
1114+ font-style : normal;
1115+ }
1116+ .token-beam__status [data-state = "paired" ] {
1117+ opacity : 1 ;
1118+ color : var (--c0 );
1119+ }
1120+ .token-beam__status [data-state = "error" ] {
1121+ opacity : 1 ;
1122+ color : red;
1123+ }
1124+
10911125 .support {
10921126 font-size : 1.4em ;
10931127 margin-top : 10vmin ;
@@ -1870,6 +1904,28 @@ <h2 id="export" class="hidden">Export</h2>
18701904
18711905 </ div >
18721906
1907+ < div class ="token-beam ">
1908+ < h2 class ="subtitle token-beam__title "> Export</ h2 >
1909+
1910+ < div class ="l-sec__controls ">
1911+ < label >
1912+ < span >
1913+ < span class ="t "> Token Beam</ span >
1914+ < em class ="token-beam__status " data-tb-status > </ em >
1915+ </ span >
1916+ < i >
1917+ < span class ="token-beam__token " data-tb-token title ="Click to copy "> connecting…</ span >
1918+ </ i >
1919+ </ label >
1920+ </ div >
1921+ < p >
1922+ Beam your "< strong class ="t "> poline</ strong > " palette directly into < a
1923+ href ="https://github.com/meodai/token-beam/releases/ " target ="_blank " rel ="noopener "> Figma, Aseprite, Blender or
1924+ Adobe XD</ a > . Copy the session token below, paste it in your design tool's Token Beam plugin and every color
1925+ update syncs instantly.
1926+ </ p >
1927+ </ div >
1928+
18731929 < div class ="support ">
18741930 < h2 class ="subtitle support__title "> Support</ h2 >
18751931 < p >
@@ -2531,6 +2587,10 @@ <h2 class="export__title">${paletteTitle}</h2>
25312587 } , 100 ) ;
25322588
25332589 updateUI ( ) ;
2590+
2591+ document . dispatchEvent (
2592+ new CustomEvent ( 'poline:colors' , { detail : { colors } } )
2593+ ) ;
25342594 }
25352595
25362596 updateSVG ( ) ;
@@ -3302,6 +3362,82 @@ <h2 class="export__title">${paletteTitle}</h2>
33023362 } , 1500 ) ;
33033363 } , 2000 ) ;
33043364 </ script >
3305- </ body >
33063365
3307- </ html >
3366+ < script type ="module ">
3367+ import { SourceSession , createCollection } from 'https://esm.sh/token-beam@1.9.0' ;
3368+
3369+ const $token = document . querySelector ( '[data-tb-token]' ) ;
3370+ const $status = document . querySelector ( '[data-tb-status]' ) ;
3371+ let session = null ;
3372+ let lastColors = [ ] ;
3373+
3374+ function setStatus ( text , state = '' ) {
3375+ $status . textContent = text ;
3376+ $status . dataset . state = state ;
3377+ }
3378+
3379+ function syncColors ( colors ) {
3380+ if ( ! session || ! colors . length ) return ;
3381+ const tokens = { } ;
3382+ colors . forEach ( ( hex , i ) => {
3383+ tokens [ `${ String ( i + 1 ) . padStart ( 2 , '0' ) } ` ] = hex ;
3384+ } ) ;
3385+ session . sync ( createCollection ( `Poline` , tokens ) ) ;
3386+ }
3387+
3388+ async function initTokenBeam ( ) {
3389+ session = new SourceSession ( {
3390+ clientType : 'web' ,
3391+ origin : 'Poline Color Palette' ,
3392+ } ) ;
3393+
3394+ session . on ( 'paired' , ( { sessionToken } ) => {
3395+ $token . textContent = sessionToken ;
3396+ $token . title = 'Click to copy' ;
3397+ setStatus ( 'waiting for plugin…' , '' ) ;
3398+ } ) ;
3399+
3400+ session . on ( 'peer-connected' , ( { clientType } ) => {
3401+ setStatus ( `connected to ${ clientType } ` , 'paired' ) ;
3402+ syncColors ( lastColors ) ;
3403+ } ) ;
3404+
3405+ session . on ( 'peer-disconnected' , ( ) => {
3406+ setStatus ( 'plugin disconnected' , '' ) ;
3407+ } ) ;
3408+
3409+ session . on ( 'error' , ( { message } ) => {
3410+ setStatus ( message , 'error' ) ;
3411+ } ) ;
3412+
3413+ session . on ( 'disconnected' , ( ) => {
3414+ setStatus ( 'reconnecting…' , '' ) ;
3415+ } ) ;
3416+
3417+ await session . connect ( ) ;
3418+ }
3419+
3420+ $token . addEventListener ( 'click' , ( ) => {
3421+ const text = $token . textContent ;
3422+ if ( text && text . startsWith ( 'beam://' ) ) {
3423+ navigator . clipboard . writeText ( text ) ;
3424+ const prev = $status . textContent ;
3425+ const prevState = $status . dataset . state ;
3426+ setStatus ( 'copied!' , '' ) ;
3427+ setTimeout ( ( ) => setStatus ( prev , prevState ) , 1500 ) ;
3428+ }
3429+ } ) ;
3430+
3431+ document . addEventListener ( 'poline:colors' , ( e ) => {
3432+ lastColors = e . detail . colors ;
3433+ if ( ! session || session . getState ( ) !== 'paired' ) return ;
3434+ syncColors ( lastColors ) ;
3435+ } ) ;
3436+
3437+ initTokenBeam ( ) . catch ( err => {
3438+ console . error ( '[token-beam]' , err ) ;
3439+ setStatus ( 'connection failed' , 'error' ) ;
3440+ } ) ;
3441+ </ script >
3442+ </ body >
3443+ </ html >
0 commit comments