taggedjs
Version:
tagged template reactive html
164 lines • 6.79 kB
JavaScript
import { output } from '../tag/output.function.js';
import { getInnerHTML } from '../TagJsTags/getInnerHTML.function.js';
import { callback, promise, setUseMemory, state } from '../state/index.js';
import { getTemplaterResult } from '../tag/getTemplaterResult.function.js';
import { tags } from '../tag/tag.utils.js';
import { getTagWrap } from '../tag/getTagWrap.function.js';
import { ValueTypes } from '../tag/ValueTypes.enum.js';
import { processTagComponentInit } from '../tag/update/processTagComponentInit.function.js';
import { checkTagValueChangeAndUpdate } from '../tag/checkTagValueChange.function.js';
import { destroySupportByContextItem } from '../tag/destroySupportByContextItem.function.js';
import { tagValueUpdateHandler } from '../tag/update/tagValueUpdateHandler.function.js';
import { getContextInCycle, getElement as getTagElement } from '../tag/cycles/setContextInCycle.function.js';
import { tagInject } from './tagInject.function.js';
import { onInit as tagOnInit } from '../state/onInit.function.js';
import { onDestroy as tagOnDestroy } from '../state/onDestroy.function.js';
import { callback as tagCallback } from '../state/callback.function.js';
import { onRender as tagOnRender } from '../state/onRender.function.js';
let tagCount = 0;
const onClick = makeEventListener('click');
const onMouseDown = makeEventListener('mousedown');
function makeEventListener(type) {
return function eventListener(toBeCalled) {
const wrapped = callback(toBeCalled); // should cause render to occur
// run one time
state(() => {
const element = getTagElement();
element.addEventListener(type, wrapped);
});
return wrapped; // this is what you remove
};
}
const tagElement = {
get: getTagElement,
onclick: onClick,
click: onClick,
onClick,
mousedown: onMouseDown,
onmousedown: onMouseDown,
onMouseDown: onMouseDown,
};
defineGetSet('onclick', onClick);
defineGetSet('click', onClick);
defineGetSet('onMouseDown', onMouseDown);
defineGetSet('onmousedown', onMouseDown);
defineGetSet('mousedown', onMouseDown);
function defineGetSet(name, eventFn) {
Object.defineProperty(tag, name, {
get() {
return eventFn;
},
set(fn) {
return eventFn(fn);
},
});
}
/** How to handle checking for prop changes aka argument changes */
export var PropWatches;
(function (PropWatches) {
PropWatches["DEEP"] = "deep";
/** checks all values up to 2 levels deep */
PropWatches["SHALLOW"] = "shallow";
PropWatches["NONE"] = "none";
PropWatches["IMMUTABLE"] = "immutable";
})(PropWatches || (PropWatches = {}));
/** Wraps a function tag in a state manager and calls wrapped function on event cycles */
export function tag(tagComponent, propWatch = PropWatches.SHALLOW) {
const isRunningContent = getContextInCycle();
if (isRunningContent) {
throw new Error('A TaggedJs tag was created within a running tag. All component tags must be created outside of anyother tag');
}
// ): TagJsComponent<any> {
/** function developer triggers */
const parentWrap = function tagWrapper(...props) {
const templater = getTemplaterResult(propWatch, props);
templater.tagJsType = ValueTypes.tagComponent;
templater.processInit = processTagComponentInit;
templater.hasValueChanged = checkTagValueChangeAndUpdate;
// attach memory back to original function that contains developer display logic
const innerTagWrap = getTagWrap(templater, parentWrap);
innerTagWrap.original = tagComponent;
templater.wrapper = innerTagWrap;
return templater;
}; // we override the function provided and pretend original is what's returned
const tag = tagComponent;
parentWrap.original = tagComponent;
// group tags together and have hmr pickup
tag.tags = tags;
tag.setUse = setUseMemory;
tag.ValueTypes = ValueTypes;
tag.tagIndex = tagCount++; // needed for things like HMR
tags.push(parentWrap);
const returnWrap = parentWrap;
/* Used for setting arguments as inputs and outputs. Runs every init and update of tag */
returnWrap.inputs = (handler) => {
const context = getContextInCycle();
context.inputsHandler = handler;
const tagJsVar = context.tagJsVar;
// const value = context.value as any
// handler(value.props)
handler(tagJsVar.props);
return true;
};
// used for argument updates
returnWrap.updates = (handler) => {
const context = getContextInCycle();
context.updatesHandler = handler;
return true;
};
returnWrap.getInnerHTML = getInnerHTML;
// returnWrap.tagJsType = 'component'
return returnWrap;
}
/** Use to structure and define a browser tag route handler
* Example: export default tag.route = (routeProps: RouteProps) => (state) => html``
*/
function routeFn(_routeProps) {
throw new Error('Do not call tag.route as a function but instead set it as: `tag.route = (routeProps: RouteProps) => (state) => html`` `');
}
/** Used to create variable scoping when calling a function that lives within a prop container function */
function tagUseFn() {
throw new Error('Do not call tag.use as a function but instead set it as: `(props) => tag.use = (use) => html`` `');
}
// actually placing of items into tag memory
;
tag.element = tagElement;
tag.use = tagUseFn;
tag.deepPropWatch = tag;
tag.route = routeFn;
tag.inject = tagInject;
tag.output = output;
tag.onInit = tagOnInit;
tag.onDestroy = tagOnDestroy;
tag.callback = tagCallback;
tag.onRender = tagOnRender;
tag.getInnerHTML = getInnerHTML;
tag.app = function (_routeTag) {
throw new Error('Do not call tag.route as a function but instead set it as: `tag.route = (routeProps: RouteProps) => (state) => html`` `');
};
tag.immutableProps = function immutableProps(tagComponent) {
return tag(tagComponent, PropWatches.IMMUTABLE);
};
tag.watchProps = function watchProps(tagComponent) {
return tag(tagComponent, PropWatches.SHALLOW);
};
/* BELOW: Cast functions into setters with no getters */
Object.defineProperty(tag, 'use', {
set(renderFunction) {
renderFunction.original = {
setUse: setUseMemory,
tags,
};
renderFunction.tagJsType = ValueTypes.stateRender;
renderFunction.processInit = processTagComponentInit;
renderFunction.processUpdate = tagValueUpdateHandler;
renderFunction.hasValueChanged = checkTagValueChangeAndUpdate;
renderFunction.destroy = destroySupportByContextItem;
},
});
Object.defineProperty(tag, 'promise', {
set(target) {
promise(target);
},
});
//# sourceMappingURL=tag.function.js.map