diff --git a/package-lock.json b/package-lock.json index 30576bb..e81ef98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tram-one", - "version": "13.2.0", + "version": "13.2.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "tram-one", - "version": "13.2.0", + "version": "13.2.1", "license": "MIT", "dependencies": { "@nx-js/observer-util": "^4.2.2", diff --git a/package.json b/package.json index 8592b57..2f8b872 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tram-one", - "version": "13.2.0", + "version": "13.2.1", "description": "🚋 Modern View Framework for Vanilla Javascript", "main": "dist/tram-one.cjs", "commonjs": "dist/tram-one.cjs", diff --git a/src/dom.ts b/src/dom.ts index 70e8cdd..3b6c70b 100644 --- a/src/dom.ts +++ b/src/dom.ts @@ -12,7 +12,14 @@ import { } from './working-key'; import observeTag from './observe-tag'; import processHooks from './process-hooks'; -import { TRAM_TAG, TRAM_TAG_NEW_EFFECTS, TRAM_TAG_CLEANUP_EFFECTS } from './node-names'; +import { + TRAM_TAG, + TRAM_TAG_NEW_EFFECTS, + TRAM_TAG_CLEANUP_EFFECTS, + TRAM_TAG_NAME, + TRAM_TAG_PROPS, + TRAM_TAG_CHILDREN, +} from './node-names'; import { Registry, Props, DOMTaggedTemplateFunction, Children, TramOneHTMLElement, TramOneSVGElement } from './types'; @@ -69,6 +76,13 @@ export const registerDom = (key?: string, value?: Store): Store = getKeyQueue(TRAM_KEY_QUEUE).push(resolvedKey); } + // if this is a development environment, save the global store key to the element + if (!isLocalStore && process.env.NODE_ENV === 'development') { + getKeyQueue(TRAM_GLOBAL_KEY_QUEUE).push(resolvedKey); + } + // return value return keyValue; }; diff --git a/src/observe-tag.ts b/src/observe-tag.ts index cef5776..ee9371b 100644 --- a/src/observe-tag.ts +++ b/src/observe-tag.ts @@ -1,6 +1,14 @@ const { observe } = require('@nx-js/observer-util'); -import { TRAM_TAG_REACTION, TRAM_TAG_NEW_EFFECTS, TRAM_TAG_CLEANUP_EFFECTS, TRAM_TAG } from './node-names'; +import { + TRAM_TAG_REACTION, + TRAM_TAG_NEW_EFFECTS, + TRAM_TAG_CLEANUP_EFFECTS, + TRAM_TAG, + TRAM_TAG_NAME, + TRAM_TAG_PROPS, + TRAM_TAG_GLOBAL_STORE_KEYS, +} from './node-names'; import { TramOneElement, RemovedElementDataStore, Reaction, ElementPotentiallyWithSelectionAndFocus } from './types'; // functions to go to nodes or indices (made for .map) @@ -97,6 +105,13 @@ export default (tagFunction: () => TramOneElement): TramOneElement => { emptyDiv[TRAM_TAG_NEW_EFFECTS] = oldTag[TRAM_TAG_NEW_EFFECTS]; emptyDiv[TRAM_TAG_CLEANUP_EFFECTS] = oldTag[TRAM_TAG_CLEANUP_EFFECTS]; + // copy over development props + if (process.env.NODE_ENV === 'development') { + emptyDiv[TRAM_TAG_NAME] = oldTag[TRAM_TAG_NAME]; + emptyDiv[TRAM_TAG_PROPS] = oldTag[TRAM_TAG_PROPS]; + emptyDiv[TRAM_TAG_GLOBAL_STORE_KEYS] = oldTag[TRAM_TAG_GLOBAL_STORE_KEYS]; + } + // set oldTag to emptyDiv, so we can replace it later oldTag = emptyDiv; } @@ -146,6 +161,13 @@ export default (tagFunction: () => TramOneElement): TramOneElement => { tagResult[TRAM_TAG_NEW_EFFECTS] = oldTag[TRAM_TAG_NEW_EFFECTS]; tagResult[TRAM_TAG_CLEANUP_EFFECTS] = oldTag[TRAM_TAG_CLEANUP_EFFECTS]; + // copy over development props + if (process.env.NODE_ENV === 'development') { + tagResult[TRAM_TAG_NAME] = oldTag[TRAM_TAG_NAME]; + tagResult[TRAM_TAG_PROPS] = oldTag[TRAM_TAG_PROPS]; + tagResult[TRAM_TAG_GLOBAL_STORE_KEYS] = oldTag[TRAM_TAG_GLOBAL_STORE_KEYS]; + } + // both these actions cause forced reflow, and can be performance issues oldTag.replaceWith(tagResult); if (elementToGiveFocus && elementToGiveFocus.focus) elementToGiveFocus.focus(); diff --git a/src/process-hooks.ts b/src/process-hooks.ts index e188a13..d784870 100644 --- a/src/process-hooks.ts +++ b/src/process-hooks.ts @@ -1,5 +1,5 @@ -import { TRAM_EFFECT_STORE, TRAM_EFFECT_QUEUE, TRAM_KEY_QUEUE } from './engine-names'; -import { TRAM_TAG_NEW_EFFECTS, TRAM_TAG_STORE_KEYS } from './node-names'; +import { TRAM_EFFECT_STORE, TRAM_EFFECT_QUEUE, TRAM_KEY_QUEUE, TRAM_GLOBAL_KEY_QUEUE } from './engine-names'; +import { TRAM_TAG_GLOBAL_STORE_KEYS, TRAM_TAG_NEW_EFFECTS, TRAM_TAG_STORE_KEYS } from './node-names'; import { getEffectStore, clearEffectStore, restoreEffectStore } from './effect-store'; import { TramOneElement } from './types'; import { clearKeyQueue, getKeyQueue, restoreKeyQueue } from './key-queue'; @@ -20,6 +20,7 @@ export default (tagFunction: () => TramOneElement) => { // clear the queues (so we can get just new effects and keys) clearEffectStore(TRAM_EFFECT_QUEUE); clearKeyQueue(TRAM_KEY_QUEUE); + clearKeyQueue(TRAM_GLOBAL_KEY_QUEUE); // create the component, which will save new effects to the effect queue const tagResult = tagFunction(); @@ -48,6 +49,16 @@ export default (tagFunction: () => TramOneElement) => { const existingNewAndBrandNewKeys = existingNewKeys.concat(newKeys); tagResult[TRAM_TAG_STORE_KEYS] = existingNewAndBrandNewKeys; + // if this is development environment, save global store keys to the element + if (process.env.NODE_ENV === 'development') { + const existingNewGlobalKeys = tagResult[TRAM_TAG_GLOBAL_STORE_KEYS] || []; + const newGlobalKeys = getKeyQueue(TRAM_GLOBAL_KEY_QUEUE); + + // store global store keys in the node we just built + const existingNewAndBrandNewGlobalKeys = existingNewGlobalKeys.concat(newGlobalKeys); + tagResult[TRAM_TAG_GLOBAL_STORE_KEYS] = existingNewAndBrandNewGlobalKeys; + } + // restore the effect and key queues to what they were before we started restoreEffectStore(TRAM_EFFECT_QUEUE, existingQueuedEffects); restoreKeyQueue(TRAM_KEY_QUEUE, existingQueuedKeys); diff --git a/src/start.ts b/src/start.ts index b9753da..c649d3a 100644 --- a/src/start.ts +++ b/src/start.ts @@ -8,6 +8,7 @@ import { TRAM_MUTATION_OBSERVER, TRAM_KEY_QUEUE, TRAM_KEY_STORE, + TRAM_GLOBAL_KEY_QUEUE, } from './engine-names'; import { setupTramOneSpace } from './namespace'; import { setupEffectStore } from './effect-store'; @@ -59,6 +60,9 @@ export default (component: RootTramOneComponent, target: ElementOrSelector) => { // setup key queue for new observable stores when resolving mounts setupKeyQueue(TRAM_KEY_QUEUE); + // setup key queue for global observable stores when resolving mounts + setupKeyQueue(TRAM_GLOBAL_KEY_QUEUE); + // setup a mutation observer for cleaning up removed elements and triggering effects setupMutationObserver(TRAM_MUTATION_OBSERVER); diff --git a/src/types.ts b/src/types.ts index 53cff5c..b207844 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,6 +4,10 @@ import { TRAM_TAG_NEW_EFFECTS, TRAM_TAG_CLEANUP_EFFECTS, TRAM_TAG_STORE_KEYS, + TRAM_TAG_NAME, + TRAM_TAG_PROPS, + TRAM_TAG_GLOBAL_STORE_KEYS, + TRAM_TAG_CHILDREN, } from './node-names'; /* ============= PUBLIC TYPES ======================================== @@ -106,6 +110,12 @@ export interface TramOneElement extends Element { [TRAM_TAG_NEW_EFFECTS]: Effect[]; [TRAM_TAG_CLEANUP_EFFECTS]: CleanupEffect[]; [TRAM_TAG_STORE_KEYS]: string[]; + + // development properties, these are not guarnteed to be on the element + [TRAM_TAG_NAME]?: string; + [TRAM_TAG_PROPS]?: Props; + [TRAM_TAG_CHILDREN]?: Children; + [TRAM_TAG_GLOBAL_STORE_KEYS]?: string[]; } export type TramOneHTMLElement = TramOneElement & HTMLElement;