create-mcp-use-app 2.0.0-beta.3 → 2.0.0-beta.5
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/README.md +68 -37
- package/dist/index.js +10 -8
- package/dist/templates/blank/README.md +1 -1
- package/dist/templates/blank/tsconfig.json +2 -1
- package/dist/templates/mcp-apps/README.md +1 -1
- package/dist/templates/mcp-apps/index.ts +71 -101
- package/dist/templates/mcp-apps/mcp-env.d.ts +1 -1
- package/dist/templates/mcp-apps/public/logo-mcp-use.svg +8 -0
- package/dist/templates/mcp-apps/tsconfig.json +2 -1
- package/dist/templates/mcp-apps/views/my-view/MeshGradient.tsx +299 -0
- package/dist/templates/mcp-apps/views/my-view/Tooltip.tsx +75 -0
- package/dist/templates/mcp-apps/views/my-view/icons.tsx +142 -0
- package/dist/templates/mcp-apps/views/my-view/view.css +5 -0
- package/dist/templates/mcp-apps/views/my-view/view.tsx +396 -0
- package/dist/templates/{starter → mcp-server}/README.md +2 -2
- package/dist/templates/{starter → mcp-server}/index.ts +0 -18
- package/dist/templates/{starter → mcp-server}/tsconfig.json +2 -1
- package/package.json +2 -2
- package/dist/templates/mcp-apps/public/fruits/apple.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/apricot.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/avocado.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/banana.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/blueberry.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/cherries.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/coconut.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/grapes.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/lemon.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/mango.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/orange.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/pear.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/pineapple.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/plum.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/strawberry.webp +0 -0
- package/dist/templates/mcp-apps/public/fruits/watermelon.webp +0 -0
- package/dist/templates/mcp-apps/views/product-search-result/components/Accordion.tsx +0 -35
- package/dist/templates/mcp-apps/views/product-search-result/components/AccordionItem.tsx +0 -35
- package/dist/templates/mcp-apps/views/product-search-result/components/Carousel.tsx +0 -52
- package/dist/templates/mcp-apps/views/product-search-result/components/CarouselItem.tsx +0 -91
- package/dist/templates/mcp-apps/views/product-search-result/components/CarouselSkeleton.tsx +0 -18
- package/dist/templates/mcp-apps/views/product-search-result/hooks/useCarouselAnimation.ts +0 -72
- package/dist/templates/mcp-apps/views/product-search-result/view.css +0 -81
- package/dist/templates/mcp-apps/views/product-search-result/view.tsx +0 -371
- /package/dist/templates/{starter → mcp-server}/gitignore +0 -0
- /package/dist/templates/{starter → mcp-server}/package.json +0 -0
- /package/dist/templates/{starter → mcp-server}/public/icon.svg +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
// Hero mesh palette (light landing surfaces)
|
|
4
|
+
const MESH_COLORS = ["#e0eaff", "#f9ffbd", "#dedede", "#ffffff"];
|
|
5
|
+
const HERO_MESH_SPEED = 1.15;
|
|
6
|
+
const HERO_MESH_SWIRL = 0.95;
|
|
7
|
+
const ORB_MAX_WIDTH_PX = 800;
|
|
8
|
+
|
|
9
|
+
const VERT = `#version 300 es
|
|
10
|
+
precision mediump float;
|
|
11
|
+
in vec4 a_position;
|
|
12
|
+
uniform vec2 u_resolution;
|
|
13
|
+
out vec2 v_objectUV;
|
|
14
|
+
void main(){
|
|
15
|
+
gl_Position=a_position;
|
|
16
|
+
vec2 uv=a_position.xy*0.5;
|
|
17
|
+
float box=min(u_resolution.x,u_resolution.y);
|
|
18
|
+
vec2 scale=box>0.0?u_resolution/box:vec2(1.);
|
|
19
|
+
v_objectUV=uv*scale;
|
|
20
|
+
}`;
|
|
21
|
+
|
|
22
|
+
const FRAG = `#version 300 es
|
|
23
|
+
precision mediump float;
|
|
24
|
+
uniform float u_time;
|
|
25
|
+
uniform vec4 u_colors[4];
|
|
26
|
+
uniform float u_colorsCount;
|
|
27
|
+
uniform float u_distortion;
|
|
28
|
+
uniform float u_swirl;
|
|
29
|
+
uniform float u_grainMixer;
|
|
30
|
+
uniform float u_grainOverlay;
|
|
31
|
+
in vec2 v_objectUV;
|
|
32
|
+
out vec4 fragColor;
|
|
33
|
+
vec2 rotate(vec2 uv,float th){return mat2(cos(th),sin(th),-sin(th),cos(th))*uv;}
|
|
34
|
+
float hash21(vec2 p){
|
|
35
|
+
p=fract(p*vec2(0.3183099,0.3678794))+0.1;
|
|
36
|
+
p+=dot(p,p+19.19);
|
|
37
|
+
return fract(p.x*p.y);
|
|
38
|
+
}
|
|
39
|
+
float valueNoise(vec2 st){
|
|
40
|
+
vec2 i=floor(st);vec2 f=fract(st);
|
|
41
|
+
float a=hash21(i),b=hash21(i+vec2(1.,0.)),c=hash21(i+vec2(0.,1.)),d=hash21(i+vec2(1.,1.));
|
|
42
|
+
vec2 u=f*f*(3.-2.*f);
|
|
43
|
+
return mix(mix(a,b,u.x),mix(c,d,u.x),u.y);
|
|
44
|
+
}
|
|
45
|
+
vec2 getPosition(int i,float t){
|
|
46
|
+
float a=float(i)*.37,b=.6+fract(float(i)/3.)*.9,c=.8+fract(float(i+1)/4.);
|
|
47
|
+
float x=sin(t*b+a),y=cos(t*c+a*1.5);
|
|
48
|
+
return .5+.5*vec2(x,y);
|
|
49
|
+
}
|
|
50
|
+
void main(){
|
|
51
|
+
vec2 uv=v_objectUV;uv+=.5;
|
|
52
|
+
vec2 grainUV=uv*1000.;
|
|
53
|
+
float grain=valueNoise(grainUV);
|
|
54
|
+
float mixerGrain=.4*u_grainMixer*(grain-.5);
|
|
55
|
+
float t=.5*(u_time+41.5);
|
|
56
|
+
float radius=smoothstep(0.,1.,length(uv-.5));
|
|
57
|
+
float center=1.-radius;
|
|
58
|
+
for(float i=1.;i<=2.;i++){
|
|
59
|
+
uv.x+=u_distortion*center/i*sin(t+i*.4*smoothstep(0.,1.,uv.y))*cos(.2*t+i*2.4*smoothstep(0.,1.,uv.y));
|
|
60
|
+
uv.y+=u_distortion*center/i*cos(t+i*2.*smoothstep(0.,1.,uv.x));
|
|
61
|
+
}
|
|
62
|
+
vec2 uvR=uv-vec2(.5);
|
|
63
|
+
float angle=3.*u_swirl*radius;
|
|
64
|
+
uvR=rotate(uvR,-angle);uvR+=vec2(.5);
|
|
65
|
+
vec3 color=vec3(0.);float opacity=0.,totalWeight=0.;
|
|
66
|
+
for(int i=0;i<4;i++){
|
|
67
|
+
if(i>=int(u_colorsCount))break;
|
|
68
|
+
vec2 pos=getPosition(i,t)+mixerGrain;
|
|
69
|
+
vec3 cf=u_colors[i].rgb*u_colors[i].a;
|
|
70
|
+
float opacityF=u_colors[i].a;
|
|
71
|
+
float dist=length(uvR-pos);
|
|
72
|
+
dist=pow(dist,3.5);
|
|
73
|
+
float w=1./(dist+1e-3);
|
|
74
|
+
color+=cf*w;opacity+=opacityF*w;totalWeight+=w;
|
|
75
|
+
}
|
|
76
|
+
color/=max(1e-4,totalWeight);
|
|
77
|
+
opacity/=max(1e-4,totalWeight);
|
|
78
|
+
float grainO=valueNoise(rotate(grainUV,1.)+vec2(3.));
|
|
79
|
+
grainO=mix(grainO,valueNoise(rotate(grainUV,2.)+vec2(-1.)),.5);
|
|
80
|
+
grainO=pow(grainO,1.3);
|
|
81
|
+
float grainOV=grainO*2.-1.;
|
|
82
|
+
vec3 grainOC=vec3(step(0.,grainOV));
|
|
83
|
+
float grainOS=u_grainOverlay*abs(grainOV);
|
|
84
|
+
grainOS=pow(grainOS,.8);
|
|
85
|
+
color=mix(color,grainOC,.35*grainOS);
|
|
86
|
+
opacity+=.5*grainOS;
|
|
87
|
+
fragColor=vec4(color,clamp(opacity,0.,1.));
|
|
88
|
+
}`;
|
|
89
|
+
|
|
90
|
+
function hexToRgba(hex: string): [number, number, number, number] {
|
|
91
|
+
return [
|
|
92
|
+
parseInt(hex.slice(1, 3), 16) / 255,
|
|
93
|
+
parseInt(hex.slice(3, 5), 16) / 255,
|
|
94
|
+
parseInt(hex.slice(5, 7), 16) / 255,
|
|
95
|
+
1,
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** WebGL2 mesh gradient canvas (self-contained; no external deps). */
|
|
100
|
+
function MeshGradientCanvas({
|
|
101
|
+
className,
|
|
102
|
+
colors = MESH_COLORS,
|
|
103
|
+
distortion = 0.8,
|
|
104
|
+
swirl = 0.1,
|
|
105
|
+
grainMixer = 0,
|
|
106
|
+
grainOverlay = 0.2,
|
|
107
|
+
speed = 1,
|
|
108
|
+
}: {
|
|
109
|
+
className?: string;
|
|
110
|
+
colors?: string[];
|
|
111
|
+
distortion?: number;
|
|
112
|
+
swirl?: number;
|
|
113
|
+
grainMixer?: number;
|
|
114
|
+
grainOverlay?: number;
|
|
115
|
+
speed?: number;
|
|
116
|
+
}) {
|
|
117
|
+
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
118
|
+
const wrapRef = useRef<HTMLDivElement>(null);
|
|
119
|
+
const propsRef = useRef({
|
|
120
|
+
colors,
|
|
121
|
+
distortion,
|
|
122
|
+
swirl,
|
|
123
|
+
grainMixer,
|
|
124
|
+
grainOverlay,
|
|
125
|
+
speed,
|
|
126
|
+
});
|
|
127
|
+
propsRef.current = {
|
|
128
|
+
colors,
|
|
129
|
+
distortion,
|
|
130
|
+
swirl,
|
|
131
|
+
grainMixer,
|
|
132
|
+
grainOverlay,
|
|
133
|
+
speed,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
const canvas = canvasRef.current;
|
|
138
|
+
const wrap = wrapRef.current;
|
|
139
|
+
if (!canvas || !wrap) return;
|
|
140
|
+
|
|
141
|
+
const gl = canvas.getContext("webgl2");
|
|
142
|
+
if (!gl) return;
|
|
143
|
+
|
|
144
|
+
const compileShader = (type: number, src: string) => {
|
|
145
|
+
const shader = gl.createShader(type);
|
|
146
|
+
if (!shader) return null;
|
|
147
|
+
gl.shaderSource(shader, src);
|
|
148
|
+
gl.compileShader(shader);
|
|
149
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
150
|
+
console.error(gl.getShaderInfoLog(shader));
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
return shader;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const vs = compileShader(gl.VERTEX_SHADER, VERT);
|
|
157
|
+
const fs = compileShader(gl.FRAGMENT_SHADER, FRAG);
|
|
158
|
+
if (!vs || !fs) return;
|
|
159
|
+
|
|
160
|
+
const prog = gl.createProgram();
|
|
161
|
+
if (!prog) return;
|
|
162
|
+
gl.attachShader(prog, vs);
|
|
163
|
+
gl.attachShader(prog, fs);
|
|
164
|
+
gl.linkProgram(prog);
|
|
165
|
+
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
|
|
166
|
+
console.error(gl.getProgramInfoLog(prog));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
gl.useProgram(prog);
|
|
170
|
+
|
|
171
|
+
const posLoc = gl.getAttribLocation(prog, "a_position");
|
|
172
|
+
const buf = gl.createBuffer();
|
|
173
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
174
|
+
gl.bufferData(
|
|
175
|
+
gl.ARRAY_BUFFER,
|
|
176
|
+
new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),
|
|
177
|
+
gl.STATIC_DRAW
|
|
178
|
+
);
|
|
179
|
+
gl.enableVertexAttribArray(posLoc);
|
|
180
|
+
gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
|
|
181
|
+
|
|
182
|
+
const uTime = gl.getUniformLocation(prog, "u_time");
|
|
183
|
+
const uResolution = gl.getUniformLocation(prog, "u_resolution");
|
|
184
|
+
const uColors = [0, 1, 2, 3].map((i) =>
|
|
185
|
+
gl.getUniformLocation(prog, `u_colors[${i}]`)
|
|
186
|
+
);
|
|
187
|
+
const uColorsCount = gl.getUniformLocation(prog, "u_colorsCount");
|
|
188
|
+
const uDistortion = gl.getUniformLocation(prog, "u_distortion");
|
|
189
|
+
const uSwirl = gl.getUniformLocation(prog, "u_swirl");
|
|
190
|
+
const uGrainMixer = gl.getUniformLocation(prog, "u_grainMixer");
|
|
191
|
+
const uGrainOverlay = gl.getUniformLocation(prog, "u_grainOverlay");
|
|
192
|
+
|
|
193
|
+
let frameMs = 0;
|
|
194
|
+
let lastNow = performance.now();
|
|
195
|
+
let raf = 0;
|
|
196
|
+
|
|
197
|
+
const resize = () => {
|
|
198
|
+
const dpr = Math.min(2, window.devicePixelRatio || 1);
|
|
199
|
+
canvas.width = Math.floor(wrap.clientWidth * dpr);
|
|
200
|
+
canvas.height = Math.floor(wrap.clientHeight * dpr);
|
|
201
|
+
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const draw = (now: number) => {
|
|
205
|
+
if (document.hidden) {
|
|
206
|
+
lastNow = now;
|
|
207
|
+
raf = requestAnimationFrame(draw);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const {
|
|
211
|
+
colors: currentColors,
|
|
212
|
+
distortion: currentDistortion,
|
|
213
|
+
swirl: currentSwirl,
|
|
214
|
+
grainMixer: currentGrainMixer,
|
|
215
|
+
grainOverlay: currentGrainOverlay,
|
|
216
|
+
speed: currentSpeed,
|
|
217
|
+
} = propsRef.current;
|
|
218
|
+
const dt = now - lastNow;
|
|
219
|
+
lastNow = now;
|
|
220
|
+
frameMs += dt * currentSpeed;
|
|
221
|
+
const rgbaColors = currentColors.map(hexToRgba);
|
|
222
|
+
gl.uniform1f(uTime, frameMs * 1e-3);
|
|
223
|
+
gl.uniform2f(uResolution, canvas.width, canvas.height);
|
|
224
|
+
for (let i = 0; i < 4; i++) {
|
|
225
|
+
const loc = uColors[i];
|
|
226
|
+
if (loc) gl.uniform4fv(loc, rgbaColors[i] ?? [1, 1, 1, 1]);
|
|
227
|
+
}
|
|
228
|
+
gl.uniform1f(uColorsCount, rgbaColors.length);
|
|
229
|
+
gl.uniform1f(uDistortion, currentDistortion);
|
|
230
|
+
gl.uniform1f(uSwirl, currentSwirl);
|
|
231
|
+
gl.uniform1f(uGrainMixer, currentGrainMixer);
|
|
232
|
+
gl.uniform1f(uGrainOverlay, currentGrainOverlay);
|
|
233
|
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
234
|
+
raf = requestAnimationFrame(draw);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
resize();
|
|
238
|
+
const ro = new ResizeObserver(resize);
|
|
239
|
+
ro.observe(wrap);
|
|
240
|
+
raf = requestAnimationFrame(draw);
|
|
241
|
+
|
|
242
|
+
return () => {
|
|
243
|
+
cancelAnimationFrame(raf);
|
|
244
|
+
ro.disconnect();
|
|
245
|
+
};
|
|
246
|
+
}, []);
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<div ref={wrapRef} className={className}>
|
|
250
|
+
<canvas ref={canvasRef} className="h-full w-full" aria-hidden />
|
|
251
|
+
</div>
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function MeshOrbContent() {
|
|
256
|
+
return (
|
|
257
|
+
<>
|
|
258
|
+
<div className="absolute inset-0 bg-[#edf2ff]" />
|
|
259
|
+
<MeshGradientCanvas
|
|
260
|
+
className="absolute inset-0 h-full w-full"
|
|
261
|
+
colors={MESH_COLORS}
|
|
262
|
+
distortion={0.8}
|
|
263
|
+
swirl={HERO_MESH_SWIRL}
|
|
264
|
+
grainMixer={0}
|
|
265
|
+
grainOverlay={0.3}
|
|
266
|
+
speed={HERO_MESH_SPEED}
|
|
267
|
+
/>
|
|
268
|
+
</>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Mesh disc peeking from the bottom — 80% of card width, capped at 800px. */
|
|
273
|
+
export function HeroMeshOrb({ flow = false }: { flow?: boolean }) {
|
|
274
|
+
if (flow) {
|
|
275
|
+
return (
|
|
276
|
+
<div
|
|
277
|
+
className="relative z-0 mt-2 w-full overflow-hidden pb-[22%]"
|
|
278
|
+
aria-hidden
|
|
279
|
+
>
|
|
280
|
+
<div
|
|
281
|
+
className="absolute bottom-0 left-1/2 aspect-square w-full -translate-x-1/2 translate-y-[78%] overflow-hidden rounded-full opacity-90"
|
|
282
|
+
style={{ maxWidth: ORB_MAX_WIDTH_PX }}
|
|
283
|
+
>
|
|
284
|
+
<MeshOrbContent />
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return (
|
|
291
|
+
<div
|
|
292
|
+
className="pointer-events-none absolute bottom-0 left-1/2 z-0 aspect-square w-[80%] -translate-x-1/2 translate-y-[78%] overflow-hidden rounded-full opacity-90"
|
|
293
|
+
style={{ maxWidth: ORB_MAX_WIDTH_PX }}
|
|
294
|
+
aria-hidden
|
|
295
|
+
>
|
|
296
|
+
<MeshOrbContent />
|
|
297
|
+
</div>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { useRef, useState, type ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/** Hover/focus tooltip clamped to the nearest [data-card-shell] ancestor. */
|
|
4
|
+
export function Tooltip({
|
|
5
|
+
label,
|
|
6
|
+
children,
|
|
7
|
+
multiline = false,
|
|
8
|
+
}: {
|
|
9
|
+
label: string;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
multiline?: boolean;
|
|
12
|
+
}) {
|
|
13
|
+
const wrapRef = useRef<HTMLSpanElement>(null);
|
|
14
|
+
const tipRef = useRef<HTMLSpanElement>(null);
|
|
15
|
+
const [open, setOpen] = useState(false);
|
|
16
|
+
const [pos, setPos] = useState({ left: 0, maxWidth: 320 });
|
|
17
|
+
|
|
18
|
+
const show = () => {
|
|
19
|
+
const wrap = wrapRef.current;
|
|
20
|
+
const tip = tipRef.current;
|
|
21
|
+
const card = wrap?.closest("[data-card-shell]");
|
|
22
|
+
if (!wrap || !tip || !card) {
|
|
23
|
+
setOpen(true);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const pad = 12;
|
|
27
|
+
const cardR = card.getBoundingClientRect();
|
|
28
|
+
const wrapR = wrap.getBoundingClientRect();
|
|
29
|
+
const maxWidth = Math.min(320, Math.max(160, cardR.width - pad * 2));
|
|
30
|
+
Object.assign(tip.style, {
|
|
31
|
+
maxWidth: `${maxWidth}px`,
|
|
32
|
+
visibility: "hidden",
|
|
33
|
+
opacity: "1",
|
|
34
|
+
});
|
|
35
|
+
const w = tip.offsetWidth;
|
|
36
|
+
tip.style.visibility = "";
|
|
37
|
+
tip.style.opacity = "";
|
|
38
|
+
const left =
|
|
39
|
+
Math.max(
|
|
40
|
+
cardR.left + pad,
|
|
41
|
+
Math.min(wrapR.left + wrapR.width / 2 - w / 2, cardR.right - pad - w)
|
|
42
|
+
) - wrapR.left;
|
|
43
|
+
setPos({ left, maxWidth });
|
|
44
|
+
setOpen(true);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<span
|
|
49
|
+
ref={wrapRef}
|
|
50
|
+
className="relative inline-flex"
|
|
51
|
+
onMouseEnter={show}
|
|
52
|
+
onMouseLeave={() => setOpen(false)}
|
|
53
|
+
onFocus={show}
|
|
54
|
+
onBlur={() => setOpen(false)}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
<span
|
|
58
|
+
ref={tipRef}
|
|
59
|
+
role="tooltip"
|
|
60
|
+
style={{
|
|
61
|
+
left: pos.left,
|
|
62
|
+
maxWidth: pos.maxWidth,
|
|
63
|
+
opacity: open ? 1 : 0,
|
|
64
|
+
}}
|
|
65
|
+
className={`pointer-events-none absolute top-full z-30 mt-1.5 w-max rounded-lg bg-zinc-900 px-3 py-2 text-[11px] font-medium text-white transition-opacity duration-200 dark:bg-zinc-800 dark:text-neutral-100 ${
|
|
66
|
+
multiline
|
|
67
|
+
? "whitespace-normal text-left leading-snug"
|
|
68
|
+
: "whitespace-nowrap"
|
|
69
|
+
}`}
|
|
70
|
+
>
|
|
71
|
+
{label}
|
|
72
|
+
</span>
|
|
73
|
+
</span>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
export function ExpandIcon() {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
width="14"
|
|
5
|
+
height="14"
|
|
6
|
+
viewBox="0 0 24 24"
|
|
7
|
+
fill="none"
|
|
8
|
+
stroke="currentColor"
|
|
9
|
+
strokeWidth="2"
|
|
10
|
+
aria-hidden
|
|
11
|
+
>
|
|
12
|
+
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" />
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function PipIcon() {
|
|
18
|
+
return (
|
|
19
|
+
<svg
|
|
20
|
+
width="14"
|
|
21
|
+
height="14"
|
|
22
|
+
viewBox="0 0 24 24"
|
|
23
|
+
fill="none"
|
|
24
|
+
stroke="currentColor"
|
|
25
|
+
strokeWidth="2"
|
|
26
|
+
aria-hidden
|
|
27
|
+
>
|
|
28
|
+
<rect x="2" y="4" width="20" height="14" rx="2" />
|
|
29
|
+
<rect x="13" y="11" width="7" height="5" rx="1" fill="currentColor" />
|
|
30
|
+
</svg>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function CloseIcon() {
|
|
35
|
+
return (
|
|
36
|
+
<svg
|
|
37
|
+
width="14"
|
|
38
|
+
height="14"
|
|
39
|
+
viewBox="0 0 24 24"
|
|
40
|
+
fill="none"
|
|
41
|
+
stroke="currentColor"
|
|
42
|
+
strokeWidth="2"
|
|
43
|
+
aria-hidden
|
|
44
|
+
>
|
|
45
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
46
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
47
|
+
</svg>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function SunIcon() {
|
|
52
|
+
return (
|
|
53
|
+
<svg
|
|
54
|
+
width="14"
|
|
55
|
+
height="14"
|
|
56
|
+
viewBox="0 0 24 24"
|
|
57
|
+
fill="none"
|
|
58
|
+
stroke="currentColor"
|
|
59
|
+
strokeWidth="2"
|
|
60
|
+
strokeLinecap="round"
|
|
61
|
+
strokeLinejoin="round"
|
|
62
|
+
aria-hidden
|
|
63
|
+
>
|
|
64
|
+
<circle cx="12" cy="12" r="4" />
|
|
65
|
+
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" />
|
|
66
|
+
</svg>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function MoonIcon() {
|
|
71
|
+
return (
|
|
72
|
+
<svg
|
|
73
|
+
width="14"
|
|
74
|
+
height="14"
|
|
75
|
+
viewBox="0 0 24 24"
|
|
76
|
+
fill="none"
|
|
77
|
+
stroke="currentColor"
|
|
78
|
+
strokeWidth="2"
|
|
79
|
+
strokeLinecap="round"
|
|
80
|
+
strokeLinejoin="round"
|
|
81
|
+
aria-hidden
|
|
82
|
+
>
|
|
83
|
+
<path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401" />
|
|
84
|
+
</svg>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function SmartphoneIcon() {
|
|
89
|
+
return (
|
|
90
|
+
<svg
|
|
91
|
+
width="14"
|
|
92
|
+
height="14"
|
|
93
|
+
viewBox="0 0 24 24"
|
|
94
|
+
fill="none"
|
|
95
|
+
stroke="currentColor"
|
|
96
|
+
strokeWidth="2"
|
|
97
|
+
strokeLinecap="round"
|
|
98
|
+
strokeLinejoin="round"
|
|
99
|
+
aria-hidden
|
|
100
|
+
>
|
|
101
|
+
<rect width="14" height="20" x="5" y="2" rx="2" ry="2" />
|
|
102
|
+
<path d="M12 18h.01" />
|
|
103
|
+
</svg>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function MonitorIcon() {
|
|
108
|
+
return (
|
|
109
|
+
<svg
|
|
110
|
+
width="14"
|
|
111
|
+
height="14"
|
|
112
|
+
viewBox="0 0 24 24"
|
|
113
|
+
fill="none"
|
|
114
|
+
stroke="currentColor"
|
|
115
|
+
strokeWidth="2"
|
|
116
|
+
strokeLinecap="round"
|
|
117
|
+
strokeLinejoin="round"
|
|
118
|
+
aria-hidden
|
|
119
|
+
>
|
|
120
|
+
<rect width="20" height="14" x="2" y="3" rx="2" />
|
|
121
|
+
<path d="M8 21h8M12 17v4" />
|
|
122
|
+
</svg>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function ExternalLinkIcon() {
|
|
127
|
+
return (
|
|
128
|
+
<svg
|
|
129
|
+
width="12"
|
|
130
|
+
height="12"
|
|
131
|
+
viewBox="0 0 24 24"
|
|
132
|
+
fill="none"
|
|
133
|
+
stroke="currentColor"
|
|
134
|
+
strokeWidth="2"
|
|
135
|
+
aria-hidden
|
|
136
|
+
>
|
|
137
|
+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
|
|
138
|
+
<polyline points="15 3 21 3 21 9" />
|
|
139
|
+
<line x1="10" y1="14" x2="21" y2="3" />
|
|
140
|
+
</svg>
|
|
141
|
+
);
|
|
142
|
+
}
|