@swan-io/lake 2.7.2 → 2.7.3
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/package.json
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import * as THREE from "three";
|
|
3
|
+
export type Card3dAssetsUrls = {
|
|
4
|
+
envNx: string;
|
|
5
|
+
envNy: string;
|
|
6
|
+
envNz: string;
|
|
7
|
+
envPx: string;
|
|
8
|
+
envPy: string;
|
|
9
|
+
envPz: string;
|
|
10
|
+
fontMaisonNeueBook: string;
|
|
11
|
+
fontMarkProRegular: string;
|
|
12
|
+
bandRoughness: string;
|
|
13
|
+
cardGltf: string;
|
|
14
|
+
chipTexture: string;
|
|
15
|
+
colorBlack: string;
|
|
16
|
+
colorSilver: string;
|
|
17
|
+
};
|
|
3
18
|
type CardParams = {
|
|
4
19
|
ownerName: string;
|
|
5
20
|
cardNumber: string;
|
|
@@ -8,6 +23,7 @@ type CardParams = {
|
|
|
8
23
|
color: "Silver" | "Black";
|
|
9
24
|
logo: SVGElement | null;
|
|
10
25
|
logoScale: number;
|
|
26
|
+
assetsUrls: Card3dAssetsUrls;
|
|
11
27
|
onSvgError?: (code: string) => void;
|
|
12
28
|
};
|
|
13
29
|
type Props = CardParams & {
|
|
@@ -4,20 +4,6 @@ import { Canvas, useFrame } from "@react-three/fiber";
|
|
|
4
4
|
import { forwardRef, useEffect, useRef, useState } from "react";
|
|
5
5
|
import * as THREE from "three";
|
|
6
6
|
import { match } from "ts-pattern";
|
|
7
|
-
import envNxUrl from "../assets/3d-card/environment/nx.png?url";
|
|
8
|
-
import envNyUrl from "../assets/3d-card/environment/ny.png?url";
|
|
9
|
-
import envNzUrl from "../assets/3d-card/environment/nz.png?url";
|
|
10
|
-
import envPxUrl from "../assets/3d-card/environment/px.png?url";
|
|
11
|
-
import envPyUrl from "../assets/3d-card/environment/py.png?url";
|
|
12
|
-
import envPzUrl from "../assets/3d-card/environment/pz.png?url";
|
|
13
|
-
import fontMaisonNeueBookUrl from "../assets/3d-card/model/MaisonNeue-Book.woff?url";
|
|
14
|
-
import fontMarkProRegularUrl from "../assets/3d-card/model/MarkPro-Regular.ttf?url";
|
|
15
|
-
import bandRoughnessUrl from "../assets/3d-card/model/band_roughness.jpg?url";
|
|
16
|
-
import cardGltfUrl from "../assets/3d-card/model/card.gltf?url";
|
|
17
|
-
import chipUrl from "../assets/3d-card/model/chip.jpg?url";
|
|
18
|
-
import colorBlackUrl from "../assets/3d-card/model/color_black.jpg?url";
|
|
19
|
-
import colorSilverUrl from "../assets/3d-card/model/color_silver.jpg?url";
|
|
20
|
-
import shinyColorFragmentShader from "../assets/3d-card/shaders/shinyColorFragment.glsl?raw";
|
|
21
7
|
import { isNotNullish, isNullish } from "../utils/nullish";
|
|
22
8
|
import { createSvgImage, getMonochromeSvg } from "../utils/svg";
|
|
23
9
|
/*
|
|
@@ -40,6 +26,19 @@ And this texture is used as an alpha map on a plane.
|
|
|
40
26
|
To reproduce the shiny effect on the back of the card, we inject a custom shader in rainbow_mastercard material.
|
|
41
27
|
This custom shader chunk change the diffuse color depending on camera position.
|
|
42
28
|
*/
|
|
29
|
+
const shinyColorFragmentShader = `
|
|
30
|
+
float red = cameraPosition.x * cameraPosition.z;
|
|
31
|
+
float green = cameraPosition.y * cameraPosition.z;
|
|
32
|
+
float blue = 0.1;
|
|
33
|
+
|
|
34
|
+
red = sin(red / 5.0) + 1.0 / 2.0;
|
|
35
|
+
green = sin(green / 5.0) + 1.0 / 2.0;
|
|
36
|
+
|
|
37
|
+
vec3 shinyColor = vec3(red, green, blue);
|
|
38
|
+
float shinyFactor = 0.35;
|
|
39
|
+
|
|
40
|
+
diffuseColor.rgb = mix(diffuseColor.rgb, shinyColor, shinyFactor);
|
|
41
|
+
`;
|
|
43
42
|
const ENV_MAP_INTENSITY = 3;
|
|
44
43
|
const CARD_WIDTH = 8.56;
|
|
45
44
|
const CARD_HEIGHT = 5.4;
|
|
@@ -72,13 +71,21 @@ export default (props) => {
|
|
|
72
71
|
return (_jsxs(Canvas, { camera: { position: [0, 0, 12], fov: 50 }, children: [_jsx(OrbitControls, { enablePan: false, enableZoom: false }), _jsx(CardScene, { ...props })] }));
|
|
73
72
|
};
|
|
74
73
|
const CardScene = ({ autoRotationDuration, ...props }) => {
|
|
74
|
+
const { assetsUrls } = props;
|
|
75
75
|
const card = useRef(null);
|
|
76
76
|
useFrame(({ clock }) => {
|
|
77
77
|
if (autoRotationDuration != null && card.current != null) {
|
|
78
78
|
card.current.rotation.y = (clock.getElapsedTime() / autoRotationDuration) * Math.PI * 2;
|
|
79
79
|
}
|
|
80
80
|
});
|
|
81
|
-
return (_jsxs(_Fragment, { children: [_jsx("ambientLight", { color: 0xffffff, intensity: 1 }), _jsx("pointLight", { intensity: 0.2, decay: 2, position: [-10, -10, -21] }), _jsx("pointLight", { intensity: 0.2, decay: 2, position: [10, 10, 21] }), _jsx(Environment, { files: [
|
|
81
|
+
return (_jsxs(_Fragment, { children: [_jsx("ambientLight", { color: 0xffffff, intensity: 1 }), _jsx("pointLight", { intensity: 0.2, decay: 2, position: [-10, -10, -21] }), _jsx("pointLight", { intensity: 0.2, decay: 2, position: [10, 10, 21] }), _jsx(Environment, { files: [
|
|
82
|
+
assetsUrls.envPx,
|
|
83
|
+
assetsUrls.envNx,
|
|
84
|
+
assetsUrls.envPy,
|
|
85
|
+
assetsUrls.envNy,
|
|
86
|
+
assetsUrls.envPz,
|
|
87
|
+
assetsUrls.envNz,
|
|
88
|
+
] }), _jsx(Card, { ref: card, ...props })] }));
|
|
82
89
|
};
|
|
83
90
|
// Set color space to sRGB for textures
|
|
84
91
|
const setTextureColorSpace = (texture) => {
|
|
@@ -86,13 +93,13 @@ const setTextureColorSpace = (texture) => {
|
|
|
86
93
|
texture.colorSpace = THREE.SRGBColorSpace;
|
|
87
94
|
}
|
|
88
95
|
};
|
|
89
|
-
export const Card = forwardRef(({ ownerName, cardNumber, expirationDate, cvv, color, logo, logoScale, onSvgError, ...props }, ref) => {
|
|
90
|
-
const { nodes, materials } = useGLTF(
|
|
96
|
+
export const Card = forwardRef(({ ownerName, cardNumber, expirationDate, cvv, color, logo, logoScale, assetsUrls, onSvgError, ...props }, ref) => {
|
|
97
|
+
const { nodes, materials } = useGLTF(assetsUrls.cardGltf);
|
|
91
98
|
const [logoData, setLogoData] = useState(null);
|
|
92
|
-
const silverTexture = useTexture(
|
|
93
|
-
const blackTexture = useTexture(
|
|
94
|
-
const chipTexture = useTexture(
|
|
95
|
-
const bandRoughnessTexture = useTexture(
|
|
99
|
+
const silverTexture = useTexture(assetsUrls.colorSilver, setTextureColorSpace);
|
|
100
|
+
const blackTexture = useTexture(assetsUrls.colorBlack, setTextureColorSpace);
|
|
101
|
+
const chipTexture = useTexture(assetsUrls.chipTexture, setTextureColorSpace);
|
|
102
|
+
const bandRoughnessTexture = useTexture(assetsUrls.bandRoughness); // keep default color space because it's grayscale
|
|
96
103
|
// Set environment map intensity for all materials
|
|
97
104
|
useEffect(() => {
|
|
98
105
|
Object.values(materials).forEach(material => {
|
|
@@ -155,7 +162,7 @@ export const Card = forwardRef(({ ownerName, cardNumber, expirationDate, cvv, co
|
|
|
155
162
|
.with("Black", () => 0xeeeeee)
|
|
156
163
|
.exhaustive(), metalness: 0.1, roughness: 0.55, envMapIntensity: ENV_MAP_INTENSITY }));
|
|
157
164
|
const secondaryTextMaterial = (_jsx("meshStandardMaterial", { color: 0x666666, metalness: 0.1, roughness: 0.55, envMapIntensity: ENV_MAP_INTENSITY }));
|
|
158
|
-
return (_jsx("group", { ref: ref, ...props, dispose: null, children: _jsxs("mesh", { geometry: nodes.card.geometry, material: materials.card, children: [_jsxs("group", { position: [0, 0, FRONT_TEXT_POSITION], children: [_jsxs(Text, { font:
|
|
165
|
+
return (_jsx("group", { ref: ref, ...props, dispose: null, children: _jsxs("mesh", { geometry: nodes.card.geometry, material: materials.card, children: [_jsxs("group", { position: [0, 0, FRONT_TEXT_POSITION], children: [_jsxs(Text, { font: assetsUrls.fontMaisonNeueBook, fontSize: 0.2, anchorX: "left", anchorY: "bottom", position: [-3.4, -1.95, 0], children: [ownerName, mainTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMarkProRegular, fontSize: 0.03, anchorX: "left", anchorY: "bottom", position: [3.85, -2.15, 0], children: ["TM", mainTextMaterial] })] }), _jsxs("group", { position: [0, 0, BACK_TEXT_POSITION], children: [_jsxs(Text, { font: assetsUrls.fontMarkProRegular, anchorX: "left", anchorY: "bottom", fontSize: 0.12, rotation: [0, Math.PI, 0], position: [4, 2.38, 0], children: ["support@swan.io", secondaryTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMarkProRegular, anchorX: "right", anchorY: "bottom", fontSize: 0.12, rotation: [0, Math.PI, 0], position: [-4, 2.38, 0], children: ["IDEMIA 9 1212121L 09/21", secondaryTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMaisonNeueBook, fontSize: 0.24, anchorX: "left", anchorY: "bottom", rotation: [0, Math.PI, 0], position: [4, 0.68, 0], children: ["Identifier: 0000000000", mainTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMaisonNeueBook, fontSize: 0.2, anchorX: "left", anchorY: "bottom", rotation: [0, Math.PI, 0], position: [4, 0.15, 0], children: ["This card is issued by Swan, pursuant to license", secondaryTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMaisonNeueBook, fontSize: 0.2, anchorX: "left", anchorY: "bottom", rotation: [0, Math.PI, 0], position: [4, -0.15, 0], children: ["by Mastercard international.", secondaryTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMaisonNeueBook, fontSize: 0.48, anchorX: "left", anchorY: "bottom", rotation: [0, Math.PI, 0], position: [4, -1.85, 0], children: [cardNumber, mainTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMaisonNeueBook, fontSize: 0.29, anchorX: "left", anchorY: "bottom", rotation: [0, Math.PI, 0], position: [4, -2.3, 0], children: [expirationDate, mainTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMaisonNeueBook, fontSize: 0.29, anchorX: "left", anchorY: "bottom", rotation: [0, Math.PI, 0], position: [2.55, -2.3, 0], children: ["CVC ", cvv, mainTextMaterial] }), _jsxs(Text, { font: assetsUrls.fontMarkProRegular, anchorX: "center", anchorY: "bottom", fontSize: 0.36, rotation: [0, Math.PI, 0], position: [-2.35, -1.15, 0], children: ["debit", mainTextMaterial] })] }), _jsx("group", {
|
|
159
166
|
// move group to change scale center at top right corner
|
|
160
167
|
position: [
|
|
161
168
|
CARD_WIDTH / 2 - LOGO_MARGIN_RIGHT,
|
|
@@ -141,7 +141,7 @@ const LakeComboboxWithRef = ({ inputRef, value, items, itemHeight = DEFAULT_ELEM
|
|
|
141
141
|
close();
|
|
142
142
|
}, 100);
|
|
143
143
|
}, [close]);
|
|
144
|
-
return (_jsxs(View, { children: [_jsx(LakeTextInput, { ref: inputTextRef, style: styles.input, ariaExpanded: isFocused, ariaControls: isFocused ? suggestionsId : "", enterKeyHint: "search", icon: icon, role: "combobox", placeholder: placeholder, value: value, disabled: disabled, error: error, hideErrors: hideErrors, onChangeText: onValueChange, onChange: onChange, onFocus: handleFocus, onBlur: handleBlur, onKeyPress: handleKeyPress, id: id, readOnly: readOnly }), _jsx(Popover, { id: suggestionsId, role: "listbox", matchReferenceWidth: true, onDismiss: close, referenceRef: ref, autoFocus:
|
|
144
|
+
return (_jsxs(View, { children: [_jsx(LakeTextInput, { ref: inputTextRef, style: styles.input, ariaExpanded: isFocused, ariaControls: isFocused ? suggestionsId : "", enterKeyHint: "search", icon: icon, role: "combobox", placeholder: placeholder, value: value, disabled: disabled, error: error, hideErrors: hideErrors, onChangeText: onValueChange, onChange: onChange, onFocus: handleFocus, onBlur: handleBlur, onKeyPress: handleKeyPress, id: id, readOnly: readOnly }), _jsx(Popover, { id: suggestionsId, role: "listbox", matchReferenceWidth: true, onDismiss: close, referenceRef: ref, autoFocus: false, returnFocus: true, visible: isFocused && !items.isNotAsked(), underlay: false, forcedMode: "Dropdown", children: _jsx(View, { style: [styles.list, { maxHeight: itemHeight * nbItemsDisplayed }], children: items.match({
|
|
145
145
|
NotAsked: () => null,
|
|
146
146
|
Loading: () => _jsx(LoadingView, { style: styles.loader }),
|
|
147
147
|
Done: items => items.match({
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
float red = cameraPosition.x * cameraPosition.z;
|
|
2
|
-
float green = cameraPosition.y * cameraPosition.z;
|
|
3
|
-
float blue = 0.1;
|
|
4
|
-
|
|
5
|
-
red = sin(red / 5.0) + 1.0 / 2.0;
|
|
6
|
-
green = sin(green / 5.0) + 1.0 / 2.0;
|
|
7
|
-
|
|
8
|
-
vec3 shinyColor = vec3(red, green, blue);
|
|
9
|
-
float shinyFactor = 0.35;
|
|
10
|
-
|
|
11
|
-
diffuseColor.rgb = mix(diffuseColor.rgb, shinyColor, shinyFactor);
|