UNPKG

@haiku/player

Version:

Haiku Player is a JavaScript library for building user interfaces

1,078 lines 44.1 kB
"use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); var Config_1 = require("./Config"); var HaikuGlobal_1 = require("./HaikuGlobal"); var HaikuTimeline_1 = require("./HaikuTimeline"); var addElementToHashTable_1 = require("./helpers/addElementToHashTable"); var applyPropertyToElement_1 = require("./helpers/applyPropertyToElement"); var clone_1 = require("./helpers/clone"); var consoleErrorOnce_1 = require("./helpers/consoleErrorOnce"); var cssQueryList_1 = require("./helpers/cssQueryList"); var interactionModes_1 = require("./helpers/interactionModes"); var isMutableProperty_1 = require("./helpers/isMutableProperty"); var manaFlattenTree_1 = require("./helpers/manaFlattenTree"); var scopifyElements_1 = require("./helpers/scopifyElements"); var SimpleEventEmitter_1 = require("./helpers/SimpleEventEmitter"); var upgradeBytecodeInPlace_1 = require("./helpers/upgradeBytecodeInPlace"); var initializeComponentTree_1 = require("./helpers/initializeComponentTree"); var Layout3D_1 = require("./Layout3D"); var ValueBuilder_1 = require("./ValueBuilder"); var assign_1 = require("./vendor/assign"); var pkg = require('./../package.json'); var PLAYER_VERSION = pkg.version; var STRING_TYPE = 'string'; var OBJECT_TYPE = 'object'; var HAIKU_ID_ATTRIBUTE = 'haiku-id'; var DEFAULT_TIMELINE_NAME = 'Default'; function HaikuComponent(bytecode, context, config, metadata) { var _this = this; if (!bytecode) { throw new Error('Empty bytecode not allowed'); } if (!bytecode.template) { throw new Error('Bytecode must define template'); } if (!context) { throw new Error('Component requires a context'); } if (!config.options) { throw new Error('Config options required'); } if (!config.options.seed) { throw new Error('Seed value must be provided'); } if (!bytecode.timelines) { bytecode.timelines = {}; } SimpleEventEmitter_1.default.create(this); this.PLAYER_VERSION = PLAYER_VERSION; this.emit('haikuComponentWillInitialize', this); if (config.onHaikuComponentWillInitialize) { config.onHaikuComponentWillInitialize(this); } if (!config.options.hotEditingMode) { this._bytecode = clone_1.default(bytecode); } else { this._bytecode = bytecode; } upgradeBytecodeInPlace_1.default(this._bytecode, { referenceUniqueness: (config.options.hotEditingMode) ? void (0) : Math.random().toString(36).slice(2), }); this._context = context; this.cache = {}; this._builder = new ValueBuilder_1.default(this); this._states = {}; this.state = {}; this._stateChanges = {}; this._anyStateChange = false; this._eventsFired = {}; this._anyEventChange = false; this.assignConfig(config); this._metadata = metadata || {}; this._timelineInstances = {}; this._mutableTimelines = undefined; this._hydrateMutableTimelines(); this._flatManaTree = []; if (!this._bytecode.template.attributes[HAIKU_ID_ATTRIBUTE]) { console.warn('[haiku player] bytecode template has no id'); } assertTemplate(this._bytecode.template); if (!config.options.hotEditingMode) { this._template = cloneTemplate(this._bytecode.template); } else { this._template = this._bytecode.template; } this._needsFullFlush = false; this._alwaysFlush = false; this._lastTemplateExpansion = null; this._lastDeltaPatches = null; this._matchedElementCache = {}; this._renderScopes = {}; this._doesEmitEventsVerbosely = false; this._frameEventListeners = {}; this._nestedComponentElements = {}; this._hashTableOfIdsToElements = {}; this._registeredElementEventListeners = {}; this._horizonElements = {}; this._controlFlowData = {}; this.on('timeline:tick', function (timelineName, timelineFrame, timelineTime) { if (_this._frameEventListeners[timelineName]) { if (_this._frameEventListeners[timelineName][timelineFrame]) { for (var i = 0; i < _this._frameEventListeners[timelineName][timelineFrame].length; i++) { _this._frameEventListeners[timelineName][timelineFrame][i](timelineFrame, timelineTime); } } } }); this.emit('haikuComponentDidInitialize', this); if (config.onHaikuComponentDidInitialize) { config.onHaikuComponentDidInitialize(this); } this._isDeactivated = false; this._isSleeping = false; this._entityIndex = HaikuComponent['components'].push(this) - 1; } exports.default = HaikuComponent; HaikuComponent['PLAYER_VERSION'] = PLAYER_VERSION; HaikuComponent['components'] = []; HaikuGlobal_1.default['HaikuComponent'] = HaikuComponent; HaikuComponent.prototype._markHorizonElement = function _markHorizonElement(virtualElement) { if (virtualElement && virtualElement.attributes) { var flexId = virtualElement.attributes[HAIKU_ID_ATTRIBUTE] || virtualElement.attributes.id; if (flexId) { this._horizonElements[flexId] = virtualElement; } } }; HaikuComponent.prototype._isHorizonElement = function _isHorizonElement(virtualElement) { if (virtualElement && virtualElement.attributes) { var flexId = virtualElement.attributes[HAIKU_ID_ATTRIBUTE] || virtualElement.attributes.id; return !!this._horizonElements[flexId]; } return false; }; HaikuComponent.prototype._getRealElementsAtId = function _getRealElementsAtId(flexId) { if (!this._hashTableOfIdsToElements[flexId]) { return []; } return this._hashTableOfIdsToElements[flexId]; }; HaikuComponent.prototype._addElementToHashTable = function _addElementToHashTable(realElement, virtualElement) { addElementToHashTable_1.default(this._hashTableOfIdsToElements, realElement, virtualElement); return this; }; HaikuComponent.prototype._didElementRenderSurrogate = function _didElementRenderSurrogate(virtualElement, surrogatePlacementKey, surrogateObject) { if (!virtualElement) { return false; } if (!virtualElement.attributes) { return false; } var flexId = virtualElement.attributes['haiku-id'] || virtualElement.attributes.id; if (!flexId) { return false; } if (!this._controlFlowData[flexId]) { return false; } if (!this._controlFlowData[flexId].renderedSurrogates) { return false; } return this._controlFlowData[flexId].renderedSurrogates[surrogatePlacementKey] === surrogateObject; }; HaikuComponent.prototype._markElementSurrogateAsRendered = function _markElementSurrogateAsRendered(virtualElement, surrogatePlacementKey, surrogateObject) { var flexId = virtualElement && virtualElement.attributes && (virtualElement.attributes['haiku-id'] || virtualElement.attributes.id); if (flexId) { if (!this._controlFlowData[flexId]) { this._controlFlowData[flexId] = {}; } if (!this._controlFlowData[flexId].renderedSurrogates) { this._controlFlowData[flexId].renderedSurrogates = {}; } this._controlFlowData[flexId].renderedSurrogates[surrogatePlacementKey] = surrogateObject; } }; HaikuComponent.prototype.callRemount = function _callRemount(incomingConfig, skipMarkForFullFlush) { this.emit('haikuComponentWillMount', this); if (this.config.onHaikuComponentWillMount) { this.config.onHaikuComponentWillMount(this); } if (incomingConfig) { this.assignConfig(incomingConfig); } if (!skipMarkForFullFlush) { this._markForFullFlush(); this.clearCaches(); } var timelineInstances = this.getTimelines(); for (var timelineName in timelineInstances) { var timelineInstance = timelineInstances[timelineName]; if (this.config.options.autoplay) { if (timelineName === DEFAULT_TIMELINE_NAME) { timelineInstance.play({ skipMarkForFullFlush: skipMarkForFullFlush }); } } else { timelineInstance.pause(); } } this._context.contextMount(); this.emit('haikuComponentDidMount', this); if (this.config.onHaikuComponentDidMount) { this.config.onHaikuComponentDidMount(this); } }; HaikuComponent.prototype.callUnmount = function _callUnmount(incomingConfig) { if (incomingConfig) { this.assignConfig(incomingConfig); } var timelineInstances = this.getTimelines(); for (var timelineName in timelineInstances) { var timelineInstance = timelineInstances[timelineName]; timelineInstance.pause(); } this._context.contextUnmount(); this.emit('haikuComponentWillUnmount', this); if (this.config.onHaikuComponentWillUnmount) { this.config.onHaikuComponentWillUnmount(this); } }; HaikuComponent.prototype.assignConfig = function _assignConfig(incomingConfig) { this.config = Config_1.default.build(this.config || {}, incomingConfig || {}); this._context.assignConfig(this.config, { skipComponentAssign: true }); for (var timelineName in this._timelineInstances) { var timelineInstance = this._timelineInstances[timelineName]; timelineInstance.assignOptions(this.config.options); } bindStates(this._states, this, this.config.states); bindEventHandlers(this, this.config.eventHandlers); assign_1.default(this._bytecode.timelines, this.config.timelines); return this; }; HaikuComponent.prototype.set = function set(key, value) { this.state[key] = value; return this; }; HaikuComponent.prototype.get = function get(key) { return this.state[key]; }; HaikuComponent.prototype.setState = function setState(states) { if (!states) { return this; } if (typeof states !== 'object') { return this; } for (var key in states) { this.set(key, states[key]); } return this; }; HaikuComponent.prototype.getStates = function getStates() { return this.state; }; HaikuComponent.prototype.clearCaches = function clearCaches(options) { this._states = {}; if (!options || (options && options.clearStates !== false)) { bindStates(this._states, this, this.config.states); } if (options && options.clearPreviouslyRegisteredEventListeners) { this.clearRegisteredElementEventListeners(); } if (!options || (options && options.clearEventHandlers !== false)) { bindEventHandlers(this, this.config.eventHandlers); } this._stateChanges = {}; this._anyStateChange = false; this._eventsFired = {}; this._anyEventChange = false; this._needsFullFlush = false; this._lastTemplateExpansion = null; this._lastDeltaPatches = null; this._renderScopes = {}; this._controlFlowData = {}; this._rehydrateFlatManaTree(); this._matchedElementCache = {}; this._clearDetectedEventsFired(); this._clearDetectedInputChanges(); this._builder.clearCaches(options); this._hydrateMutableTimelines(); this.cache = {}; if (this._bytecode.timelines) { for (var timelineName in this._bytecode.timelines) { delete this._bytecode.timelines[timelineName].__max; } } return this; }; HaikuComponent.prototype.getClock = function getClock() { return this._context.getClock(); }; HaikuComponent.prototype.getTimelines = function getTimelines() { return this._fetchTimelines(); }; HaikuComponent.prototype._fetchTimelines = function _fetchTimelines() { var names = Object.keys(this._bytecode.timelines); for (var i = 0; i < names.length; i++) { var name_1 = names[i]; if (!name_1) { continue; } var descriptor = this._getTimelineDescriptor(name_1); var existing = this._timelineInstances[name_1]; if (!existing) { this._timelineInstances[name_1] = new HaikuTimeline_1.default(this, name_1, descriptor, this.config.options); } } return this._timelineInstances; }; HaikuComponent.prototype.getTimeline = function getTimeline(name) { return this.getTimelines()[name]; }; HaikuComponent.prototype.getDefaultTimeline = function getDefaultTimeline() { var timelines = this.getTimelines(); return timelines[DEFAULT_TIMELINE_NAME]; }; HaikuComponent.prototype.getActiveTimelines = function getActiveTimelines() { var activeTimelines = {}; var timelines = this.getTimelines(); for (var timelineName in timelines) { var timelineInstance = timelines[timelineName]; if (timelineInstance.isActive()) { activeTimelines[timelineName] = timelineInstance; } } return activeTimelines; }; HaikuComponent.prototype.stopAllTimelines = function stopAllTimelines() { for (var timelineName in this._timelineInstances) { this.stopTimeline(timelineName); } }; HaikuComponent.prototype.startAllTimelines = function startAllTimelines() { for (var timelineName in this._timelineInstances) { this.startTimeline(timelineName); } }; HaikuComponent.prototype.startTimeline = function startTimeline(timelineName) { var time = this._context.clock.getExplicitTime(); var descriptor = this._getTimelineDescriptor(timelineName); var existing = this._timelineInstances[timelineName]; if (existing) { existing.start(time, descriptor); } else { var fresh = new HaikuTimeline_1.default(this, timelineName, descriptor, this.config.options); fresh.start(time, descriptor); this._timelineInstances[timelineName] = fresh; } }; HaikuComponent.prototype.stopTimeline = function startTimeline(timelineName) { var time = this._context.clock.getExplicitTime(); var descriptor = this._getTimelineDescriptor(timelineName); var existing = this._timelineInstances[timelineName]; if (existing) { existing.stop(time, descriptor); } }; HaikuComponent.prototype._getTimelineDescriptor = function _getTimelineDescriptor(timelineName) { return this._bytecode.timelines[timelineName]; }; HaikuComponent.prototype._getInjectables = function _getInjectables(element) { var injectables = {}; assign_1.default(injectables, this._builder._getSummonablesSchema(element)); for (var key in this._states) { var type = this._states[key].type; if (!type) { type = typeof this._states[key]; } injectables[key] = type; } return injectables; }; HaikuComponent.prototype._getTopLevelElement = function _getTopLevelElement() { return this._template; }; HaikuComponent.prototype.deactivate = function deactivate() { this._isDeactivated = true; return this; }; HaikuComponent.prototype.isDeactivated = function isDeactivated() { return this._isDeactivated; }; HaikuComponent.prototype.sleepOn = function sleepOn() { this._isSleeping = true; return this; }; HaikuComponent.prototype.sleepOff = function sleepOff() { this._isSleeping = false; return this; }; HaikuComponent.prototype.isSleeping = function isSleeping() { return this._isSleeping; }; HaikuComponent.prototype.clearRegisteredElementEventListeners = function clearRegisteredElementEventListeners() { for (var flexId in this._registeredElementEventListeners) { for (var eventName in this._registeredElementEventListeners[flexId]) { var _a = this._registeredElementEventListeners[flexId][eventName], target = _a.target, handler = _a.handler; if (target && handler && this._context._renderer.removeListener) { this._context._renderer.removeListener(target, handler, eventName); } delete this._registeredElementEventListeners[flexId][eventName]; } } this._frameEventListeners = {}; }; HaikuComponent.prototype.hasRegisteredListenerOnElement = function hasRegisteredListenerOnElement(virtualElement, eventName) { var flexId = virtualElement.attributes[HAIKU_ID_ATTRIBUTE] || virtualElement.attributes.id; if (!flexId) { return false; } return this._registeredElementEventListeners[flexId] && this._registeredElementEventListeners[flexId][eventName]; }; HaikuComponent.prototype.markDidRegisterListenerOnElement = function markDidRegisterListenerOnElement(virtualElement, domElement, eventName, listenerFunction) { var flexId = virtualElement.attributes[HAIKU_ID_ATTRIBUTE] || virtualElement.attributes.id; if (!flexId) { return this; } if (!this._registeredElementEventListeners[flexId]) { this._registeredElementEventListeners[flexId] = {}; } this._registeredElementEventListeners[flexId][eventName] = { handler: listenerFunction, target: domElement, }; return this; }; HaikuComponent.prototype.dump = function dump() { var metadata = this.getBytecodeMetadata(); return metadata.relpath + ":" + this.getComponentId() + "[" + this._entityIndex + "]"; }; HaikuComponent.prototype.getComponentId = function getComponentId() { return this._bytecode.template.attributes[HAIKU_ID_ATTRIBUTE]; }; HaikuComponent.prototype.getBytecodeMetadata = function getBytecodeMetadata() { return this._bytecode.metadata; }; HaikuComponent.prototype.getAddressableProperties = function getAddressableProperties(out) { var _this = this; if (out === void 0) { out = {}; } if (!this._bytecode.states) { return out; } var _loop_1 = function (name_2) { var state = this_1._bytecode.states[name_2]; out[name_2] = { name: name_2, type: 'state', prefix: name_2, suffix: undefined, fallback: state.value, typedef: state.type, mock: state.mock, target: this_1, value: function () { return _this.state[name_2]; }, }; }; var this_1 = this; for (var name_2 in this._bytecode.states) { _loop_1(name_2); } return out; }; function cloneTemplate(mana) { if (!mana) { return mana; } if (typeof mana === STRING_TYPE) { return mana; } var out = { elementName: mana.elementName, attributes: null, children: null, }; if (mana.attributes) { out.attributes = {}; for (var key in mana.attributes) { if (mana.attributes[key] && typeof mana.attributes[key] === 'object') { out.attributes[key] = {}; for (var subkey in mana.attributes[key]) { out.attributes[key][subkey] = mana.attributes[key][subkey]; } } else { out.attributes[key] = mana.attributes[key]; } } } if (mana.children) { out.children = []; for (var i = 0; i < mana.children.length; i++) { out.children[i] = cloneTemplate(mana.children[i]); } } return out; } function assertTemplate(template) { if (!template) { throw new Error('Empty template not allowed'); } if (typeof template === OBJECT_TYPE) { if (!template.elementName) { console.warn('[haiku player] warning: saw unexpected bytecode template format'); } return template; } throw new Error('Unknown bytecode template format'); } function bindEventHandlers(component, extraEventHandlers) { var allEventHandlers = assign_1.default({}, component._bytecode.eventHandlers, extraEventHandlers); for (var selector in allEventHandlers) { var handlerGroup = allEventHandlers[selector]; for (var eventName in handlerGroup) { var eventHandlerDescriptor = handlerGroup[eventName]; bindEventHandler(component, eventHandlerDescriptor, selector, eventName); } } } function bindEventHandler(component, eventHandlerDescriptor, selector, eventName) { if (eventHandlerDescriptor.original) { eventHandlerDescriptor.handler = eventHandlerDescriptor.original; } eventHandlerDescriptor.original = eventHandlerDescriptor.handler; eventHandlerDescriptor.handler = function _wrappedEventHandler(event) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } if (interactionModes_1.isPreviewMode(component.config.options.interactionMode)) { component._anyEventChange = true; if (!component._eventsFired[selector]) { component._eventsFired[selector] = {}; } component._eventsFired[selector][eventName] = event || true; try { (_a = eventHandlerDescriptor.original).call.apply(_a, [component, event].concat(args)); } catch (exception) { consoleErrorOnce_1.default(exception); return 1; } } var _a; }; } function typecheckStateSpec(stateSpec, stateSpecName) { if (stateSpec.type === 'any' || stateSpec.type === '*' || stateSpec.type === undefined || stateSpec.type === null) { return void 0; } if (stateSpec.type === 'event' || stateSpec.type === 'listener') { if (typeof stateSpec.value !== 'function' && stateSpec.value !== null && stateSpec.value !== undefined) { throw new Error('Property value `' + stateSpecName + '` must be an event listener function'); } return void 0; } if (stateSpec.type === 'array') { if (!Array.isArray(stateSpec.value)) { throw new Error('Property value `' + stateSpecName + '` must be an array'); } } else if (stateSpec.type === 'object') { if (stateSpec.value && typeof stateSpec.value !== 'object') { throw new Error('Property value `' + stateSpecName + '` must be an object'); } } else { if (typeof stateSpec.value !== stateSpec.type) { throw new Error('Property value `' + stateSpecName + '` must be a `' + stateSpec.type + '`'); } } } function bindStates(statesTargetObject, component, extraStates) { var allStates = assign_1.default({}, component._bytecode.states, extraStates); for (var stateSpecName in allStates) { var stateSpec = allStates[stateSpecName]; if (stateSpec.value === undefined) { throw new Error('Property `' + stateSpecName + '` cannot be undefined; use null for empty states'); } typecheckStateSpec(stateSpec, stateSpecName); statesTargetObject[stateSpecName] = stateSpec.value; defineSettableState(component, component.state, statesTargetObject, stateSpec, stateSpecName); } } function defineSettableState(component, statesHostObject, statesTargetObject, stateSpec, stateSpecName) { Object.defineProperty(statesHostObject, stateSpecName, { configurable: true, get: function get() { return statesTargetObject[stateSpecName]; }, set: function set(inputValue) { component._stateChanges[stateSpecName] = inputValue; component._anyStateChange = true; if (stateSpec.setter) { statesTargetObject[stateSpecName] = stateSpec.setter.call(component, inputValue); } else { statesTargetObject[stateSpecName] = inputValue; } if (component._doesEmitEventsVerbosely) { component.emit('state:set', stateSpecName, statesTargetObject[stateSpecName], statesTargetObject); } return statesTargetObject[stateSpecName]; }, }); } HaikuComponent.prototype._markForFullFlush = function _markForFullFlush() { this._needsFullFlush = true; return this; }; HaikuComponent.prototype._unmarkForFullFlush = function _unmarkForFullFlush() { this._needsFullFlush = false; return this; }; HaikuComponent.prototype._shouldPerformFullFlush = function _shouldPerformFullFlush() { return this._needsFullFlush || this._alwaysFlush; }; HaikuComponent.prototype._clearDetectedEventsFired = function _clearDetectedEventsFired() { this._anyEventChange = false; this._eventsFired = {}; return this; }; HaikuComponent.prototype._clearDetectedInputChanges = function _clearDetectedInputChanges() { this._anyStateChange = false; this._stateChanges = {}; return this; }; HaikuComponent.prototype.patch = function patch(container, patchOptions, skipCache) { if (skipCache === void 0) { skipCache = false; } if (this.isDeactivated()) { return {}; } var time = this._context.clock.getExplicitTime(); var timelinesRunning = []; for (var timelineName in this._timelineInstances) { var timeline = this._timelineInstances[timelineName]; if (timeline.isActive()) { timeline._doUpdateWithGlobalClockTime(time); if (timelineName === 'Default' || !timeline.isFinished()) { timelinesRunning.push(timeline); } } } this._lastDeltaPatches = gatherDeltaPatches(this, this._template, container, this._context, timelinesRunning, patchOptions, skipCache); for (var flexId in this._nestedComponentElements) { var compElement = this._nestedComponentElements[flexId]; this._lastDeltaPatches[flexId] = compElement; compElement.__instance.patch(compElement, {}); } this._clearDetectedEventsFired(); this._clearDetectedInputChanges(); return this._lastDeltaPatches; }; HaikuComponent.prototype._getPrecalcedPatches = function _getPrecalcedPatches() { if (this.isDeactivated()) { return {}; } return this._lastDeltaPatches || {}; }; HaikuComponent.prototype._rehydrateFlatManaTree = function _rehydrateFlatManaTree() { this._flatManaTree = manaFlattenTree_1.default(this._template, CSS_QUERY_MAPPING); return this._flatManaTree; }; HaikuComponent.prototype.render = function render(container, renderOptions) { if (this.isDeactivated()) { return void 0; } var time = this._context.clock.getExplicitTime(); var prevFlatManaTreeLen = this._flatManaTree.length; this._rehydrateFlatManaTree(); if (prevFlatManaTreeLen.length !== this._flatManaTree.length) { this._matchedElementCache = {}; } for (var timelineName in this._timelineInstances) { var timeline = this._timelineInstances[timelineName]; if (timeline.isActive()) { timeline._doUpdateWithGlobalClockTime(time); } } applyContextChanges(this, this._template, container, this._context, renderOptions || {}); this._lastTemplateExpansion = expandTreeElement(this._template, this, this._context); this._unmarkForFullFlush(); return this._lastTemplateExpansion; }; HaikuComponent.prototype.findElementsByHaikuId = function findElementsByHaikuId(componentId) { return findMatchingElementsByCssSelector('haiku:' + componentId, this._flatManaTree, this._matchedElementCache); }; HaikuComponent.prototype._hydrateMutableTimelines = function _hydrateMutableTimelines() { this._mutableTimelines = {}; if (this._bytecode.timelines) { for (var timelineName in this._bytecode.timelines) { for (var selector in this._bytecode.timelines[timelineName]) { for (var propertyName in this._bytecode.timelines[timelineName][selector]) { if (isMutableProperty_1.default(this._bytecode.timelines[timelineName][selector][propertyName], propertyName)) { var timeline = this._mutableTimelines[timelineName] || {}; var propertyGroup = timeline[selector] || {}; this._mutableTimelines = __assign({}, this._mutableTimelines, (_a = {}, _a[timelineName] = __assign({}, timeline, (_b = {}, _b[selector] = __assign({}, propertyGroup, (_c = {}, _c[propertyName] = this._bytecode.timelines[timelineName][selector][propertyName], _c)), _b)), _a)); } } } } } var _a, _b, _c; }; function bindContextualEventHandlers(component) { if (component._bytecode.eventHandlers) { for (var eventSelector in component._bytecode.eventHandlers) { var eventHandlerGroup = component._bytecode.eventHandlers[eventSelector]; for (var eventName1 in eventHandlerGroup) { var eventHandlerSpec1 = eventHandlerGroup[eventName1]; if (!eventHandlerSpec1.handler.__subscribed && !eventHandlerSpec1.handler.__external) { if (eventName1 === 'component:will-mount') { component.on('haikuComponentWillMount', eventHandlerSpec1.handler); eventHandlerSpec1.handler.__subscribed = true; continue; } if (eventName1 === 'component:did-mount') { component.on('haikuComponentDidMount', eventHandlerSpec1.handler); eventHandlerSpec1.handler.__subscribed = true; continue; } if (eventName1 === 'component:will-unmount') { component.on('haikuComponentWillUnmount', eventHandlerSpec1.handler); eventHandlerSpec1.handler.__subscribed = true; continue; } var namePieces = eventName1.split(':'); if (namePieces.length > 1) { if (namePieces[0] === 'timeline') { var timelineNamePiece = namePieces[1]; var frameValuePiece = parseInt(namePieces[2], 10); if (!component._frameEventListeners[timelineNamePiece]) { component._frameEventListeners[timelineNamePiece] = {}; } if (!component._frameEventListeners[timelineNamePiece][frameValuePiece]) { component._frameEventListeners[timelineNamePiece][frameValuePiece] = []; } component._frameEventListeners[timelineNamePiece][frameValuePiece].push(eventHandlerSpec1.handler); eventHandlerSpec1.handler.__subscribed = true; continue; } } eventHandlerSpec1.handler.__external = true; } } var matchingElementsForEvents = findMatchingElementsByCssSelector(eventSelector, component._flatManaTree, component._matchedElementCache); if (!matchingElementsForEvents || matchingElementsForEvents.length < 1) { continue; } for (var k = 0; k < matchingElementsForEvents.length; k++) { for (var eventName in eventHandlerGroup) { var eventHandlerSpec = eventHandlerGroup[eventName]; if (!eventHandlerSpec.__subscribed) { applyHandlerToElement(matchingElementsForEvents[k], eventName, eventHandlerSpec.handler); } } } } } } function applyBehaviors(timelinesRunning, deltas, component, context, isPatchOperation, skipCache) { if (skipCache === void 0) { skipCache = false; } if (!isPatchOperation) { bindContextualEventHandlers(component); } for (var i = 0; i < timelinesRunning.length; i++) { var timelineInstance = timelinesRunning[i]; var timelineName = timelineInstance.getName(); var timelineDescriptor = isPatchOperation && !component.config.options.hotEditingMode ? component._mutableTimelines[timelineName] : component._bytecode.timelines[timelineName]; if (typeof timelineDescriptor !== 'object') { continue; } var timelineTime = timelineInstance.getBoundedTime(); for (var behaviorSelector in timelineDescriptor) { var propertiesGroup = timelineDescriptor[behaviorSelector]; if (!propertiesGroup) { continue; } var matchingElementsForBehavior = findMatchingElementsByCssSelector(behaviorSelector, component._flatManaTree, component._matchedElementCache); if (!matchingElementsForBehavior || matchingElementsForBehavior.length < 1) { continue; } for (var j = 0; j < matchingElementsForBehavior.length; j++) { var matchingElement = matchingElementsForBehavior[j]; var domId = matchingElement && matchingElement.attributes && matchingElement.attributes.id; var haikuId = matchingElement && matchingElement.attributes && matchingElement.attributes[HAIKU_ID_ATTRIBUTE]; var flexId = haikuId || domId; var assembledOutputs = component._builder.build({}, timelineName, timelineTime, flexId, matchingElement, propertiesGroup, isPatchOperation, component, skipCache); if (assembledOutputs && assembledOutputs.transform) { matchingElement.__transformed = true; } if (assembledOutputs && deltas && flexId) { deltas[flexId] = matchingElement; } if (assembledOutputs) { for (var behaviorKey in assembledOutputs) { var behaviorValue = assembledOutputs[behaviorKey]; applyPropertyToElement_1.default(matchingElement, behaviorKey, behaviorValue, context, component); } } } } } } function gatherDeltaPatches(component, template, container, context, timelinesRunning, patchOptions, skipCache) { if (skipCache === void 0) { skipCache = false; } Layout3D_1.default.initializeTreeAttributes(template, container); initializeComponentTree_1.default(template, component, context, null); var deltas = {}; applyBehaviors(timelinesRunning, deltas, component, context, true, skipCache); if (patchOptions.sizing) { computeAndApplyPresetSizing(template, container, patchOptions.sizing, deltas); } for (var flexId in deltas) { var changedNode = deltas[flexId]; computeAndApplyTreeLayouts(changedNode, changedNode.__parent, patchOptions, context); } return deltas; } function applyContextChanges(component, template, container, context, renderOptions) { var timelinesRunning = []; if (component._bytecode.timelines) { for (var timelineName in component._bytecode.timelines) { var timeline = component.getTimeline(timelineName); if (!timeline) { continue; } if (!timeline.isActive()) { continue; } if (timeline.isFinished()) { if (timelineName !== DEFAULT_TIMELINE_NAME) { continue; } } timelinesRunning.push(timeline); } } Layout3D_1.default.initializeTreeAttributes(template, container); initializeComponentTree_1.default(template, component, context, null); scopifyElements_1.default(template, null, null); applyBehaviors(timelinesRunning, null, component, context, false); if (renderOptions.sizing) { computeAndApplyPresetSizing(template, container, renderOptions.sizing, null); } computeAndApplyTreeLayouts(template, container, renderOptions, context); return template; } function expandTreeElement(element, component, context) { if (element.__handlers) { for (var key in element.__handlers) { var handler = element.__handlers[key]; if (!handler.__subscribed) { if (element.__instance) { if (element.__instance.instance) { element.__instance.instance.on(key, handler); handler.__subscribed = true; } } } } } if (element.__instance) { var wrapper = shallowCloneComponentTreeElement(element); var surrogates = wrapper.children; var subtree = element.__instance.render(element, element.__instance.config.options, surrogates); if (subtree) { var expansion = expandTreeElement(subtree, element.__instance, context); wrapper.children = [expansion]; } else { wrapper.children = []; } return wrapper; } if (typeof element.elementName === STRING_TYPE) { var copy = shallowCloneComponentTreeElement(element); if (element.children && element.children.length > 0) { for (var i = 0; i < element.children.length; i++) { var child = element.children[i]; copy.children[i] = expandTreeElement(child, component, context); } } return copy; } return element; } function shallowCloneComponentTreeElement(element) { var clone = { __instance: null, __handlers: null, __transformed: null, __parent: null, __scope: null, __target: null, layout: null, elementName: null, attributes: null, children: null, }; clone.__instance = element.__instance; clone.__handlers = element.__handlers; clone.__transformed = element.__transformed; clone.__parent = element.__parent; clone.__scope = element.__scope; clone.__target = element.__target; clone.layout = element.layout; clone.elementName = element.elementName; clone.attributes = {}; for (var key in element.attributes) { clone.attributes[key] = element.attributes[key]; } clone.children = []; return clone; } var CSS_QUERY_MAPPING = { name: 'elementName', attributes: 'attributes', children: 'children', }; function findMatchingElementsByCssSelector(selector, flatManaTree, cache) { if (cache[selector]) { return cache[selector]; } return cache[selector] = cssQueryList_1.default(flatManaTree, selector, CSS_QUERY_MAPPING); } function computeAndApplyTreeLayouts(tree, container, options, context) { if (!tree || typeof tree === 'string') { return void 0; } computeAndApplyNodeLayout(tree, container); if (!tree.children || tree.children.length < 1) { return void 0; } for (var i = 0; i < tree.children.length; i++) { computeAndApplyTreeLayouts(tree.children[i], tree, options, context); } } function computeAndApplyNodeLayout(element, parent) { if (parent) { var parentSize = parent.layout.computed.size; element.layout.computed = Layout3D_1.default.computeLayout(element.layout, element.layout.matrix, parentSize); } } function applyHandlerToElement(match, name, fn) { if (!match.__handlers) { match.__handlers = {}; } match.__handlers[name] = fn; return match; } function computeAndApplyPresetSizing(element, container, mode, deltas) { var elementWidth = element.layout.sizeAbsolute.x; var elementHeight = element.layout.sizeAbsolute.y; var containerWidth = container.layout.computed.size.x; var containerHeight = container.layout.computed.size.y; var scaleDiffX = containerWidth / elementWidth; var scaleDiffY = containerHeight / elementHeight; if (!element.attributes.style['transform-origin']) { element.attributes.style['transform-origin'] = 'top left'; } var changed = false; switch (mode) { case 'normal': if (element.layout.scale.x !== 1.0 || element.layout.scale.y !== 1.0) { changed = true; element.layout.scale.x = element.layout.scale.y = 1.0; } break; case 'stretch': if (scaleDiffX !== element.layout.scale.x) { changed = true; element.layout.scale.x = scaleDiffX; } if (scaleDiffY !== element.layout.scale.y) { changed = true; element.layout.scale.y = scaleDiffY; } break; case 'contain': case true: var containScaleToUse = null; if (~~(scaleDiffX * elementWidth) <= containerWidth && ~~(scaleDiffX * elementHeight) <= containerHeight) { containScaleToUse = scaleDiffX; } if (~~(scaleDiffY * elementWidth) <= containerWidth && ~~(scaleDiffY * elementHeight) <= containerHeight) { if (containScaleToUse === null) { containScaleToUse = scaleDiffY; } else { if (scaleDiffY >= containScaleToUse) { containScaleToUse = scaleDiffY; } } } if (element.layout.scale.x !== containScaleToUse) { changed = true; element.layout.scale.x = containScaleToUse; } if (element.layout.scale.y !== containScaleToUse) { changed = true; element.layout.scale.y = containScaleToUse; } var containTranslationOffsetX = -(containScaleToUse * elementWidth - containerWidth) / 2; var containTranslationOffsetY = -(containScaleToUse * elementHeight - containerHeight) / 2; if (element.layout.translation.x !== containTranslationOffsetX) { changed = true; element.layout.translation.x = containTranslationOffsetX; } if (element.layout.translation.y !== containTranslationOffsetY) { changed = true; element.layout.translation.y = containTranslationOffsetY; } break; case 'cover': var coverScaleToUse = null; if (~~(scaleDiffX * elementHeight) >= containerHeight) { coverScaleToUse = scaleDiffX; } else if (~~(scaleDiffY * elementWidth) >= containerWidth) { coverScaleToUse = scaleDiffY; } else { coverScaleToUse = Math.max(scaleDiffX, scaleDiffY); } if (element.layout.scale.x !== coverScaleToUse) { changed = true; element.layout.scale.x = coverScaleToUse; } if (element.layout.scale.y !== coverScaleToUse) { changed = true; element.layout.scale.y = coverScaleToUse; } var coverTranslationOffsetX = -(coverScaleToUse * elementWidth - containerWidth) / 2; var coverTranslationOffsetY = -(coverScaleToUse * elementHeight - containerHeight) / 2; if (element.layout.translation.x !== coverTranslationOffsetX) { changed = true; element.layout.translation.x = coverTranslationOffsetX; } if (element.layout.translation.y !== coverTranslationOffsetY) { changed = true; element.layout.translation.y = coverTranslationOffsetY; } break; } if (changed && deltas) { deltas[element.attributes[HAIKU_ID_ATTRIBUTE]] = element; } } //# sourceMappingURL=HaikuComponent.js.map