jd-solanki / anu

Anu - DX focused utility based vue component library built on top of UnoCSS & VueUse ⚡️🔥
https://anu-vue.netlify.app/
MIT License
1.04k stars 56 forks source link

feat: chip closable advance #201

Closed jingyuexing closed 1 year ago

jingyuexing commented 1 year ago

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.

jd-solanki commented 1 year ago

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?

jingyuexing commented 1 year ago

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.