jd-solanki / anu

Anu - DX focused utility based vue component library built on top of UnoCSS & VueUse ⚡️🔥

Home Page:https://anu-vue.netlify.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

feat: chip closable advance

jingyuexing opened this issue · comments

When I used the Closable feature of the Chip component in an actual project, I found that there were many limitations, such as being unable to delete or add items freely. Therefore, I wrote an enhanced version of the useSelection hook. Since I only tested it in my own project, I cannot predict how it will work in your project. Please modify it according to your specific situation.

export function useSelectionAdavance<Item, Multi extends boolean, Closable extends boolean, InitialValue extends Item>(
  params: Params<Item, Multi, Closable, InitialValue>
): ReturnValue<Item, Multi> {
  const { items, multi = false, initialValue = undefined, closable = false } = params;

  const _items = toRef(items);
  const _multi = toRef(multi);
  const _initialValue = toRef(initialValue);
  const _val = ref(
    // _initialValue.value,

    // (_items.value as Item[]).find(i => {
      //   // ℹ️ If initial value is object compare using `JSON.stringify` else just use `===`
      //   return (isObject(_initialValue.value) && isObject(i))
      //     ? JSON.stringify(_initialValue.value) === JSON.stringify(i)
      //     : _initialValue.value === i
      // }),
      (_items.value as Item[]).find(i => isEqual(_initialValue.value, i))
      ) as ReturnValue<Item, Multi>["value"];
  const select = (option: Item) => {
    // If multiple selection is enabled
    if (_multi.value) {
      // If value is not set (Means previously multi was false) => Initialize new set and assign it to value
      if (!Array.isArray(_val.value)) {
        _val.value = [option] as UnwrapRef<ReturnValue<Item, Multi>["value"]>;
      } else {
    
        // Else toggle option in array
        const index = _val.value.indexOf(option);
        if (index === -1) _val.value.push(option);
        else _val.value.splice(index, 1);
      }
    } else {
      _val.value = option as UnwrapRef<ReturnValue<Item, Multi>["value"]>;
    }
  };
  const close = (option:Item) => {
    if (_multi.value && Array.isArray(_items.value)) {
      const index = _items.value.indexOf(option);
      if (index !== -1) _items.value.splice(index, 1);
    } else {
      _val.value = undefined as UnwrapRef<ReturnValue<Item, Multi>["value"]>;
    }
  }
  const append = (val:Item)=>{
    if (_multi.value && Array.isArray(_items.value)) {
      _items.value.push(val);
    }
  }
  watch(_multi, val => {
    _val.value = (val ? [] : undefined) as UnwrapRef<ReturnValue<Item, Multi>["value"]>;
  });
  const _options = computed(() => _items.value.map(item => ({
    value: item,
    isSelected: _multi.value
      ? Array.isArray(_val.value) ? _val.value.includes(item) : false
      : isEqual(item, _val.value),
    isClosed:false
  }))) as ReturnValue<Item, Multi>['options']
  return {
    value: _val,
    select,
    close,
    append,
    options: _options
  };
}

Two new hooks have been added: close, which removes an element from the items array, and append, which adds an element to the items array.

I wonder what if we update the passed array while using useSelection:

const items = ref(['apple', 'banana', 'orange', 'watermelon'])
const { options, select, value } = useSelection({
  items: items,
  multi: isMultiEnabled,
})

setTimeout(() => {
  items.value.push('mango')
}, 2000);

Can you please give it a try and let know if above works?

I wonder what if we update the passed array while using useSelection:

const items = ref(['apple', 'banana', 'orange', 'watermelon'])
const { options, select, value } = useSelection({
  items: items,
  multi: isMultiEnabled,
})

setTimeout(() => {
  items.value.push('mango')
}, 2000);

Can you please give it a try and let know if above works?

I'm not sure if you are showing me another way to achieve the same goal. As for the above code, there's no problem and it can run as expected.