@flikk/ui 1.0.0-beta.11 → 1.0.0-beta.13
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/components/ai/ApprovalCard/ApprovalCard.js +1 -1
- package/dist/components/ai/MessageHistory/MessageHistory.js +1 -0
- package/dist/components/ai/PromptInput/PromptInput.js +7 -125
- package/dist/components/ai/PromptInput/VoiceRecorder.js +0 -77
- package/dist/components/ai/StreamingResponse/StreamingResponse.js +1 -0
- package/dist/components/ai/StreamingResponse/StreamingResponse.types.d.ts +7 -7
- package/dist/components/ai/index.js +1 -0
- package/dist/components/core/Accordion/Accordion.d.ts +1 -1
- package/dist/components/core/Accordion/Accordion.js +2 -2
- package/dist/components/core/Accordion/Accordion.theme.d.ts +2 -2
- package/dist/components/core/Accordion/Accordion.theme.js +4 -4
- package/dist/components/core/Accordion/Accordion.types.d.ts +19 -20
- package/dist/components/core/Accordion/AccordionBody.d.ts +3 -0
- package/dist/components/core/Accordion/{AccordionContent.js → AccordionBody.js} +4 -4
- package/dist/components/core/Accordion/AccordionItem.js +1 -1
- package/dist/components/core/Accordion/AccordionTrigger.js +14 -7
- package/dist/components/core/Accordion/index.d.ts +2 -2
- package/dist/components/core/Alert/Alert.js +5 -1
- package/dist/components/core/Alert/Alert.types.d.ts +4 -4
- package/dist/components/core/Avatar/Avatar.js +22 -18
- package/dist/components/core/Avatar/Avatar.theme.js +1 -1
- package/dist/components/core/Avatar/Avatar.types.d.ts +9 -8
- package/dist/components/core/AvatarGroup/AvatarGroup.js +2 -2
- package/dist/components/core/Badge/Badge.js +7 -5
- package/dist/components/core/Badge/Badge.theme.js +11 -4
- package/dist/components/core/Badge/Badge.types.d.ts +2 -2
- package/dist/components/core/Breadcrumbs/Breadcrumbs.js +7 -3
- package/dist/components/core/Breadcrumbs/Breadcrumbs.types.d.ts +1 -1
- package/dist/components/core/Button/Button.js +2 -8
- package/dist/components/core/Button/Button.theme.js +7 -7
- package/dist/components/core/Calendar/Calendar.js +3 -3
- package/dist/components/core/Calendar/CalendarEvent/CalendarEvent.types.d.ts +5 -6
- package/dist/components/core/Card/Card.d.ts +2 -2
- package/dist/components/core/Card/Card.js +3 -3
- package/dist/components/core/Card/Card.theme.js +3 -3
- package/dist/components/core/Card/Card.types.d.ts +4 -4
- package/dist/components/core/Card/CardBody.d.ts +3 -0
- package/dist/components/core/Card/CardBody.js +11 -0
- package/dist/components/core/Card/index.d.ts +2 -2
- package/dist/components/core/Carousel/Carousel.js +4 -4
- package/dist/components/core/Carousel/Carousel.types.d.ts +4 -4
- package/dist/components/core/Carousel/CarouselBody.d.ts +4 -0
- package/dist/components/core/Carousel/{CarouselContent.js → CarouselBody.js} +3 -3
- package/dist/components/core/Carousel/index.d.ts +2 -1
- package/dist/components/core/ContextMenu/ContextMenu.d.ts +2 -2
- package/dist/components/core/ContextMenu/ContextMenu.js +6 -6
- package/dist/components/core/ContextMenu/ContextMenu.types.d.ts +2 -2
- package/dist/components/core/ContextMenu/ContextMenuBody.d.ts +6 -0
- package/dist/components/core/ContextMenu/{ContextMenuContent.js → ContextMenuBody.js} +4 -4
- package/dist/components/core/ContextMenu/ContextMenuSubBody.d.ts +6 -0
- package/dist/components/core/ContextMenu/{ContextMenuSubContent.js → ContextMenuSubBody.js} +4 -4
- package/dist/components/core/ContextMenu/index.d.ts +1 -1
- package/dist/components/core/Drawer/Drawer.d.ts +2 -2
- package/dist/components/core/Drawer/Drawer.js +28 -9
- package/dist/components/core/Drawer/Drawer.theme.js +1 -1
- package/dist/components/core/Drawer/Drawer.types.d.ts +8 -6
- package/dist/components/core/Drawer/DrawerBody.d.ts +5 -0
- package/dist/components/core/Drawer/DrawerBody.js +11 -0
- package/dist/components/core/Drawer/index.d.ts +2 -1
- package/dist/components/core/Dropdown/Dropdown.types.d.ts +3 -3
- package/dist/components/core/Dropdown/DropdownSection.js +3 -1
- package/dist/components/core/FileTypeIcon/FileTypeIcon.d.ts +3 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.js +33 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.theme.d.ts +2 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.theme.js +12 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.types.d.ts +19 -0
- package/dist/components/core/FileTypeIcon/fileTypes.d.ts +7 -0
- package/dist/components/core/FileTypeIcon/fileTypes.js +30 -0
- package/dist/components/core/FileTypeIcon/index.d.ts +2 -0
- package/dist/components/core/MenuItem/MenuItem.js +3 -1
- package/dist/components/core/MenuItem/MenuItem.theme.js +1 -1
- package/dist/components/core/MenuItem/MenuItem.types.d.ts +1 -1
- package/dist/components/core/Message/Message.d.ts +1 -1
- package/dist/components/core/Message/Message.js +3 -3
- package/dist/components/core/Message/Message.theme.js +2 -2
- package/dist/components/core/Message/Message.types.d.ts +7 -7
- package/dist/components/core/Message/MessageAvatar.d.ts +2 -2
- package/dist/components/core/Message/MessageAvatar.js +3 -3
- package/dist/components/core/Message/MessageBody.d.ts +8 -0
- package/dist/components/core/Message/{MessageContent.js → MessageBody.js} +3 -3
- package/dist/components/core/Message/index.d.ts +2 -0
- package/dist/components/core/Modal/Modal.js +5 -1
- package/dist/components/core/Modal/Modal.theme.js +1 -1
- package/dist/components/core/Modal/Modal.types.d.ts +5 -2
- package/dist/components/core/ModalStack/ModalStackModal.js +1 -0
- package/dist/components/core/PageHeading/PageHeading.types.d.ts +1 -1
- package/dist/components/core/PageHeading/PageHeadingBackButton.js +3 -1
- package/dist/components/core/Popover/Popover.d.ts +1 -1
- package/dist/components/core/Popover/Popover.js +4 -4
- package/dist/components/core/Popover/Popover.theme.d.ts +1 -1
- package/dist/components/core/Popover/Popover.theme.js +2 -2
- package/dist/components/core/Popover/Popover.types.d.ts +3 -3
- package/dist/components/core/Popover/PopoverBody.d.ts +7 -0
- package/dist/components/core/Popover/{PopoverContent.js → PopoverBody.js} +24 -13
- package/dist/components/core/Popover/index.d.ts +4 -3
- package/dist/components/core/Tabs/Tabs.animations.d.ts +2 -2
- package/dist/components/core/Tabs/Tabs.animations.js +3 -3
- package/dist/components/core/Tabs/Tabs.d.ts +1 -1
- package/dist/components/core/Tabs/Tabs.js +3 -3
- package/dist/components/core/Tabs/Tabs.theme.d.ts +1 -1
- package/dist/components/core/Tabs/Tabs.theme.js +2 -2
- package/dist/components/core/Tabs/Tabs.types.d.ts +9 -9
- package/dist/components/core/Tabs/TabsBody.d.ts +6 -0
- package/dist/components/core/Tabs/{TabsContent.js → TabsBody.js} +8 -8
- package/dist/components/core/Tabs/index.d.ts +2 -2
- package/dist/components/core/Tag/Tag.d.ts +1 -1
- package/dist/components/core/Tag/Tag.js +2 -2
- package/dist/components/core/Tag/Tag.types.d.ts +1 -1
- package/dist/components/core/Toast/Toast.js +5 -1
- package/dist/components/core/Toast/Toast.types.d.ts +9 -9
- package/dist/components/core/index.d.ts +1 -1
- package/dist/components/core/index.js +7 -3
- package/dist/components/data-display/Feed/Feed.animations.d.ts +40 -0
- package/dist/components/data-display/Feed/Feed.animations.js +26 -0
- package/dist/components/data-display/Feed/Feed.d.ts +5 -1
- package/dist/components/data-display/Feed/Feed.js +87 -52
- package/dist/components/data-display/Feed/Feed.theme.js +11 -13
- package/dist/components/data-display/Feed/Feed.types.d.ts +35 -34
- package/dist/components/data-display/Feed/index.d.ts +1 -1
- package/dist/components/data-display/GanttChart/GanttTaskBar.js +11 -9
- package/dist/components/data-display/GanttChart/GanttTaskContextMenu.js +1 -1
- package/dist/components/data-display/KPI/KPI.js +2 -2
- package/dist/components/data-display/KPI/KPI.types.d.ts +3 -3
- package/dist/components/data-display/Metric/Metric.js +2 -2
- package/dist/components/data-display/Metric/Metric.types.d.ts +3 -3
- package/dist/components/data-display/Table/TableColumnManager.js +2 -1
- package/dist/components/data-display/Table/TableFilter.js +2 -1
- package/dist/components/data-display/Timeline/TimelineMarker.js +2 -2
- package/dist/components/effects/3d/index.d.ts +1 -1
- package/dist/components/effects/AIOrb/AIOrb.d.ts +1 -0
- package/dist/components/effects/AIOrb/AIOrb.js +3 -2
- package/dist/components/effects/AIOrb/AIOrb.types.d.ts +1 -0
- package/dist/components/effects/AIOrb/hooks/index.d.ts +2 -0
- package/dist/components/effects/AIOrb/hooks/useOrbState.d.ts +20 -0
- package/dist/components/effects/AIOrb/hooks/useOrbState.js +27 -0
- package/dist/components/effects/AIOrb/index.d.ts +2 -2
- package/dist/components/effects/AIOrb/variants/Aura/Aura.d.ts +3 -0
- package/dist/components/effects/AIOrb/variants/Aura/Aura.js +75 -0
- package/dist/components/effects/AIOrb/variants/Aura/Aura.shaders.d.ts +28 -0
- package/dist/components/effects/AIOrb/variants/Aura/Aura.shaders.js +191 -0
- package/dist/components/effects/AIOrb/variants/Aura/Aura.types.d.ts +53 -0
- package/dist/components/effects/AIOrb/variants/Aura/ShaderCanvas.d.ts +17 -0
- package/dist/components/effects/AIOrb/variants/Aura/ShaderCanvas.js +149 -0
- package/dist/components/effects/AIOrb/variants/Aura/index.d.ts +2 -0
- package/dist/components/effects/AIOrb/variants/DotSphere/DotSphere.js +38 -7
- package/dist/components/effects/AIOrb/variants/DotSphere/DotSphere.types.d.ts +6 -0
- package/dist/components/effects/AIOrb/variants/Liquid/Liquid.js +34 -8
- package/dist/components/effects/AIOrb/variants/Liquid/Liquid.types.d.ts +6 -0
- package/dist/components/effects/AIOrb/variants/index.d.ts +2 -0
- package/dist/components/effects/CustomCursor/CustomCursor.d.ts +2 -2
- package/dist/components/effects/CustomCursor/CustomCursor.js +50 -47
- package/dist/components/effects/GlassSurface/GlassSurface.js +24 -12
- package/dist/components/effects/GlassSurface/GlassSurface.types.d.ts +8 -0
- package/dist/components/forms/Checkbox/Checkbox.js +1 -1
- package/dist/components/forms/Checkbox/Checkbox.types.d.ts +5 -5
- package/dist/components/forms/Checkbox/CheckboxGroup.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPicker.d.ts +1 -1
- package/dist/components/forms/ColorPicker/ColorPicker.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerBody.d.ts +7 -0
- package/dist/components/forms/ColorPicker/{ColorPickerContent.js → ColorPickerBody.js} +5 -5
- package/dist/components/forms/ColorPicker/index.d.ts +2 -2
- package/dist/components/forms/DatePicker/DatePicker.d.ts +7 -3
- package/dist/components/forms/DatePicker/DatePicker.js +6 -5
- package/dist/components/forms/DatePicker/DatePicker.theme.js +3 -3
- package/dist/components/forms/DatePicker/DatePicker.types.d.ts +9 -4
- package/dist/components/forms/DatePicker/DatePickerBody.d.ts +7 -0
- package/dist/components/forms/DatePicker/{DatePickerContent.js → DatePickerBody.js} +10 -9
- package/dist/components/forms/DatePicker/index.d.ts +2 -2
- package/dist/components/forms/FileUpload/FileUpload.js +0 -78
- package/dist/components/forms/Input/Input.js +2 -2
- package/dist/components/forms/Input/Input.types.d.ts +4 -4
- package/dist/components/forms/Mention/Mention.js +2 -2
- package/dist/components/forms/Radio/Radio.js +1 -1
- package/dist/components/forms/Radio/Radio.types.d.ts +5 -5
- package/dist/components/forms/Radio/RadioGroup.js +1 -1
- package/dist/components/forms/Select/Select.js +2 -2
- package/dist/components/forms/Select/Select.types.d.ts +4 -4
- package/dist/components/forms/Switch/Switch.js +1 -1
- package/dist/components/forms/Switch/Switch.types.d.ts +4 -4
- package/dist/components/forms/Textarea/Textarea.js +2 -2
- package/dist/components/forms/Textarea/Textarea.types.d.ts +4 -4
- package/dist/components/forms/TimePicker/TimePickerContent.js +1 -78
- package/dist/components/forms/index.d.ts +2 -2
- package/dist/components/forms/index.js +2 -80
- package/dist/components/layout/FormLayout/FormLayout.d.ts +0 -2
- package/dist/components/layout/FormLayout/FormLayout.js +12 -6
- package/dist/components/layout/FormLayout/FormLayout.theme.js +2 -5
- package/dist/components/layout/FormLayout/FormLayout.types.d.ts +8 -26
- package/dist/components/layout/FormLayout/FormLayoutSection.js +3 -2
- package/dist/components/layout/FormLayout/index.d.ts +1 -1
- package/dist/index.js +197 -199
- package/dist/styles.css +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/paletteGenerator.d.ts +46 -0
- package/package.json +1 -1
- package/src/styles/theme.css +2 -6
- package/dist/components/core/Accordion/AccordionContent.d.ts +0 -3
- package/dist/components/core/Card/CardContent.d.ts +0 -3
- package/dist/components/core/Card/CardContent.js +0 -11
- package/dist/components/core/Carousel/CarouselContent.d.ts +0 -4
- package/dist/components/core/ContextMenu/ContextMenuContent.d.ts +0 -6
- package/dist/components/core/ContextMenu/ContextMenuSubContent.d.ts +0 -6
- package/dist/components/core/Drawer/DrawerContent.d.ts +0 -5
- package/dist/components/core/Drawer/DrawerContent.js +0 -11
- package/dist/components/core/Loader/Loader.d.ts +0 -24
- package/dist/components/core/Loader/Loader.js +0 -57
- package/dist/components/core/Loader/Loader.theme.d.ts +0 -27
- package/dist/components/core/Loader/Loader.theme.js +0 -60
- package/dist/components/core/Loader/Loader.types.d.ts +0 -71
- package/dist/components/core/Loader/index.d.ts +0 -2
- package/dist/components/core/Message/MessageContent.d.ts +0 -8
- package/dist/components/core/Popover/PopoverContent.d.ts +0 -7
- package/dist/components/core/Tabs/TabsContent.d.ts +0 -6
- package/dist/components/forms/ColorPicker/ColorPickerContent.d.ts +0 -7
- package/dist/components/forms/DatePicker/DatePickerContent.d.ts +0 -7
- package/dist/components/layout/FormLayout/FormLayoutBody.d.ts +0 -3
- package/dist/components/layout/FormLayout/FormLayoutBody.js +0 -91
- package/dist/components/layout/FormLayout/FormLayoutHeader.d.ts +0 -3
- package/dist/components/layout/FormLayout/FormLayoutHeader.js +0 -12
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
const VERTEX_SHADER = `#version 300 es
|
|
5
|
+
in vec2 a_position;
|
|
6
|
+
void main() {
|
|
7
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
8
|
+
}`;
|
|
9
|
+
/**
|
|
10
|
+
* Minimal raw WebGL2 canvas renderer for fullscreen fragment shaders.
|
|
11
|
+
* - Built-in uniforms: iTime (float), iResolution (vec2)
|
|
12
|
+
* - Custom uniforms read from `uniformsRef` each frame (no stale closures)
|
|
13
|
+
* - ResizeObserver for responsive canvas sizing
|
|
14
|
+
* - rAF animation loop with cleanup on unmount
|
|
15
|
+
* - Graceful degradation: renders nothing if WebGL2 unavailable
|
|
16
|
+
*/
|
|
17
|
+
const ShaderCanvas = ({ fragmentShader, uniformsRef, maxDpr = 2, className, style, }) => {
|
|
18
|
+
const canvasRef = useRef(null);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
const canvas = canvasRef.current;
|
|
21
|
+
if (!canvas)
|
|
22
|
+
return;
|
|
23
|
+
const gl = canvas.getContext("webgl2", {
|
|
24
|
+
alpha: true,
|
|
25
|
+
premultipliedAlpha: false,
|
|
26
|
+
antialias: false,
|
|
27
|
+
});
|
|
28
|
+
if (!gl)
|
|
29
|
+
return;
|
|
30
|
+
// ── Compile shaders ────────────────────────────────────────────────
|
|
31
|
+
const compileShader = (type, src) => {
|
|
32
|
+
const shader = gl.createShader(type);
|
|
33
|
+
if (!shader)
|
|
34
|
+
return null;
|
|
35
|
+
gl.shaderSource(shader, src);
|
|
36
|
+
gl.compileShader(shader);
|
|
37
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
38
|
+
if (process.env.NODE_ENV !== "production") {
|
|
39
|
+
console.error("[ShaderCanvas]", gl.getShaderInfoLog(shader));
|
|
40
|
+
}
|
|
41
|
+
gl.deleteShader(shader);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return shader;
|
|
45
|
+
};
|
|
46
|
+
const vs = compileShader(gl.VERTEX_SHADER, VERTEX_SHADER);
|
|
47
|
+
const fs = compileShader(gl.FRAGMENT_SHADER, fragmentShader);
|
|
48
|
+
if (!vs || !fs)
|
|
49
|
+
return;
|
|
50
|
+
const program = gl.createProgram();
|
|
51
|
+
gl.attachShader(program, vs);
|
|
52
|
+
gl.attachShader(program, fs);
|
|
53
|
+
gl.linkProgram(program);
|
|
54
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
55
|
+
if (process.env.NODE_ENV !== "production") {
|
|
56
|
+
console.error("[ShaderCanvas]", gl.getProgramInfoLog(program));
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
gl.useProgram(program);
|
|
61
|
+
// ── Fullscreen quad ────────────────────────────────────────────────
|
|
62
|
+
const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
|
|
63
|
+
const vao = gl.createVertexArray();
|
|
64
|
+
gl.bindVertexArray(vao);
|
|
65
|
+
const buf = gl.createBuffer();
|
|
66
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
67
|
+
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
|
|
68
|
+
const aPos = gl.getAttribLocation(program, "a_position");
|
|
69
|
+
gl.enableVertexAttribArray(aPos);
|
|
70
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
71
|
+
// ── Uniform locations ──────────────────────────────────────────────
|
|
72
|
+
const uTime = gl.getUniformLocation(program, "iTime");
|
|
73
|
+
const uRes = gl.getUniformLocation(program, "iResolution");
|
|
74
|
+
// Cache custom uniform locations
|
|
75
|
+
const customLocs = new Map();
|
|
76
|
+
const getCustomLoc = (name) => {
|
|
77
|
+
var _a;
|
|
78
|
+
if (!customLocs.has(name)) {
|
|
79
|
+
customLocs.set(name, gl.getUniformLocation(program, name));
|
|
80
|
+
}
|
|
81
|
+
return (_a = customLocs.get(name)) !== null && _a !== void 0 ? _a : null;
|
|
82
|
+
};
|
|
83
|
+
// ── Resize handling ────────────────────────────────────────────────
|
|
84
|
+
const dpr = Math.min(window.devicePixelRatio || 1, maxDpr);
|
|
85
|
+
let width = 0;
|
|
86
|
+
let height = 0;
|
|
87
|
+
const resize = () => {
|
|
88
|
+
const rect = canvas.getBoundingClientRect();
|
|
89
|
+
const w = Math.round(rect.width * dpr);
|
|
90
|
+
const h = Math.round(rect.height * dpr);
|
|
91
|
+
if (w !== width || h !== height) {
|
|
92
|
+
width = w;
|
|
93
|
+
height = h;
|
|
94
|
+
canvas.width = w;
|
|
95
|
+
canvas.height = h;
|
|
96
|
+
gl.viewport(0, 0, w, h);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const observer = new ResizeObserver(resize);
|
|
100
|
+
observer.observe(canvas);
|
|
101
|
+
resize();
|
|
102
|
+
// ── Animation loop ─────────────────────────────────────────────────
|
|
103
|
+
gl.enable(gl.BLEND);
|
|
104
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
105
|
+
let rafId = 0;
|
|
106
|
+
const startTime = performance.now();
|
|
107
|
+
const frame = () => {
|
|
108
|
+
rafId = requestAnimationFrame(frame);
|
|
109
|
+
const t = (performance.now() - startTime) / 1000;
|
|
110
|
+
gl.uniform1f(uTime, t);
|
|
111
|
+
gl.uniform2f(uRes, width, height);
|
|
112
|
+
// Set custom uniforms from ref
|
|
113
|
+
const uniforms = uniformsRef.current;
|
|
114
|
+
for (const name in uniforms) {
|
|
115
|
+
const loc = getCustomLoc(name);
|
|
116
|
+
if (!loc)
|
|
117
|
+
continue;
|
|
118
|
+
const val = uniforms[name];
|
|
119
|
+
if (typeof val === "number") {
|
|
120
|
+
gl.uniform1f(loc, val);
|
|
121
|
+
}
|
|
122
|
+
else if (Array.isArray(val)) {
|
|
123
|
+
if (val.length === 2)
|
|
124
|
+
gl.uniform2f(loc, val[0], val[1]);
|
|
125
|
+
else if (val.length === 3)
|
|
126
|
+
gl.uniform3f(loc, val[0], val[1], val[2]);
|
|
127
|
+
else if (val.length === 4)
|
|
128
|
+
gl.uniform4f(loc, val[0], val[1], val[2], val[3]);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
132
|
+
};
|
|
133
|
+
rafId = requestAnimationFrame(frame);
|
|
134
|
+
return () => {
|
|
135
|
+
cancelAnimationFrame(rafId);
|
|
136
|
+
observer.disconnect();
|
|
137
|
+
gl.deleteProgram(program);
|
|
138
|
+
gl.deleteShader(vs);
|
|
139
|
+
gl.deleteShader(fs);
|
|
140
|
+
gl.deleteBuffer(buf);
|
|
141
|
+
gl.deleteVertexArray(vao);
|
|
142
|
+
};
|
|
143
|
+
// Fragment shader is static — only set up once
|
|
144
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
145
|
+
}, []);
|
|
146
|
+
return (jsx("canvas", { ref: canvasRef, className: className, style: { display: "block", width: "100%", height: "100%", ...style } }));
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export { ShaderCanvas };
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { useRef, useMemo, useEffect } from 'react';
|
|
3
3
|
import { Canvas, useFrame } from '@react-three/fiber';
|
|
4
|
-
import { Color,
|
|
4
|
+
import { Color, OneFactor, ZeroFactor, AddEquation, CustomBlending, BackSide } from 'three';
|
|
5
5
|
import { waveFragment, waveVertex, dotSphereFragment, dotSphereVertex, glowFragment, glowVertex } from './DotSphere.shaders.js';
|
|
6
|
+
import { useOrbState } from '../../hooks/useOrbState.js';
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
+
const STATE_CONFIG = {
|
|
9
|
+
idle: { speed: 0.3, glowIntensity: 0.6, rimIntensity: 1.0 },
|
|
10
|
+
listening: { speed: 0.6, glowIntensity: 1.0, rimIntensity: 1.5 },
|
|
11
|
+
thinking: { speed: 1.2, glowIntensity: 1.4, rimIntensity: 2.0 },
|
|
12
|
+
speaking: { speed: 0.8, glowIntensity: 1.2, rimIntensity: 1.8 },
|
|
13
|
+
};
|
|
14
|
+
const OrbScene = ({ colors, speed, gridDensity, dotSize, rimIntensity, glowIntensity, glowSize, state, }) => {
|
|
8
15
|
const groupRef = useRef(null);
|
|
9
16
|
const dotMatRef = useRef(null);
|
|
10
17
|
const innerGlowRef = useRef(null);
|
|
@@ -74,6 +81,9 @@ const OrbScene = ({ colors, speed, gridDensity, dotSize, rimIntensity, glowInten
|
|
|
74
81
|
}),
|
|
75
82
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
76
83
|
[]);
|
|
84
|
+
// ── State-driven interpolation ─────────────────────────────────────────
|
|
85
|
+
const stateProps = useMemo(() => ({ speed, glowIntensity, rimIntensity }), [speed, glowIntensity, rimIntensity]);
|
|
86
|
+
const { valuesRef: stateRef, tick: stateTick } = useOrbState(state, STATE_CONFIG, stateProps);
|
|
77
87
|
// ── Sync prop changes → uniforms ──────────────────────────────────────
|
|
78
88
|
useEffect(() => {
|
|
79
89
|
// Dot sphere
|
|
@@ -108,8 +118,21 @@ const OrbScene = ({ colors, speed, gridDensity, dotSize, rimIntensity, glowInten
|
|
|
108
118
|
}
|
|
109
119
|
}, [colorObjs, dotSize, gridDensity, rimIntensity, glowIntensity]);
|
|
110
120
|
// ── Animation loop ────────────────────────────────────────────────────
|
|
111
|
-
useFrame(({ clock }) => {
|
|
112
|
-
|
|
121
|
+
useFrame(({ clock }, delta) => {
|
|
122
|
+
// Tick state interpolation
|
|
123
|
+
stateTick(delta);
|
|
124
|
+
const sv = stateRef.current;
|
|
125
|
+
const t = clock.getElapsedTime() * sv.speed;
|
|
126
|
+
// Sync interpolated rimIntensity / glowIntensity into uniforms
|
|
127
|
+
if (dotMatRef.current) {
|
|
128
|
+
dotMatRef.current.uniforms.u_rimIntensity.value = sv.rimIntensity;
|
|
129
|
+
}
|
|
130
|
+
if (innerGlowRef.current) {
|
|
131
|
+
innerGlowRef.current.uniforms.u_intensity.value = sv.glowIntensity * 0.8;
|
|
132
|
+
}
|
|
133
|
+
if (outerGlowRef.current) {
|
|
134
|
+
outerGlowRef.current.uniforms.u_intensity.value = sv.glowIntensity * 0.55;
|
|
135
|
+
}
|
|
113
136
|
// Update time uniform on every material
|
|
114
137
|
for (const ref of [
|
|
115
138
|
dotMatRef,
|
|
@@ -125,12 +148,20 @@ const OrbScene = ({ colors, speed, gridDensity, dotSize, rimIntensity, glowInten
|
|
|
125
148
|
groupRef.current.rotation.y = clock.getElapsedTime() * 0.12;
|
|
126
149
|
}
|
|
127
150
|
});
|
|
128
|
-
return (jsxs("group", { ref: groupRef, children: [jsxs("mesh", { scale: 0.85, children: [jsx("sphereGeometry", { args: [1, 48, 48] }), jsx("shaderMaterial", { ref: waveDeepRef, vertexShader: waveVertex, fragmentShader: waveFragment, uniforms: waveDeepUniforms, transparent: true,
|
|
151
|
+
return (jsxs("group", { ref: groupRef, children: [jsxs("mesh", { scale: 0.85, children: [jsx("sphereGeometry", { args: [1, 48, 48] }), jsx("shaderMaterial", { ref: waveDeepRef, vertexShader: waveVertex, fragmentShader: waveFragment, uniforms: waveDeepUniforms, transparent: true, depthWrite: false })] }), jsxs("mesh", { scale: 0.96, children: [jsx("sphereGeometry", { args: [1, 48, 48] }), jsx("shaderMaterial", { ref: waveSurfaceRef, vertexShader: waveVertex, fragmentShader: waveFragment, uniforms: waveSurfaceUniforms, transparent: true, depthWrite: false })] }), jsxs("mesh", { children: [jsx("sphereGeometry", { args: [1, 64, 64] }), jsx("shaderMaterial", { ref: dotMatRef, vertexShader: dotSphereVertex, fragmentShader: dotSphereFragment, uniforms: dotUniforms, transparent: true, depthWrite: false })] }), jsxs("mesh", { scale: 1.12, children: [jsx("sphereGeometry", { args: [1, 32, 32] }), jsx("shaderMaterial", { ref: innerGlowRef, vertexShader: glowVertex, fragmentShader: glowFragment, uniforms: innerGlowUniforms, transparent: true, side: BackSide, blending: CustomBlending, blendEquation: AddEquation, blendSrc: OneFactor, blendDst: OneFactor, blendSrcAlpha: ZeroFactor, blendDstAlpha: OneFactor, depthWrite: false })] }), jsxs("mesh", { scale: glowSize, children: [jsx("sphereGeometry", { args: [1, 32, 32] }), jsx("shaderMaterial", { ref: outerGlowRef, vertexShader: glowVertex, fragmentShader: glowFragment, uniforms: outerGlowUniforms, transparent: true, side: BackSide, blending: CustomBlending, blendEquation: AddEquation, blendSrc: OneFactor, blendDst: OneFactor, blendSrcAlpha: ZeroFactor, blendDstAlpha: OneFactor, depthWrite: false })] })] }));
|
|
129
152
|
};
|
|
130
153
|
// ── Public DotSphere variant ─────────────────────────────────────────────────
|
|
131
154
|
const DEFAULT_COLORS = ["#00d2ff", "#a855f7", "#f97316"];
|
|
132
|
-
const DotSphere = ({ colors = DEFAULT_COLORS, speed = 0.6, gridDensity = 40, dotSize = 0.055, rimIntensity = 1.5, glowIntensity = 1.0, glowSize = 1.5, }) => {
|
|
133
|
-
return (jsx(Canvas, { className: "!absolute inset-0 w-full h-full",
|
|
155
|
+
const DotSphere = ({ colors = DEFAULT_COLORS, speed = 0.6, gridDensity = 40, dotSize = 0.055, rimIntensity = 1.5, glowIntensity = 1.0, glowSize = 1.5, state, }) => {
|
|
156
|
+
return (jsx(Canvas, { className: "!absolute inset-0 w-full h-full", style: {
|
|
157
|
+
filter: [
|
|
158
|
+
'drop-shadow(0 0 10px rgba(168, 85, 247, 0.7))',
|
|
159
|
+
'drop-shadow(0 0 25px rgba(147, 51, 234, 0.35))',
|
|
160
|
+
'drop-shadow(0 0 50px rgba(124, 58, 237, 0.15))',
|
|
161
|
+
].join(' '),
|
|
162
|
+
}, dpr: [1, 2], camera: { position: [0, 0, 3], fov: 50 }, gl: { antialias: true, alpha: true, premultipliedAlpha: false }, onCreated: ({ gl }) => {
|
|
163
|
+
gl.setClearColor(0x000000, 0);
|
|
164
|
+
}, children: jsx(OrbScene, { colors: colors, speed: speed, gridDensity: gridDensity, dotSize: dotSize, rimIntensity: rimIntensity, glowIntensity: glowIntensity, glowSize: glowSize, state: state }) }));
|
|
134
165
|
};
|
|
135
166
|
|
|
136
167
|
export { DotSphere };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { OrbState } from "../../AIOrb.types";
|
|
1
2
|
export interface DotSphereProps {
|
|
2
3
|
/**
|
|
3
4
|
* Three gradient colours [top, middle, bottom] as hex strings.
|
|
@@ -34,4 +35,9 @@ export interface DotSphereProps {
|
|
|
34
35
|
* @default 1.5
|
|
35
36
|
*/
|
|
36
37
|
glowSize?: number;
|
|
38
|
+
/**
|
|
39
|
+
* State-driven animation. When set, smoothly interpolates speed,
|
|
40
|
+
* glowIntensity, and rimIntensity towards state targets.
|
|
41
|
+
*/
|
|
42
|
+
state?: OrbState;
|
|
37
43
|
}
|
|
@@ -2,11 +2,18 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useRef, useMemo, useEffect } from 'react';
|
|
3
3
|
import { Canvas, useFrame } from '@react-three/fiber';
|
|
4
4
|
import { Environment } from '@react-three/drei';
|
|
5
|
-
import { ACESFilmicToneMapping, Color,
|
|
5
|
+
import { ACESFilmicToneMapping, Color, OneFactor, ZeroFactor, AddEquation, CustomBlending, BackSide } from 'three';
|
|
6
6
|
import { simplex3 } from './Liquid.noise.js';
|
|
7
7
|
import { atmosphereFragment, glowVertex } from './Liquid.shaders.js';
|
|
8
|
+
import { useOrbState } from '../../hooks/useOrbState.js';
|
|
8
9
|
|
|
9
|
-
const
|
|
10
|
+
const STATE_CONFIG = {
|
|
11
|
+
idle: { speed: 0.5, noiseAmplitude: 0.06, glowIntensity: 0.6 },
|
|
12
|
+
listening: { speed: 1.0, noiseAmplitude: 0.1, glowIntensity: 1.0 },
|
|
13
|
+
thinking: { speed: 1.8, noiseAmplitude: 0.15, glowIntensity: 1.4 },
|
|
14
|
+
speaking: { speed: 1.2, noiseAmplitude: 0.12, glowIntensity: 1.2 },
|
|
15
|
+
};
|
|
16
|
+
const LiquidScene = ({ colors, meshColor, speed, roughness, metalness, noiseScale, noiseAmplitude, glowIntensity, glowSize, state, }) => {
|
|
10
17
|
const groupRef = useRef(null);
|
|
11
18
|
const meshRef = useRef(null);
|
|
12
19
|
const atmosphereRef = useRef(null);
|
|
@@ -15,6 +22,9 @@ const LiquidScene = ({ colors, meshColor, speed, roughness, metalness, noiseScal
|
|
|
15
22
|
// Keep latest props in a ref so useFrame always reads current values
|
|
16
23
|
const propsRef = useRef({ speed, noiseScale, noiseAmplitude });
|
|
17
24
|
propsRef.current = { speed, noiseScale, noiseAmplitude };
|
|
25
|
+
// ── State-driven interpolation ─────────────────────────────────────────
|
|
26
|
+
const stateProps = useMemo(() => ({ speed, noiseAmplitude, glowIntensity }), [speed, noiseAmplitude, glowIntensity]);
|
|
27
|
+
const { valuesRef: stateRef, tick: stateTick } = useOrbState(state, STATE_CONFIG, stateProps);
|
|
18
28
|
// Colour objects (rebuilt only when hex strings change)
|
|
19
29
|
const [c1, c2, c3] = colors;
|
|
20
30
|
const colorObjs = useMemo(() => ({
|
|
@@ -59,9 +69,18 @@ const LiquidScene = ({ colors, meshColor, speed, roughness, metalness, noiseScal
|
|
|
59
69
|
}
|
|
60
70
|
}, [colorObjs, meshColor, roughness, metalness, glowIntensity]);
|
|
61
71
|
// ── Animation loop ──────────────────────────────────────────────────────
|
|
62
|
-
useFrame(({ clock }) => {
|
|
72
|
+
useFrame(({ clock }, delta) => {
|
|
73
|
+
// Tick state interpolation
|
|
74
|
+
stateTick(delta);
|
|
75
|
+
const sv = stateRef.current;
|
|
63
76
|
const t = clock.getElapsedTime();
|
|
64
|
-
const
|
|
77
|
+
const spd = sv.speed;
|
|
78
|
+
const na = sv.noiseAmplitude;
|
|
79
|
+
const ns = propsRef.current.noiseScale;
|
|
80
|
+
// Sync interpolated glowIntensity into atmosphere uniform
|
|
81
|
+
if (atmosphereRef.current) {
|
|
82
|
+
atmosphereRef.current.uniforms.u_intensity.value = sv.glowIntensity * 0.65;
|
|
83
|
+
}
|
|
65
84
|
// Vertex deformation
|
|
66
85
|
if (meshRef.current && origData.current) {
|
|
67
86
|
const geo = meshRef.current.geometry;
|
|
@@ -92,14 +111,21 @@ const LiquidScene = ({ colors, meshColor, speed, roughness, metalness, noiseScal
|
|
|
92
111
|
atmosphereRef.current.uniforms.u_time.value = t * spd;
|
|
93
112
|
}
|
|
94
113
|
});
|
|
95
|
-
return (jsxs("group", { ref: groupRef, children: [jsx(Environment, { preset: "sunset" }), jsx("ambientLight", { intensity: 2 }), jsx("pointLight", { color: colors[0], intensity: 18, distance: 50, position: [-3, 1, 2] }), jsx("pointLight", { color: colors[1], intensity: 18, distance: 50, position: [3, -1, 2] }), jsx("pointLight", { color: colors[2], intensity: 10, distance: 50, position: [0, 0, 4] }), jsx("pointLight", { color: "#6428b4", intensity: 12, distance: 50, position: [0, -3, 2] }), jsxs("mesh", { ref: meshRef, children: [jsx("sphereGeometry", { args: [1, 64, 64] }), jsx("meshStandardMaterial", { color: meshColor, roughness: roughness, metalness: metalness, envMapIntensity: 2.5, emissive: "#5A1878", emissiveIntensity: 0.8 })] }), jsxs("mesh", { scale: glowSize, children: [jsx("sphereGeometry", { args: [1, 32, 32] }), jsx("shaderMaterial", { ref: atmosphereRef, vertexShader: glowVertex, fragmentShader: atmosphereFragment, uniforms: atmosphereUniforms, transparent: true, side: BackSide, blending:
|
|
114
|
+
return (jsxs("group", { ref: groupRef, children: [jsx(Environment, { preset: "sunset" }), jsx("ambientLight", { intensity: 2 }), jsx("pointLight", { color: colors[0], intensity: 18, distance: 50, position: [-3, 1, 2] }), jsx("pointLight", { color: colors[1], intensity: 18, distance: 50, position: [3, -1, 2] }), jsx("pointLight", { color: colors[2], intensity: 10, distance: 50, position: [0, 0, 4] }), jsx("pointLight", { color: "#6428b4", intensity: 12, distance: 50, position: [0, -3, 2] }), jsxs("mesh", { ref: meshRef, children: [jsx("sphereGeometry", { args: [1, 64, 64] }), jsx("meshStandardMaterial", { color: meshColor, roughness: roughness, metalness: metalness, envMapIntensity: 2.5, emissive: "#5A1878", emissiveIntensity: 0.8 })] }), jsxs("mesh", { scale: glowSize, children: [jsx("sphereGeometry", { args: [1, 32, 32] }), jsx("shaderMaterial", { ref: atmosphereRef, vertexShader: glowVertex, fragmentShader: atmosphereFragment, uniforms: atmosphereUniforms, transparent: true, side: BackSide, blending: CustomBlending, blendEquation: AddEquation, blendSrc: OneFactor, blendDst: OneFactor, blendSrcAlpha: ZeroFactor, blendDstAlpha: OneFactor, depthWrite: false })] })] }));
|
|
96
115
|
};
|
|
97
116
|
// ── Public Liquid variant ────────────────────────────────────────────────────
|
|
98
117
|
const DEFAULT_COLORS = ["#2C35B7", "#C9242F", "#9DD9EB"];
|
|
99
|
-
const Liquid = ({ colors = DEFAULT_COLORS, meshColor = "#350F3F", speed = 1.0, roughness = 0.15, metalness = 0.95, noiseScale = 0.8, noiseAmplitude = 0.1, glowIntensity = 1.0, glowSize = 1.8, }) => {
|
|
100
|
-
return (jsxs(Fragment, { children: [jsx(Canvas, { className: "!absolute inset-0 w-full h-full",
|
|
118
|
+
const Liquid = ({ colors = DEFAULT_COLORS, meshColor = "#350F3F", speed = 1.0, roughness = 0.15, metalness = 0.95, noiseScale = 0.8, noiseAmplitude = 0.1, glowIntensity = 1.0, glowSize = 1.8, state, }) => {
|
|
119
|
+
return (jsxs(Fragment, { children: [jsx(Canvas, { className: "!absolute inset-0 w-full h-full", style: {
|
|
120
|
+
filter: [
|
|
121
|
+
'drop-shadow(0 0 10px rgba(192, 132, 252, 0.7))',
|
|
122
|
+
'drop-shadow(0 0 25px rgba(147, 51, 234, 0.35))',
|
|
123
|
+
'drop-shadow(0 0 50px rgba(124, 58, 237, 0.15))',
|
|
124
|
+
].join(' '),
|
|
125
|
+
}, dpr: [1, 2], camera: { position: [0, 0, 3.2], fov: 50 }, gl: { antialias: true, alpha: true, premultipliedAlpha: false, toneMapping: ACESFilmicToneMapping }, onCreated: ({ gl }) => {
|
|
101
126
|
gl.toneMappingExposure = 1.8;
|
|
102
|
-
|
|
127
|
+
gl.setClearColor(0x000000, 0);
|
|
128
|
+
}, children: jsx(LiquidScene, { colors: colors, meshColor: meshColor, speed: speed, roughness: roughness, metalness: metalness, noiseScale: noiseScale, noiseAmplitude: noiseAmplitude, glowIntensity: glowIntensity, glowSize: glowSize, state: state }) }), jsx("div", { className: "absolute inset-0 pointer-events-none", style: {
|
|
103
129
|
background: "radial-gradient(circle at center, rgba(255,255,255,0.35) 0%, rgba(180,120,255,0.2) 15%, rgba(100,40,180,0.08) 35%, transparent 55%)",
|
|
104
130
|
mixBlendMode: "screen",
|
|
105
131
|
} })] }));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { OrbState } from "../../AIOrb.types";
|
|
1
2
|
export interface LiquidProps {
|
|
2
3
|
/**
|
|
3
4
|
* Three light colours as hex strings.
|
|
@@ -44,4 +45,9 @@ export interface LiquidProps {
|
|
|
44
45
|
* @default 1.8
|
|
45
46
|
*/
|
|
46
47
|
glowSize?: number;
|
|
48
|
+
/**
|
|
49
|
+
* State-driven animation. When set, smoothly interpolates speed,
|
|
50
|
+
* noiseAmplitude, and glowIntensity towards state targets.
|
|
51
|
+
*/
|
|
52
|
+
state?: OrbState;
|
|
47
53
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import type { CustomCursorContextType, CustomCursorProviderProps, CustomCursorProps, CustomCursorFollowProps } from
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { CustomCursorContextType, CustomCursorProviderProps, CustomCursorProps, CustomCursorFollowProps } from "./CustomCursor.types";
|
|
3
3
|
/**
|
|
4
4
|
* Hook to access CustomCursor context
|
|
5
5
|
* @throws Error if used outside CustomCursorProvider
|
|
@@ -18,7 +18,7 @@ const CustomCursorContext = React.createContext(undefined);
|
|
|
18
18
|
const useCustomCursor = () => {
|
|
19
19
|
const context = React.useContext(CustomCursorContext);
|
|
20
20
|
if (!context) {
|
|
21
|
-
throw new Error(
|
|
21
|
+
throw new Error("useCustomCursor must be used within a CustomCursorProvider");
|
|
22
22
|
}
|
|
23
23
|
return context;
|
|
24
24
|
};
|
|
@@ -36,7 +36,7 @@ const useCustomCursor = () => {
|
|
|
36
36
|
* </CustomCursorProvider>
|
|
37
37
|
* ```
|
|
38
38
|
*/
|
|
39
|
-
const CustomCursorProvider = React.forwardRef(({ children, className, allowedPointerTypes = [
|
|
39
|
+
const CustomCursorProvider = React.forwardRef(({ children, className, allowedPointerTypes = ["mouse"], ...props }, ref) => {
|
|
40
40
|
const [cursorPos, setCursorPos] = React.useState({ x: 0, y: 0 });
|
|
41
41
|
const [isActive, setIsActive] = React.useState(false);
|
|
42
42
|
const containerRef = React.useRef(null);
|
|
@@ -52,12 +52,13 @@ const CustomCursorProvider = React.forwardRef(({ children, className, allowedPoi
|
|
|
52
52
|
// Ensure parent has positioning context for absolute children
|
|
53
53
|
const computedPosition = getComputedStyle(parent).position;
|
|
54
54
|
const previousInlinePosition = parent.style.position;
|
|
55
|
-
const shouldOverridePosition = computedPosition ===
|
|
55
|
+
const shouldOverridePosition = computedPosition === "static";
|
|
56
56
|
if (shouldOverridePosition) {
|
|
57
|
-
parent.style.position =
|
|
57
|
+
parent.style.position = "relative";
|
|
58
58
|
}
|
|
59
59
|
const handlePointerMove = (event) => {
|
|
60
|
-
const pointerType = (event.pointerType ||
|
|
60
|
+
const pointerType = (event.pointerType ||
|
|
61
|
+
"mouse");
|
|
61
62
|
if (!allowedPointerTypesSet.has(pointerType))
|
|
62
63
|
return;
|
|
63
64
|
const rect = parent.getBoundingClientRect();
|
|
@@ -69,7 +70,8 @@ const CustomCursorProvider = React.forwardRef(({ children, className, allowedPoi
|
|
|
69
70
|
setIsActive(true);
|
|
70
71
|
};
|
|
71
72
|
const handlePointerLeave = (event) => {
|
|
72
|
-
const pointerType = (event.pointerType ||
|
|
73
|
+
const pointerType = (event.pointerType ||
|
|
74
|
+
"mouse");
|
|
73
75
|
if (!allowedPointerTypesSet.has(pointerType))
|
|
74
76
|
return;
|
|
75
77
|
setIsActive(false);
|
|
@@ -85,23 +87,23 @@ const CustomCursorProvider = React.forwardRef(({ children, className, allowedPoi
|
|
|
85
87
|
const handleMouseLeave = () => {
|
|
86
88
|
setIsActive(false);
|
|
87
89
|
};
|
|
88
|
-
const supportsPointerEvents = typeof window !==
|
|
90
|
+
const supportsPointerEvents = typeof window !== "undefined" && "PointerEvent" in window;
|
|
89
91
|
if (supportsPointerEvents) {
|
|
90
|
-
parent.addEventListener(
|
|
91
|
-
parent.addEventListener(
|
|
92
|
+
parent.addEventListener("pointermove", handlePointerMove);
|
|
93
|
+
parent.addEventListener("pointerleave", handlePointerLeave);
|
|
92
94
|
}
|
|
93
95
|
else {
|
|
94
|
-
parent.addEventListener(
|
|
95
|
-
parent.addEventListener(
|
|
96
|
+
parent.addEventListener("mousemove", handleMouseMove);
|
|
97
|
+
parent.addEventListener("mouseleave", handleMouseLeave);
|
|
96
98
|
}
|
|
97
99
|
return () => {
|
|
98
100
|
if (supportsPointerEvents) {
|
|
99
|
-
parent.removeEventListener(
|
|
100
|
-
parent.removeEventListener(
|
|
101
|
+
parent.removeEventListener("pointermove", handlePointerMove);
|
|
102
|
+
parent.removeEventListener("pointerleave", handlePointerLeave);
|
|
101
103
|
}
|
|
102
104
|
else {
|
|
103
|
-
parent.removeEventListener(
|
|
104
|
-
parent.removeEventListener(
|
|
105
|
+
parent.removeEventListener("mousemove", handleMouseMove);
|
|
106
|
+
parent.removeEventListener("mouseleave", handleMouseLeave);
|
|
105
107
|
}
|
|
106
108
|
if (shouldOverridePosition) {
|
|
107
109
|
parent.style.position = previousInlinePosition;
|
|
@@ -111,7 +113,7 @@ const CustomCursorProvider = React.forwardRef(({ children, className, allowedPoi
|
|
|
111
113
|
const contextValue = React.useMemo(() => ({ cursorPos, isActive, containerRef, cursorRef }), [cursorPos, isActive]);
|
|
112
114
|
return (jsx(CustomCursorContext.Provider, { value: contextValue, children: jsx("div", { ref: containerRef, "data-slot": "custom-cursor-provider", className: className, ...props, children: children }) }));
|
|
113
115
|
});
|
|
114
|
-
CustomCursorProvider.displayName =
|
|
116
|
+
CustomCursorProvider.displayName = "CustomCursorProvider";
|
|
115
117
|
/**
|
|
116
118
|
* CustomCursor - Main cursor element component
|
|
117
119
|
* Follows mouse position exactly with instant movement
|
|
@@ -123,7 +125,7 @@ CustomCursorProvider.displayName = 'CustomCursorProvider';
|
|
|
123
125
|
* </CustomCursor>
|
|
124
126
|
* ```
|
|
125
127
|
*/
|
|
126
|
-
const CustomCursor = React.forwardRef(({ children, size =
|
|
128
|
+
const CustomCursor = React.forwardRef(({ children, size = "md", color = "primary", variant = "default", shape = "arrow", className, style, ...props }, ref) => {
|
|
127
129
|
const { cursorPos, isActive, containerRef, cursorRef } = useCustomCursor();
|
|
128
130
|
React.useImperativeHandle(ref, () => cursorRef.current);
|
|
129
131
|
const x = useMotionValue(0);
|
|
@@ -136,7 +138,7 @@ const CustomCursor = React.forwardRef(({ children, size = 'md', color = 'primary
|
|
|
136
138
|
return;
|
|
137
139
|
}
|
|
138
140
|
const previousInlineCursor = parentElement.style.cursor;
|
|
139
|
-
parentElement.style.cursor =
|
|
141
|
+
parentElement.style.cursor = "none";
|
|
140
142
|
return () => {
|
|
141
143
|
parentElement.style.cursor = previousInlineCursor;
|
|
142
144
|
};
|
|
@@ -147,32 +149,32 @@ const CustomCursor = React.forwardRef(({ children, size = 'md', color = 'primary
|
|
|
147
149
|
y.set(cursorPos.y);
|
|
148
150
|
}, [cursorPos, x, y]);
|
|
149
151
|
// Default content based on shape
|
|
150
|
-
const defaultContent = shape ===
|
|
152
|
+
const defaultContent = shape === "arrow" ? (jsx(PaperAirplaneIcon, { className: "w-full h-full rotate-180" })) : (jsx("div", { className: "w-full h-full" }));
|
|
151
153
|
return (jsx(AnimatePresence, { children: isActive && (jsx(motion.div, { ref: cursorRef, "data-slot": "custom-cursor", className: cn(customCursorTheme.baseStyle, customCursorTheme.cursorStyle, customCursorTheme.sizes[size], customCursorTheme.colors[color], customCursorTheme.variants[variant], customCursorTheme.shapes[shape], className), style: { top: y, left: x, ...style }, variants: customCursorVariants, initial: "initial", animate: "animate", exit: "exit", role: "presentation", "aria-hidden": "true", ...props, children: children || defaultContent })) }));
|
|
152
154
|
});
|
|
153
|
-
CustomCursor.displayName =
|
|
155
|
+
CustomCursor.displayName = "CustomCursor";
|
|
154
156
|
/**
|
|
155
157
|
* Calculate offset based on alignment and element dimensions
|
|
156
158
|
*/
|
|
157
159
|
const calculateOffset = (align, sideOffset, width, height) => {
|
|
158
160
|
switch (align) {
|
|
159
|
-
case
|
|
161
|
+
case "center":
|
|
160
162
|
return { x: width / 2, y: height / 2 };
|
|
161
|
-
case
|
|
163
|
+
case "top":
|
|
162
164
|
return { x: width / 2, y: height + sideOffset };
|
|
163
|
-
case
|
|
165
|
+
case "top-left":
|
|
164
166
|
return { x: width + sideOffset, y: height + sideOffset };
|
|
165
|
-
case
|
|
167
|
+
case "top-right":
|
|
166
168
|
return { x: -sideOffset, y: height + sideOffset };
|
|
167
|
-
case
|
|
169
|
+
case "bottom":
|
|
168
170
|
return { x: width / 2, y: -sideOffset };
|
|
169
|
-
case
|
|
171
|
+
case "bottom-left":
|
|
170
172
|
return { x: width + sideOffset, y: -sideOffset };
|
|
171
|
-
case
|
|
173
|
+
case "bottom-right":
|
|
172
174
|
return { x: -sideOffset, y: -sideOffset };
|
|
173
|
-
case
|
|
175
|
+
case "left":
|
|
174
176
|
return { x: width + sideOffset, y: height / 2 };
|
|
175
|
-
case
|
|
177
|
+
case "right":
|
|
176
178
|
return { x: -sideOffset, y: height / 2 };
|
|
177
179
|
default:
|
|
178
180
|
return { x: 0, y: 0 };
|
|
@@ -193,12 +195,12 @@ const calculateOffset = (align, sideOffset, width, height) => {
|
|
|
193
195
|
*/
|
|
194
196
|
/** Available colors for random selection in user variant */
|
|
195
197
|
const userVariantColors = [
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
"primary",
|
|
199
|
+
"success",
|
|
200
|
+
"warning",
|
|
201
|
+
"danger",
|
|
200
202
|
];
|
|
201
|
-
const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align =
|
|
203
|
+
const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align = "bottom-right", transition, variant = "default", avatar, name, color, className, style, ...props }, ref) => {
|
|
202
204
|
const { cursorPos, isActive, cursorRef } = useCustomCursor();
|
|
203
205
|
const cursorFollowRef = React.useRef(null);
|
|
204
206
|
const shouldReduceMotion = useReducedMotion();
|
|
@@ -223,7 +225,7 @@ const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align
|
|
|
223
225
|
// Apply spring physics for smooth following
|
|
224
226
|
const springConfig = shouldReduceMotion
|
|
225
227
|
? reducedMotionSpringConfig
|
|
226
|
-
: transition !== null && transition !== void 0 ? transition : defaultSpringConfig;
|
|
228
|
+
: (transition !== null && transition !== void 0 ? transition : defaultSpringConfig);
|
|
227
229
|
const springX = useSpring(x, springConfig);
|
|
228
230
|
const springY = useSpring(y, springConfig);
|
|
229
231
|
// Track size changes on the follow element
|
|
@@ -244,14 +246,14 @@ const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align
|
|
|
244
246
|
};
|
|
245
247
|
updateDimensions();
|
|
246
248
|
const cleanupFns = [];
|
|
247
|
-
if (typeof ResizeObserver !==
|
|
249
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
248
250
|
const observer = new ResizeObserver(updateDimensions);
|
|
249
251
|
observer.observe(followElement);
|
|
250
252
|
cleanupFns.push(() => observer.disconnect());
|
|
251
253
|
}
|
|
252
|
-
if (typeof window !==
|
|
253
|
-
window.addEventListener(
|
|
254
|
-
cleanupFns.push(() => window.removeEventListener(
|
|
254
|
+
if (typeof window !== "undefined") {
|
|
255
|
+
window.addEventListener("resize", updateDimensions);
|
|
256
|
+
cleanupFns.push(() => window.removeEventListener("resize", updateDimensions));
|
|
255
257
|
}
|
|
256
258
|
return () => {
|
|
257
259
|
cleanupFns.forEach((cleanup) => cleanup());
|
|
@@ -275,14 +277,14 @@ const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align
|
|
|
275
277
|
};
|
|
276
278
|
updateCursorDimensions();
|
|
277
279
|
const cleanupFns = [];
|
|
278
|
-
if (typeof ResizeObserver !==
|
|
280
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
279
281
|
const observer = new ResizeObserver(updateCursorDimensions);
|
|
280
282
|
observer.observe(cursorElement);
|
|
281
283
|
cleanupFns.push(() => observer.disconnect());
|
|
282
284
|
}
|
|
283
|
-
if (typeof window !==
|
|
284
|
-
window.addEventListener(
|
|
285
|
-
cleanupFns.push(() => window.removeEventListener(
|
|
285
|
+
if (typeof window !== "undefined") {
|
|
286
|
+
window.addEventListener("resize", updateCursorDimensions);
|
|
287
|
+
cleanupFns.push(() => window.removeEventListener("resize", updateCursorDimensions));
|
|
286
288
|
}
|
|
287
289
|
return () => {
|
|
288
290
|
cleanupFns.forEach((cleanup) => cleanup());
|
|
@@ -311,13 +313,14 @@ const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align
|
|
|
311
313
|
]);
|
|
312
314
|
// Determine content based on variant
|
|
313
315
|
const renderContent = () => {
|
|
314
|
-
if (variant ===
|
|
315
|
-
return (jsxs(Fragment, { children: [avatar && jsx(Avatar, { src: avatar,
|
|
316
|
+
if (variant === "user") {
|
|
317
|
+
return (jsxs(Fragment, { children: [avatar && jsx(Avatar, { src: avatar, name: name || "User", size: "xs" }), name && (jsx("span", { className: "text-white text-sm font-medium whitespace-nowrap", children: name }))] }));
|
|
316
318
|
}
|
|
317
319
|
return children;
|
|
318
320
|
};
|
|
319
|
-
return (jsx(AnimatePresence, { children: isActive && (jsx(motion.div, { ref: cursorFollowRef, "data-slot": "custom-cursor-follow", className: cn(customCursorTheme.baseStyle, customCursorTheme.cursorFollowVariants[variant], variant ===
|
|
321
|
+
return (jsx(AnimatePresence, { children: isActive && (jsx(motion.div, { ref: cursorFollowRef, "data-slot": "custom-cursor-follow", className: cn(customCursorTheme.baseStyle, customCursorTheme.cursorFollowVariants[variant], variant === "user" &&
|
|
322
|
+
customCursorTheme.cursorFollowColors[resolvedColor], className), style: { top: springY, left: springX, ...style }, variants: customCursorVariants, initial: "initial", animate: "animate", exit: "exit", role: "presentation", "aria-hidden": "true", ...props, children: renderContent() })) }));
|
|
320
323
|
});
|
|
321
|
-
CustomCursorFollow.displayName =
|
|
324
|
+
CustomCursorFollow.displayName = "CustomCursorFollow";
|
|
322
325
|
|
|
323
326
|
export { CustomCursor, CustomCursorFollow, CustomCursorProvider, useCustomCursor };
|