{
  "schemaVersion": "1.0.0",
  "readme": "",
  "modules": [
    {
      "kind": "javascript-module",
      "path": "src/scripts/compare-images-slider.js",
      "declarations": [
        {
          "kind": "function",
          "name": "isDoubleTap",
          "parameters": [
            {
              "name": "now",
              "description": "Timestamp of the press that just ended.",
              "type": {
                "text": "number"
              }
            },
            {
              "name": "lastTapAt",
              "description": "Timestamp of the previous tap, 0 if there was none.",
              "type": {
                "text": "number"
              }
            },
            {
              "name": "movedBy",
              "description": "How far the press travelled, in percent.",
              "type": {
                "text": "number"
              }
            },
            {
              "name": "windowMs",
              "default": "DOUBLE_TAP_MS",
              "description": "Longest gap still counting as one gesture.",
              "optional": true,
              "type": {
                "text": "number"
              }
            },
            {
              "name": "slop",
              "default": "TAP_SLOP",
              "description": "Travel over which a press is a drag, not a tap.",
              "optional": true,
              "type": {
                "text": "number"
              }
            }
          ],
          "description": "Decide whether a press that has just ended completes a double tap.\n\niOS Safari never fires `dblclick` from a double tap - the gesture is the browser's\nown zoom - so the snap is detected from the pointer stream for every pointer type\nrather than kept in two places that would disagree per platform.",
          "return": {
            "type": {
              "text": "boolean"
            }
          }
        },
        {
          "kind": "function",
          "name": "nearestExtreme",
          "parameters": [
            {
              "name": "position",
              "description": "Current position (0-100).",
              "type": {
                "text": "number"
              }
            }
          ],
          "description": "The extreme a snap sends the handle to - whichever edge it is further from, so a\nrepeated snap toggles rather than sitting still.",
          "return": {
            "type": {
              "text": "number"
            }
          }
        },
        {
          "kind": "function",
          "name": "edgeEvent",
          "parameters": [
            {
              "name": "previous",
              "description": "Position before the move.",
              "type": {
                "text": "number"
              }
            },
            {
              "name": "next",
              "description": "Position after it.",
              "type": {
                "text": "number"
              }
            }
          ],
          "description": "The event a move has just earned by arriving at an extreme, if it arrived at one.\n\nEdge-triggered: sitting at an extreme is not arriving at it. A held arrow key, an\ninertia glide clamped at the edge for several frames, a second Home press - each\nkeeps the handle at 0 without reaching it again, and none of them fire.",
          "return": {
            "type": {
              "text": "'start'|'end'|null"
            }
          }
        },
        {
          "kind": "function",
          "name": "collapseToggle",
          "parameters": [
            {
              "name": "position",
              "description": "Current position (0-100).",
              "type": {
                "text": "number"
              }
            },
            {
              "name": "restoreTo",
              "description": "Position recorded when the pane was last collapsed.",
              "type": {
                "text": "number"
              }
            }
          ],
          "description": "Next position for the splitter's Enter key: collapse the primary pane if it is\nopen, restore it to where it was before the collapse if it is not.",
          "return": {
            "type": {
              "text": "number"
            }
          }
        },
        {
          "kind": "function",
          "name": "keyboardStep",
          "parameters": [
            {
              "name": "current",
              "description": "Current position (0-100).",
              "type": {
                "text": "number"
              }
            },
            {
              "name": "key",
              "description": "KeyboardEvent.key value.",
              "type": {
                "text": "string"
              }
            },
            {
              "name": "step",
              "description": "Arrow-key step in percent.",
              "type": {
                "text": "number"
              }
            },
            {
              "name": "pageStep",
              "description": "Page-key step in percent.",
              "type": {
                "text": "number"
              }
            }
          ],
          "description": "Compute the next position for a discrete keyboard action.",
          "return": {
            "type": {
              "text": "number|null"
            }
          }
        },
        {
          "kind": "function",
          "name": "upgradeAction",
          "parameters": [
            {
              "name": "hasChildren",
              "description": "Whether both required children are present.",
              "type": {
                "text": "boolean"
              }
            },
            {
              "name": "readyState",
              "description": "`document.readyState`.",
              "type": {
                "text": "string"
              }
            }
          ],
          "description": "What a connection should do about the required children.\n\nThe parser inserts an element - and so fires `connectedCallback` - at its start tag,\nbefore any child of it exists, so absent children are ambiguous on their own. The\ndocument's ready state is what disambiguates: still `loading` means the parser has\nnot reached them yet, anything else means it has been and gone and the markup is\nsimply wrong.",
          "return": {
            "type": {
              "text": "'build'|'wait'|'fail'"
            }
          }
        },
        {
          "kind": "class",
          "description": "",
          "name": "CompareImagesSlider",
          "members": [
            {
              "kind": "method",
              "name": "setupAccessibility",
              "description": "Wire up the W3C APG Window Splitter pattern on the handle: a focusable\nrole=\"separator\" reporting its position via ARIA. The pattern's keys live in\n`onKeyDown` - arrows and Page Up/Down to move, Home/End to the extremes, Enter\nto collapse and restore the pane named by `aria-controls`."
            },
            {
              "kind": "method",
              "name": "onKeyDown",
              "parameters": [
                {
                  "name": "e"
                }
              ]
            },
            {
              "kind": "method",
              "name": "snapToExtreme",
              "description": "Double-click or double-tap snaps to the nearest extreme (0 or 100)."
            },
            {
              "kind": "method",
              "name": "positionFromDrag",
              "parameters": [
                {
                  "name": "detail",
                  "description": "A `drag()` detail.",
                  "type": {
                    "text": "object"
                  }
                }
              ],
              "description": "Where along the slider a gesture is, out of what `drag()` measured.\n\n`within` is the slider root rather than the handle, so the percentage is along the track\nthe handle runs on rather than across the handle itself, and it is held at 0 and 100 when\nthe pointer runs off the end. The vertical layout is the same number down the other axis.",
              "return": {
                "type": {
                  "text": "number"
                }
              }
            },
            {
              "kind": "method",
              "name": "onPointerDown",
              "parameters": [
                {
                  "name": "e"
                }
              ],
              "description": "Take hold of the slider.\n\nThe gesture is `drag()` from book-of-spells, started from this `pointerdown` rather than\nhanded the element to own: started that way it writes no attributes and no inline\n`touch-action` into an element this class already set one on, and the `preventDefault`\nbelow stays this class's to do. What `drag()` owns is the pointer - the capture, the\n`pointercancel` path, the moves heard on the document - and the glide after it: the flick\nsampled over a window and capped in per cent of the track, the friction, the walls of\n`within`.\n\nWhat it is told differs from the options in two places. Its glide is two-dimensional\nunless told the axis, and the velocity across a track can outlive the one along it by most\nof a second - so it is told, and the glide is over when the handle is. And it is always\ntold to bounce: without bounce its glide carries on past the wall of `within` with\nthe percentage pinned to the edge, decaying out of sight for up to a second, whereas a\nbounce that keeps nothing is the stop at the wall this element means by `bounce: false`."
            },
            {
              "kind": "method",
              "name": "onDragStart",
              "parameters": [
                {
                  "name": "e"
                }
              ],
              "description": "The press itself, once `drag()` has measured it.\n\nRead from the gesture rather than from the `pointerdown`, so the sum that turns a pointer\ninto a percentage lives in exactly one place.\n\n`dragstart` and `dragend` are the native drag and drop API's names too, and the native ones\nbubble - with `dragAnywhere` the target is the whole slider, and an `<img>` inside it is\ndraggable without being asked. book-of-spells sends an object as `detail`; a native\n`dragstart` carries the number `UIEvent` gives it, which is what tells the two apart."
            },
            {
              "kind": "method",
              "name": "follow",
              "parameters": [
                {
                  "name": "detail"
                }
              ],
              "description": "Every move `drag()` reports, under the pointer and through the glide alike."
            },
            {
              "kind": "method",
              "name": "onDragEnd",
              "parameters": [
                {
                  "name": "e"
                }
              ]
            },
            {
              "kind": "method",
              "name": "onGlideEnd",
              "description": "The glide has settled - decayed, or stopped at the wall - and this is where `change` reports it."
            },
            {
              "kind": "method",
              "name": "onDragCancel",
              "parameters": [
                {
                  "name": "e"
                }
              ],
              "description": "The system took the gesture away - a call arriving, the page scrolling out from\nunder the finger. iOS Safari raises this far more readily than a desktop browser\ndoes. `drag()` drops the flick it was carrying and starts no glide, so the handle stops\nwhere it stands rather than flying off on a flick nobody meant to throw."
            },
            {
              "kind": "method",
              "name": "endDrag",
              "description": "Tear down a gesture, however it ended - under the pointer, through the glide, or cut short."
            },
            {
              "kind": "method",
              "name": "stopGlide",
              "description": "A key pressed mid-glide takes over from it; one pressed mid-drag leaves the pointer its gesture."
            },
            {
              "kind": "method",
              "name": "setPosition",
              "parameters": [
                {
                  "name": "pct"
                }
              ],
              "description": "Set the position (0-100), clamped, re-render and report the move."
            },
            {
              "kind": "method",
              "name": "commit",
              "description": "Report a settled position as `change`, the way a range input does - once a gesture\nis over rather than throughout it. Silent when the gesture put the handle back where\nit found it, so a press that goes nowhere is not a change."
            },
            {
              "kind": "method",
              "name": "emit",
              "parameters": [
                {
                  "name": "type",
                  "description": "Event name; the position rides along as `detail.position`.",
                  "type": {
                    "text": "string"
                  }
                }
              ]
            },
            {
              "kind": "method",
              "name": "render"
            },
            {
              "kind": "method",
              "name": "destroy"
            },
            {
              "kind": "field",
              "name": "element",
              "default": "element"
            },
            {
              "kind": "field",
              "name": "reveal"
            },
            {
              "kind": "field",
              "name": "handle"
            },
            {
              "kind": "field",
              "name": "options"
            },
            {
              "kind": "field",
              "name": "position"
            },
            {
              "kind": "field",
              "name": "committedPosition"
            },
            {
              "kind": "field",
              "name": "gesture",
              "type": {
                "text": "null"
              },
              "default": "null"
            },
            {
              "kind": "field",
              "name": "gliding",
              "type": {
                "text": "boolean"
              },
              "default": "false"
            },
            {
              "kind": "field",
              "name": "pressPosition",
              "type": {
                "text": "number"
              },
              "default": "0"
            },
            {
              "kind": "field",
              "name": "lastTapAt",
              "type": {
                "text": "number"
              },
              "default": "0"
            },
            {
              "kind": "field",
              "name": "restorePosition"
            },
            {
              "kind": "field",
              "name": "dragTarget"
            }
          ]
        },
        {
          "kind": "variable",
          "name": "DEFAULT_OPTIONS",
          "type": {
            "text": "object"
          },
          "default": "{ inertia: false, bounce: false, friction: 0.9, bounceFactor: 0.1, maxFlickVelocity: 0.5, dragAnywhere: false, vertical: false, initialPosition: 50, step: 5, pageStep: 25 }"
        },
        {
          "kind": "function",
          "name": "readOptionsFromElement",
          "parameters": [
            {
              "name": "el",
              "type": {
                "text": "HTMLElement"
              }
            }
          ],
          "description": "Read slider options from an element's attributes (bare, `data-*` or kebab).",
          "return": {
            "type": {
              "text": "Object"
            }
          }
        },
        {
          "kind": "function",
          "name": "resolveOptions",
          "parameters": [
            {
              "name": "el",
              "type": {
                "text": "HTMLElement"
              }
            },
            {
              "name": "options",
              "optional": true,
              "type": {
                "text": "Object"
              }
            }
          ],
          "description": "Merge the three option sources into one. Attributes are applied last, so markup\nwins over the options object - which is what `vertical` did back when it was the\nonly attribute the constructor honoured.",
          "return": {
            "type": {
              "text": "Object"
            }
          }
        },
        {
          "kind": "class",
          "description": "`<compare-images-slider>` custom element. Uses light DOM (no shadow root) so\nthe images, reveal layer and handle stay fully stylable by the page author.\n\nEvery attribute below is also readable as `data-*` or passed to the\n`CompareImagesSlider` constructor in its camelCase form. The constructor reads the\nelement's attributes itself, so markup wins over the options object, `data-*` wins\nover the bare attribute, and a boolean is turned off with `=\"false\"` or `=\"0\"`.",
          "name": "CompareImagesSliderElement",
          "cssProperties": [
            {
              "type": {
                "text": "<length-percentage>"
              },
              "description": "Where the reveal edge sits before the script has run. Declared on `:root`, so it is the pre-upgrade paint and not the live position.",
              "name": "--compare-images-slider-initial-position",
              "default": "50%"
            },
            {
              "type": {
                "text": "<length-percentage>"
              },
              "description": "The live reveal position, written inline by the script on every render. Read it to hang your own styling off the reveal; setting it is overwritten on the next move. Defaults to `--compare-images-slider-initial-position`.",
              "name": "--compare-images-slider-position"
            },
            {
              "type": {
                "text": "<color>"
              },
              "description": "Handle fill.",
              "name": "--compare-images-slider-handle-bg",
              "default": "#fff"
            },
            {
              "type": {
                "text": "<color>"
              },
              "description": "Handle foreground — the knob's arrows.",
              "name": "--compare-images-slider-handle-fg",
              "default": "#000"
            },
            {
              "type": {
                "text": "<length>"
              },
              "description": "Handle diameter.",
              "name": "--compare-images-slider-handle-size",
              "default": "42px"
            },
            {
              "type": {
                "text": "<length>"
              },
              "description": "Handle glyph size, for a handle drawn with text rather than the svg knob.",
              "name": "--compare-images-slider-handle-font-size",
              "default": "28px"
            }
          ],
          "events": [
            {
              "type": {
                "text": "CustomEvent<{ position: number }>"
              },
              "description": "Every move as it happens - drag, key, inertia frame - like an `<input type=\"range\">`. Silent when a move lands where the handle already was.",
              "name": "input"
            },
            {
              "type": {
                "text": "CustomEvent<{ position: number }>"
              },
              "description": "The position has settled: a press released, a flick come to rest, a key pressed. Silent when the gesture ended where it started.",
              "name": "change"
            },
            {
              "type": {
                "text": "CustomEvent<{ position: number }>"
              },
              "description": "The handle has just reached 0, the fully collapsed end. Fires on arrival, not while it sits there.",
              "name": "start"
            },
            {
              "type": {
                "text": "CustomEvent<{ position: number }>"
              },
              "description": "The handle has just reached 100, the fully revealed end. Fires on arrival, not while it sits there.",
              "name": "end"
            }
          ],
          "attributes": [
            {
              "type": {
                "text": "boolean"
              },
              "description": "Keep gliding after a flick.",
              "name": "inertia",
              "default": "false"
            },
            {
              "type": {
                "text": "boolean"
              },
              "description": "Bounce off the edges while under inertia. Does nothing without `inertia`.",
              "name": "bounce",
              "default": "false"
            },
            {
              "type": {
                "text": "boolean"
              },
              "description": "Split top and bottom instead of left and right.",
              "name": "vertical",
              "default": "false"
            },
            {
              "type": {
                "text": "boolean"
              },
              "description": "A press anywhere on the images starts a drag, not only the handle.",
              "name": "drag-anywhere",
              "default": "false"
            },
            {
              "type": {
                "text": "number"
              },
              "description": "Inertia decay per frame, 0-1. Applied frame-rate independently, so the feel holds across displays.",
              "name": "friction",
              "default": "0.9"
            },
            {
              "type": {
                "text": "number"
              },
              "description": "Energy kept on a bounce, 0-1.",
              "name": "bounce-factor",
              "default": "0.1"
            },
            {
              "type": {
                "text": "number"
              },
              "description": "Cap on flick velocity, percent per millisecond.",
              "name": "max-flick-velocity",
              "default": "0.5"
            },
            {
              "type": {
                "text": "number"
              },
              "description": "Starting position, 0-100. Paint it with `--compare-images-slider-initial-position` too, or the reveal layer is at 50% until the script runs.",
              "name": "initial-position",
              "default": "50"
            },
            {
              "type": {
                "text": "number"
              },
              "description": "Arrow-key step, in percent.",
              "name": "step",
              "default": "5"
            },
            {
              "type": {
                "text": "number"
              },
              "description": "Page Up/Down step, in percent.",
              "name": "page-step",
              "default": "25"
            }
          ],
          "superclass": {
            "name": "ElementBase",
            "module": "src/scripts/compare-images-slider.js"
          },
          "tagName": "compare-images-slider",
          "customElement": true
        }
      ],
      "exports": [
        {
          "kind": "js",
          "name": "isDoubleTap",
          "declaration": {
            "name": "isDoubleTap",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "nearestExtreme",
          "declaration": {
            "name": "nearestExtreme",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "edgeEvent",
          "declaration": {
            "name": "edgeEvent",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "collapseToggle",
          "declaration": {
            "name": "collapseToggle",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "keyboardStep",
          "declaration": {
            "name": "keyboardStep",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "upgradeAction",
          "declaration": {
            "name": "upgradeAction",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "default",
          "declaration": {
            "name": "CompareImagesSlider",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "DEFAULT_OPTIONS",
          "declaration": {
            "name": "DEFAULT_OPTIONS",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "readOptionsFromElement",
          "declaration": {
            "name": "readOptionsFromElement",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "resolveOptions",
          "declaration": {
            "name": "resolveOptions",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "js",
          "name": "CompareImagesSliderElement",
          "declaration": {
            "name": "CompareImagesSliderElement",
            "module": "src/scripts/compare-images-slider.js"
          }
        },
        {
          "kind": "custom-element-definition",
          "name": "compare-images-slider",
          "declaration": {
            "name": "CompareImagesSliderElement",
            "module": "src/scripts/compare-images-slider.js"
          }
        }
      ]
    }
  ]
}
