Skip to content

Commit

Permalink
Expose morphing functions for consumer use
Browse files Browse the repository at this point in the history
Document and export the range of morphing available to Turbo's
internals. The continuum spans from morphing elements, to morphing their
children, to morphing turbo-frame elements, to morphing body elements.

Instead of exporting Idiomorph directly, this commit exports a mix of
the utility functions and the Morphing-prefixed `.renderElement` class
functions. This way, the range of `turbo:`-prefixed are dispatched
regardless of whether the call originated Turbo-side or
application-side.
  • Loading branch information
seanpdoyle committed Sep 24, 2024
1 parent 73cde75 commit 4e78842
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { PageSnapshot } from "./drive/page_snapshot"
import { FrameRenderer } from "./frames/frame_renderer"
import { fetch, recentRequests } from "../http/fetch"
import { config } from "./config"
import { MorphingPageRenderer } from "./drive/morphing_page_renderer"
import { MorphingFrameRenderer } from "./frames/morphing_frame_renderer"

export { morphChildren, morphElements } from "./morphing"

const session = new Session(recentRequests)
const { cache, navigator } = session
Expand Down Expand Up @@ -116,3 +120,29 @@ export function setFormMode(mode) {
)
config.forms.mode = mode
}

/**
* Morph the state of the currentBody based on the attributes and contents of
* the newBody. Morphing body elements may dispatch turbo:morph,
* turbo:before-morph-element, turbo:before-morph-attribute, and
* turbo:morph-element events.
*
* @param currentBody HTMLBodyElement destination of morphing changes
* @param newBody HTMLBodyElement source of morphing changes
*/
export function morphBodyElements(currentBody, newBody) {
MorphingPageRenderer.renderElement(currentBody, newBody)
}

/**
* Morph the child elements of the currentFrame based on the child elements of
* the newFrame. Morphing turbo-frame elements may dispatch turbo:before-frame-morph,
* turbo:before-morph-element, turbo:before-morph-attribute, and
* turbo:morph-element events.
*
* @param currentFrame FrameElement destination of morphing children changes
* @param newFrame FrameElement source of morphing children changes
*/
export function morphTurboFrameElements(currentFrame, newFrame) {
MorphingFrameRenderer.renderElement(currentFrame, newFrame)
}
16 changes: 16 additions & 0 deletions src/core/morphing.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { Idiomorph } from "idiomorph/dist/idiomorph.esm.js"
import { dispatch } from "../util"

/**
* Morph the state of the currentElement based on the attributes and contents of
* the newElement. Morphing may dispatch turbo:before-morph-element,
* turbo:before-morph-attribute, and turbo:morph-element events.
*
* @param currentElement Element destination of morphing changes
* @param newElement Element source of morphing changes
*/
export function morphElements(currentElement, newElement, { callbacks, ...options } = {}) {
Idiomorph.morph(currentElement, newElement, {
...options,
callbacks: new DefaultIdiomorphCallbacks(callbacks)
})
}

/**
* Morph the child elements of the currentElement based on the child elements of
* the newElement. Morphing children may dispatch turbo:before-morph-element,
* turbo:before-morph-attribute, and turbo:morph-element events.
*
* @param currentElement Element destination of morphing children changes
* @param newElement Element source of morphing children changes
*/
export function morphChildren(currentElement, newElement) {
morphElements(currentElement, newElement.children, {
morphStyle: "innerHTML"
Expand Down
4 changes: 4 additions & 0 deletions src/tests/unit/export_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ test("Turbo interface", () => {
assert.equal(typeof Turbo.session.drive, "boolean")
assert.equal(typeof Turbo.session.formMode, "string")
assert.equal(typeof Turbo.fetch, "function")
assert.equal(typeof Turbo.morphElements, "function")
assert.equal(typeof Turbo.morphChildren, "function")
assert.equal(typeof Turbo.morphBodyElements, "function")
assert.equal(typeof Turbo.morphTurboFrameElements, "function")
})

test("Session interface", () => {
Expand Down

0 comments on commit 4e78842

Please sign in to comment.