treeloom 0.0.0-stage → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/README.md +91 -2
- package/browser/treeloom.js +11232 -0
- package/browser/treeloom.min.js +1 -0
- package/browser/treeloomRenderOnly.js +11115 -0
- package/browser/treeloomRenderOnly.min.js +1 -0
- package/dist/deflate/domItemToJson.d.ts +14 -0
- package/dist/deflate/domItemToJson.js +43 -0
- package/dist/deflate/domItemToJson.min.js +1 -0
- package/dist/deflate/index.d.ts +7 -0
- package/dist/deflate/index.js +19 -0
- package/dist/deflate/index.min.js +1 -0
- package/dist/deflate/removeEmptyProperties.d.ts +8 -0
- package/dist/deflate/removeEmptyProperties.js +43 -0
- package/dist/deflate/removeEmptyProperties.min.js +1 -0
- package/dist/diff/appliedSnapshot.d.ts +34 -0
- package/dist/diff/appliedSnapshot.js +134 -0
- package/dist/diff/appliedSnapshot.min.js +1 -0
- package/dist/diff/createChangeList.d.ts +9 -0
- package/dist/diff/createChangeList.js +44 -0
- package/dist/diff/createChangeList.min.js +1 -0
- package/dist/diff/domItemChanges.d.ts +9 -0
- package/dist/diff/domItemChanges.js +167 -0
- package/dist/diff/domItemChanges.min.js +1 -0
- package/dist/diff/domItemHasAttribute.d.ts +11 -0
- package/dist/diff/domItemHasAttribute.js +63 -0
- package/dist/diff/domItemHasAttribute.min.js +1 -0
- package/dist/diff/elementChanges.d.ts +10 -0
- package/dist/diff/elementChanges.js +151 -0
- package/dist/diff/elementChanges.min.js +1 -0
- package/dist/diff/elementHasAttribute.d.ts +10 -0
- package/dist/diff/elementHasAttribute.js +70 -0
- package/dist/diff/elementHasAttribute.min.js +1 -0
- package/dist/diff/getAssignedStyles.d.ts +9 -0
- package/dist/diff/getAssignedStyles.js +22 -0
- package/dist/diff/getAssignedStyles.min.js +1 -0
- package/dist/diff/index.d.ts +9 -0
- package/dist/diff/index.js +27 -0
- package/dist/diff/index.min.js +1 -0
- package/dist/diff/types.d.ts +17 -0
- package/dist/diff/types.js +8 -0
- package/dist/diff/types.min.js +1 -0
- package/dist/domItem/index.d.ts +34 -0
- package/dist/domItem/index.js +81 -0
- package/dist/domItem/index.min.js +1 -0
- package/dist/domItem/objects/addDomItemProperties.d.ts +7 -0
- package/dist/domItem/objects/addDomItemProperties.js +27 -0
- package/dist/domItem/objects/addDomItemProperties.min.js +1 -0
- package/dist/domItem/objects/createCoreItem.d.ts +9 -0
- package/dist/domItem/objects/createCoreItem.js +53 -0
- package/dist/domItem/objects/createCoreItem.min.js +1 -0
- package/dist/domItem/objects/createDomItem.d.ts +10 -0
- package/dist/domItem/objects/createDomItem.js +40 -0
- package/dist/domItem/objects/createDomItem.min.js +1 -0
- package/dist/domItem/objects/documentDomItem.d.ts +12 -0
- package/dist/domItem/objects/documentDomItem.js +36 -0
- package/dist/domItem/objects/documentDomItem.min.js +1 -0
- package/dist/domItem/objects/documentItem.d.ts +18 -0
- package/dist/domItem/objects/documentItem.js +40 -0
- package/dist/domItem/objects/documentItem.min.js +1 -0
- package/dist/domItem/objects/initChildren.d.ts +6 -0
- package/dist/domItem/objects/initChildren.js +44 -0
- package/dist/domItem/objects/initChildren.min.js +1 -0
- package/dist/domItem/objects/initRoot.d.ts +9 -0
- package/dist/domItem/objects/initRoot.js +32 -0
- package/dist/domItem/objects/initRoot.min.js +1 -0
- package/dist/domItem/query/gatherChildItems.d.ts +12 -0
- package/dist/domItem/query/gatherChildItems.js +19 -0
- package/dist/domItem/query/gatherChildItems.min.js +1 -0
- package/dist/domItem/query/getChildTest.d.ts +8 -0
- package/dist/domItem/query/getChildTest.js +15 -0
- package/dist/domItem/query/getChildTest.min.js +1 -0
- package/dist/domItem/query/getChildrenByClass.d.ts +11 -0
- package/dist/domItem/query/getChildrenByClass.js +26 -0
- package/dist/domItem/query/getChildrenByClass.min.js +1 -0
- package/dist/domItem/query/getChildrenByName.d.ts +9 -0
- package/dist/domItem/query/getChildrenByName.js +23 -0
- package/dist/domItem/query/getChildrenByName.min.js +1 -0
- package/dist/domItem/query/getChildrenFromAttribute.d.ts +13 -0
- package/dist/domItem/query/getChildrenFromAttribute.js +28 -0
- package/dist/domItem/query/getChildrenFromAttribute.min.js +1 -0
- package/dist/domItem/query/getItemByElement.d.ts +11 -0
- package/dist/domItem/query/getItemByElement.js +29 -0
- package/dist/domItem/query/getItemByElement.min.js +1 -0
- package/dist/domItem/query/getParentsByClass.d.ts +12 -0
- package/dist/domItem/query/getParentsByClass.js +40 -0
- package/dist/domItem/query/getParentsByClass.min.js +1 -0
- package/dist/domItem/query/getParentsByName.d.ts +9 -0
- package/dist/domItem/query/getParentsByName.js +23 -0
- package/dist/domItem/query/getParentsByName.min.js +1 -0
- package/dist/domItem/query/getParentsByTagName.d.ts +9 -0
- package/dist/domItem/query/getParentsByTagName.js +23 -0
- package/dist/domItem/query/getParentsByTagName.min.js +1 -0
- package/dist/domItem/query/getParentsFromAttribute.d.ts +13 -0
- package/dist/domItem/query/getParentsFromAttribute.js +39 -0
- package/dist/domItem/query/getParentsFromAttribute.min.js +1 -0
- package/dist/domItem/traits/defineTrait.d.ts +10 -0
- package/dist/domItem/traits/defineTrait.js +26 -0
- package/dist/domItem/traits/defineTrait.min.js +1 -0
- package/dist/domItem/traits/definitions.d.ts +7 -0
- package/dist/domItem/traits/definitions.js +20 -0
- package/dist/domItem/traits/definitions.min.js +1 -0
- package/dist/domItem/traits/getNonSerializableKeys.d.ts +9 -0
- package/dist/domItem/traits/getNonSerializableKeys.js +25 -0
- package/dist/domItem/traits/getNonSerializableKeys.min.js +1 -0
- package/dist/domItem/traits/getTraitDefinition.d.ts +7 -0
- package/dist/domItem/traits/getTraitDefinition.js +20 -0
- package/dist/domItem/traits/getTraitDefinition.min.js +1 -0
- package/dist/domItem/traits/hasTrait.d.ts +8 -0
- package/dist/domItem/traits/hasTrait.js +15 -0
- package/dist/domItem/traits/hasTrait.min.js +1 -0
- package/dist/domItem/traits/hasTraits.d.ts +9 -0
- package/dist/domItem/traits/hasTraits.js +16 -0
- package/dist/domItem/traits/hasTraits.min.js +1 -0
- package/dist/domItem/traits/isDomItem.d.ts +8 -0
- package/dist/domItem/traits/isDomItem.js +21 -0
- package/dist/domItem/traits/isDomItem.min.js +1 -0
- package/dist/domItem/traits/withTrait.d.ts +11 -0
- package/dist/domItem/traits/withTrait.js +30 -0
- package/dist/domItem/traits/withTrait.min.js +1 -0
- package/dist/domItem/tree/appendChild.d.ts +8 -0
- package/dist/domItem/tree/appendChild.js +19 -0
- package/dist/domItem/tree/appendChild.min.js +1 -0
- package/dist/domItem/tree/getItemByPath.d.ts +10 -0
- package/dist/domItem/tree/getItemByPath.js +23 -0
- package/dist/domItem/tree/getItemByPath.min.js +1 -0
- package/dist/domItem/tree/getItemPath.d.ts +9 -0
- package/dist/domItem/tree/getItemPath.js +31 -0
- package/dist/domItem/tree/getItemPath.min.js +1 -0
- package/dist/domItem/tree/getTopParentItem.d.ts +8 -0
- package/dist/domItem/tree/getTopParentItem.js +29 -0
- package/dist/domItem/tree/getTopParentItem.min.js +1 -0
- package/dist/domItem/tree/insertChild.d.ts +11 -0
- package/dist/domItem/tree/insertChild.js +22 -0
- package/dist/domItem/tree/insertChild.min.js +1 -0
- package/dist/domItem/tree/itemIdIndex.d.ts +43 -0
- package/dist/domItem/tree/itemIdIndex.js +118 -0
- package/dist/domItem/tree/itemIdIndex.min.js +1 -0
- package/dist/domItem/tree/removeChild.d.ts +8 -0
- package/dist/domItem/tree/removeChild.js +21 -0
- package/dist/domItem/tree/removeChild.min.js +1 -0
- package/dist/domItem/tree/setParentItemReferences.d.ts +7 -0
- package/dist/domItem/tree/setParentItemReferences.js +24 -0
- package/dist/domItem/tree/setParentItemReferences.min.js +1 -0
- package/dist/domItem/types.d.ts +131 -0
- package/dist/domItem/types.js +8 -0
- package/dist/domItem/types.min.js +1 -0
- package/dist/events/functions/activateListener.d.ts +10 -0
- package/dist/events/functions/activateListener.js +45 -0
- package/dist/events/functions/activateListener.min.js +1 -0
- package/dist/events/functions/addEventListener.d.ts +23 -0
- package/dist/events/functions/addEventListener.js +54 -0
- package/dist/events/functions/addEventListener.min.js +1 -0
- package/dist/events/functions/applyActiveListeners.d.ts +9 -0
- package/dist/events/functions/applyActiveListeners.js +52 -0
- package/dist/events/functions/applyActiveListeners.min.js +1 -0
- package/dist/events/functions/assignListener.d.ts +12 -0
- package/dist/events/functions/assignListener.js +39 -0
- package/dist/events/functions/assignListener.min.js +1 -0
- package/dist/events/functions/bindAllListeners.d.ts +10 -0
- package/dist/events/functions/bindAllListeners.js +28 -0
- package/dist/events/functions/bindAllListeners.min.js +1 -0
- package/dist/events/functions/bindElementListeners.d.ts +7 -0
- package/dist/events/functions/bindElementListeners.js +34 -0
- package/dist/events/functions/bindElementListeners.min.js +1 -0
- package/dist/events/functions/bindListeners.d.ts +9 -0
- package/dist/events/functions/bindListeners.js +23 -0
- package/dist/events/functions/bindListeners.min.js +1 -0
- package/dist/events/functions/deactivateListener.d.ts +13 -0
- package/dist/events/functions/deactivateListener.js +58 -0
- package/dist/events/functions/deactivateListener.min.js +1 -0
- package/dist/events/functions/deactivateListeners.d.ts +7 -0
- package/dist/events/functions/deactivateListeners.js +22 -0
- package/dist/events/functions/deactivateListeners.min.js +1 -0
- package/dist/events/functions/findEventListener.d.ts +22 -0
- package/dist/events/functions/findEventListener.js +61 -0
- package/dist/events/functions/findEventListener.min.js +1 -0
- package/dist/events/functions/fullAddEventListener.d.ts +20 -0
- package/dist/events/functions/fullAddEventListener.js +45 -0
- package/dist/events/functions/fullAddEventListener.min.js +1 -0
- package/dist/events/functions/fullRemoveEventListener.d.ts +22 -0
- package/dist/events/functions/fullRemoveEventListener.js +37 -0
- package/dist/events/functions/fullRemoveEventListener.min.js +1 -0
- package/dist/events/functions/listenerOptions.d.ts +12 -0
- package/dist/events/functions/listenerOptions.js +31 -0
- package/dist/events/functions/listenerOptions.min.js +1 -0
- package/dist/events/functions/makeEventHandler.d.ts +10 -0
- package/dist/events/functions/makeEventHandler.js +23 -0
- package/dist/events/functions/makeEventHandler.min.js +1 -0
- package/dist/events/functions/makeForwardingListener.d.ts +11 -0
- package/dist/events/functions/makeForwardingListener.js +46 -0
- package/dist/events/functions/makeForwardingListener.min.js +1 -0
- package/dist/events/functions/receiveForwardedEvent.d.ts +23 -0
- package/dist/events/functions/receiveForwardedEvent.js +40 -0
- package/dist/events/functions/receiveForwardedEvent.min.js +1 -0
- package/dist/events/functions/registerListener.d.ts +11 -0
- package/dist/events/functions/registerListener.js +25 -0
- package/dist/events/functions/registerListener.min.js +1 -0
- package/dist/events/functions/registerListeners.d.ts +10 -0
- package/dist/events/functions/registerListeners.js +26 -0
- package/dist/events/functions/registerListeners.min.js +1 -0
- package/dist/events/functions/removeEventListener.d.ts +18 -0
- package/dist/events/functions/removeEventListener.js +42 -0
- package/dist/events/functions/removeEventListener.min.js +1 -0
- package/dist/events/functions/retrieveListener.d.ts +14 -0
- package/dist/events/functions/retrieveListener.js +39 -0
- package/dist/events/functions/retrieveListener.min.js +1 -0
- package/dist/events/functions/revokeActiveListeners.d.ts +12 -0
- package/dist/events/functions/revokeActiveListeners.js +54 -0
- package/dist/events/functions/revokeActiveListeners.min.js +1 -0
- package/dist/events/functions/setForwardEvents.d.ts +11 -0
- package/dist/events/functions/setForwardEvents.js +26 -0
- package/dist/events/functions/setForwardEvents.min.js +1 -0
- package/dist/events/functions/unassignListener.d.ts +12 -0
- package/dist/events/functions/unassignListener.js +32 -0
- package/dist/events/functions/unassignListener.min.js +1 -0
- package/dist/events/index.d.ts +37 -0
- package/dist/events/index.js +72 -0
- package/dist/events/index.min.js +1 -0
- package/dist/events/objects/createEventListener.d.ts +13 -0
- package/dist/events/objects/createEventListener.js +30 -0
- package/dist/events/objects/createEventListener.min.js +1 -0
- package/dist/events/objects/createEventProxy.d.ts +10 -0
- package/dist/events/objects/createEventProxy.js +48 -0
- package/dist/events/objects/createEventProxy.min.js +1 -0
- package/dist/events/objects/createEventResponder.d.ts +8 -0
- package/dist/events/objects/createEventResponder.js +27 -0
- package/dist/events/objects/createEventResponder.min.js +1 -0
- package/dist/events/objects/options/getListenerOptions.d.ts +6 -0
- package/dist/events/objects/options/getListenerOptions.js +22 -0
- package/dist/events/objects/options/getListenerOptions.min.js +1 -0
- package/dist/events/objects/options/numberToOptions.d.ts +8 -0
- package/dist/events/objects/options/numberToOptions.js +21 -0
- package/dist/events/objects/options/numberToOptions.min.js +1 -0
- package/dist/events/objects/options/optionsToNumber.d.ts +9 -0
- package/dist/events/objects/options/optionsToNumber.js +27 -0
- package/dist/events/objects/options/optionsToNumber.min.js +1 -0
- package/dist/events/objects/options.d.ts +6 -0
- package/dist/events/objects/options.js +24 -0
- package/dist/events/objects/options.min.js +1 -0
- package/dist/events/types.d.ts +87 -0
- package/dist/events/types.js +8 -0
- package/dist/events/types.min.js +1 -0
- package/dist/inflate/index.d.ts +4 -0
- package/dist/inflate/index.js +17 -0
- package/dist/inflate/index.min.js +1 -0
- package/dist/inflate/jsonToDomItem.d.ts +7 -0
- package/dist/inflate/jsonToDomItem.js +30 -0
- package/dist/inflate/jsonToDomItem.min.js +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +24 -0
- package/dist/main.min.js +1 -0
- package/dist/render/generateElement.d.ts +7 -0
- package/dist/render/generateElement.js +41 -0
- package/dist/render/generateElement.min.js +1 -0
- package/dist/render/index.d.ts +9 -0
- package/dist/render/index.js +27 -0
- package/dist/render/index.min.js +1 -0
- package/dist/render/reconcile.d.ts +16 -0
- package/dist/render/reconcile.js +169 -0
- package/dist/render/reconcile.min.js +1 -0
- package/dist/render/renderHtml.d.ts +16 -0
- package/dist/render/renderHtml.js +57 -0
- package/dist/render/renderHtml.min.js +1 -0
- package/dist/render/updateChildNodes.d.ts +7 -0
- package/dist/render/updateChildNodes.js +53 -0
- package/dist/render/updateChildNodes.min.js +1 -0
- package/dist/render/updateElement.d.ts +14 -0
- package/dist/render/updateElement.js +113 -0
- package/dist/render/updateElement.min.js +1 -0
- package/dist/render/updateElements.d.ts +9 -0
- package/dist/render/updateElements.js +33 -0
- package/dist/render/updateElements.min.js +1 -0
- package/dist/renderOnly.d.ts +2 -0
- package/dist/renderOnly.js +27 -0
- package/dist/renderOnly.min.js +1 -0
- package/dist/sync/index.d.ts +6 -0
- package/dist/sync/index.js +21 -0
- package/dist/sync/index.min.js +1 -0
- package/dist/sync/updateChildren.d.ts +7 -0
- package/dist/sync/updateChildren.js +38 -0
- package/dist/sync/updateChildren.min.js +1 -0
- package/dist/sync/updateDomItem.d.ts +8 -0
- package/dist/sync/updateDomItem.js +53 -0
- package/dist/sync/updateDomItem.min.js +1 -0
- package/dist/sync/updateDomItems.d.ts +9 -0
- package/dist/sync/updateDomItems.js +33 -0
- package/dist/sync/updateDomItems.min.js +1 -0
- package/package.json +74 -4
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
7
|
+
return mod && mod.__esModule ? mod : {
|
|
8
|
+
"default": mod
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", {
|
|
12
|
+
value: true
|
|
13
|
+
});
|
|
14
|
+
const si_funciona_1 = __importDefault(require("si-funciona"));
|
|
15
|
+
/**
|
|
16
|
+
* Take an integer representation of the listener options and convert them to the listener options object.
|
|
17
|
+
* @param optionsTemplate
|
|
18
|
+
* @param binaryOptions
|
|
19
|
+
*/
|
|
20
|
+
const numberToOptions = (optionsTemplate, binaryOptions) => si_funciona_1.default.mapObject(optionsTemplate, flag => !!(binaryOptions & flag));
|
|
21
|
+
exports.default = numberToOptions;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const si_funciona_1=__importDefault(require("si-funciona")),numberToOptions=(e,t)=>si_funciona_1.default.mapObject(e,e=>!!(t&e));exports.default=numberToOptions;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ListenerOptions, OptionsTemplate } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Take the given options and convert them (using binary) to an integer. Given listener options, each one is assigned a
|
|
4
|
+
* bitwise position. The resulting binary number represents any possible combination of the available flags set.
|
|
5
|
+
* @param optionsTemplate
|
|
6
|
+
* @param listenerOptions
|
|
7
|
+
*/
|
|
8
|
+
declare const optionsToNumber: (optionsTemplate: OptionsTemplate, listenerOptions?: ListenerOptions | null) => number;
|
|
9
|
+
export default optionsToNumber;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
7
|
+
return mod && mod.__esModule ? mod : {
|
|
8
|
+
"default": mod
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", {
|
|
12
|
+
value: true
|
|
13
|
+
});
|
|
14
|
+
const si_funciona_1 = __importDefault(require("si-funciona"));
|
|
15
|
+
/**
|
|
16
|
+
* Take the given options and convert them (using binary) to an integer. Given listener options, each one is assigned a
|
|
17
|
+
* bitwise position. The resulting binary number represents any possible combination of the available flags set.
|
|
18
|
+
* @param optionsTemplate
|
|
19
|
+
* @param listenerOptions
|
|
20
|
+
*/
|
|
21
|
+
const optionsToNumber = (optionsTemplate, listenerOptions) => {
|
|
22
|
+
if (!listenerOptions) {
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
return si_funciona_1.default.reduceObject(optionsTemplate, (binaryOptions, flag, name) => listenerOptions[name] ? binaryOptions | flag : binaryOptions, 0);
|
|
26
|
+
};
|
|
27
|
+
exports.default = optionsToNumber;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const si_funciona_1=__importDefault(require("si-funciona")),optionsToNumber=(e,t)=>t?si_funciona_1.default.reduceObject(e,(e,o,u)=>t[u]?e|o:e,0):0;exports.default=optionsToNumber;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
getListenerOptions: () => import("../types").OptionsTemplate;
|
|
3
|
+
numberToOptions: (optionsTemplate: import("../types").OptionsTemplate, binaryOptions: number) => import("../types").OptionsObject;
|
|
4
|
+
optionsToNumber: (optionsTemplate: import("../types").OptionsTemplate, listenerOptions?: import("../types").ListenerOptions | null) => number;
|
|
5
|
+
};
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
7
|
+
return mod && mod.__esModule ? mod : {
|
|
8
|
+
"default": mod
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", {
|
|
12
|
+
value: true
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Be able to use Flags (Options) in a well-formed way.
|
|
16
|
+
*/
|
|
17
|
+
const getListenerOptions_1 = __importDefault(require("./options/getListenerOptions"));
|
|
18
|
+
const numberToOptions_1 = __importDefault(require("./options/numberToOptions"));
|
|
19
|
+
const optionsToNumber_1 = __importDefault(require("./options/optionsToNumber"));
|
|
20
|
+
exports.default = {
|
|
21
|
+
getListenerOptions: getListenerOptions_1.default,
|
|
22
|
+
numberToOptions: numberToOptions_1.default,
|
|
23
|
+
optionsToNumber: optionsToNumber_1.default
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const getListenerOptions_1=__importDefault(require("./options/getListenerOptions")),numberToOptions_1=__importDefault(require("./options/numberToOptions")),optionsToNumber_1=__importDefault(require("./options/optionsToNumber"));exports.default={getListenerOptions:getListenerOptions_1.default,numberToOptions:numberToOptions_1.default,optionsToNumber:optionsToNumber_1.default};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { DomItem } from '../domItem/types';
|
|
2
|
+
/** The name of a DOM event: click, submit, keydown, ... */
|
|
3
|
+
export type EventName = string;
|
|
4
|
+
/** The old boolean form of the options argument of addEventListener. */
|
|
5
|
+
export type UseCapture = boolean;
|
|
6
|
+
/** The listener options which treeloom understands (each one is a flag, see {@link OptionsTemplate}). */
|
|
7
|
+
export type OptionsObject = {
|
|
8
|
+
/** Events of this type are dispatched to the listener before any other target beneath it. */
|
|
9
|
+
capture?: boolean;
|
|
10
|
+
/** The listener is removed after it has been invoked once. */
|
|
11
|
+
once?: boolean;
|
|
12
|
+
/** The listener will never call preventDefault(). */
|
|
13
|
+
passive?: boolean;
|
|
14
|
+
/** The listener is removed when the AbortSignal's abort() is called. */
|
|
15
|
+
signal?: boolean | AbortSignal;
|
|
16
|
+
};
|
|
17
|
+
/** The options given with a listener: an options object, or just the useCapture boolean. */
|
|
18
|
+
export type ListenerOptions = OptionsObject | UseCapture;
|
|
19
|
+
/** An Event which also remembers whether stopImmediatePropagation() was called on it, and carries the DomItems
|
|
20
|
+
* target/currentTarget correspond to. */
|
|
21
|
+
export type EventProxy = Event & {
|
|
22
|
+
immediatePropagationStopped: boolean;
|
|
23
|
+
/** The DomItem whose element matches the real event's target, searched for within currentDomItemTarget's own
|
|
24
|
+
* subtree (an event's target is always itself or a descendant of the item a listener is attached to - that is
|
|
25
|
+
* what bubbling means). Null when none is found. */
|
|
26
|
+
domItemTarget: DomItem | null;
|
|
27
|
+
/** The DomItem the listener is attached to (the real event's currentTarget). */
|
|
28
|
+
currentDomItemTarget: DomItem;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A function which handles an event on a DomItem. It receives the event, the DomItem which owns the listener and any
|
|
32
|
+
* listenerArgs. (The extra arguments are whatever the listener needs, so they can only be typed by the listener.)
|
|
33
|
+
*/
|
|
34
|
+
export type ListenerFunction = (event: EventProxy | Event, target: DomItem, ...args: any[]) => unknown;
|
|
35
|
+
/** A listenerFunction wrapped so it skips events which stopped propagating, ready to be attached to an element. */
|
|
36
|
+
export type EventHandler = (event?: EventProxy | Event | null) => unknown;
|
|
37
|
+
/** The description of one listener on a DomItem: what to call, with what, and how. */
|
|
38
|
+
export type ListenerDescriptor = {
|
|
39
|
+
/** Prefer a string name registered with registerListener: it survives being converted to json. */
|
|
40
|
+
listenerFunc: string | ListenerFunction;
|
|
41
|
+
/** Additional arguments for the listener function. */
|
|
42
|
+
listenerArgs?: object | null;
|
|
43
|
+
listenerOptions?: ListenerOptions;
|
|
44
|
+
/** Whether this listener has been applied to the element. */
|
|
45
|
+
listenerActive?: boolean;
|
|
46
|
+
/** Set while the listener is active: the responder which attaches it to the element and can detach it again. */
|
|
47
|
+
activeResponder?: EventResponder | null;
|
|
48
|
+
};
|
|
49
|
+
/** All the listeners of one event type. */
|
|
50
|
+
export type EventListeners = ListenerDescriptor[];
|
|
51
|
+
/** What a forwarded event is packaged as in render-only mode. See retrieveListener, makeForwardingListener. */
|
|
52
|
+
export type ForwardedEvent = {
|
|
53
|
+
/** The id of the item the event fired on (domItemTarget, falling back to the item the listener is attached
|
|
54
|
+
* to when no domItemTarget was found) - read directly off that item's own id, not computed. Resolution is a
|
|
55
|
+
* lookup (getItemById) rather than a tree walk, so it still finds the right item even if the receiving end's
|
|
56
|
+
* own tree does not match the sending end's shape exactly (see getItemById vs the position-based
|
|
57
|
+
* getItemPath/getItemByPath this replaced). */
|
|
58
|
+
itemId: number;
|
|
59
|
+
/** The type of event which fired (event.type). */
|
|
60
|
+
eventType: EventName;
|
|
61
|
+
/** The registered name of the listener which would have run locally. */
|
|
62
|
+
listenerFunc: string;
|
|
63
|
+
/** The custom args the listener was registered with. */
|
|
64
|
+
data: unknown[];
|
|
65
|
+
/** Live state read directly off the real event's target when present - a listener which reads e.g.
|
|
66
|
+
* (event.target as HTMLInputElement).checked needs this replayed onto the real target on the receiving end
|
|
67
|
+
* (see receiveForwardedEvent), since the two ends' elements are otherwise independent objects. */
|
|
68
|
+
targetState?: {
|
|
69
|
+
checked?: boolean;
|
|
70
|
+
value?: string;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
/** Where a forwarded event's envelope is sent, in render-only mode. Set on the root item with setForwardEvents. */
|
|
74
|
+
export type ForwardEventsFunction = (envelope: ForwardedEvent) => unknown;
|
|
75
|
+
/** An event handler and the way to detach it again: the handler as attached, and an optional AbortController. */
|
|
76
|
+
export type EventResponder = {
|
|
77
|
+
handler: EventHandler;
|
|
78
|
+
abort: AbortController | null;
|
|
79
|
+
/** The exact function reference passed to the element's addEventListener, needed to remove it again. */
|
|
80
|
+
assignedHandler: EventHandler | null;
|
|
81
|
+
};
|
|
82
|
+
/** Bit flags for each of the listener options. */
|
|
83
|
+
export type OptionsTemplate = Record<string, number>;
|
|
84
|
+
/** What treeloom needs from an element to attach a listener, including the very old ways of doing it. */
|
|
85
|
+
export type ListenerTarget = EventTarget & {
|
|
86
|
+
attachEvent?: (eventName: string, handler: EventHandler) => void;
|
|
87
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
Object.defineProperty(exports, "__esModule", {
|
|
7
|
+
value: true
|
|
8
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
7
|
+
return mod && mod.__esModule ? mod : {
|
|
8
|
+
"default": mod
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", {
|
|
12
|
+
value: true
|
|
13
|
+
});
|
|
14
|
+
const jsonToDomItem_1 = __importDefault(require("./jsonToDomItem"));
|
|
15
|
+
exports.default = {
|
|
16
|
+
jsonToDomItem: jsonToDomItem_1.default
|
|
17
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const jsonToDomItem_1=__importDefault(require("./jsonToDomItem"));exports.default={jsonToDomItem:jsonToDomItem_1.default};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
7
|
+
return mod && mod.__esModule ? mod : {
|
|
8
|
+
"default": mod
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", {
|
|
12
|
+
value: true
|
|
13
|
+
});
|
|
14
|
+
const setParentItemReferences_1 = __importDefault(require("../domItem/tree/setParentItemReferences"));
|
|
15
|
+
const addDomItemProperties_1 = __importDefault(require("../domItem/objects/addDomItemProperties"));
|
|
16
|
+
/**
|
|
17
|
+
* Convert DOM Item to JSON string.
|
|
18
|
+
* @param jsonString
|
|
19
|
+
*/
|
|
20
|
+
const jsonToDomItem = jsonString => {
|
|
21
|
+
const parsedJson = (0, setParentItemReferences_1.default)((0, addDomItemProperties_1.default)(JSON.parse(jsonString)));
|
|
22
|
+
if (parsedJson.nodeName === '#document') {
|
|
23
|
+
const root = parsedJson;
|
|
24
|
+
root.element = document;
|
|
25
|
+
root.head = root.children[0];
|
|
26
|
+
root.body = root.children[1];
|
|
27
|
+
}
|
|
28
|
+
return parsedJson;
|
|
29
|
+
};
|
|
30
|
+
exports.default = jsonToDomItem;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const setParentItemReferences_1=__importDefault(require("../domItem/tree/setParentItemReferences")),addDomItemProperties_1=__importDefault(require("../domItem/objects/addDomItemProperties")),jsonToDomItem=e=>{const t=(0,setParentItemReferences_1.default)((0,addDomItemProperties_1.default)(JSON.parse(e)));if("#document"===t.nodeName){const e=t;e.element=document,e.head=e.children[0],e.body=e.children[1]}return t};exports.default=jsonToDomItem;
|
package/dist/main.d.ts
ADDED
package/dist/main.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
7
|
+
return mod && mod.__esModule ? mod : {
|
|
8
|
+
"default": mod
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* All of the JSON DOM system functions for building and syncing a Virtual DOM (DomItem tree) to the real HTML DOM.
|
|
13
|
+
*/
|
|
14
|
+
const index_1 = __importDefault(require("./events/index"));
|
|
15
|
+
const index_2 = __importDefault(require("./domItem/index"));
|
|
16
|
+
const documentItem_1 = require("./domItem/objects/documentItem");
|
|
17
|
+
const index_3 = __importDefault(require("./inflate/index"));
|
|
18
|
+
const index_4 = __importDefault(require("./deflate/index"));
|
|
19
|
+
const index_5 = __importDefault(require("./render/index"));
|
|
20
|
+
const index_6 = __importDefault(require("./sync/index"));
|
|
21
|
+
const index_7 = __importDefault(require("./diff/index"));
|
|
22
|
+
// documentItem is a getter (see withDocumentItem), so loading treeloom never touches a real document
|
|
23
|
+
const treeloom = (0, documentItem_1.withDocumentItem)(Object.assign({}, index_1.default, index_2.default, index_3.default, index_4.default, index_5.default, index_6.default, index_7.default));
|
|
24
|
+
module.exports = treeloom;
|
package/dist/main.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};const index_1=__importDefault(require("./events/index")),index_2=__importDefault(require("./domItem/index")),documentItem_1=require("./domItem/objects/documentItem"),index_3=__importDefault(require("./inflate/index")),index_4=__importDefault(require("./deflate/index")),index_5=__importDefault(require("./render/index")),index_6=__importDefault(require("./sync/index")),index_7=__importDefault(require("./diff/index")),treeloom=(0,documentItem_1.withDocumentItem)(Object.assign({},index_1.default,index_2.default,index_3.default,index_4.default,index_5.default,index_6.default,index_7.default));module.exports=treeloom;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DomItem } from '../domItem/types';
|
|
2
|
+
/**
|
|
3
|
+
* Create an HTML element based on the provided attributes and return the element as an Object.
|
|
4
|
+
* @param domItem - The DomItem requiring matching HTML element property
|
|
5
|
+
*/
|
|
6
|
+
declare const generateElement: (domItem: DomItem) => DomItem;
|
|
7
|
+
export default generateElement;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
7
|
+
return mod && mod.__esModule ? mod : {
|
|
8
|
+
"default": mod
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", {
|
|
12
|
+
value: true
|
|
13
|
+
});
|
|
14
|
+
const updateElement_1 = __importDefault(require("./updateElement"));
|
|
15
|
+
/**
|
|
16
|
+
* Create a new DOM Node based on name and data.
|
|
17
|
+
* @param nodeName
|
|
18
|
+
* @param data
|
|
19
|
+
*/
|
|
20
|
+
const makeElementType = (nodeName, data = null, is) => {
|
|
21
|
+
switch (nodeName) {
|
|
22
|
+
case '#text':
|
|
23
|
+
return document.createTextNode(data);
|
|
24
|
+
case '#comment':
|
|
25
|
+
return document.createComment(data);
|
|
26
|
+
default:
|
|
27
|
+
// A customized built-in element (<button is="fancy-button">) has to be given its name when it is created
|
|
28
|
+
return is ? document.createElement(nodeName, {
|
|
29
|
+
is
|
|
30
|
+
}) : document.createElement(nodeName);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Create an HTML element based on the provided attributes and return the element as an Object.
|
|
35
|
+
* @param domItem - The DomItem requiring matching HTML element property
|
|
36
|
+
*/
|
|
37
|
+
const generateElement = domItem => {
|
|
38
|
+
domItem.element = makeElementType(domItem.nodeName, domItem.nodeValue, typeof domItem.attributes.is === 'string' ? domItem.attributes.is : undefined);
|
|
39
|
+
return (0, updateElement_1.default)(domItem);
|
|
40
|
+
};
|
|
41
|
+
exports.default = generateElement;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const updateElement_1=__importDefault(require("./updateElement")),makeElementType=(e,t=null,n)=>{switch(e){case"#text":return document.createTextNode(t);case"#comment":return document.createComment(t);default:return n?document.createElement(e,{is:n}):document.createElement(e)}},generateElement=e=>(e.element=makeElementType(e.nodeName,e.nodeValue,"string"==typeof e.attributes.is?e.attributes.is:void 0),(0,updateElement_1.default)(e));exports.default=generateElement;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
generateElement: (domItem: import("../domItem/types").DomItem) => import("../domItem/types").DomItem;
|
|
3
|
+
reconcile: (existing: import("../domItem/types").DomItem, next: import("../domItem/types").DomItem) => import("../domItem/types").DomItem;
|
|
4
|
+
renderHtml: (item?: import("../domItem/types").DomItem | null, parent?: import("../domItem/types").DomItem, index?: number) => import("../domItem/types").DomItem;
|
|
5
|
+
updateChildNodes: (domItem: import("../domItem/types").DomItem) => import("../domItem/types").DomItem;
|
|
6
|
+
updateElement: (domItem: import("../domItem/types").DomItem) => import("../domItem/types").DomItem;
|
|
7
|
+
updateElements: (config: import("../domItem/types").DomItem) => import("../domItem/types").DomItem;
|
|
8
|
+
};
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
6
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
7
|
+
return mod && mod.__esModule ? mod : {
|
|
8
|
+
"default": mod
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", {
|
|
12
|
+
value: true
|
|
13
|
+
});
|
|
14
|
+
const generateElement_1 = __importDefault(require("./generateElement"));
|
|
15
|
+
const reconcile_1 = __importDefault(require("./reconcile"));
|
|
16
|
+
const renderHtml_1 = __importDefault(require("./renderHtml"));
|
|
17
|
+
const updateChildNodes_1 = __importDefault(require("./updateChildNodes"));
|
|
18
|
+
const updateElement_1 = __importDefault(require("./updateElement"));
|
|
19
|
+
const updateElements_1 = __importDefault(require("./updateElements"));
|
|
20
|
+
exports.default = {
|
|
21
|
+
generateElement: generateElement_1.default,
|
|
22
|
+
reconcile: reconcile_1.default,
|
|
23
|
+
renderHtml: renderHtml_1.default,
|
|
24
|
+
updateChildNodes: updateChildNodes_1.default,
|
|
25
|
+
updateElement: updateElement_1.default,
|
|
26
|
+
updateElements: updateElements_1.default
|
|
27
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const generateElement_1=__importDefault(require("./generateElement")),reconcile_1=__importDefault(require("./reconcile")),renderHtml_1=__importDefault(require("./renderHtml")),updateChildNodes_1=__importDefault(require("./updateChildNodes")),updateElement_1=__importDefault(require("./updateElement")),updateElements_1=__importDefault(require("./updateElements"));exports.default={generateElement:generateElement_1.default,reconcile:reconcile_1.default,renderHtml:renderHtml_1.default,updateChildNodes:updateChildNodes_1.default,updateElement:updateElement_1.default,updateElements:updateElements_1.default};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DomItem } from '../domItem/types';
|
|
2
|
+
/**
|
|
3
|
+
* Update a rendered tree to match a new version of it (the next tree, such as one inflated from a server's JSON), by
|
|
4
|
+
* changing only what differs instead of rendering everything again. Children are matched by id, otherwise by
|
|
5
|
+
* position and node name. A matched item keeps its element, its id and its listeners; it takes the next item's
|
|
6
|
+
* attributes and data, and its named listeners are made the next item's. Items the next tree doesn't have are removed,
|
|
7
|
+
* new ones are added, and then only the changed attributes and nodes are written to the page (see updateElement).
|
|
8
|
+
*
|
|
9
|
+
* Listeners added as functions (locally, not carried by the next tree) and focus stay where they are, since the
|
|
10
|
+
* elements do.
|
|
11
|
+
* @param existing - An item already rendered (it has an element). It stays the same kind of node: next must be one too.
|
|
12
|
+
* @param next - The tree it should now match. Its items are taken over: don't render it separately.
|
|
13
|
+
* @returns existing, updated.
|
|
14
|
+
*/
|
|
15
|
+
declare const reconcile: (existing: DomItem, next: DomItem) => DomItem;
|
|
16
|
+
export default reconcile;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
require("core-js/modules/es.array.includes.js");
|
|
4
|
+
require("core-js/modules/es.json.stringify.js");
|
|
5
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
6
|
+
return mod && mod.__esModule ? mod : {
|
|
7
|
+
"default": mod
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", {
|
|
11
|
+
value: true
|
|
12
|
+
});
|
|
13
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
14
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
15
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
16
|
+
const removeEventListener_1 = __importDefault(require("../events/functions/removeEventListener"));
|
|
17
|
+
const itemIdIndex_1 = require("../domItem/tree/itemIdIndex");
|
|
18
|
+
const updateElements_1 = __importDefault(require("./updateElements"));
|
|
19
|
+
/** What makes an item part of the tree rather than its data: kept on the existing item, never taken from the next.
|
|
20
|
+
* The id is taken from the next item, so ids stay the ones the next tree (a server's, say) gives its items. */
|
|
21
|
+
const STRUCTURE = new Set(['element', 'parentItem', 'children', 'eventListeners', 'activeListeners']);
|
|
22
|
+
/**
|
|
23
|
+
* A named listener as plain data, to tell whether two items have the same one. Only named listeners are compared: they
|
|
24
|
+
* are the ones a tree carries as JSON. A listener given as a function was added locally (keyboard navigation, say)
|
|
25
|
+
* and is never in the next tree, so it is left alone.
|
|
26
|
+
* @param listener
|
|
27
|
+
*/
|
|
28
|
+
const listenerKey = listener => typeof listener.listenerFunc === 'string' ? JSON.stringify([listener.listenerFunc, listener.listenerArgs ?? null, listener.listenerOptions ?? null]) : null;
|
|
29
|
+
/**
|
|
30
|
+
* Make existing's named listeners the next item's: remove the ones the next item doesn't have (detached from the
|
|
31
|
+
* element), and add the ones it gains (bound when the element is updated). Unchanged ones stay bound as they are.
|
|
32
|
+
* @param existing
|
|
33
|
+
* @param next
|
|
34
|
+
*/
|
|
35
|
+
const reconcileListeners = (existing, next) => {
|
|
36
|
+
const nextListeners = next.eventListeners ?? {};
|
|
37
|
+
existing.eventListeners = existing.eventListeners ?? {};
|
|
38
|
+
for (const eventName of Object.keys(existing.eventListeners)) {
|
|
39
|
+
const wanted = (nextListeners[eventName] ?? []).map(listenerKey);
|
|
40
|
+
for (const listener of [...existing.eventListeners[eventName]]) {
|
|
41
|
+
const key = listenerKey(listener);
|
|
42
|
+
if (key !== null && !wanted.includes(key)) {
|
|
43
|
+
(0, removeEventListener_1.default)(eventName, listener.listenerFunc, listener.listenerArgs, listener.listenerOptions, existing);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
for (const eventName of Object.keys(nextListeners)) {
|
|
48
|
+
const have = (existing.eventListeners[eventName] ?? []).map(listenerKey);
|
|
49
|
+
for (const listener of nextListeners[eventName]) {
|
|
50
|
+
const key = listenerKey(listener);
|
|
51
|
+
if (key !== null && !have.includes(key)) {
|
|
52
|
+
existing.eventListeners[eventName] = existing.eventListeners[eventName] ?? [];
|
|
53
|
+
existing.eventListeners[eventName].push({
|
|
54
|
+
...listener,
|
|
55
|
+
listenerActive: false,
|
|
56
|
+
activeResponder: null
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Make existing's own data the next item's (its id included): every property but the structure (element, parent,
|
|
64
|
+
* children, listeners). A property the next item doesn't have is removed, unless it is a function (something added locally).
|
|
65
|
+
* @param existing
|
|
66
|
+
* @param next
|
|
67
|
+
*/
|
|
68
|
+
const reconcileData = (existing, next) => {
|
|
69
|
+
const target = existing;
|
|
70
|
+
const source = next;
|
|
71
|
+
for (const key of Object.keys(target)) {
|
|
72
|
+
if (!STRUCTURE.has(key) && !(key in source) && typeof target[key] !== 'function') {
|
|
73
|
+
delete target[key];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (const key of Object.keys(source)) {
|
|
77
|
+
if (!STRUCTURE.has(key)) {
|
|
78
|
+
target[key] = source[key];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Pair each next child with the existing child it updates: the one with the same id, otherwise the one at the same
|
|
84
|
+
* position when it is the same kind of node and no next child has it by id (an item without an id in the JSON, a
|
|
85
|
+
* text node say, gets a fresh one when inflated, so its id says nothing about which item it was). Unpaired next
|
|
86
|
+
* children are new.
|
|
87
|
+
* @param existing
|
|
88
|
+
* @param next
|
|
89
|
+
*/
|
|
90
|
+
const pairChildren = (existing, next) => {
|
|
91
|
+
const byId = new Map();
|
|
92
|
+
existing.forEach(child => {
|
|
93
|
+
if (typeof child.id === 'number') {
|
|
94
|
+
byId.set(child.id, child);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
// An existing child some next child has by id is that one's, never another's by position
|
|
98
|
+
const claimed = new Set(next.map(child => typeof child.id === 'number' ? byId.get(child.id) : undefined).filter(Boolean));
|
|
99
|
+
const taken = new Set();
|
|
100
|
+
return next.map((nextChild, index) => {
|
|
101
|
+
const sameId = typeof nextChild.id === 'number' ? byId.get(nextChild.id) : undefined;
|
|
102
|
+
const atPosition = existing[index] && !claimed.has(existing[index]) ? existing[index] : undefined;
|
|
103
|
+
const candidate = sameId ?? atPosition;
|
|
104
|
+
if (candidate && !taken.has(candidate) && candidate.nodeName === nextChild.nodeName) {
|
|
105
|
+
taken.add(candidate);
|
|
106
|
+
return candidate;
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Update existing's subtree to match next's, reusing every item (and its element and listeners) that next still has.
|
|
113
|
+
* Items next no longer has are removed; new ones are added. Elements are not touched here; see reconcile.
|
|
114
|
+
* @param existing
|
|
115
|
+
* @param next
|
|
116
|
+
*/
|
|
117
|
+
const reconcileItem = (existing, next) => {
|
|
118
|
+
reconcileData(existing, next);
|
|
119
|
+
reconcileListeners(existing, next);
|
|
120
|
+
const previous = existing.children ?? [];
|
|
121
|
+
const nextChildren = next.children ?? [];
|
|
122
|
+
const pairs = pairChildren(previous, nextChildren);
|
|
123
|
+
const kept = new Set(pairs.filter(Boolean));
|
|
124
|
+
previous.filter(child => !kept.has(child)).forEach(child => {
|
|
125
|
+
// Removed (already out of the id index, see reconcile): its element out of the page
|
|
126
|
+
;
|
|
127
|
+
child.element?.remove?.();
|
|
128
|
+
});
|
|
129
|
+
existing.children = nextChildren.map((nextChild, index) => {
|
|
130
|
+
const child = pairs[index];
|
|
131
|
+
if (child) {
|
|
132
|
+
reconcileItem(child, nextChild);
|
|
133
|
+
return child;
|
|
134
|
+
}
|
|
135
|
+
// New: taken as it is; its element is generated when the subtree is updated below
|
|
136
|
+
nextChild.parentItem = existing;
|
|
137
|
+
return nextChild;
|
|
138
|
+
});
|
|
139
|
+
existing.children.forEach(child => {
|
|
140
|
+
child.parentItem = existing;
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Update a rendered tree to match a new version of it (the next tree, such as one inflated from a server's JSON), by
|
|
145
|
+
* changing only what differs instead of rendering everything again. Children are matched by id, otherwise by
|
|
146
|
+
* position and node name. A matched item keeps its element, its id and its listeners; it takes the next item's
|
|
147
|
+
* attributes and data, and its named listeners are made the next item's. Items the next tree doesn't have are removed,
|
|
148
|
+
* new ones are added, and then only the changed attributes and nodes are written to the page (see updateElement).
|
|
149
|
+
*
|
|
150
|
+
* Listeners added as functions (locally, not carried by the next tree) and focus stay where they are, since the
|
|
151
|
+
* elements do.
|
|
152
|
+
* @param existing - An item already rendered (it has an element). It stays the same kind of node: next must be one too.
|
|
153
|
+
* @param next - The tree it should now match. Its items are taken over: don't render it separately.
|
|
154
|
+
* @returns existing, updated.
|
|
155
|
+
*/
|
|
156
|
+
const reconcile = (existing, next) => {
|
|
157
|
+
// The item updated in place is where the page's content lives (a <main>, a <body>): changing its kind of node would
|
|
158
|
+
// replace that element with a new one outside the page. Children of another kind are replaced; this one never is.
|
|
159
|
+
if (existing.nodeName.toLowerCase() !== next.nodeName.toLowerCase()) {
|
|
160
|
+
throw new Error(`reconcile can't turn a ${existing.nodeName} into a ${next.nodeName}: give it a tree of the same node, or reconcile its parent.`);
|
|
161
|
+
}
|
|
162
|
+
// Ids can change (they follow the next tree), so the subtree leaves the id index first and is indexed again after
|
|
163
|
+
(0, itemIdIndex_1.unregisterItemIds)(existing);
|
|
164
|
+
reconcileItem(existing, next);
|
|
165
|
+
(0, itemIdIndex_1.registerItemIds)(existing);
|
|
166
|
+
// updateElements patches each item's element (only what changed) and puts its children's elements in order
|
|
167
|
+
return (0, updateElements_1.default)(existing);
|
|
168
|
+
};
|
|
169
|
+
exports.default = reconcile;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";require("core-js/modules/es.array.includes.js"),require("core-js/modules/es.json.stringify.js");var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const removeEventListener_1=__importDefault(require("../events/functions/removeEventListener")),itemIdIndex_1=require("../domItem/tree/itemIdIndex"),updateElements_1=__importDefault(require("./updateElements")),STRUCTURE=new Set(["element","parentItem","children","eventListeners","activeListeners"]),listenerKey=e=>"string"==typeof e.listenerFunc?JSON.stringify([e.listenerFunc,e.listenerArgs??null,e.listenerOptions??null]):null,reconcileListeners=(e,t)=>{const n=t.eventListeners??{};e.eventListeners=e.eventListeners??{};for(const t of Object.keys(e.eventListeners)){const r=(n[t]??[]).map(listenerKey);for(const n of[...e.eventListeners[t]]){const s=listenerKey(n);null===s||r.includes(s)||(0,removeEventListener_1.default)(t,n.listenerFunc,n.listenerArgs,n.listenerOptions,e)}}for(const t of Object.keys(n)){const r=(e.eventListeners[t]??[]).map(listenerKey);for(const s of n[t]){const n=listenerKey(s);null===n||r.includes(n)||(e.eventListeners[t]=e.eventListeners[t]??[],e.eventListeners[t].push({...s,listenerActive:!1,activeResponder:null}))}}},reconcileData=(e,t)=>{const n=e,r=t;for(const e of Object.keys(n))STRUCTURE.has(e)||e in r||"function"==typeof n[e]||delete n[e];for(const e of Object.keys(r))STRUCTURE.has(e)||(n[e]=r[e])},pairChildren=(e,t)=>{const n=new Map;e.forEach(e=>{"number"==typeof e.id&&n.set(e.id,e)});const r=new Set(t.map(e=>"number"==typeof e.id?n.get(e.id):void 0).filter(Boolean)),s=new Set;return t.map((t,i)=>{const o="number"==typeof t.id?n.get(t.id):void 0,c=e[i]&&!r.has(e[i])?e[i]:void 0,l=o??c;if(l&&!s.has(l)&&l.nodeName===t.nodeName)return s.add(l),l})},reconcileItem=(e,t)=>{reconcileData(e,t),reconcileListeners(e,t);const n=e.children??[],r=t.children??[],s=pairChildren(n,r),i=new Set(s.filter(Boolean));n.filter(e=>!i.has(e)).forEach(e=>{e.element?.remove?.()}),e.children=r.map((t,n)=>{const r=s[n];return r?(reconcileItem(r,t),r):(t.parentItem=e,t)}),e.children.forEach(t=>{t.parentItem=e})},reconcile=(e,t)=>{if(e.nodeName.toLowerCase()!==t.nodeName.toLowerCase())throw new Error(`reconcile can't turn a ${e.nodeName} into a ${t.nodeName}: give it a tree of the same node, or reconcile its parent.`);return(0,itemIdIndex_1.unregisterItemIds)(e),reconcileItem(e,t),(0,itemIdIndex_1.registerItemIds)(e),(0,updateElements_1.default)(e)};exports.default=reconcile;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DomItem } from '../domItem/types';
|
|
2
|
+
/**
|
|
3
|
+
* This is a shortcut for syncing a Virtual DOM (DomItem tree) item onto the real HTML DOM: builds the real elements
|
|
4
|
+
* for it and its descendants, inserts them into parent's children (the document body by default), and binds their
|
|
5
|
+
* associated listeners.
|
|
6
|
+
* @param item - The DomItem that we want to render the element for
|
|
7
|
+
* @param parent - Where to insert item, when it does not already have a parent - defaults to the
|
|
8
|
+
* document body, so passing nothing keeps working exactly as before
|
|
9
|
+
* @param index - Where in parent's children to put item - defaults to the end (a plain append), so passing nothing
|
|
10
|
+
* keeps working exactly as before. To insert item among parent's already-rendered content (existing real HTML),
|
|
11
|
+
* parent's children must already reflect that content first - see {@link updateDomItems}, which captures the real
|
|
12
|
+
* DOM into items. Skipping that step and inserting anyway will make the next render remove the untracked content,
|
|
13
|
+
* since it is invisible to parent.children.
|
|
14
|
+
*/
|
|
15
|
+
declare const renderHtml: (item?: DomItem | null, parent?: DomItem, index?: number) => DomItem;
|
|
16
|
+
export default renderHtml;
|