Is there really not a color picker input component?

I am adding a color picker so my users can set custom colors for their user avatar. is there no color picker plugin/component available? would i use JS for this?

do i need to investigate creating my own via the html component?

I’d use a little bit of JS for this. Here’s a color picker I found on the web. One can add the relevant link and script tag via custom code embed (or use a bit of code on pageload to dynamically load it)

I’d have the onChange event handler fire an executeWorkflow to make an arbitrary workflow respond to changes in the color, letting you minimize the amount of code you’re doing in javascript-land.

This might not be exactly the right component for you, but the general pattern would apply for finding something that might work more out-of-the-box than having to make your own Vue component or some such.

just keep in mind that weweb’s onChange event will not be triggered when the input value is changed by the library because the manipulation happens outside weweb’s vue app.

Edit: This specific library is clever enough to let the underlying vue app know about the change, so all the other weweb stuff should work as expected.

Here is the start to my final solution that is a working fix

function rgbaToHex(rgba) {
  const colorArray = rgba.match(/[.\d]+/g);
  const r = Math.round(parseFloat(colorArray[0]));
  const g = Math.round(parseFloat(colorArray[1]));
  const b = Math.round(parseFloat(colorArray[2]));

  const hex = ((r << 16) | (g << 8) | b).toString(16).padStart(6, '0');
  return '#' + hex;
}

var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://cdn.jsdelivr.net/npm/@simonwep/pickr@1.8.1/dist/themes/classic.min.css';
document.head.appendChild(link);

const style = document.createElement('style');
style.innerHTML = `
  .pickr .pcr-button:before {
    width: 60px;
    height: 60px;
    border-radius: 8px;
  }
  
  
  .pickr .pcr-button {
    width: 60px;
    height: 60px;
    border-radius: 8px !important
}

  .pickr .pcr-button:after {
    width: 60px;
    height: 60px;
    border-radius: 8px !important!
}
`;
document.head.appendChild(style);


// Load JavaScript
var script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/@simonwep/pickr@1.8.1';
document.body.appendChild(script);

script.onload = function() {
  console.log('script loaded');
  var checkExist = setInterval(function() {
    console.log('checking');
    if (document.getElementById('colorpickerholder')) {
    const e = document.getElementById('colorpickerholder')
    console.log(e)
      console.log('asdf')
      clearInterval(checkExist);

      var pickr = Pickr.create({
        el: '#colorpickerholder',
        theme: 'classic', // or 'monolith', or 'nano'
        default: 'rgba(9, 162, 255, 1)',

        swatches: [
          'rgba(244, 67, 54, 1)',
          'rgba(233, 30, 99, 0.95)',
          'rgba(156, 39, 176, 0.9)',
          'rgba(103, 58, 183, 0.85)',
          'rgba(63, 81, 181, 0.8)',
          'rgba(33, 150, 243, 0.75)',
          'rgba(3, 169, 244, 0.7)',
          'rgba(0, 188, 212, 0.7)',
          'rgba(0, 150, 136, 0.75)',
          'rgba(76, 175, 80, 0.8)',
          'rgba(139, 195, 74, 0.85)',
          'rgba(205, 220, 57, 0.9)',
          'rgba(255, 235, 59, 0.95)',
          'rgba(255, 193, 7, 1)'
        ],

        components: {
          preview: true,
          opacity: true,
          hue: true,

          interaction: {
            hex: true,
            rgba: true,
            hsla: true,
            hsva: true,
            cmyk: true,
            input: true,
            clear: true,
            save: true
          }
        }
      });
      console.log(e)
      e.addEventListener('click', function() {
        console.log('hello');
        pickr.show();
        console.log(pickr);
      });
      
const link2 = document.createElement('link');
link2.type = 'text/css';
link2.classList.add('dynamic-style'); // Add a class name
link2.innerHTML = `.pickr .pcr-button:before {
  content: '';
  border-radius: 8px;
}`;
document.head.appendChild(link2);


      pickr.on('save', (color, instance) => {
        console.log(color.toRGBA().toString());
        console.log(rgbaToHex(color.toRGBA().toString()))
        window.color = color.toRGBA().toString();
        wwLib.wwVariable.updateValue('35811b4c-868c-488b-bb3d-617b91d4b84f',rgbaToHex(color.toRGBA().toString()))
        console.log(window.color)
        pickr.hide();
      });


    }
  }, 100); // check every 100ms
};

allowing me to use the wwLib.wwVariable.updateValue(UID,VALUE) value setter BUT how do i do this ray?

where do i grab the workflow id’s?

NVM! I figured it out with the help of @dorilama and the thread he shared. i’ve detailed the simple steps here to avoid having to go too deep into threads in the future for other wewebershere to keep the info more vissible

2 Likes

setInterval is a good way to introduce an infinite loop in your code. An observer is probably what you want to use.

2 Likes

Some of this you can make simpler by just separating the concerns of adding the external link and then using it. I like to use an early app load for loading the external JS and something later in the process for binding. Then the code you have for loading the picker object I would probably do on the click event itself of your input element. That allows natural lifecycle to work to your advantage. If you need to know about the mount of the component before other events fire on it, that’s where a DOM observer could benefit you.

I made embedding code in weweb actions a one-step process with https://weweb-embed.statechange.ai. I used @jaredgibb’s use case of the color picker in tutorial too!

2 Likes

Hey there,

We just added a basic color picker input element in the default UI kit:

We’re exploring options to create a more advanced one in the future.

1 Like

Nice!

We are pretty happy with coloris. I’ll try to capture a screen grab of how I’m using it!

Super happy with the results for now

1 Like