toddler.popup
Popup namespace that offers components and functions that focus on popup placement.
Use Container component from this namespace as close to mounted react element as possible.
All popup elements will look for Container component and render at that DOM element.
There are few preference position sequences available
(def default-preference
[#{:bottom :left}
#{:bottom :right}
#{:top :left}
#{:top :right}
#{:bottom :center}
#{:top :center}
#{:left :center}
#{:right :center}])
In addition to default-preferences other available preferences are:
- central-preference
- left-preference
- right-preference
- cross-preference
Following components and hooks should be used in most cases:
*area-element*
dynamic
Area element context. Area element is DOM element that will cause popup to appear on user event
*container*
dynamic
Is container context. Container is component where popups will be mounted using reacts createPortal function.
*offset*
dynamic
Offset context. How much in px is offset for popup from PopupArea element
*outside-action-channel*
dynamic
Context for outside action channel. This channel will receive events when scroll or click outside happened
*position*
dynamic
Position of popup. Value should be set of max two keywords
- :top
- :bottom
- :left
- :right
- :center
adjust-scroll-width
(adjust-scroll-width data)
(adjust-scroll-width {:keys [position], :as data} scroll-width)
Keep in mind that scroll can appear. This function will move computed candidate for scroll-width
Area
Component that will generate div element around children that will be provided as *area-element*
context.
It is element that will listen for user events and open popup
best-candidate
(best-candidate candidates)
For given number of candidates, this function will find candidate that has least overflow, that is candidate that has most visibility
computation-props
(computation-props target el)
For given target (popup area) element and popup element function will return map with keys that are important for popup position computation:
- :top, :left, :right :bottom keys
- :popup-width, :popup-height
- :half-popup-width, :half-popup-height
- :vertical-center, horizontal-center
- :window-width :window-height
compute-candidate
multimethod
Function will compute candidate for popup element bounding rect by specifying prefered position. I.E. for #{:bottom :left} position function will enrich input data with keys
- :position/left
- :position/right
- :position/top
- :position/bottom
- :overflow/top
- :overflow/bottom
- :overflow/left
- :overflow/right
compute-container-props
(compute-container-props target el)
(compute-container-props target el preference)
For given popup area and popup element function will return candidate that is most suitable for showing popup
Container
Component that in most cases is instantiated only once. Somewhere near react mounted component.
This component is target for popups to mount. So Element function will look for this component that will provide *container*
context and mount popup in Container.
default-preference
Sequence of prefered positions. First :bottom positions are tested, than :top positions and finally central
Element
Creates fixed positioned div element that is positioned based on preference to area context element.
Popup size will adjust to content that is inside of this element. Props:
- :preference - position preference in form of sequence with set options. I.E.
[#{:bottom :left} #{:top :left}]
- :style - style that will override Element div
- :offset - distance between Area and Element
- :on-change - when popup position changes this will be called
ok-candidate?
(ok-candidate? {:keys [overflow/top overflow/bottom overflow/left overflow/right], :as candidate})
Returns true if candidate didn’t overflow. Than this position is OK
use-focusable-items
(use-focusable-items)
(use-focusable-items direction)
Should be used with popups that can focus some option or elmenent. Like dropdowns or multiselects
Hook will return ref-fn
and focus-option
function.
ref-fn
accepts option and binds that option element with ref to DOM element in internal state.
When focus-option function is called for some option it will use .scrollIntoView to focus that option, by pulling out ref from internal memory using input option
use-outside-action
(use-outside-action area handler)
(use-outside-action area popup handler)
(use-outside-action opened area popup handler)
Hook accepts area and optionally popup element and handler that will be called when outside click or scroll actions are made.
wrap-container
(wrap-container component)
Wrapper that will use Container component to render children if user is authorized