@needle-tools/engine 4.11.3-next.2d2dff8 → 4.11.3-next.35d1b4d
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/dist/{needle-engine.bundle-GysGCdkn.umd.cjs → needle-engine.bundle-BTf7HHet.umd.cjs} +121 -121
- package/dist/{needle-engine.bundle-Buwrv7Cc.js → needle-engine.bundle-COMN0eJQ.js} +4107 -4083
- package/dist/{needle-engine.bundle-CMdUN8y6.min.js → needle-engine.bundle-_QBUSIl2.min.js} +134 -134
- package/dist/needle-engine.js +2 -2
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +36 -11
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/engine_utils_attributes.d.ts +48 -0
- package/lib/engine/engine_utils_attributes.js +70 -0
- package/lib/engine/engine_utils_attributes.js.map +1 -0
- package/package.json +1 -1
- package/src/engine/engine_utils.ts +38 -14
- package/src/engine/engine_utils_attributes.ts +72 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
*/
|
|
4
|
+
export declare namespace InternalAttributeUtils {
|
|
5
|
+
/**
|
|
6
|
+
* Checks if the given value is considered "falsey" in the context of HTML attributes.
|
|
7
|
+
* A value is considered falsey if it is "0" or "false" (case-insensitive).
|
|
8
|
+
*
|
|
9
|
+
* @param value - The attribute value to check.
|
|
10
|
+
* @returns True if the value is falsey, otherwise false.
|
|
11
|
+
*/
|
|
12
|
+
function isFalsey(value: string | null): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Retrieves the value of the specified attribute from the given element.
|
|
15
|
+
* If the attribute value is considered falsey, it returns null.
|
|
16
|
+
* @returns The attribute value or null if falsey.
|
|
17
|
+
*/
|
|
18
|
+
function getAttributeValueIfNotFalsey(element: Element, attributeName: string, opts?: {
|
|
19
|
+
onAttribute: (value: string) => void;
|
|
20
|
+
}): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Retrieves the value of the specified attribute from the given element.
|
|
23
|
+
* If the attribute value is considered falsey, it returns false.
|
|
24
|
+
* If the attribute is not set at all, it returns null.
|
|
25
|
+
* @returns The attribute value, false if falsey, or null if not set.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const result = HTMLAttributeUtils.getAttributeAndCheckFalsey(element, 'data-example', {
|
|
30
|
+
* onAttribute: (value, falsey) => {
|
|
31
|
+
* console.log(`Attribute value: ${value}
|
|
32
|
+
* , Is falsey: ${falsey}`);
|
|
33
|
+
* }
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* if (result === false) {
|
|
37
|
+
* console.log('The attribute is set to a falsey value.');
|
|
38
|
+
* } else if (result === null) {
|
|
39
|
+
* console.log('The attribute is not set.');
|
|
40
|
+
* } else {
|
|
41
|
+
* console.log(`The attribute value is: ${result}`);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
function getAttributeAndCheckFalsey(element: Element, attributeName: string, opts?: {
|
|
46
|
+
onAttribute: (value: string, falsey: boolean) => void;
|
|
47
|
+
}): false | string | null;
|
|
48
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
*/
|
|
4
|
+
export var InternalAttributeUtils;
|
|
5
|
+
(function (InternalAttributeUtils) {
|
|
6
|
+
/**
|
|
7
|
+
* Checks if the given value is considered "falsey" in the context of HTML attributes.
|
|
8
|
+
* A value is considered falsey if it is "0" or "false" (case-insensitive).
|
|
9
|
+
*
|
|
10
|
+
* @param value - The attribute value to check.
|
|
11
|
+
* @returns True if the value is falsey, otherwise false.
|
|
12
|
+
*/
|
|
13
|
+
function isFalsey(value) {
|
|
14
|
+
return value === "0" || value?.toLowerCase() === "false";
|
|
15
|
+
}
|
|
16
|
+
InternalAttributeUtils.isFalsey = isFalsey;
|
|
17
|
+
/**
|
|
18
|
+
* Retrieves the value of the specified attribute from the given element.
|
|
19
|
+
* If the attribute value is considered falsey, it returns null.
|
|
20
|
+
* @returns The attribute value or null if falsey.
|
|
21
|
+
*/
|
|
22
|
+
function getAttributeValueIfNotFalsey(element, attributeName, opts) {
|
|
23
|
+
const attrValue = element.getAttribute(attributeName);
|
|
24
|
+
if (isFalsey(attrValue)) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
opts?.onAttribute?.call(null, attrValue);
|
|
28
|
+
return attrValue;
|
|
29
|
+
}
|
|
30
|
+
InternalAttributeUtils.getAttributeValueIfNotFalsey = getAttributeValueIfNotFalsey;
|
|
31
|
+
/**
|
|
32
|
+
* Retrieves the value of the specified attribute from the given element.
|
|
33
|
+
* If the attribute value is considered falsey, it returns false.
|
|
34
|
+
* If the attribute is not set at all, it returns null.
|
|
35
|
+
* @returns The attribute value, false if falsey, or null if not set.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const result = HTMLAttributeUtils.getAttributeAndCheckFalsey(element, 'data-example', {
|
|
40
|
+
* onAttribute: (value, falsey) => {
|
|
41
|
+
* console.log(`Attribute value: ${value}
|
|
42
|
+
* , Is falsey: ${falsey}`);
|
|
43
|
+
* }
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* if (result === false) {
|
|
47
|
+
* console.log('The attribute is set to a falsey value.');
|
|
48
|
+
* } else if (result === null) {
|
|
49
|
+
* console.log('The attribute is not set.');
|
|
50
|
+
* } else {
|
|
51
|
+
* console.log(`The attribute value is: ${result}`);
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
function getAttributeAndCheckFalsey(element, attributeName, opts) {
|
|
56
|
+
const attrValue = element.getAttribute(attributeName);
|
|
57
|
+
// If the attribute is not set at all we just return
|
|
58
|
+
if (attrValue === null) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
if (isFalsey(attrValue)) {
|
|
62
|
+
opts?.onAttribute?.call(null, attrValue, true);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
opts?.onAttribute?.call(null, attrValue, false);
|
|
66
|
+
return attrValue;
|
|
67
|
+
}
|
|
68
|
+
InternalAttributeUtils.getAttributeAndCheckFalsey = getAttributeAndCheckFalsey;
|
|
69
|
+
})(InternalAttributeUtils || (InternalAttributeUtils = {}));
|
|
70
|
+
//# sourceMappingURL=engine_utils_attributes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine_utils_attributes.js","sourceRoot":"","sources":["../../src/engine/engine_utils_attributes.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,KAAW,sBAAsB,CAiEtC;AAjED,WAAiB,sBAAsB;IAEnC;;;;;;OAMG;IACH,SAAgB,QAAQ,CAAC,KAAoB;QACzC,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC;IAC7D,CAAC;IAFe,+BAAQ,WAEvB,CAAA;IAED;;;;OAIG;IACH,SAAgB,4BAA4B,CAAC,OAAgB,EAAE,aAAqB,EAAE,IAA+C;QACjI,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QACtD,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE;YACrB,OAAO,IAAI,CAAC;SACf;QACD,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,SAAU,CAAC,CAAC;QAC1C,OAAO,SAAS,CAAC;IACrB,CAAC;IAPe,mDAA4B,+BAO3C,CAAA;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,SAAgB,0BAA0B,CAAC,OAAgB,EAAE,aAAqB,EAAE,IAA+D;QAC/I,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QACtD,oDAAoD;QACpD,IAAG,SAAS,KAAK,IAAI,EAAE;YACnB,OAAO,IAAI,CAAC;SACf;QACD,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE;YACrB,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,SAAU,EAAE,IAAI,CAAC,CAAC;YAChD,OAAO,KAAK,CAAC;SAChB;QACD,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,SAAU,EAAE,KAAK,CAAC,CAAC;QACjD,OAAO,SAAS,CAAC;IACrB,CAAC;IAZe,iDAA0B,6BAYzC,CAAA;AAEL,CAAC,EAjEgB,sBAAsB,KAAtB,sBAAsB,QAiEtC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "4.11.3-next.
|
|
3
|
+
"version": "4.11.3-next.35d1b4d",
|
|
4
4
|
"description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.",
|
|
5
5
|
"main": "dist/needle-engine.min.js",
|
|
6
6
|
"exports": {
|
|
@@ -4,9 +4,11 @@ import { Quaternion, Vector2, Vector3, Vector4 } from "three";
|
|
|
4
4
|
declare type Vector = Vector2 | Vector3 | Vector4 | Quaternion;
|
|
5
5
|
|
|
6
6
|
import { needleLogoOnlySVG } from "./assets/index.js";
|
|
7
|
+
import { isDevEnvironment } from "./debug/debug.js";
|
|
7
8
|
import type { Context } from "./engine_context.js";
|
|
8
9
|
import { ContextRegistry } from "./engine_context_registry.js";
|
|
9
10
|
import { type SourceIdentifier } from "./engine_types.js";
|
|
11
|
+
import { InternalAttributeUtils } from "./engine_utils_attributes.js";
|
|
10
12
|
import type { NeedleEngineWebComponent } from "./webcomponents/needle-engine.js";
|
|
11
13
|
|
|
12
14
|
// https://schneidenbach.gitbooks.io/typescript-cookbook/content/nameof-operator.html
|
|
@@ -908,7 +910,7 @@ export async function PromiseAllWithErrors<T>(promise: Promise<T>[]): Promise<{
|
|
|
908
910
|
* @param args.colorDark The color of the dark squares
|
|
909
911
|
* @param args.colorLight The color of the light squares
|
|
910
912
|
* @param args.correctLevel The error correction level to use
|
|
911
|
-
* @param args.showLogo If true, the
|
|
913
|
+
* @param args.showLogo If true, the logo will be shown in the center of the QR code. By default the Needle Logo will be used. You can override which logo is being used by setting the `needle-engine` web component's `qr-logo-src` attribute. The logo can also be disabled by setting that attribute to a falsey value (e.g. "0" or "false")
|
|
912
914
|
* @param args.showUrl If true, the URL will be shown below the QR code
|
|
913
915
|
* @param args.domElement The dom element to append the QR code to. If not provided a new div will be created and returned
|
|
914
916
|
* @returns The dom element containing the QR code
|
|
@@ -946,16 +948,16 @@ export async function generateQRCode(args: { domElement?: HTMLElement, text: str
|
|
|
946
948
|
// Number of rows/columns of the generated QR code
|
|
947
949
|
const moduleCount = qrCode?._oQRCode.moduleCount || 0;
|
|
948
950
|
const canvas = qrCode?._oDrawing?._elCanvas as HTMLCanvasElement;
|
|
949
|
-
|
|
951
|
+
|
|
950
952
|
let sizePercentage = 0.25;
|
|
951
953
|
if (moduleCount < 40)
|
|
952
954
|
sizePercentage = Math.floor(moduleCount / 4) / moduleCount;
|
|
953
955
|
else
|
|
954
956
|
sizePercentage = Math.floor(moduleCount / 6) / moduleCount;
|
|
955
|
-
|
|
957
|
+
|
|
956
958
|
const paddingPercentage = Math.floor(moduleCount / 20) / moduleCount;
|
|
957
959
|
try {
|
|
958
|
-
const img = await
|
|
960
|
+
const img = await internalRenderQRCodeOverlays(canvas, { showLogo: args.showLogo, logoSize: sizePercentage, logoPadding: paddingPercentage }).catch(_e => { /** ignore */ });
|
|
959
961
|
if (img) {
|
|
960
962
|
target.innerHTML = "";
|
|
961
963
|
target.append(img);
|
|
@@ -1002,7 +1004,8 @@ export async function generateQRCode(args: { domElement?: HTMLElement, text: str
|
|
|
1002
1004
|
return target;
|
|
1003
1005
|
}
|
|
1004
1006
|
|
|
1005
|
-
|
|
1007
|
+
|
|
1008
|
+
async function internalRenderQRCodeOverlays(canvas: HTMLCanvasElement, args: { showLogo?: boolean, logoSize?: number, logoPadding?: number }): Promise<HTMLImageElement | void> {
|
|
1006
1009
|
if (!canvas) return;
|
|
1007
1010
|
|
|
1008
1011
|
// Internal settings
|
|
@@ -1019,18 +1022,38 @@ async function addOverlays(canvas: HTMLCanvasElement, args: { showLogo?: boolean
|
|
|
1019
1022
|
const rectangleRadius = 0;
|
|
1020
1023
|
|
|
1021
1024
|
// Draw the website's icon in the center of the QR code
|
|
1022
|
-
const
|
|
1025
|
+
const image = new Image();
|
|
1023
1026
|
const element = document.querySelector("needle-engine") as NeedleEngineWebComponent;
|
|
1024
|
-
|
|
1027
|
+
if (!element) {
|
|
1028
|
+
console.debug("[QR Code] No web component found")
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// Query logo src from needle-engine attribute.
|
|
1032
|
+
// For any supported attribute it's possible to use "falsey" values (e.g. "0" or "false" to disable the logo in the QR code)
|
|
1033
|
+
let logoSrc: false | string | null = null;
|
|
1034
|
+
logoSrc = InternalAttributeUtils.getAttributeAndCheckFalsey(element, "qrcode-logo-src");
|
|
1035
|
+
if (args.showLogo !== true && logoSrc === false) return; // Explictly disabled
|
|
1036
|
+
logoSrc ||= InternalAttributeUtils.getAttributeAndCheckFalsey(element, "logo-src");
|
|
1037
|
+
if (args.showLogo !== true && logoSrc === false) return; // Explicitly disabled
|
|
1038
|
+
logoSrc ||= InternalAttributeUtils.getAttributeAndCheckFalsey(element, "loading-logo-src", {
|
|
1039
|
+
onAttribute: () => {
|
|
1040
|
+
if (isDevEnvironment()) console.warn("[QR Code] 'loading-logo-src' is deprecated, please use 'logo-src' or 'qrcode-logo-src' instead.");
|
|
1041
|
+
else console.debug("[QR Code] 'loading-logo-src' is deprecated.");
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
if (args.showLogo !== true && logoSrc === false) return; // Explicitly disabled
|
|
1045
|
+
|
|
1046
|
+
logoSrc ||= needleLogoOnlySVG;
|
|
1025
1047
|
if (!logoSrc) return;
|
|
1026
1048
|
|
|
1027
1049
|
let haveLogo = false;
|
|
1028
1050
|
if (args.showLogo !== false) {
|
|
1029
|
-
|
|
1051
|
+
image.src = logoSrc;
|
|
1030
1052
|
haveLogo = await new Promise((resolve, _reject) => {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1053
|
+
image.onload = () => resolve(true);
|
|
1054
|
+
image.onerror = (err) => {
|
|
1055
|
+
let errorUrl = logoSrc !== needleLogoOnlySVG ? "'" + logoSrc + "'" : null;
|
|
1056
|
+
console.error("[QR Code] Error loading logo image for QR code", errorUrl, isDevEnvironment() ? err : "");
|
|
1034
1057
|
resolve(false);
|
|
1035
1058
|
};
|
|
1036
1059
|
});
|
|
@@ -1073,7 +1096,7 @@ async function addOverlays(canvas: HTMLCanvasElement, args: { showLogo?: boolean
|
|
|
1073
1096
|
|
|
1074
1097
|
if (haveLogo) {
|
|
1075
1098
|
// Get aspect of image
|
|
1076
|
-
const aspect =
|
|
1099
|
+
const aspect = image.width / image.height;
|
|
1077
1100
|
if (aspect > 1) sizeY = sizeX / aspect;
|
|
1078
1101
|
else sizeX = sizeY * aspect;
|
|
1079
1102
|
|
|
@@ -1114,7 +1137,7 @@ async function addOverlays(canvas: HTMLCanvasElement, args: { showLogo?: boolean
|
|
|
1114
1137
|
paddedContext.shadowColor = "transparent";
|
|
1115
1138
|
const logoX = (paddedCanvas.width - sizeX) / 2;
|
|
1116
1139
|
const logoY = (paddedCanvas.height - sizeY) / 2;
|
|
1117
|
-
paddedContext.drawImage(
|
|
1140
|
+
paddedContext.drawImage(image, logoX, logoY, sizeX, sizeY);
|
|
1118
1141
|
}
|
|
1119
1142
|
|
|
1120
1143
|
// Replace the canvas with the padded one
|
|
@@ -1125,4 +1148,5 @@ async function addOverlays(canvas: HTMLCanvasElement, args: { showLogo?: boolean
|
|
|
1125
1148
|
img.style.height = "auto";
|
|
1126
1149
|
|
|
1127
1150
|
return img;
|
|
1128
|
-
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export namespace InternalAttributeUtils {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Checks if the given value is considered "falsey" in the context of HTML attributes.
|
|
10
|
+
* A value is considered falsey if it is "0" or "false" (case-insensitive).
|
|
11
|
+
*
|
|
12
|
+
* @param value - The attribute value to check.
|
|
13
|
+
* @returns True if the value is falsey, otherwise false.
|
|
14
|
+
*/
|
|
15
|
+
export function isFalsey(value: string | null): boolean {
|
|
16
|
+
return value === "0" || value?.toLowerCase() === "false";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Retrieves the value of the specified attribute from the given element.
|
|
21
|
+
* If the attribute value is considered falsey, it returns null.
|
|
22
|
+
* @returns The attribute value or null if falsey.
|
|
23
|
+
*/
|
|
24
|
+
export function getAttributeValueIfNotFalsey(element: Element, attributeName: string, opts?: { onAttribute: (value: string) => void }): string | null {
|
|
25
|
+
const attrValue = element.getAttribute(attributeName);
|
|
26
|
+
if (isFalsey(attrValue)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
opts?.onAttribute?.call(null, attrValue!);
|
|
30
|
+
return attrValue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves the value of the specified attribute from the given element.
|
|
35
|
+
* If the attribute value is considered falsey, it returns false.
|
|
36
|
+
* If the attribute is not set at all, it returns null.
|
|
37
|
+
* @returns The attribute value, false if falsey, or null if not set.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const result = HTMLAttributeUtils.getAttributeAndCheckFalsey(element, 'data-example', {
|
|
42
|
+
* onAttribute: (value, falsey) => {
|
|
43
|
+
* console.log(`Attribute value: ${value}
|
|
44
|
+
* , Is falsey: ${falsey}`);
|
|
45
|
+
* }
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* if (result === false) {
|
|
49
|
+
* console.log('The attribute is set to a falsey value.');
|
|
50
|
+
* } else if (result === null) {
|
|
51
|
+
* console.log('The attribute is not set.');
|
|
52
|
+
* } else {
|
|
53
|
+
* console.log(`The attribute value is: ${result}`);
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function getAttributeAndCheckFalsey(element: Element, attributeName: string, opts?: { onAttribute: (value: string, falsey:boolean) => void }): false | string | null {
|
|
58
|
+
const attrValue = element.getAttribute(attributeName);
|
|
59
|
+
// If the attribute is not set at all we just return
|
|
60
|
+
if(attrValue === null) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (isFalsey(attrValue)) {
|
|
64
|
+
opts?.onAttribute?.call(null, attrValue!, true);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
opts?.onAttribute?.call(null, attrValue!, false);
|
|
68
|
+
return attrValue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|