1 line
13 KiB
Plaintext
1 line
13 KiB
Plaintext
{"version":3,"file":"nanopop.mjs","sources":["../src/index.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 arrow?: 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 AvailableArrowVariants = {\n s: number;\n m: number;\n e: 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 arrow,\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 let 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 let variantVal = variantStore[((vertical ? 'v' : 'h') + v) as keyof AvailableVariants];\n\n if (variantVal < variantMinimum || (variantVal + variantSize + padding) > variantMaximum) {\n continue;\n }\n\n // Subtract popBox's initial position\n variantVal -= popBox[variantKey];\n positionVal -= popBox[positionKey];\n\n // Apply styles and normalize viewport\n popper.style[variantKey] = `${variantVal}px`;\n popper.style[positionKey] = `${positionVal}px`;\n\n if (arrow) {\n // Calculate refBox's center offset from its variant position for arrow positioning\n const refBoxCenterOffset = vertical ? refBox.width / 2 : refBox.height / 2;\n const popBoxCenterOffset = variantSize / 2;\n\n // Check if refBox is larger than popBox\n const isRefBoxLarger = refBoxCenterOffset > popBoxCenterOffset;\n\n /**\n * Holds corresponding offset variants (start, middle, end) of arrow from the popper variant values.\n * When refBox is larger than popBox, have the arrow's variant position be the center of popBox instead.\n */\n const arrowVariantStore: AvailableArrowVariants = {\n s: isRefBoxLarger ? popBoxCenterOffset : refBoxCenterOffset,\n m: popBoxCenterOffset,\n e: isRefBoxLarger ? popBoxCenterOffset : variantSize - refBoxCenterOffset,\n };\n\n /**\n * Holds offsets of top, left, bottom and right alignment of arrow from the popper position values.\n */\n const arrowPositionStore: AvailablePositions = {\n t: positionSize,\n b: 0,\n r: 0,\n l: positionSize\n };\n\n const arrowVariantVal = variantVal + arrowVariantStore[v as keyof AvailableArrowVariants];\n const arrowPositionVal = positionVal + arrowPositionStore[p as keyof AvailablePositions];\n\n // Apply styles to arrow\n arrow.style[variantKey] = `${arrowVariantVal}px`;\n arrow.style[positionKey] = `${arrowPositionVal}px`;\n }\n\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","reposition","reference","popper","opt","container","arrow","margin","padding","position","variantFlipOrder","positionFlipOrder","originalLeft","originalTop","refBox","popBox","positionStore","variantStore","posKey","varKey","positions","variants","top","left","bottom","right","p","vertical","positionVal","positionKey","variantKey","positionSize","variantSize","positionMaximum","variantMaximum","positionMinimum","variantMinimum","v","variantVal","refBoxCenterOffset","popBoxCenterOffset","isRefBoxLarger","arrowVariantStore","arrowPositionStore","arrowVariantVal","arrowPositionVal","createPopper","options","baseOptions"],"mappings":"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"} |