@abuzareal/contour-ui 0.1.1 → 0.2.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/CHANGELOG.md +86 -11
- package/CODE_OF_CONDUCT.md +5 -0
- package/CONTRIBUTING.md +15 -0
- package/NEXTJS.md +51 -0
- package/README.md +176 -76
- package/RELEASING.md +14 -28
- package/SECURITY.md +1 -1
- package/dist/components/hero/SceneBoundary.js +1 -0
- package/dist/components/hero/Sculpture.js +6 -4
- package/dist/components/three/ObjectStudy.js +7 -3
- package/dist/components/ui/Alert.js +1 -0
- package/dist/components/ui/BrandMark.js +1 -0
- package/dist/components/ui/Checkbox.js +1 -0
- package/dist/components/ui/CountUp.js +1 -0
- package/dist/components/ui/DataTable.js +1 -0
- package/dist/components/ui/Dialog.js +1 -0
- package/dist/components/ui/DropdownMenu.d.ts +7 -1
- package/dist/components/ui/DropdownMenu.js +62 -14
- package/dist/components/ui/FlipCard.js +1 -0
- package/dist/components/ui/Magnetic.js +1 -0
- package/dist/components/ui/Pagination.js +1 -0
- package/dist/components/ui/Popover.d.ts +4 -1
- package/dist/components/ui/Popover.js +7 -5
- package/dist/components/ui/RadioGroup.js +1 -0
- package/dist/components/ui/Reveal.js +1 -0
- package/dist/components/ui/ScrollProgress.js +1 -0
- package/dist/components/ui/SegmentedControl.js +1 -0
- package/dist/components/ui/SelectField.d.ts +11 -1
- package/dist/components/ui/SelectField.js +6 -4
- package/dist/components/ui/Slider.js +1 -0
- package/dist/components/ui/Switch.js +1 -0
- package/dist/components/ui/Tabs.d.ts +4 -1
- package/dist/components/ui/Tabs.js +12 -5
- package/dist/components/ui/Tag.js +1 -0
- package/dist/components/ui/TextArea.d.ts +8 -1
- package/dist/components/ui/TextArea.js +21 -7
- package/dist/components/ui/TextField.d.ts +10 -1
- package/dist/components/ui/TextField.js +17 -6
- package/dist/components/ui/ThemeToggle.js +1 -0
- package/dist/components/ui/TiltCard.js +1 -0
- package/dist/components/ui/ToastProvider.js +1 -0
- package/dist/components/ui/Tooltip.js +1 -0
- package/dist/fonts/dm-mono-LICENSE.txt +93 -0
- package/dist/fonts/dm-mono-latin-400-normal.woff2 +0 -0
- package/dist/fonts/dm-sans-LICENSE.txt +93 -0
- package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-LICENSE.txt +93 -0
- package/dist/fonts/space-grotesk-latin-wght-normal.woff2 +0 -0
- package/dist/fonts-latin.css +35 -0
- package/dist/hooks/useClipboardCopy.js +1 -0
- package/dist/hooks/useControlRef.d.ts +6 -0
- package/dist/hooks/useControlRef.js +13 -0
- package/dist/hooks/useDismiss.js +1 -0
- package/dist/hooks/useFormReset.d.ts +3 -0
- package/dist/hooks/useFormReset.js +31 -0
- package/dist/hooks/useHeaderScroll.js +1 -0
- package/dist/hooks/useIdleTrigger.js +1 -0
- package/dist/hooks/useInitialHashScroll.js +1 -0
- package/dist/hooks/useMobileMenu.js +1 -0
- package/dist/hooks/useMotionPreference.js +1 -0
- package/dist/hooks/useOpenState.d.ts +2 -0
- package/dist/hooks/useOpenState.js +15 -0
- package/dist/hooks/usePrintPreparation.js +1 -0
- package/dist/hooks/useScrollSpy.js +1 -0
- package/dist/hooks/useSmoothScroll.js +1 -0
- package/dist/hooks/useTheme.js +1 -0
- package/dist/hooks/useThreeStage.d.ts +4 -0
- package/dist/hooks/useThreeStage.js +165 -128
- package/dist/hooks/useToast.js +1 -0
- package/package.json +29 -12
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
/** Shared Three.js stage: renderer, studio lighting, resizing, a visibility-aware render loop, pointer tracking, and cleanup. */
|
|
2
3
|
import { useEffect, useRef } from "react";
|
|
3
4
|
import * as THREE from "three";
|
|
@@ -16,140 +17,176 @@ export default function useThreeStage(hostRef, { motionEnabled, setup, cameraDis
|
|
|
16
17
|
const host = hostRef.current;
|
|
17
18
|
if (!host)
|
|
18
19
|
return;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
renderer.toneMapping = THREE.NeutralToneMapping;
|
|
31
|
-
renderer.toneMappingExposure = 1.05;
|
|
32
|
-
renderer.domElement.setAttribute("aria-hidden", "true");
|
|
33
|
-
host.appendChild(renderer.domElement);
|
|
34
|
-
// Studio lighting shared by every stage so materials read consistently.
|
|
35
|
-
const scene = new THREE.Scene();
|
|
36
|
-
const camera = new THREE.PerspectiveCamera(35, 1, 0.1, 30);
|
|
37
|
-
camera.position.set(0, 0, 10.5);
|
|
38
|
-
const environment = new RoomEnvironment();
|
|
39
|
-
const generator = new THREE.PMREMGenerator(renderer);
|
|
40
|
-
const environmentMap = generator.fromScene(environment, 0.04);
|
|
41
|
-
scene.environment = environmentMap.texture;
|
|
42
|
-
environment.dispose();
|
|
43
|
-
generator.dispose();
|
|
44
|
-
const keyLight = new THREE.DirectionalLight(0xffffff, 4);
|
|
45
|
-
keyLight.position.set(4, 5, 6);
|
|
46
|
-
const rimLight = new THREE.DirectionalLight(0xcad9ff, 3);
|
|
47
|
-
rimLight.position.set(-5, 1, -2);
|
|
48
|
-
scene.add(keyLight, rimLight, new THREE.AmbientLight(0xffffff, 0.7));
|
|
49
|
-
const stage = setupRef.current.setup({ scene, camera, renderer });
|
|
50
|
-
// Loop state: frames run only while visible, focused, and motion is on.
|
|
51
|
-
const pointer = new THREE.Vector2();
|
|
52
|
-
let visible = true;
|
|
53
|
-
let contextLost = false;
|
|
54
|
-
let running = false;
|
|
55
|
-
let frame = 0;
|
|
56
|
-
let elapsed = 0;
|
|
57
|
-
let previousTime = 0;
|
|
58
|
-
const render = () => {
|
|
59
|
-
if (contextLost)
|
|
60
|
-
return;
|
|
61
|
-
renderer.render(scene, camera);
|
|
62
|
-
host.dataset.state = "ready";
|
|
63
|
-
};
|
|
64
|
-
const resize = () => {
|
|
65
|
-
const { width, height } = host.getBoundingClientRect();
|
|
66
|
-
if (!width || !height)
|
|
67
|
-
return;
|
|
68
|
-
camera.aspect = width / height;
|
|
69
|
-
camera.position.z = setupRef.current.cameraDistance(camera.aspect);
|
|
70
|
-
camera.updateProjectionMatrix();
|
|
71
|
-
renderer.setSize(width, height);
|
|
72
|
-
render();
|
|
73
|
-
};
|
|
74
|
-
const trackPointer = (event) => {
|
|
75
|
-
if (event.pointerType === "touch" || !motionRef.current)
|
|
76
|
-
return;
|
|
77
|
-
const bounds = host.getBoundingClientRect();
|
|
78
|
-
pointer.set((event.clientX - bounds.left) / bounds.width - 0.5, (event.clientY - bounds.top) / bounds.height - 0.5);
|
|
20
|
+
const disposers = [];
|
|
21
|
+
const own = (dispose) => {
|
|
22
|
+
let disposed = false;
|
|
23
|
+
const release = () => {
|
|
24
|
+
if (disposed)
|
|
25
|
+
return;
|
|
26
|
+
disposed = true;
|
|
27
|
+
dispose();
|
|
28
|
+
};
|
|
29
|
+
disposers.push(release);
|
|
30
|
+
return release;
|
|
79
31
|
};
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
frame = requestAnimationFrame(animate);
|
|
90
|
-
};
|
|
91
|
-
/** Starts or stops the loop to match visibility and motion; snaps to rest when paused. */
|
|
92
|
-
const sync = () => {
|
|
93
|
-
const motion = motionRef.current;
|
|
94
|
-
const shouldRun = motion && visible && !document.hidden && !contextLost;
|
|
95
|
-
if (shouldRun && !running) {
|
|
96
|
-
running = true;
|
|
97
|
-
previousTime = performance.now();
|
|
98
|
-
frame = requestAnimationFrame(animate);
|
|
32
|
+
const cleanup = () => {
|
|
33
|
+
syncRef.current = undefined;
|
|
34
|
+
for (const dispose of disposers.reverse()) {
|
|
35
|
+
try {
|
|
36
|
+
dispose();
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error("Contour stage cleanup failed", error);
|
|
40
|
+
}
|
|
99
41
|
}
|
|
100
|
-
|
|
42
|
+
disposers.length = 0;
|
|
43
|
+
};
|
|
44
|
+
try {
|
|
45
|
+
const renderer = new THREE.WebGLRenderer({
|
|
46
|
+
alpha: true,
|
|
47
|
+
antialias: true,
|
|
48
|
+
});
|
|
49
|
+
own(() => renderer.dispose());
|
|
50
|
+
own(() => renderer.domElement.remove());
|
|
51
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio, maxPixelRatio));
|
|
52
|
+
renderer.setClearColor(0x000000, 0);
|
|
53
|
+
// Neutral tone mapping keeps the lime close to the CSS accent colour.
|
|
54
|
+
renderer.toneMapping = THREE.NeutralToneMapping;
|
|
55
|
+
renderer.toneMappingExposure = 1.05;
|
|
56
|
+
renderer.domElement.setAttribute("aria-hidden", "true");
|
|
57
|
+
host.appendChild(renderer.domElement);
|
|
58
|
+
// Studio lighting shared by every stage so materials read consistently.
|
|
59
|
+
const scene = new THREE.Scene();
|
|
60
|
+
const camera = new THREE.PerspectiveCamera(35, 1, 0.1, 30);
|
|
61
|
+
camera.position.set(0, 0, 10.5);
|
|
62
|
+
const environment = new RoomEnvironment();
|
|
63
|
+
const releaseEnvironment = own(() => environment.dispose());
|
|
64
|
+
const generator = new THREE.PMREMGenerator(renderer);
|
|
65
|
+
const releaseGenerator = own(() => generator.dispose());
|
|
66
|
+
const environmentMap = generator.fromScene(environment, 0.04);
|
|
67
|
+
own(() => environmentMap.dispose());
|
|
68
|
+
scene.environment = environmentMap.texture;
|
|
69
|
+
releaseEnvironment();
|
|
70
|
+
releaseGenerator();
|
|
71
|
+
const keyLight = new THREE.DirectionalLight(0xffffff, 4);
|
|
72
|
+
keyLight.position.set(4, 5, 6);
|
|
73
|
+
const rimLight = new THREE.DirectionalLight(0xcad9ff, 3);
|
|
74
|
+
rimLight.position.set(-5, 1, -2);
|
|
75
|
+
scene.add(keyLight, rimLight, new THREE.AmbientLight(0xffffff, 0.7));
|
|
76
|
+
const stage = setupRef.current.setup({
|
|
77
|
+
scene,
|
|
78
|
+
camera,
|
|
79
|
+
renderer,
|
|
80
|
+
onDispose: own,
|
|
81
|
+
});
|
|
82
|
+
own(() => stage.dispose());
|
|
83
|
+
// Loop state: frames run only while visible, focused, and motion is on.
|
|
84
|
+
const pointer = new THREE.Vector2();
|
|
85
|
+
let visible = true;
|
|
86
|
+
let contextLost = false;
|
|
87
|
+
let running = false;
|
|
88
|
+
let frame = 0;
|
|
89
|
+
let elapsed = 0;
|
|
90
|
+
let previousTime = 0;
|
|
91
|
+
own(() => {
|
|
101
92
|
running = false;
|
|
102
93
|
cancelAnimationFrame(frame);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
94
|
+
});
|
|
95
|
+
const render = () => {
|
|
96
|
+
if (contextLost)
|
|
97
|
+
return;
|
|
98
|
+
renderer.render(scene, camera);
|
|
99
|
+
host.dataset.state = "ready";
|
|
100
|
+
};
|
|
101
|
+
const resize = () => {
|
|
102
|
+
const { width, height } = host.getBoundingClientRect();
|
|
103
|
+
if (!width || !height)
|
|
104
|
+
return;
|
|
105
|
+
camera.aspect = width / height;
|
|
106
|
+
camera.position.z = setupRef.current.cameraDistance(camera.aspect);
|
|
107
|
+
camera.updateProjectionMatrix();
|
|
108
|
+
renderer.setSize(width, height);
|
|
109
|
+
stage.resize?.();
|
|
107
110
|
render();
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
111
|
+
};
|
|
112
|
+
const trackPointer = (event) => {
|
|
113
|
+
if (event.pointerType === "touch" || !motionRef.current)
|
|
114
|
+
return;
|
|
115
|
+
const bounds = host.getBoundingClientRect();
|
|
116
|
+
pointer.set((event.clientX - bounds.left) / bounds.width - 0.5, (event.clientY - bounds.top) / bounds.height - 0.5);
|
|
117
|
+
};
|
|
118
|
+
const resetPointer = () => pointer.set(0, 0);
|
|
119
|
+
const animate = (time) => {
|
|
120
|
+
if (!running)
|
|
121
|
+
return;
|
|
122
|
+
const delta = Math.min(Math.max(time - previousTime, 0) / 1000, 0.05);
|
|
123
|
+
previousTime = time;
|
|
124
|
+
elapsed += delta;
|
|
125
|
+
stage.update({ delta, elapsed, pointer });
|
|
126
|
+
render();
|
|
127
|
+
frame = requestAnimationFrame(animate);
|
|
128
|
+
};
|
|
129
|
+
/** Starts or stops the loop to match visibility and motion; snaps to rest when paused. */
|
|
130
|
+
const sync = () => {
|
|
131
|
+
const motion = motionRef.current;
|
|
132
|
+
const shouldRun = motion && visible && !document.hidden && !contextLost;
|
|
133
|
+
if (shouldRun && !running) {
|
|
134
|
+
running = true;
|
|
135
|
+
previousTime = performance.now();
|
|
136
|
+
frame = requestAnimationFrame(animate);
|
|
137
|
+
}
|
|
138
|
+
else if (!shouldRun && running) {
|
|
139
|
+
running = false;
|
|
140
|
+
cancelAnimationFrame(frame);
|
|
141
|
+
}
|
|
142
|
+
if (!motion) {
|
|
143
|
+
pointer.set(0, 0);
|
|
144
|
+
stage.rest();
|
|
145
|
+
render();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
syncRef.current = sync;
|
|
149
|
+
const loseContext = (event) => {
|
|
150
|
+
event.preventDefault();
|
|
151
|
+
contextLost = true;
|
|
152
|
+
host.dataset.state = "unavailable";
|
|
153
|
+
sync();
|
|
154
|
+
};
|
|
155
|
+
const restoreContext = () => {
|
|
156
|
+
contextLost = false;
|
|
125
157
|
render();
|
|
158
|
+
sync();
|
|
159
|
+
};
|
|
160
|
+
const visibilityObserver = new IntersectionObserver(([entry]) => {
|
|
161
|
+
visible = entry.isIntersecting;
|
|
162
|
+
if (visible)
|
|
163
|
+
render();
|
|
164
|
+
sync();
|
|
165
|
+
});
|
|
166
|
+
own(() => visibilityObserver.disconnect());
|
|
167
|
+
const resizeObserver = new ResizeObserver(resize);
|
|
168
|
+
own(() => resizeObserver.disconnect());
|
|
169
|
+
visibilityObserver.observe(host);
|
|
170
|
+
resizeObserver.observe(host);
|
|
171
|
+
host.addEventListener("pointermove", trackPointer);
|
|
172
|
+
own(() => host.removeEventListener("pointermove", trackPointer));
|
|
173
|
+
host.addEventListener("pointerleave", resetPointer);
|
|
174
|
+
own(() => host.removeEventListener("pointerleave", resetPointer));
|
|
175
|
+
document.addEventListener("visibilitychange", sync);
|
|
176
|
+
own(() => document.removeEventListener("visibilitychange", sync));
|
|
177
|
+
renderer.domElement.addEventListener("webglcontextlost", loseContext);
|
|
178
|
+
own(() => renderer.domElement.removeEventListener("webglcontextlost", loseContext));
|
|
179
|
+
renderer.domElement.addEventListener("webglcontextrestored", restoreContext);
|
|
180
|
+
own(() => renderer.domElement.removeEventListener("webglcontextrestored", restoreContext));
|
|
181
|
+
resize();
|
|
126
182
|
sync();
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
renderer.domElement.addEventListener("webglcontextrestored", restoreContext);
|
|
136
|
-
resize();
|
|
137
|
-
sync();
|
|
138
|
-
return () => {
|
|
139
|
-
running = false;
|
|
140
|
-
syncRef.current = undefined;
|
|
141
|
-
cancelAnimationFrame(frame);
|
|
142
|
-
visibilityObserver.disconnect();
|
|
143
|
-
resizeObserver.disconnect();
|
|
144
|
-
host.removeEventListener("pointermove", trackPointer);
|
|
145
|
-
host.removeEventListener("pointerleave", resetPointer);
|
|
146
|
-
document.removeEventListener("visibilitychange", sync);
|
|
147
|
-
renderer.domElement.removeEventListener("webglcontextlost", loseContext);
|
|
148
|
-
renderer.domElement.removeEventListener("webglcontextrestored", restoreContext);
|
|
149
|
-
stage.dispose();
|
|
150
|
-
environmentMap.dispose();
|
|
151
|
-
renderer.dispose();
|
|
152
|
-
renderer.domElement.remove();
|
|
153
|
-
};
|
|
183
|
+
return cleanup;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
cleanup();
|
|
187
|
+
host.dataset.state = "unavailable";
|
|
188
|
+
console.error("Contour stage initialization failed", error);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
154
191
|
}, [hostRef]);
|
|
155
192
|
}
|
package/dist/hooks/useToast.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abuzareal/contour-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Editorial React components, themes, restrained motion, and optional Three.js objects.",
|
|
6
6
|
"type": "module",
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
"LICENSE",
|
|
11
11
|
"CHANGELOG.md",
|
|
12
12
|
"SECURITY.md",
|
|
13
|
-
"RELEASING.md"
|
|
13
|
+
"RELEASING.md",
|
|
14
|
+
"CONTRIBUTING.md",
|
|
15
|
+
"CODE_OF_CONDUCT.md",
|
|
16
|
+
"NEXTJS.md"
|
|
14
17
|
],
|
|
15
18
|
"sideEffects": [
|
|
16
19
|
"**/*.css"
|
|
@@ -18,24 +21,29 @@
|
|
|
18
21
|
"exports": {
|
|
19
22
|
".": {
|
|
20
23
|
"types": "./dist/index.d.ts",
|
|
21
|
-
"import": "./dist/index.js"
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"default": "./dist/index.js"
|
|
22
26
|
},
|
|
23
27
|
"./three": {
|
|
24
28
|
"types": "./dist/three.d.ts",
|
|
25
|
-
"import": "./dist/three.js"
|
|
29
|
+
"import": "./dist/three.js",
|
|
30
|
+
"default": "./dist/three.js"
|
|
26
31
|
},
|
|
27
32
|
"./scroll": {
|
|
28
33
|
"types": "./dist/scroll.d.ts",
|
|
29
|
-
"import": "./dist/scroll.js"
|
|
34
|
+
"import": "./dist/scroll.js",
|
|
35
|
+
"default": "./dist/scroll.js"
|
|
30
36
|
},
|
|
31
37
|
"./theme-bootstrap": {
|
|
32
38
|
"types": "./dist/lib/themeBootstrap.d.ts",
|
|
33
|
-
"import": "./dist/lib/themeBootstrap.js"
|
|
39
|
+
"import": "./dist/lib/themeBootstrap.js",
|
|
40
|
+
"default": "./dist/lib/themeBootstrap.js"
|
|
34
41
|
},
|
|
35
42
|
"./styles.css": "./dist/styles.css",
|
|
36
43
|
"./reset.css": "./dist/reset.css",
|
|
37
44
|
"./tokens.css": "./dist/tokens.css",
|
|
38
|
-
"./fonts.css": "./dist/fonts.css"
|
|
45
|
+
"./fonts.css": "./dist/fonts.css",
|
|
46
|
+
"./fonts-latin.css": "./dist/fonts-latin.css"
|
|
39
47
|
},
|
|
40
48
|
"scripts": {
|
|
41
49
|
"build": "node scripts/build.mjs",
|
|
@@ -45,9 +53,12 @@
|
|
|
45
53
|
"test:browser": "node --test tests/*.browser.mjs",
|
|
46
54
|
"check:package": "node scripts/check-package.mjs",
|
|
47
55
|
"validate": "npm run typecheck && npm run lint && npm run build && npm test && npm run test:browser && npm run check:package",
|
|
48
|
-
"prepublishOnly": "
|
|
56
|
+
"prepublishOnly": "node scripts/verify-release.mjs",
|
|
49
57
|
"test:consumer": "node scripts/test-consumer.mjs",
|
|
50
|
-
"test:compat": "node scripts/test-compat.mjs"
|
|
58
|
+
"test:compat": "node scripts/test-compat.mjs",
|
|
59
|
+
"test:optional": "node scripts/test-optional-consumer.mjs",
|
|
60
|
+
"test:next": "npm run build && node scripts/test-next.mjs",
|
|
61
|
+
"verify:release": "node scripts/verify-release.mjs"
|
|
51
62
|
},
|
|
52
63
|
"dependencies": {
|
|
53
64
|
"@fontsource-variable/dm-sans": "^5.3.0",
|
|
@@ -72,7 +83,6 @@
|
|
|
72
83
|
"devDependencies": {
|
|
73
84
|
"@playwright/test": "1.63.0",
|
|
74
85
|
"@testing-library/react": "^16.3.3",
|
|
75
|
-
"@types/node": "^24.13.3",
|
|
76
86
|
"@types/react": "^18.3.5",
|
|
77
87
|
"@types/react-dom": "^18.3.0",
|
|
78
88
|
"@types/three": "^0.186.0",
|
|
@@ -97,8 +107,15 @@
|
|
|
97
107
|
"type": "git",
|
|
98
108
|
"url": "git+https://github.com/abuzareal/contour-ui.git"
|
|
99
109
|
},
|
|
100
|
-
"homepage": "https://
|
|
110
|
+
"homepage": "https://contour.abuzr.in/",
|
|
101
111
|
"bugs": {
|
|
102
112
|
"url": "https://github.com/abuzareal/contour-ui/issues"
|
|
103
|
-
}
|
|
113
|
+
},
|
|
114
|
+
"keywords": [
|
|
115
|
+
"react",
|
|
116
|
+
"typescript",
|
|
117
|
+
"components",
|
|
118
|
+
"design-system",
|
|
119
|
+
"contour-ui"
|
|
120
|
+
]
|
|
104
121
|
}
|