| 1 | {"version":3,"file":"nanopop.min.mjs","sources":["../src/NanoPop.ts"],"sourcesContent":["type Direction = 'top' | 'left' | 'bottom' | 'right';\ntype Alignment = 'start' | 'middle' | 'end';\n\nexport type VariantFlipOrder = {\n    start: string;\n    middle: string;\n    end: string;\n};\n\nexport type PositionFlipOrder = {\n    top: string;\n    right: string;\n    bottom: string;\n    left: string;\n};\n\nexport type NanoPopPosition = `${Direction}-${Alignment}` | Direction;\n\nexport type NanoPopOptions = {\n    container: DOMRect;\n    position: NanoPopPosition;\n    variantFlipOrder: VariantFlipOrder;\n    positionFlipOrder: PositionFlipOrder;\n    margin: number;\n    reference?: HTMLElement;\n    popper?: HTMLElement;\n    padding?: number;\n};\n\ntype AvailablePositions = {\n    t: number;\n    b: number;\n    l: number;\n    r: number;\n};\n\ntype AvailableVariants = {\n    vs: number;\n    vm: number;\n    ve: number;\n    hs: number;\n    hm: number;\n    he: number;\n};\n\ntype PositionPairs = [Direction, Direction];\n\nexport type PositionMatch = 'ts' | 'tm' | 'te' | 'bs' | 'bm' | 'be' | 'ls' | 'lm' | 'le' | 'rs' | 'rm' | 're';\n\nexport interface NanoPop {\n    update(updatedOptions?: Partial<NanoPopOptions>): PositionMatch | null;\n}\n\nexport interface NanoPopConstructor {\n\n    /**\n     * @param reference Reference element\n     * @param popper Actual popper element\n     * @param options Optional options\n     */\n    (reference: HTMLElement, popper: HTMLElement, options?: Partial<NanoPopOptions>): NanoPop;\n\n    /**\n     * @param options Partial options which get merged with the current one\n     */\n    (options?: Partial<NanoPopOptions>): NanoPop;\n}\n\n// Export current version\nexport const version = VERSION;\n\n// Export default\nexport const defaults = {\n    variantFlipOrder: {start: 'sme', middle: 'mse', end: 'ems'},\n    positionFlipOrder: {top: 'tbrl', right: 'rltb', bottom: 'btrl', left: 'lrbt'},\n    position: 'bottom',\n    margin: 8,\n    padding: 0\n};\n\n/**\n * Repositions an element once using the provided options and elements.\n * @param reference Reference element\n * @param popper Popper element\n * @param opt Optional, additional options\n */\nexport const reposition = (\n    reference: HTMLElement,\n    popper: HTMLElement,\n    opt?: Partial<NanoPopOptions>\n): PositionMatch | null => {\n    const {\n        container,\n        margin,\n        padding,\n        position,\n        variantFlipOrder,\n        positionFlipOrder\n    } = {\n        container: document.documentElement.getBoundingClientRect(),\n        ...defaults,\n        ...opt\n    };\n\n    /**\n     * Reset position to resolve viewport\n     * See https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed\n     */\n    const {left: originalLeft, top: originalTop} = popper.style;\n    popper.style.left = '0';\n    popper.style.top = '0';\n\n    const refBox = reference.getBoundingClientRect();\n    const popBox = popper.getBoundingClientRect();\n\n    /**\n     * Holds coordinates of top, left, bottom and right alignment\n     */\n    const positionStore: AvailablePositions = {\n        t: refBox.top - popBox.height - margin,\n        b: refBox.bottom + margin,\n        r: refBox.right + margin,\n        l: refBox.left - popBox.width - margin\n    };\n\n    /**\n     * Holds corresponding variants (start, middle, end).\n     * The values depend on horizontal / vertical orientation\n     */\n    const variantStore: AvailableVariants = {\n        vs: refBox.left,\n        vm: refBox.left + refBox.width / 2 + -popBox.width / 2,\n        ve: refBox.left + refBox.width - popBox.width,\n        hs: refBox.top,\n        hm: refBox.bottom - refBox.height / 2 - popBox.height / 2,\n        he: refBox.bottom - popBox.height\n    };\n\n    // Extract position and variant\n    // Top-start -> top is \"position\" and \"start\" is the variant\n    const [posKey, varKey = 'middle'] = position.split('-');\n    const positions = positionFlipOrder[posKey as keyof PositionFlipOrder];\n    const variants = variantFlipOrder[varKey as keyof VariantFlipOrder];\n\n    // Try out all possible combinations, starting with the preferred one.\n    const {top, left, bottom, right} = container;\n\n    for (const p of positions) {\n        const vertical = (p === 't' || p === 'b');\n\n        // The position-value\n        const positionVal = positionStore[p as keyof AvailablePositions];\n\n        // Which property has to be changes.\n        const [positionKey, variantKey] = (vertical ? ['top', 'left'] : ['left', 'top']) as PositionPairs;\n\n        /**\n         * box refers to the size of the popper element. Depending on the orientation this is width or height.\n         * The limit is the corresponding, maximum value for this position.\n         */\n        const [positionSize, variantSize] = vertical ? [popBox.height, popBox.width] : [popBox.width, popBox.height];\n\n        const [positionMaximum, variantMaximum] = vertical ? [bottom, right] : [right, bottom];\n        const [positionMinimum, variantMinimum] = vertical ? [top, left] : [left, top];\n\n        // Skip pre-clipped values\n        if (positionVal < positionMinimum || (positionVal + positionSize + padding) > positionMaximum) {\n            continue;\n        }\n\n        for (const v of variants) {\n\n            // The position-value, the related size value of the popper and the limit\n            const variantVal = variantStore[((vertical ? 'v' : 'h') + v) as keyof AvailableVariants];\n\n            if (variantVal < variantMinimum || (variantVal + variantSize + padding) > variantMaximum) {\n                continue;\n            }\n\n            // Apply styles and normalize viewport\n            popper.style[variantKey] = `${variantVal - popBox[variantKey]}px`;\n            popper.style[positionKey] = `${positionVal - popBox[positionKey]}px`;\n            return (p + v) as PositionMatch;\n        }\n    }\n\n    // Revert style values (won't work with styled-elements or similar systems)\n    // \"Fix\" for https://github.com/Simonwep/nanopop/issues/7\n    popper.style.left = originalLeft;\n    popper.style.top = originalTop;\n\n    return null;\n};\n\n/**\n * Creates a stateful popper.\n * You can either...\n * ... pass an options object: createPopper(<options>)\n * ... pass both the reference and popper: create(<ref>, <el>, <?options>)\n * ... pass nothing, in this case you'll have to set at least both a reference and a popper in update.\n *\n * @param reference | options Reference element or options\n * @param popper Popper element\n * @param options Optional additional options\n */\nexport const createPopper: NanoPopConstructor = (\n    reference?: HTMLElement | Partial<NanoPopOptions>,\n    popper?: HTMLElement,\n    options?: Partial<NanoPopOptions>\n): NanoPop => {\n\n    // Resolve options\n    const baseOptions: Partial<NanoPopOptions> = typeof reference === 'object' && !(reference instanceof HTMLElement) ?\n        reference : {reference, popper, ...options};\n\n    return {\n\n        /**\n         * Repositions the current popper.\n         * @param options Optional options which get merged with the current ones.\n         */\n        update(options: Partial<NanoPopOptions> = baseOptions): PositionMatch | null {\n            const {reference, popper} = Object.assign(baseOptions, options);\n\n            if (!popper || !reference) {\n                throw new Error('Popper- or reference-element missing.');\n            }\n\n            return reposition(reference, popper, baseOptions);\n        }\n    };\n};\n"],"names":["version","defaults","variantFlipOrder","start","middle","end","positionFlipOrder","top","right","bottom","left","position","margin","padding","reposition","reference","popper","opt","container","document","documentElement","getBoundingClientRect","originalLeft","originalTop","style","refBox","popBox","positionStore","t","height","b","r","l","width","variantStore","vs","vm","ve","hs","hm","he","posKey","varKey","split","positions","variants","p","vertical","positionVal","positionKey","variantKey","positionSize","variantSize","positionMaximum","variantMaximum","positionMinimum","variantMinimum","v","variantVal","createPopper","options","baseOptions","HTMLElement","update","Object","assign","Error"],"mappings":";AA2DO,MAAMA,EAAU,QAEVC,EAAW,CACpBC,iBAAkB,CAAEC,MAAO,MAAOC,OAAQ,MAAOC,IAAK,OACtDC,kBAAmB,CAAEC,IAAK,OAAQC,MAAO,OAAQC,OAAQ,OAAQC,KAAM,QACvEC,SAAU,SACVC,OAAQ,EACRC,QAAS,GAQAC,EAAa,CAACC,EAAwBC,EAAqBC,KACpE,MAAMC,UAAEA,EAASN,OAAEA,EAAMC,QAAEA,EAAOF,SAAEA,EAAQT,iBAAEA,EAAgBI,kBAAEA,GAAsB,CAClFY,UAAWC,SAASC,gBAAgBC,2BACjCpB,KACAgB,IAMCP,KAAMY,EAAcf,IAAKgB,GAAgBP,EAAOQ,MACxDR,EAAOQ,MAAMd,KAAO,IACpBM,EAAOQ,MAAMjB,IAAM,IACnB,MAAMkB,EAASV,EAAUM,wBACnBK,EAASV,EAAOK,wBAIhBM,EAAoC,CACtCC,EAAGH,EAAOlB,IAAMmB,EAAOG,OAASjB,EAChCkB,EAAGL,EAAOhB,OAASG,EACnBmB,EAAGN,EAAOjB,MAAQI,EAClBoB,EAAGP,EAAOf,KAAOgB,EAAOO,MAAQrB,GAM9BsB,EAAkC,CACpCC,GAAIV,EAAOf,KACX0B,GAAIX,EAAOf,KAAOe,EAAOQ,MAAQ,GAAKP,EAAOO,MAAQ,EACrDI,GAAIZ,EAAOf,KAAOe,EAAOQ,MAAQP,EAAOO,MACxCK,GAAIb,EAAOlB,IACXgC,GAAId,EAAOhB,OAASgB,EAAOI,OAAS,EAAIH,EAAOG,OAAS,EACxDW,GAAIf,EAAOhB,OAASiB,EAAOG,SAIxBY,EAAQC,EAAS,UAAY/B,EAASgC,MAAM,KAC7CC,EAAYtC,EAAkBmC,GAC9BI,EAAW3C,EAAiBwC,IAE5BnC,IAAEA,EAAGG,KAAEA,EAAID,OAAEA,EAAMD,MAAEA,GAAUU,EACrC,IAAK,MAAM4B,KAAKF,EAAW,CACvB,MAAMG,EAAkB,MAAND,GAAmB,MAANA,EAEzBE,EAAcrB,EAAcmB,IAE3BG,EAAaC,GAAeH,EAAW,CAAC,MAAO,QAAU,CAAC,OAAQ,QAKlEI,EAAcC,GAAeL,EAAW,CAACrB,EAAOG,OAAQH,EAAOO,OAAS,CAACP,EAAOO,MAAOP,EAAOG,SAC9FwB,EAAiBC,GAAkBP,EAAW,CAACtC,EAAQD,GAAS,CAACA,EAAOC,IACxE8C,EAAiBC,GAAkBT,EAAW,CAACxC,EAAKG,GAAQ,CAACA,EAAMH,GAE1E,KAAIyC,EAAcO,GAAoBP,EAAcG,EAAetC,EAAWwC,GAG9E,IAAK,MAAMI,KAAKZ,EAAU,CAEtB,MAAMa,EAAaxB,GAAea,EAAW,IAAM,KAAOU,GAC1D,KAAIC,EAAaF,GAAmBE,EAAaN,EAAcvC,EAAWyC,GAM1E,OAFAtC,EAAOQ,MAAM0B,GAAiBQ,EAAahC,EAAOwB,GAAvB,KAC3BlC,EAAOQ,MAAMyB,GAAkBD,EAActB,EAAOuB,GAAxB,KACpBH,EAAIW,CACf,CACJ,CAKD,OAFAzC,EAAOQ,MAAMd,KAAOY,EACpBN,EAAOQ,MAAMjB,IAAMgB,EACZ,IAAI,EAaFoC,EAAmC,CAAC5C,EAAmDC,EAAsB4C,KAEtH,MAAMC,EAA4D,iBAAd9C,GAA4BA,aAAqB+C,YACrF,CAAE/C,YAAWC,YAAW4C,GAApC7C,EACJ,MAAO,CAKHgD,OAAOH,EAAmCC,GACtC,MAAM9C,UAAEA,EAASC,OAAEA,GAAWgD,OAAOC,OAAOJ,EAAaD,GACzD,IAAK5C,IAAWD,EACZ,MAAM,IAAImD,MAAM,yCAEpB,OAAOpD,EAAWC,EAAWC,EAAQ6C,EACxC,EACJ"}
 |