Skip to content

Commit

Permalink
release
Browse files Browse the repository at this point in the history
  • Loading branch information
martrapp committed Jan 25, 2025
1 parent e6e678d commit 8b2d2f5
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 61 deletions.
5 changes: 5 additions & 0 deletions .changeset/calm-bulldogs-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vtbag/utensil-drawer': patch
---

Still not officially supported. Code refactorings and renames. Breaking: vtn -> declarative-names.
36 changes: 18 additions & 18 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
],
"exports": {
".": "./lib/index.js",
"./vtn": "./lib/bundled/vtn.js"
"./declarative-names": "./lib/bundled/declarative-names.js"
},
"scripts": {
"dev": "bin/bundle dev",
Expand Down Expand Up @@ -47,12 +47,12 @@
"url": "https://github.com/sponsors/martrapp"
},
"devDependencies": {
"@changesets/cli": "^2.27.11",
"@eslint/js": "^9.17.0",
"@changesets/cli": "^2.27.12",
"@eslint/js": "^9.19.0",
"@types/dom-navigation": "^1.0.4",
"@types/dom-view-transitions": "^1.0.5",
"esbuild": "^0.24.2",
"prettier": "^3.4.2",
"typescript": "^5.7.2"
"typescript": "^5.7.3"
}
}
39 changes: 39 additions & 0 deletions src/bundled/declarative-names.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { setSelectedViewTransitionNames } from '../set-view-transition-names';

/* This scripts must be loaded inside the `<head>` of a page.
The function sets up eventListeners that look for script elements with a `data-vtbag-decl` attribute and uses its value to set view transition names. The value is interpreted as a semicolon separated list of `<selector> '=' <prefix>` pairs. Those pairs are then used to set view transition names.
See setSelectedViewTransitionNames() for additional information.
Do not use '=' or ';' in <selector> or <prefix> values
While the `data-vtbag-decl` attribute is interpreted for the old and for the new page, the `data-vtbag-decl-new` and `data-vtbag-decl-old` attributes are only interpreted when the page is entered and left, respectively. This allows for different view transition names to be set for defining different enter and exit animations when the page is the source or the target page of a navigation.
The elements are also labeled after the DOM is initially loaded but will be updated (extended) on pageswap.
This behavior enables you to access the view transition names before the swap event, e.g. in a click handler, even after a full page reload.
*/
export function setViewTransitionNamesFromScripts() {
addEventListener('DOMContentLoaded', set('old'));
addEventListener('pagereveal', set('new'));
addEventListener('pageswap', set('old'));
}
function set(what: 'new' | 'old') {
return () => {
document.querySelectorAll('script').forEach((script) => {
const spec =
(script.getAttribute('data-vtbag-decl') ?? '') +
';' +
(script.getAttribute(`data-vtbag-decl-${what}`) ?? '');
spec.split(/\s*;\s*/).forEach((cmd) => {
let [selector, prefix] = cmd.split(/=/, 2);
if (prefix !== undefined) {
const weak = selector.endsWith('~');
weak && (selector = selector.slice(0, -1));
setSelectedViewTransitionNames(selector.trim(), prefix.trim(), !weak);
}});
});
};
}
setViewTransitionNamesFromScripts();
30 changes: 0 additions & 30 deletions src/bundled/vtn.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/dom-view-transisions-level2.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ declare global {
}

type UpdateCallback = undefined | (() => void | Promise<void>);
type StartViewTransitionParameter = { types?: string[]; update?: UpdateCallback };
type StartViewTransitionParameter = { types?: string[] | Set<string>; update?: UpdateCallback };

interface Document {
startViewTransition(param?: StartViewTransitionParameter | UpdateCallback): ViewTransition;
Expand Down
1 change: 0 additions & 1 deletion src/drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ function patch(startViewTransition: typeof Document.prototype.startViewTransitio
function update(updateDOM?: () => Promise<void> | void) {
return async () => {
updateDOM && (await updateDOM());
console.log('drawer.viewTransition :>> ', drawer.viewTransition);
drawer.after.map((interceptor) => interceptor(drawer.viewTransition!));
drawer.after = [];
};
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export {
setViewTransitionNames,
setGivenViewTransitionNames,
setSelectedViewTransitionNames,
setOldPageViewTransitionNames,
setNewPageViewTransitionNames,
} from './set-view-transition-names';
Expand Down
1 change: 0 additions & 1 deletion src/may-start-view-transition.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ensureDrawer } from './drawer';
import { Update } from './types';

export function mayStartViewTransition(param: StartViewTransitionParameter, breakExisting = false) {
const drawer = ensureDrawer();
Expand Down
35 changes: 30 additions & 5 deletions src/set-view-transition-names.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
export function setViewTransitionNames(selector: string, prefix: any) {
const elements = document.querySelectorAll<HTMLElement>(selector);
/* Sets the view transition name in the style attribute of selected elements, see setGivenViewTransitionNames.
`selector´is an arbitrary CSS selector for the current document
*/
export function setSelectedViewTransitionNames(selector: string, prefix: any, force = false) {
setGivenViewTransitionNames([...document.querySelectorAll<HTMLElement>(selector)], prefix, force);
}

/* Sets the view transition name in the style attribute of the given elements.
If `elements` has exactly one entry, `prefix` is used as a name.
Otherwise the `elements` are named with the `prefix` with an appended index starting from 0.
If `force` is true, the names are always set, otherwise only if they are not already set.
If the prefix string ends with a '~', the character is replaced by a '-' and the names are assigned in random order.
*/
export function setGivenViewTransitionNames(elements: HTMLElement[], prefix: string, force = false) {
if (prefix[prefix.length - 1] === '~') {
prefix = prefix.slice(0, -1) + '-';
shuffle(elements);
}
elements.forEach((element, idx, array) => {
element.style.viewTransitionName = `${prefix}${array.length > 1 ? idx : ''}`;
force && (element.style.viewTransitionName = `${prefix}${array.length > 1 ? idx : ''}`)
|| (element.style.viewTransitionName ||= `${prefix}${array.length > 1 ? idx : ''}`);
});
}

export function setOldPageViewTransitionNames(selector: string, prefix: any) {
addEventListener('pageswap', () => setViewTransitionNames(selector, prefix));
addEventListener('pageswap', () => setSelectedViewTransitionNames(selector, prefix));
}

// The pagereveal event fires very early. Thus scripts using this code should load inside the <head>
export function setNewPageViewTransitionNames(selector: string, prefix: any) {
addEventListener('pagereveal', () => setViewTransitionNames(selector, prefix));
addEventListener('pagereveal', () => setSelectedViewTransitionNames(selector, prefix));
}

function shuffle<T>(array: T[]): T[] {
for (let i = array.length - 1; i > 0; --i) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}

0 comments on commit 8b2d2f5

Please sign in to comment.