.net - Can I use the same editor for Control.Anchor property for my own user control's designer support? - TagMerge
5Can I use the same editor for Control.Anchor property for my own user control's designer support?Can I use the same editor for Control.Anchor property for my own user control's designer support?

Can I use the same editor for Control.Anchor property for my own user control's designer support?

Asked 1 years ago
2
5 answers

I used .NET Reflector to find the answer:

[Flags, 
Editor("System.Windows.Forms.Design.AnchorEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
public enum AnchorStyles

Source: link

1

HTML

<a href="https://www.mozilla.com">
  Mozilla
</a>

HTML

<a href="//example.com">Scheme-relative URL</a>
<a href="/en-US/docs/Web/HTML">Origin-relative URL</a>
<a href="./p">Directory-relative URL</a>

<a href="//example.com">Scheme-relative URL</a> <a href="/en-US/docs/Web/HTML">Origin-relative URL</a> <a href="./p">Directory-relative URL</a>

a { display: block; margin-bottom: 0.5em }

<!-- <a> element links to the section below -->

<a href="#Section_further_down"> Jump to the heading below </a>

<!-- Heading to link to --> <h2 id="Section_further_down">Section further down</h2>

To create links that open in the user's email program to let them send a new message, use the mailto: scheme:

<a href="mailto:nowhere@mozilla.org">Send email to nowhere</a>

<a href="tel:+49.157.0156">+49 157 0156</a>
<a href="tel:+1(555)5309">(555) 5309</a>

HTML

Paint by holding down the mouse button and moving it. <a href="" download="my_painting.png">Download my painting</a>

<canvas width="300" height="300"></canvas>

CSS

html {
  font-family: sans-serif;
}
canvas {
  background: #fff;
  border: 1px dashed;
}
a {
  display: inline-block;
  background: #69c;
  color: #fff;
  padding: 5px 10px;
}

JavaScript

var canvas = document.querySelector('canvas'),
    c = canvas.getContext('2d');
c.fillStyle = 'hotpink';

function draw(x, y) {
  if (isDrawing) {
    c.beginPath();
    c.arc(x, y, 10, 0, Math.PI*2);
    c.closePath();
    c.fill();
  }
}

canvas.addEventListener('mousemove', event =>
  draw(event.offsetX, event.offsetY)
);
canvas.addEventListener('mousedown', () => isDrawing = true);
canvas.addEventListener('mouseup', () => isDrawing = false);

document.querySelector('a').addEventListener('click', event =>
  event.target.href = canvas.toDataURL()
);

A sadly common mistake is to only link the words “click here” or “here”:

Learn more about our products <a href="/products">here</a>.

Luckily, this is an easy fix, and it’s actually shorter than the inaccessible version!

Learn more <a href="/products">about our products</a>.

Link that opens a new tab/window

<a target="_blank" href="https://www.wikipedia.org">
  Wikipedia (opens in new tab)
</a>

Link to a non-HTML resource

<a href="2017-annual-report.ppt">
  2017 Annual Report (PowerPoint)
</a>

If an icon is used to signify link behavior, make sure it has alt text:

<a  target="_blank" href="https://www.wikipedia.org">
  Wikipedia
  <img alt="(opens in new tab)" src="newtab.svg">
</a>

<a href="2017-annual-report.ppt">
  2017 Annual Report
  <img alt="(PowerPoint file)" src="ppt-icon.svg">
</a>

A skip link is a link placed as early as possible in <body> content that points to the beginning of the page's main content. Usually, CSS hides a skip link offscreen until focused.

<body>
  <a href="#content" class="skip-link">Skip to main content</a>

  <header>
    …
  </header>

  <main id="content"> </main> <!-- The skip link jumps to here -->

</body>

<body> <a href="#content" class="skip-link">Skip to main content</a> <header> … </header> <main id="content"> </main> <!-- The skip link jumps to here --> </body>

.skip-link {
  position: absolute;
  top: -3em;
  background: #fff;
}
.skip-link:focus {
  top: 0;
}

Source: link

1

<a id="anchor-name">The  name where you want to jump</a>

<a href="#anchor-name">Jump to the part of the page with the “anchor-name” id </a>

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
    .main-content {
      height: 100vh;
      text-align: justify;
    }
    </style>
  </head>
  <body>
    <h2 id="Lorem_Ipsum">Lorem Ipsum</h2>
    <p class="main-content">
      Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.
    

Go to the <a href="#Lorem_Ipsum">top</a>.

</body> </html>

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
    .main-content {
      height: 100vh;
      text-align: justify;
    }
    h2 {
      color: #1c87c9;
    }
    h2:target {
      color: white;
      background: #1c87c9;
    }
    </style>
  </head>
  <body>
    <h2 id="Lorem_Ipsum">Lorem Ipsum</h2>
    <div class="main-content ">
      

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

</div>

Go to the <a href="#Lorem_Ipsum">top</a>.

</body> </html>

<a href="/learn-html/html-links.html#html_links">Go to the HTML Links in our website.</a>

<a href="https://en.wikipedia.org/wiki/Main_Page#wikipedia">Go to the main page of Wikipedia .</a>

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <h2 id="Lorem_Ipsum">Lorem Ipsum</h2>
    

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

<a href="/learn-html/html-links.html#html_links">Go to the HTML Links in our website.</a>

<a href="https://en.wikipedia.org/wiki/Main_Page#wikipedia">Go to the main page of Wikipedia.</a>

</body> </html>

Source: link

1

For instance, we can check the current network (and other) configuration with this command:

solana config get

# output
Config File: /Users/user/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: /Users/user/.config/solana/id.json
Commitment: confirmed

We can change the network like so:

# set to localhost
solana config set --url localhost

# set to devnet
solana config set --url devnet

We can also use the CLI to see our current local wallet address:

solana address

And then get the full details about an account:

solana account <address from above>

Next let's airdrop some tokens. To do so, first switch to the local network, as this is where we will be working to start off with:

solana config set --url localhost

Next, start the local network. This is going to be a local Solana node that we can deploy to for testing:

solana-test-validator

Once the local network is running, you can airdrop tokens to your account. With the network running, open a separate window and run the following command:

solana airdrop 100

You can the check the balance of your wallet:

solana balance

# or

solana balance <address>

To get started, initialize a new anchor project and change into the new directory:

anchor init mysolanaapp --javascript

cd mysolanaapp

Anchor uses, and enables us to write, an eDSL (embedded DSL) that abstracts away many of the more complex low level operations you'd typically need to do if you were using Solana & Rust without it, making it more approachable for me.

// programs/src/lib.rs
use anchor_lang::prelude::*;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
pub mod mysolanaapp {
    use super::*;
    pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize {}

To compile this program, we can run the Anchor build command:

anchor build

The test should look like this:

const anchor = require('@project-serum/anchor');

describe('mysolanaapp', () => {
  // Configure the client to use the local cluster.
  anchor.setProvider(anchor.Provider.env());

  it('Is initialized!', async () => {
    const program = anchor.workspace.Mysolanaapp;
    const tx = await program.rpc.initialize();
    console.log("Your transaction signature", tx);
  });
});

Once we have these two things, we can start calling functions in our program. For example, in our program we have an initialize function. In our test, you'll see we can invoke that function directly using program.rpc.functionName:

const tx = await program.rpc.initialize();

We can now test the program by running the test script:

anchor test

The first thing we need to do is open programs/mysolanaapp/src/lib.rs and update it with the following code:

use anchor_lang::prelude::*;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
mod mysolanaapp {
    use super::*;

    pub fn create(ctx: Context<Create>) -> ProgramResult {
        let base_account = &mut ctx.accounts.base_account;
        base_account.count = 0;
        Ok(())
    }

    pub fn increment(ctx: Context<Increment>) -> ProgramResult {
        let base_account = &mut ctx.accounts.base_account;
        base_account.count += 1;
        Ok(())
    }
}

// Transaction instructions
#[derive(Accounts)]
pub struct Create<'info> {
    #[account(init, payer = user, space = 16 + 16)]
    pub base_account: Account<'info, BaseAccount>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program <'info, System>,
}

// Transaction instructions
#[derive(Accounts)]
pub struct Increment<'info> {
    #[account(mut)]
    pub base_account: Account<'info, BaseAccount>,
}

// An account that goes inside a transaction instruction
#[account]
pub struct BaseAccount {
    pub count: u64,
}

To build the program:

anchor build

Next, let's write a test that uses this counter program. To do so, open tests/mysolanaapp.js and update with the following code:

const assert = require("assert");
const anchor = require("@project-serum/anchor");
const { SystemProgram } = anchor.web3;

describe("mysolanaapp", () => {
  /* create and set a Provider */
  const provider = anchor.Provider.env();
  anchor.setProvider(provider);
  const program = anchor.workspace.Mysolanaapp;
  it("Creates a counter)", async () => {
    /* Call the create function via RPC */
    const baseAccount = anchor.web3.Keypair.generate();
    await program.rpc.create({
      accounts: {
        baseAccount: baseAccount.publicKey,
        user: provider.wallet.publicKey,
        systemProgram: SystemProgram.programId,
      },
      signers: [baseAccount],
    });

    /* Fetch the account and check the value of count */
    const account = await program.account.baseAccount.fetch(baseAccount.publicKey);
    console.log('Count 0: ', account.count.toString())
    assert.ok(account.count.toString() == 0);
    _baseAccount = baseAccount;

  });

  it("Increments the counter", async () => {
    const baseAccount = _baseAccount;

    await program.rpc.increment({
      accounts: {
        baseAccount: baseAccount.publicKey,
      },
    });

    const account = await program.account.baseAccount.fetch(baseAccount.publicKey);
    console.log('Count 1: ', account.count.toString())
    assert.ok(account.count.toString() == 1);
  });
});

Before we continue to test and deploy the program, we want to get the dynamically generated Program ID that was generated by the build. We need this ID to use in the Rust program to replace the placeholder ID we set up when we created the project. To get this ID, we can run the following command:

solana address -k target/deploy/mysolanaapp-keypair.json

We can now update the program IDs in lib.rs:

// mysolanaapp/src/lib.rs

declare_id!("your-program-id");

And in Anchor.toml:

# Anchor.toml
[programs.localnet]
mysolanaapp = "your-program-id"

Next, run the test:

anchor test

We can now deploy the program. Be sure that solana-test-validator is running:

anchor deploy

In the root of the Anchor project, create a new react app to overwrite the existing app directory:

npx create-react-app app

Next, install the dependencies we'll need for Anchor and Solana Web3:

cd app

npm install @project-serum/anchor @solana/web3.js

We'll also be using Solana Wallet Adapter to handle connecting the user's Solana wallet. Let's install those dependencies as well:

npm install @solana/wallet-adapter-react \
@solana/wallet-adapter-react-ui @solana/wallet-adapter-wallets \
@solana/wallet-adapter-base

If you want a script like this, you can do it in just a couple of lines of code:

// copyIdl.js
const fs = require('fs');
const idl = require('./target/idl/mysolanaapp.json');

fs.writeFileSync('./app/src/idl.json', JSON.stringify(idl));

Next, open app/src/App.js and update it with the following:

import './App.css';
import { useState } from 'react';
import { Connection, PublicKey } from '@solana/web3.js';
import {
  Program, Provider, web3
} from '@project-serum/anchor';
import idl from './idl.json';

import { getPhantomWallet } from '@solana/wallet-adapter-wallets';
import { useWallet, WalletProvider, ConnectionProvider } from '@solana/wallet-adapter-react';
import { WalletModalProvider, WalletMultiButton } from '@solana/wallet-adapter-react-ui';
require('@solana/wallet-adapter-react-ui/styles.css');

const wallets = [
  /* view list of available wallets at https://github.com/solana-labs/wallet-adapter#wallets */
  getPhantomWallet()
]

const { SystemProgram, Keypair } = web3;
/* create an account  */
const baseAccount = Keypair.generate();
const opts = {
  preflightCommitment: "processed"
}
const programID = new PublicKey(idl.metadata.address);

function App() {
  const [value, setValue] = useState(null);
  const wallet = useWallet();

  async function getProvider() {
    /* create the provider and return it to the caller */
    /* network set to local network for now */
    const network = "http://127.0.0.1:8899";
    const connection = new Connection(network, opts.preflightCommitment);

    const provider = new Provider(
      connection, wallet, opts.preflightCommitment,
    );
    return provider;
  }

  async function createCounter() {    
    const provider = await getProvider()
    /* create the program interface combining the idl, program ID, and provider */
    const program = new Program(idl, programID, provider);
    try {
      /* interact with the program via rpc */
      await program.rpc.create({
        accounts: {
          baseAccount: baseAccount.publicKey,
          user: provider.wallet.publicKey,
          systemProgram: SystemProgram.programId,
        },
        signers: [baseAccount]
      });

      const account = await program.account.baseAccount.fetch(baseAccount.publicKey);
      console.log('account: ', account);
      setValue(account.count.toString());
    } catch (err) {
      console.log("Transaction error: ", err);
    }
  }

  async function increment() {
    const provider = await getProvider();
    const program = new Program(idl, programID, provider);
    await program.rpc.increment({
      accounts: {
        baseAccount: baseAccount.publicKey
      }
    });

    const account = await program.account.baseAccount.fetch(baseAccount.publicKey);
    console.log('account: ', account);
    setValue(account.count.toString());
  }

  if (!wallet.connected) {
    /* If the user's wallet is not connected, display connect wallet button. */
    return (
      <div style={{ display: 'flex', justifyContent: 'center', marginTop:'100px' }}>
        <WalletMultiButton />
      </div>
    )
  } else {
    return (
      <div className="App">
        <div>
          {
            !value && (<button onClick={createCounter}>Create counter</button>)
          }
          {
            value && <button onClick={increment}>Increment counter</button>
          }

          {
            value && value >= Number(0) ? (
              <h2>{value}</h2>
            ) : (
              <h3>Please create the counter.</h3>
            )
          }
        </div>
      </div>
    );
  }
}

/* wallet configuration as specified here: https://github.com/solana-labs/wallet-adapter#setup */
const AppWithProvider = () => (
  <ConnectionProvider endpoint="http://127.0.0.1:8899">
    <WalletProvider wallets={wallets} autoConnect>
      <WalletModalProvider>
        <App />
      </WalletModalProvider>
    </WalletProvider>
  </ConnectionProvider>
)

export default AppWithProvider;

Next, open your terminal and run this command (be sure solana-test-validator is running):

solana airdrop 10 <address>

Change into the app directory and run the following command:

npm start

To do so, let's update our Rust program to look like this:

/* programs/mysolanaapp/src/lib.rs */
use anchor_lang::prelude::*;

declare_id!("your-program-id");

#[program]
mod mysolanaapp {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>, data: String) -> ProgramResult {
        let base_account = &mut ctx.accounts.base_account;
        let copy = data.clone();
        base_account.data = data;
        base_account.data_list.push(copy);
        Ok(())
    }

    pub fn update(ctx: Context<Update>, data: String) -> ProgramResult {
        let base_account = &mut ctx.accounts.base_account;
        let copy = data.clone();
        base_account.data = data;
        base_account.data_list.push(copy);
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(init, payer = user, space = 64 + 64)]
    pub base_account: Account<'info, BaseAccount>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct Update<'info> {
    #[account(mut)]
    pub base_account: Account<'info, BaseAccount>,
}

#[account]
pub struct BaseAccount {
    pub data: String,
    pub data_list: Vec<String>,
}

Next, we can update the test for this new program:

const assert = require("assert");
const anchor = require("@project-serum/anchor");
const { SystemProgram } = anchor.web3;

describe("Mysolanaapp", () => {
  const provider = anchor.Provider.env();
  anchor.setProvider(provider);
  const program = anchor.workspace.Mysolanaapp;
  it("It initializes the account", async () => {
    const baseAccount = anchor.web3.Keypair.generate();
    await program.rpc.initialize("Hello World", {
      accounts: {
        baseAccount: baseAccount.publicKey,
        user: provider.wallet.publicKey,
        systemProgram: SystemProgram.programId,
      },
      signers: [baseAccount],
    });

    const account = await program.account.baseAccount.fetch(baseAccount.publicKey);
    console.log('Data: ', account.data);
    assert.ok(account.data === "Hello World");
    _baseAccount = baseAccount;

  });

  it("Updates a previously created account", async () => {
    const baseAccount = _baseAccount;

    await program.rpc.update("Some new data", {
      accounts: {
        baseAccount: baseAccount.publicKey,
      },
    });

    const account = await program.account.baseAccount.fetch(baseAccount.publicKey);
    console.log('Updated data: ', account.data)
    assert.ok(account.data === "Some new data");
    console.log('all account data:', account)
    console.log('All data: ', account.dataList);
    assert.ok(account.dataList.length === 2);
  });
});

To test it out:

anchor test

Next, let's update the client.

import './App.css';
import { useState } from 'react';
import { Connection, PublicKey } from '@solana/web3.js';
import { Program, Provider, web3 } from '@project-serum/anchor';
import idl from './idl.json';

import { getPhantomWallet } from '@solana/wallet-adapter-wallets';
import { useWallet, WalletProvider, ConnectionProvider } from '@solana/wallet-adapter-react';
import { WalletModalProvider, WalletMultiButton } from '@solana/wallet-adapter-react-ui';
require('@solana/wallet-adapter-react-ui/styles.css');

const wallets = [ getPhantomWallet() ]

const { SystemProgram, Keypair } = web3;
const baseAccount = Keypair.generate();
const opts = {
  preflightCommitment: "processed"
}
const programID = new PublicKey(idl.metadata.address);

function App() {
  const [value, setValue] = useState('');
  const [dataList, setDataList] = useState([]);
  const [input, setInput] = useState('');
  const wallet = useWallet()

  async function getProvider() {
    /* create the provider and return it to the caller */
    /* network set to local network for now */
    const network = "http://127.0.0.1:8899";
    const connection = new Connection(network, opts.preflightCommitment);

    const provider = new Provider(
      connection, wallet, opts.preflightCommitment,
    );
    return provider;
  }

  async function initialize() {    
    const provider = await getProvider();
    /* create the program interface combining the idl, program ID, and provider */
    const program = new Program(idl, programID, provider);
    try {
      /* interact with the program via rpc */
      await program.rpc.initialize("Hello World", {
        accounts: {
          baseAccount: baseAccount.publicKey,
          user: provider.wallet.publicKey,
          systemProgram: SystemProgram.programId,
        },
        signers: [baseAccount]
      });

      const account = await program.account.baseAccount.fetch(baseAccount.publicKey);
      console.log('account: ', account);
      setValue(account.data.toString());
      setDataList(account.dataList);
    } catch (err) {
      console.log("Transaction error: ", err);
    }
  }

  async function update() {
    if (!input) return
    const provider = await getProvider();
    const program = new Program(idl, programID, provider);
    await program.rpc.update(input, {
      accounts: {
        baseAccount: baseAccount.publicKey
      }
    });

    const account = await program.account.baseAccount.fetch(baseAccount.publicKey);
    console.log('account: ', account);
    setValue(account.data.toString());
    setDataList(account.dataList);
    setInput('');
  }

  if (!wallet.connected) {
    return (
      <div style={{ display: 'flex', justifyContent: 'center', marginTop:'100px' }}>
        <WalletMultiButton />
      </div>
    )
  } else {
    return (
      <div className="App">
        <div>
          {
            !value && (<button onClick={initialize}>Initialize</button>)
          }

          {
            value ? (
              <div>
                <h2>Current value: {value}</h2>
                <input
                  placeholder="Add new data"
                  onChange={e => setInput(e.target.value)}
                  value={input}
                />
                <button onClick={update}>Add data</button>
              </div>
            ) : (
              <h3>Please Inialize.</h3>
            )
          }
          {
            dataList.map((d, i) => <h4 key={i}>{d}</h4>)
          }
        </div>
      </div>
    );
  }
}

const AppWithProvider = () => (
  <ConnectionProvider endpoint="http://127.0.0.1:8899">
    <WalletProvider wallets={wallets} autoConnect>
      <WalletModalProvider>
        <App />
      </WalletModalProvider>
    </WalletProvider>
  </ConnectionProvider>
)

export default AppWithProvider;

Next, build and deploy the program (be sure that solana-test-validator is running):

anchor build

anchor deploy

Change into the app directory and run the start command:

npm start

Update the Solana CLI to use devnet:

solana config set --url devnet

Update Phantom wallet to use devnet Open Anchor.toml and update the cluster from localnet to devnet. Rebuild the program. Be sure the program ID in Anchor.toml matches the current program ID. Deploy the program again, this time it will be deployed to devnet In app/src/App.js, we need to also update the network, this time using the clusterApiUrl from @solana/web3, like this:

/* before */
<ConnectionProvider endpoint="http://127.0.0.1:8899">

/* after */
import {
  ...,
  clusterApiUrl
} from '@solana/web3.js';

const network = clusterApiUrl('devnet');

<ConnectionProvider endpoint={network}>

I've carefully checked everything step-by-step and it works. I think my mistake was in

solana address -k target/deploy/mysolanaapp-keypair.json

If you end up with

Module not found: Error: Can't resolve './adapter' in '/Users/me/Desktop/mysolanaapp/app/node_modules/@solana/wallet-adapter-bitkeep/lib'
Did you mean 'adapter.js'?
BREAKING CHANGE: The request './adapter' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request."

Yes, looks like you need to install anchor using Cargo:

cargo install --git https://github.com/project-serum/anchor --tag v0.17.0 anchor-cli --locked

My problem was that I had the npm anchor package installed globally (which I did before I realized that it doesn't work on the M1 mac currently). Uninstalling it fixed the issue. (of course you also need to build anchor for it to work properly on the M1)

npm uninstall -g @project-serum/anchor-cli

Source: link

1

Using core/gallery as an example, due to it only having 3 controls currently, something like this:

let controls = {
    setColumnsNumber: <RangeControl
        label={ __( 'Columns' ) }
        value={ columns }
        onChange={ this.setColumnsNumber }
        min={ 1 }
        max={ Math.min( MAX_COLUMNS, images.length ) }
    />,
    imageCrop: <ToggleControl
        label={ __( 'Crop Images' ) }
        checked={ !! imageCrop }
        onChange={ this.toggleImageCrop }
    />,
    linkTo: <SelectControl
        label={ __( 'Link to' ) }
        value={ linkTo }
        onChange={ this.setLinkTo }
        options={ linkOptions }
    />,
};
controls = applyFilters( 'blocks.inspectorControls', controls, this );

Then with such a pattern in place, one can easily remove controls as they desire. Assuming lodash is being used, this filter would remove the setColumnsNumber and imageCrop controls:

function removeGalleryControls( controls, block ) {
    if ( 'core/gallery' == block.props.name ) {
        return omit( controls, [ 'setColumnsNumber', 'imageCrop' ] );
    }
    return controls;
}
addFilter( 'blocks.inspectorControls', 'remove-gallery-controls', removeGalleryControls );

This filter would update the Columns control by changing the maximum range, and updating its label:

function replaceGalleryControl( controls, block ) {
    if ( 'core/gallery' == block.props.name ) {
        const { columns } = block.props.attributes
        
        controls.setColumnsNumber = <RangeControl
            label={ __( 'New Label!' ) }
            value={ columns }
            onChange={ block.setColumnsNumber }
            min={ 1 }
            max={ 3 }
        />;
    }
    return controls;
}
addFilter( 'blocks.inspectorControls', 'replace-gallery-control', replaceGalleryControl );

For clarify sake, here is what I'm doing to add new controls:

function onUpdate( BlockEdit ) {
    const WrappedBlockEdit = ( props ) => {
        if ( 'core/heading' !== props.name ) {
            return <BlockEdit { ...props } />
        }

        const { attributes, setAttributes, isSelected } = props
        
        return [
            <BlockEdit { ...props } />,
            isSelected && <InspectorControls key="inspector">
                <ToggleControl
                    label={ __( 'Custom Control' ) }
                    checked={ !! attributes.customControl }
                    onChange={ onChangeEvent }
                />
            </InspectorControls>,
        ]
    }
    return WrappedBlockEdit
}
addFilter( 'blocks.BlockEdit', 'custom/heading/update', onUpdate )

In the end we'd have something far more manageable — every inspector would look like this:

[block description]
---
Block Settings ▼
... various block settings ...
---
Other Settings ▶
---
Advanced Settings ▶

Also the proposed API for modifying the list of controls could be as simple as:

supports: {
    allowedInspectorControls: [ 'align', 'fontSize' ],
}

Source: link

Recent Questions on .net

    Programming Languages