{"version":3,"file":"sorted.cjs","names":["getSecureRandomIfPossible"],"sources":["../../../src/common/data/sorted.ts"],"sourcesContent":["import { getSecureRandomIfPossible } from './math'\n\n/** CRDT compatible sorting with a single operation. Default name is `sort` */\nexport function useSorted<S extends Record<string, any>>(\n  config: {\n    getter?: (item: S) => number\n    // setter?: (item: S, value: number) => void\n  } = {},\n) {\n  const {\n    getter = (item: any): number => item.sort,\n    // setter = (item: any, value) => (item.sort = value),\n  } = config\n\n  /** Return sorted list from low to high. */\n  function items<T extends S>(items: T[]): T[] {\n    items.sort((a, b) => (getter(a) || 0) - (getter(b) || 0))\n    return items\n  }\n\n  /** Get a sort suitable for adding to start of list. */\n  function start(items: S[]): number {\n    return (\n      items.reduce((acc, item) => Math.min(acc, getter(item) || 0), 0) - 1 - getSecureRandomIfPossible()\n    )\n  }\n\n  /** Get a sort suitable for adding to end of list. */\n  function end(items: S[]): number {\n    return (\n      items.reduce((acc, item) => Math.max(acc, getter(item) || 0), 0) + 1 + getSecureRandomIfPossible()\n    )\n  }\n\n  /** Find a suitable value inbetween a lower and upper bound. */\n  function between(lower?: number, upper?: number): number {\n    if (lower == null)\n      lower = (upper ?? 0) - 1\n    if (upper == null)\n      upper = (lower ?? 0) + 1\n\n    const distance = upper - lower\n    // if (distance === 0)\n\n    const middle = lower + distance / 2\n    const fuzzy = distance * 0.01 * (getSecureRandomIfPossible() - 0.5) // 1% fuzziness to avoid conflicts\n    return middle + fuzzy\n  }\n\n  /** Mainly for drag and drop movements, where an item has to be moved to another index. Respects its own move as well. */\n  function move(\n    newIndex: number,\n    oldIndex: number,\n    sortableItems: S[],\n  ): number {\n    const count = sortableItems.length\n\n    const moveLower = newIndex < oldIndex\n    if (count <= 0 || newIndex >= count - 1)\n      return end(sortableItems)\n\n    if (newIndex <= 0)\n      return start(sortableItems)\n\n    // Make sure they are sorted\n    sortableItems = items([...sortableItems])\n\n    const step = moveLower ? -1 : 0 // use Math.sign(?) for performance?\n    const lower = getter(sortableItems[newIndex + step]) || 0\n    const upper = getter(sortableItems[newIndex + step + 1]) || 0\n    const distance = upper - lower\n    if (distance === 0) {\n      // Ugly list with no presets, make the best guess\n      if (moveLower)\n        return start(sortableItems)\n\n      return end(sortableItems)\n    }\n    const middle = lower + distance / 2\n    const fuzzy = distance * 0.01 * (getSecureRandomIfPossible() - 0.5) // 1% fuzziness to avoid conflicts\n    return middle + fuzzy\n  }\n\n  return {\n    start,\n    end,\n    between,\n    move,\n    items,\n  }\n}\n"],"mappings":";;;;;AAGA,SAAgB,UACd,SAGI,EAAE,EACN;CACA,MAAM,EACJ,UAAU,SAAsB,KAAK,SAEnC;;CAGJ,SAAS,MAAmB,OAAiB;AAC3C,QAAM,MAAM,GAAG,OAAO,OAAO,EAAE,IAAI,MAAM,OAAO,EAAE,IAAI,GAAG;AACzD,SAAO;;;CAIT,SAAS,MAAM,OAAoB;AACjC,SACE,MAAM,QAAQ,KAAK,SAAS,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,EAAE,EAAE,EAAE,GAAG,IAAIA,oDAA2B;;;CAKtG,SAAS,IAAI,OAAoB;AAC/B,SACE,MAAM,QAAQ,KAAK,SAAS,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,EAAE,EAAE,EAAE,GAAG,IAAIA,oDAA2B;;;CAKtG,SAAS,QAAQ,OAAgB,OAAwB;AACvD,MAAI,SAAS,KACX,UAAS,SAAS,KAAK;AACzB,MAAI,SAAS,KACX,UAAS,SAAS,KAAK;EAEzB,MAAM,WAAW,QAAQ;AAKzB,SAFe,QAAQ,WAAW,IACpB,WAAW,OAAQA,oDAA2B,GAAG;;;CAKjE,SAAS,KACP,UACA,UACA,eACQ;EACR,MAAM,QAAQ,cAAc;EAE5B,MAAM,YAAY,WAAW;AAC7B,MAAI,SAAS,KAAK,YAAY,QAAQ,EACpC,QAAO,IAAI,cAAc;AAE3B,MAAI,YAAY,EACd,QAAO,MAAM,cAAc;AAG7B,kBAAgB,MAAM,CAAC,GAAG,cAAc,CAAC;EAEzC,MAAM,OAAO,YAAY,KAAK;EAC9B,MAAM,QAAQ,OAAO,cAAc,WAAW,MAAM,IAAI;EAExD,MAAM,YADQ,OAAO,cAAc,WAAW,OAAO,GAAG,IAAI,KACnC;AACzB,MAAI,aAAa,GAAG;AAElB,OAAI,UACF,QAAO,MAAM,cAAc;AAE7B,UAAO,IAAI,cAAc;;AAI3B,SAFe,QAAQ,WAAW,IACpB,WAAW,OAAQA,oDAA2B,GAAG;;AAIjE,QAAO;EACL;EACA;EACA;EACA;EACA;EACD"}