{"version":3,"file":"spinner.cjs","names":[],"sources":["../../src/core/spinner.ts"],"sourcesContent":["import { clamp as clampRange } from '@vielzeug/arsenal/math';\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { dispatchKeyboardAction } from './keyboard';\nimport { toFiniteNumber, toPositiveStep } from './numbers';\n\nexport type SpinnerControlOptions = {\n  commit: (value: number | null, originalEvent?: Event) => void;\n  disabled?: Readable<boolean | undefined>;\n  largeStep?: Readable<number | string | undefined>;\n  max?: Readable<number | string | undefined>;\n  min?: Readable<number | string | undefined>;\n  parse: () => number | null;\n  readonly?: Readable<boolean | undefined>;\n  step?: Readable<number | string | undefined>;\n};\n\nexport type SpinnerControl = {\n  atMax: () => boolean;\n  atMin: () => boolean;\n  handleKeydown: (event: KeyboardEvent) => boolean;\n  incrementBy: (delta: number, originalEvent?: Event) => void;\n};\n\nexport const createSpinnerControl = (options: SpinnerControlOptions): SpinnerControl => {\n  const isBlocked = (): boolean => Boolean(options.disabled?.value) || Boolean(options.readonly?.value);\n\n  const min = (): number | undefined => {\n    return toFiniteNumber(options.min?.value);\n  };\n\n  const max = (): number | undefined => {\n    return toFiniteNumber(options.max?.value);\n  };\n\n  const clamp = (value: number): number => {\n    return clampRange(value, min(), max());\n  };\n\n  const step = (): number => toPositiveStep(options.step?.value, 1);\n\n  const largeStep = (): number => {\n    const s = step();\n\n    return toPositiveStep(options.largeStep?.value, s * 10);\n  };\n\n  const currentOrFallback = (): number => {\n    const parsed = options.parse();\n\n    if (parsed != null) return parsed;\n\n    const minValue = min();\n\n    if (minValue != null) return minValue;\n\n    return 0;\n  };\n\n  const commit = (value: number | null, originalEvent?: Event): void => {\n    if (value == null) {\n      options.commit(null, originalEvent);\n\n      return;\n    }\n\n    options.commit(clamp(value), originalEvent);\n  };\n\n  const incrementBy = (delta: number, originalEvent?: Event): void => {\n    if (isBlocked()) return;\n\n    commit(currentOrFallback() + delta, originalEvent);\n  };\n\n  const atMin = (): boolean => {\n    const parsed = options.parse();\n    const minValue = min();\n\n    return parsed != null && minValue != null && parsed <= minValue;\n  };\n\n  const atMax = (): boolean => {\n    const parsed = options.parse();\n    const maxValue = max();\n\n    return parsed != null && maxValue != null && parsed >= maxValue;\n  };\n\n  const handleKeydown = (event: KeyboardEvent): boolean => {\n    if (isBlocked()) return false;\n\n    return dispatchKeyboardAction(event, {\n      keymap: {\n        ArrowDown: () => incrementBy(-step(), event),\n        ArrowUp: () => incrementBy(step(), event),\n        End: () => {\n          const maxValue = max();\n\n          if (maxValue == null) return false;\n\n          commit(maxValue, event);\n        },\n        Home: () => {\n          const minValue = min();\n\n          if (minValue == null) return false;\n\n          commit(minValue, event);\n        },\n        PageDown: () => incrementBy(-largeStep(), event),\n        PageUp: () => incrementBy(largeStep(), event),\n      },\n      preventDefault: 'after',\n    });\n  };\n\n  return {\n    atMax,\n    atMin,\n    handleKeydown,\n    incrementBy,\n  };\n};\n"],"mappings":"qGAwBA,IAAa,EAAwB,GAAmD,CACtF,IAAM,MAA2B,EAAQ,EAAQ,UAAU,OAAU,EAAQ,EAAQ,UAAU,MAEzF,MACG,EAAA,eAAe,EAAQ,KAAK,KAAK,EAGpC,MACG,EAAA,eAAe,EAAQ,KAAK,KAAK,EAGpC,EAAS,IACb,EAAO,EAAA,MAAA,CAAW,EAAO,EAAI,EAAG,EAAI,CAAC,EAGjC,MAAqB,EAAA,eAAe,EAAQ,MAAM,MAAO,CAAC,EAE1D,MAA0B,CAC9B,IAAM,EAAI,EAAK,EAEf,OAAO,EAAA,eAAe,EAAQ,WAAW,MAAO,EAAI,EAAE,CACxD,EAEM,MACW,EAAQ,MAEnB,GAEa,EAEb,GAEG,EAGH,GAAU,EAAsB,IAAgC,CACpE,GAAI,GAAS,KAAM,CACjB,EAAQ,OAAO,KAAM,CAAa,EAElC,MACF,CAEA,EAAQ,OAAO,EAAM,CAAK,EAAG,CAAa,CAC5C,EAEM,GAAe,EAAe,IAAgC,CAC9D,EAAU,GAEd,EAAO,EAAkB,EAAI,EAAO,CAAa,CACnD,EA4CA,MAAO,CACL,UApC2B,CAC3B,IAAM,EAAS,EAAQ,MAAM,EACvB,EAAW,EAAI,EAErB,OAAO,GAAU,MAAQ,GAAY,MAAQ,GAAU,CACzD,EAgCE,UA5C2B,CAC3B,IAAM,EAAS,EAAQ,MAAM,EACvB,EAAW,EAAI,EAErB,OAAO,GAAU,MAAQ,GAAY,MAAQ,GAAU,CACzD,EAwCE,cA/BqB,GACrB,CAAI,EAAU,GAEP,EAAA,uBAAuB,EAAO,CACnC,OAAQ,CACN,cAAiB,EAAY,CAAC,EAAK,EAAG,CAAK,EAC3C,YAAe,EAAY,EAAK,EAAG,CAAK,EACxC,QAAW,CACT,IAAM,EAAW,EAAI,EAErB,GAAI,GAAY,KAAM,MAAO,GAE7B,EAAO,EAAU,CAAK,CACxB,EACA,SAAY,CACV,IAAM,EAAW,EAAI,EAErB,GAAI,GAAY,KAAM,MAAO,GAE7B,EAAO,EAAU,CAAK,CACxB,EACA,aAAgB,EAAY,CAAC,EAAU,EAAG,CAAK,EAC/C,WAAc,EAAY,EAAU,EAAG,CAAK,CAC9C,EACA,eAAgB,OAClB,CAAC,EAOD,aACF,CACF"}