From 8b2d2f524369ab5d67feb0a98651b3cc9909b6f7 Mon Sep 17 00:00:00 2001
From: Martin Trapp <94928215+martrapp@users.noreply.github.com>
Date: Sat, 25 Jan 2025 08:45:30 +0100
Subject: [PATCH] release
---
.changeset/calm-bulldogs-repeat.md | 5 ++++
package-lock.json | 36 ++++++++++++-------------
package.json | 8 +++---
src/bundled/declarative-names.ts | 39 ++++++++++++++++++++++++++++
src/bundled/vtn.ts | 30 ---------------------
src/dom-view-transisions-level2.d.ts | 2 +-
src/drawer.ts | 1 -
src/index.ts | 3 ++-
src/may-start-view-transition.ts | 1 -
src/set-view-transition-names.ts | 35 +++++++++++++++++++++----
10 files changed, 99 insertions(+), 61 deletions(-)
create mode 100644 .changeset/calm-bulldogs-repeat.md
create mode 100644 src/bundled/declarative-names.ts
delete mode 100644 src/bundled/vtn.ts
diff --git a/.changeset/calm-bulldogs-repeat.md b/.changeset/calm-bulldogs-repeat.md
new file mode 100644
index 0000000..9efa4f2
--- /dev/null
+++ b/.changeset/calm-bulldogs-repeat.md
@@ -0,0 +1,5 @@
+---
+'@vtbag/utensil-drawer': patch
+---
+
+Still not officially supported. Code refactorings and renames. Breaking: vtn -> declarative-names.
diff --git a/package-lock.json b/package-lock.json
index ea1b787..f7d5d1d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,21 +1,21 @@
{
"name": "@vtbag/utensil-drawer",
- "version": "0.0.2",
+ "version": "0.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@vtbag/utensil-drawer",
- "version": "0.0.2",
+ "version": "0.0.3",
"license": "ISC",
"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"
},
"funding": {
"type": "github",
@@ -36,9 +36,9 @@
}
},
"node_modules/@changesets/apply-release-plan": {
- "version": "7.0.7",
- "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.7.tgz",
- "integrity": "sha512-qnPOcmmmnD0MfMg9DjU1/onORFyRpDXkMMl2IJg9mECY6RnxL3wN0TCCc92b2sXt1jt8DgjAUUsZYGUGTdYIXA==",
+ "version": "7.0.8",
+ "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.8.tgz",
+ "integrity": "sha512-qjMUj4DYQ1Z6qHawsn7S71SujrExJ+nceyKKyI9iB+M5p9lCL55afuEd6uLBPRpLGWQwkwvWegDHtwHJb1UjpA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -98,13 +98,13 @@
}
},
"node_modules/@changesets/cli": {
- "version": "2.27.11",
- "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.27.11.tgz",
- "integrity": "sha512-1QislpE+nvJgSZZo9+Lj3Lno5pKBgN46dAV8IVxKJy9wX8AOrs9nn5pYVZuDpoxWJJCALmbfOsHkyxujgetQSg==",
+ "version": "2.27.12",
+ "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.27.12.tgz",
+ "integrity": "sha512-9o3fOfHYOvBnyEn0mcahB7wzaA3P4bGJf8PNqGit5PKaMEFdsRixik+txkrJWd2VX+O6wRFXpxQL8j/1ANKE9g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@changesets/apply-release-plan": "^7.0.7",
+ "@changesets/apply-release-plan": "^7.0.8",
"@changesets/assemble-release-plan": "^6.0.5",
"@changesets/changelog-git": "^0.2.0",
"@changesets/config": "^3.0.5",
@@ -732,9 +732,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.17.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz",
- "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==",
+ "version": "9.19.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
+ "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1743,9 +1743,9 @@
}
},
"node_modules/typescript": {
- "version": "5.7.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
- "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
+ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
diff --git a/package.json b/package.json
index 5423e14..92db00b 100644
--- a/package.json
+++ b/package.json
@@ -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",
@@ -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"
}
}
diff --git a/src/bundled/declarative-names.ts b/src/bundled/declarative-names.ts
new file mode 100644
index 0000000..15e627c
--- /dev/null
+++ b/src/bundled/declarative-names.ts
@@ -0,0 +1,39 @@
+import { setSelectedViewTransitionNames } from '../set-view-transition-names';
+
+/* This scripts must be loaded inside the `
` 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 ` '=' ` pairs. Those pairs are then used to set view transition names.
+
+See setSelectedViewTransitionNames() for additional information.
+
+Do not use '=' or ';' in or 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();
diff --git a/src/bundled/vtn.ts b/src/bundled/vtn.ts
deleted file mode 100644
index b1e46eb..0000000
--- a/src/bundled/vtn.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { setViewTransitionNames } from '../set-view-transition-names';
-
-/* The pagereveal event fires very early. Thus this scripts should load inside the ``
-
-The function sets up eventListeners that look for script elements with a `data-spec` attribute and uses its value to set view transition names. The value is interpreted as a semicolon separated list of `:` pairs. Those pairs are then used to set view transition names by calling setViewTransitionNames().
-
-While the `data-spec` attribute is interpreted on both, when the page is entered and when it is left, the `data-spec-in` and `data-spec-out` attributes are only interpreted when the page is entered and left, respectively. This allows for different view transition names to be set when the page is entered and left thus defining enter and exit animations.
-
-The elements are also labeled after the DOM is initially loaded but will be updated on pageswap. This 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('in'));
- addEventListener('pagereveal', set('in'));
- addEventListener('pageswap', set('out'));
-}
-function set(what: 'in' | 'out') {
- return () => {
- document.querySelectorAll('script').forEach((script) => {
- const spec =
- (script.getAttribute('data-spec') ?? '') +
- ';' +
- (script.getAttribute(`data-spec-${what}`) ?? '');
- spec.split(/\s*;\s*/).forEach((cmd) => {
- const [selector, prefix] = cmd.split(/\s*:\s*/, 2);
- if (prefix !== undefined) setViewTransitionNames(selector, prefix.trim());
- });
- });
- };
-}
-setViewTransitionNamesFromScripts();
diff --git a/src/dom-view-transisions-level2.d.ts b/src/dom-view-transisions-level2.d.ts
index 3971a20..3636a4c 100644
--- a/src/dom-view-transisions-level2.d.ts
+++ b/src/dom-view-transisions-level2.d.ts
@@ -5,7 +5,7 @@ declare global {
}
type UpdateCallback = undefined | (() => void | Promise);
- type StartViewTransitionParameter = { types?: string[]; update?: UpdateCallback };
+ type StartViewTransitionParameter = { types?: string[] | Set; update?: UpdateCallback };
interface Document {
startViewTransition(param?: StartViewTransitionParameter | UpdateCallback): ViewTransition;
diff --git a/src/drawer.ts b/src/drawer.ts
index 96ddb64..d4dce80 100644
--- a/src/drawer.ts
+++ b/src/drawer.ts
@@ -31,7 +31,6 @@ function patch(startViewTransition: typeof Document.prototype.startViewTransitio
function update(updateDOM?: () => Promise | void) {
return async () => {
updateDOM && (await updateDOM());
- console.log('drawer.viewTransition :>> ', drawer.viewTransition);
drawer.after.map((interceptor) => interceptor(drawer.viewTransition!));
drawer.after = [];
};
diff --git a/src/index.ts b/src/index.ts
index a3c50e1..327d091 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,6 @@
export {
- setViewTransitionNames,
+ setGivenViewTransitionNames,
+ setSelectedViewTransitionNames,
setOldPageViewTransitionNames,
setNewPageViewTransitionNames,
} from './set-view-transition-names';
diff --git a/src/may-start-view-transition.ts b/src/may-start-view-transition.ts
index 1f7eb35..ead44e5 100644
--- a/src/may-start-view-transition.ts
+++ b/src/may-start-view-transition.ts
@@ -1,5 +1,4 @@
import { ensureDrawer } from './drawer';
-import { Update } from './types';
export function mayStartViewTransition(param: StartViewTransitionParameter, breakExisting = false) {
const drawer = ensureDrawer();
diff --git a/src/set-view-transition-names.ts b/src/set-view-transition-names.ts
index 1b51ad3..a4850ac 100644
--- a/src/set-view-transition-names.ts
+++ b/src/set-view-transition-names.ts
@@ -1,15 +1,40 @@
-export function setViewTransitionNames(selector: string, prefix: any) {
- const elements = document.querySelectorAll(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(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
export function setNewPageViewTransitionNames(selector: string, prefix: any) {
- addEventListener('pagereveal', () => setViewTransitionNames(selector, prefix));
+ addEventListener('pagereveal', () => setSelectedViewTransitionNames(selector, prefix));
+}
+
+function shuffle(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;
}