@nous-research/ui 0.3.0 → 0.4.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/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -6
- package/dist/index.js.map +1 -1
- package/dist/ui/components/command-block.d.ts +25 -0
- package/dist/ui/components/command-block.d.ts.map +1 -0
- package/dist/ui/components/command-block.js +27 -0
- package/dist/ui/components/command-block.js.map +1 -0
- package/dist/ui/components/icons/hamburger.d.ts +7 -0
- package/dist/ui/components/icons/hamburger.d.ts.map +1 -0
- package/dist/ui/components/icons/hamburger.js +6 -0
- package/dist/ui/components/icons/hamburger.js.map +1 -0
- package/dist/ui/components/icons/index.d.ts +1 -0
- package/dist/ui/components/icons/index.d.ts.map +1 -1
- package/dist/ui/components/icons/index.js +1 -0
- package/dist/ui/components/icons/index.js.map +1 -1
- package/dist/ui/components/image-distortion.d.ts +15 -0
- package/dist/ui/components/image-distortion.d.ts.map +1 -0
- package/dist/ui/components/image-distortion.js +278 -0
- package/dist/ui/components/image-distortion.js.map +1 -0
- package/dist/ui/components/terminal-demo.d.ts +33 -0
- package/dist/ui/components/terminal-demo.d.ts.map +1 -0
- package/dist/ui/components/terminal-demo.js +79 -0
- package/dist/ui/components/terminal-demo.js.map +1 -0
- package/dist/ui/components/theme-toggle.d.ts +7 -0
- package/dist/ui/components/theme-toggle.d.ts.map +1 -0
- package/dist/ui/components/theme-toggle.js +10 -0
- package/dist/ui/components/theme-toggle.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { BlendMode, useBlendMode, withBlendMode } from './ui/components/blend-mo
|
|
|
6
6
|
export type { BlendModeProps } from './ui/components/blend-mode';
|
|
7
7
|
export { Blink } from './ui/components/blink';
|
|
8
8
|
export { Button } from './ui/components/button';
|
|
9
|
+
export { CommandBlock, CopyButton } from './ui/components/command-block';
|
|
9
10
|
export { Cursor } from './ui/components/cursor';
|
|
10
11
|
export { DropdownMenu } from './ui/components/dropdown-menu';
|
|
11
12
|
export { FitText } from './ui/components/fit-text';
|
|
@@ -13,6 +14,7 @@ export { BarChart, LineChart } from './ui/components/graphs';
|
|
|
13
14
|
export { Cell, Grid } from './ui/components/grid';
|
|
14
15
|
export { HoverBg } from './ui/components/hover-bg';
|
|
15
16
|
export * as Icons from './ui/components/icons';
|
|
17
|
+
export { ImageDistortion } from './ui/components/image-distortion';
|
|
16
18
|
export { LevaClient } from './ui/components/leva-client';
|
|
17
19
|
export { Modal } from './ui/components/modal';
|
|
18
20
|
export { applyLens, LENSES, LENS_0, LENS_5I, toggleLens, $lightMode } from './ui/components/overlays';
|
|
@@ -23,6 +25,9 @@ export { SceneCanvas } from './ui/components/scene-canvas';
|
|
|
23
25
|
export { Scramble } from './ui/components/scramble';
|
|
24
26
|
export { SelectionSwitcher } from './ui/components/selection-switcher';
|
|
25
27
|
export { Stats } from './ui/components/stats';
|
|
28
|
+
export { TerminalDemo } from './ui/components/terminal-demo';
|
|
29
|
+
export type { TerminalDemoStep } from './ui/components/terminal-demo';
|
|
30
|
+
export { ThemeToggle } from './ui/components/theme-toggle';
|
|
26
31
|
export { TV } from './ui/components/tv';
|
|
27
32
|
export { Watchlist } from './ui/components/watchlist';
|
|
28
33
|
export { Typography } from './ui/components/typography';
|
|
@@ -42,5 +47,6 @@ export type { PolyComponent, PolyProps, PolyRef } from './utils';
|
|
|
42
47
|
export { hexToRgb, rgbToHex, colorDodge, colorMix } from './utils/color';
|
|
43
48
|
export { useCappedFrame } from './hooks/use-capped-frame';
|
|
44
49
|
export { useCssVarDims } from './hooks/use-css-var-dims';
|
|
50
|
+
export { $gpuTier, useGpuTier } from './hooks/use-gpu-tier';
|
|
45
51
|
export { useSmoothControls, getControlAtom, setControlValue } from './hooks/use-smooth-controls';
|
|
46
52
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// Components
|
|
2
1
|
export { AnimatedCount, useAnimatedCount } from './ui/components/animated-count';
|
|
3
2
|
export { AsciiSkeleton, Scramble as AsciiScramble } from './ui/components/ascii';
|
|
4
3
|
export { Badge } from './ui/components/badge';
|
|
@@ -6,6 +5,7 @@ export { NouseGirlBadge } from './ui/components/badges/nous-girl';
|
|
|
6
5
|
export { BlendMode, useBlendMode, withBlendMode } from './ui/components/blend-mode';
|
|
7
6
|
export { Blink } from './ui/components/blink';
|
|
8
7
|
export { Button } from './ui/components/button';
|
|
8
|
+
export { CommandBlock, CopyButton } from './ui/components/command-block';
|
|
9
9
|
export { Cursor } from './ui/components/cursor';
|
|
10
10
|
export { DropdownMenu } from './ui/components/dropdown-menu';
|
|
11
11
|
export { FitText } from './ui/components/fit-text';
|
|
@@ -13,6 +13,7 @@ export { BarChart, LineChart } from './ui/components/graphs';
|
|
|
13
13
|
export { Cell, Grid } from './ui/components/grid';
|
|
14
14
|
export { HoverBg } from './ui/components/hover-bg';
|
|
15
15
|
export * as Icons from './ui/components/icons';
|
|
16
|
+
export { ImageDistortion } from './ui/components/image-distortion';
|
|
16
17
|
export { LevaClient } from './ui/components/leva-client';
|
|
17
18
|
export { Modal } from './ui/components/modal';
|
|
18
19
|
export { applyLens, LENSES, LENS_0, LENS_5I, toggleLens, $lightMode } from './ui/components/overlays';
|
|
@@ -22,27 +23,25 @@ export { SceneCanvas } from './ui/components/scene-canvas';
|
|
|
22
23
|
export { Scramble } from './ui/components/scramble';
|
|
23
24
|
export { SelectionSwitcher } from './ui/components/selection-switcher';
|
|
24
25
|
export { Stats } from './ui/components/stats';
|
|
26
|
+
export { TerminalDemo } from './ui/components/terminal-demo';
|
|
27
|
+
export { ThemeToggle } from './ui/components/theme-toggle';
|
|
25
28
|
export { TV } from './ui/components/tv';
|
|
26
29
|
export { Watchlist } from './ui/components/watchlist';
|
|
27
|
-
// Typography
|
|
28
30
|
export { Typography } from './ui/components/typography';
|
|
29
31
|
export { H1 } from './ui/components/typography/h1';
|
|
30
32
|
export { H2 } from './ui/components/typography/h2';
|
|
31
33
|
export { Legend } from './ui/components/typography/legend';
|
|
32
34
|
export { Small } from './ui/components/typography/small';
|
|
33
|
-
// Layout
|
|
34
35
|
export { BasicPage } from './ui/basic-page';
|
|
35
36
|
export { Header } from './ui/header';
|
|
36
37
|
export { Footer } from './ui/footer';
|
|
37
38
|
export { LayoutWrapper } from './ui/layout-wrapper';
|
|
38
|
-
// Fonts
|
|
39
39
|
export { FONT_SANS, FONT_MONO, FONT_RULES_COMPRESSED, FONT_RULES_EXPANDED, FONT_MONDWEST } from './fonts';
|
|
40
|
-
// Utils
|
|
41
40
|
export { cn, clamp, smoothstep, hexToVec3, truncate, stripWpStyles } from './utils';
|
|
42
41
|
export { polyRef } from './utils';
|
|
43
42
|
export { hexToRgb, rgbToHex, colorDodge, colorMix } from './utils/color';
|
|
44
|
-
// Hooks
|
|
45
43
|
export { useCappedFrame } from './hooks/use-capped-frame';
|
|
46
44
|
export { useCssVarDims } from './hooks/use-css-var-dims';
|
|
45
|
+
export { $gpuTier, useGpuTier } from './hooks/use-gpu-tier';
|
|
47
46
|
export { useSmoothControls, getControlAtom, setControlValue } from './hooks/use-smooth-controls';
|
|
48
47
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { AnimatedCount, useAnimatedCount } from './ui/components/animated-count'\nexport { AsciiSkeleton, Scramble as AsciiScramble } from './ui/components/ascii'\nexport { Badge } from './ui/components/badge'\nexport { NouseGirlBadge } from './ui/components/badges/nous-girl'\nexport { BlendMode, useBlendMode, withBlendMode } from './ui/components/blend-mode'\nexport type { BlendModeProps } from './ui/components/blend-mode'\nexport { Blink } from './ui/components/blink'\nexport { Button } from './ui/components/button'\nexport { CommandBlock, CopyButton } from './ui/components/command-block'\nexport { Cursor } from './ui/components/cursor'\nexport { DropdownMenu } from './ui/components/dropdown-menu'\nexport { FitText } from './ui/components/fit-text'\nexport { BarChart, LineChart } from './ui/components/graphs'\nexport { Cell, Grid } from './ui/components/grid'\nexport { HoverBg } from './ui/components/hover-bg'\nexport * as Icons from './ui/components/icons'\nexport { ImageDistortion } from './ui/components/image-distortion'\nexport { LevaClient } from './ui/components/leva-client'\nexport { Modal } from './ui/components/modal'\nexport {\n applyLens,\n LENSES,\n LENS_0,\n LENS_5I,\n toggleLens,\n $lightMode\n} from './ui/components/overlays'\nexport { Overlays } from './ui/components/overlays'\nexport type { LensPreset } from './ui/components/overlays'\nexport { Progress } from './ui/components/progress'\nexport { SceneCanvas } from './ui/components/scene-canvas'\nexport { Scramble } from './ui/components/scramble'\nexport { SelectionSwitcher } from './ui/components/selection-switcher'\nexport { Stats } from './ui/components/stats'\nexport { TerminalDemo } from './ui/components/terminal-demo'\nexport type { TerminalDemoStep } from './ui/components/terminal-demo'\nexport { ThemeToggle } from './ui/components/theme-toggle'\nexport { TV } from './ui/components/tv'\nexport { Watchlist } from './ui/components/watchlist'\n\nexport { Typography } from './ui/components/typography'\nexport type { TypographyProps } from './ui/components/typography'\nexport { H1 } from './ui/components/typography/h1'\nexport { H2 } from './ui/components/typography/h2'\nexport { Legend } from './ui/components/typography/legend'\nexport { Small } from './ui/components/typography/small'\n\nexport { BasicPage } from './ui/basic-page'\nexport { Header } from './ui/header'\nexport { Footer } from './ui/footer'\nexport { LayoutWrapper } from './ui/layout-wrapper'\n\nexport {\n FONT_SANS,\n FONT_MONO,\n FONT_RULES_COMPRESSED,\n FONT_RULES_EXPANDED,\n FONT_MONDWEST\n} from './fonts'\n\nexport { cn, clamp, smoothstep, hexToVec3, truncate, stripWpStyles } from './utils'\nexport { polyRef } from './utils'\nexport type { PolyComponent, PolyProps, PolyRef } from './utils'\nexport { hexToRgb, rgbToHex, colorDodge, colorMix } from './utils/color'\n\nexport { useCappedFrame } from './hooks/use-capped-frame'\nexport { useCssVarDims } from './hooks/use-css-var-dims'\nexport { $gpuTier, useGpuTier } from './hooks/use-gpu-tier'\nexport {\n useSmoothControls,\n getControlAtom,\n setControlValue\n} from './hooks/use-smooth-controls'\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A "copy to clipboard" button that briefly shows a "Copied!" confirmation.
|
|
3
|
+
* Designed to sit alongside a short command string, not as a general button.
|
|
4
|
+
*/
|
|
5
|
+
export declare function CopyButton({ children, className, copiedLabel, label, resetDelayMs, text }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
/**
|
|
7
|
+
* A labeled, copy-able command (or code) display. Pairs `<CopyButton>` with
|
|
8
|
+
* a monospace code block. Used for install/setup instructions.
|
|
9
|
+
*/
|
|
10
|
+
export declare function CommandBlock({ className, code, label }: CommandBlockProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
interface CommandBlockProps {
|
|
12
|
+
className?: string;
|
|
13
|
+
code: string;
|
|
14
|
+
label: string;
|
|
15
|
+
}
|
|
16
|
+
interface CopyButtonProps {
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
className?: string;
|
|
19
|
+
copiedLabel?: string;
|
|
20
|
+
label?: string;
|
|
21
|
+
resetDelayMs?: number;
|
|
22
|
+
text: string;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=command-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-block.d.ts","sourceRoot":"","sources":["../../../src/ui/components/command-block.tsx"],"names":[],"mappings":"AAQA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,WAAuB,EACvB,KAAc,EACd,YAAmB,EACnB,IAAI,EACL,EAAE,eAAe,2CA0BjB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,iBAAiB,2CAmBzE;AAED,UAAU,iBAAiB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;CACb"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState } from 'react';
|
|
4
|
+
import { cn } from '../../utils';
|
|
5
|
+
import { Small } from './typography/small';
|
|
6
|
+
/**
|
|
7
|
+
* A "copy to clipboard" button that briefly shows a "Copied!" confirmation.
|
|
8
|
+
* Designed to sit alongside a short command string, not as a general button.
|
|
9
|
+
*/
|
|
10
|
+
export function CopyButton({ children, className, copiedLabel = 'Copied!', label = 'Copy', resetDelayMs = 2000, text }) {
|
|
11
|
+
const [copied, setCopied] = useState(false);
|
|
12
|
+
const handleCopy = useCallback(() => {
|
|
13
|
+
void navigator.clipboard.writeText(text).then(() => {
|
|
14
|
+
setCopied(true);
|
|
15
|
+
setTimeout(() => setCopied(false), resetDelayMs);
|
|
16
|
+
});
|
|
17
|
+
}, [resetDelayMs, text]);
|
|
18
|
+
return (_jsx("button", { className: cn('font-courier cursor-pointer border-none bg-transparent text-[0.6875rem]', 'tracking-widest uppercase', 'hover:text-midground tap-highlight-transparent transition-colors', 'flex items-center justify-center', copied ? 'text-midground' : 'text-current opacity-60', className), onClick: handleCopy, type: "button", children: children ?? (copied ? copiedLabel : label) }));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A labeled, copy-able command (or code) display. Pairs `<CopyButton>` with
|
|
22
|
+
* a monospace code block. Used for install/setup instructions.
|
|
23
|
+
*/
|
|
24
|
+
export function CommandBlock({ className, code, label }) {
|
|
25
|
+
return (_jsxs("div", { className: cn('flex flex-col gap-1', className), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Small, { className: "opacity-50", children: label }), _jsx(CopyButton, { text: code })] }), _jsx("div", { className: cn('bg-background/40 font-courier border border-current/20', 'px-3 py-2 text-[0.6875rem] leading-relaxed lowercase'), children: _jsx("code", { className: "break-all", children: code }) })] }));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=command-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-block.js","sourceRoot":"","sources":["../../../src/ui/components/command-block.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAE7C,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,WAAW,GAAG,SAAS,EACvB,KAAK,GAAG,MAAM,EACd,YAAY,GAAG,IAAI,EACnB,IAAI,EACY;IAChB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE3C,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;QAClC,KAAK,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACjD,SAAS,CAAC,IAAI,CAAC,CAAA;YACf,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAA;IAExB,OAAO,CACL,iBACE,SAAS,EAAE,EAAE,CACX,yEAAyE,EACzE,2BAA2B,EAC3B,kEAAkE,EAClE,kCAAkC,EAClC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,yBAAyB,EACrD,SAAS,CACV,EACD,OAAO,EAAE,UAAU,EACnB,IAAI,EAAC,QAAQ,YAEZ,QAAQ,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,GACpC,CACV,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAqB;IACxE,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,qBAAqB,EAAE,SAAS,CAAC,aAClD,eAAK,SAAS,EAAC,mCAAmC,aAChD,KAAC,KAAK,IAAC,SAAS,EAAC,YAAY,YAAE,KAAK,GAAS,EAE7C,KAAC,UAAU,IAAC,IAAI,EAAE,IAAI,GAAI,IACtB,EAEN,cACE,SAAS,EAAE,EAAE,CACX,wDAAwD,EACxD,sDAAsD,CACvD,YAED,eAAM,SAAS,EAAC,WAAW,YAAE,IAAI,GAAQ,GACrC,IACF,CACP,CAAA;AACH,CAAC","sourcesContent":["'use client'\n\nimport { useCallback, useState } from 'react'\n\nimport { cn } from '../../utils'\n\nimport { Small } from './typography/small'\n\n/**\n * A \"copy to clipboard\" button that briefly shows a \"Copied!\" confirmation.\n * Designed to sit alongside a short command string, not as a general button.\n */\nexport function CopyButton({\n children,\n className,\n copiedLabel = 'Copied!',\n label = 'Copy',\n resetDelayMs = 2000,\n text\n}: CopyButtonProps) {\n const [copied, setCopied] = useState(false)\n\n const handleCopy = useCallback(() => {\n void navigator.clipboard.writeText(text).then(() => {\n setCopied(true)\n setTimeout(() => setCopied(false), resetDelayMs)\n })\n }, [resetDelayMs, text])\n\n return (\n <button\n className={cn(\n 'font-courier cursor-pointer border-none bg-transparent text-[0.6875rem]',\n 'tracking-widest uppercase',\n 'hover:text-midground tap-highlight-transparent transition-colors',\n 'flex items-center justify-center',\n copied ? 'text-midground' : 'text-current opacity-60',\n className\n )}\n onClick={handleCopy}\n type=\"button\"\n >\n {children ?? (copied ? copiedLabel : label)}\n </button>\n )\n}\n\n/**\n * A labeled, copy-able command (or code) display. Pairs `<CopyButton>` with\n * a monospace code block. Used for install/setup instructions.\n */\nexport function CommandBlock({ className, code, label }: CommandBlockProps) {\n return (\n <div className={cn('flex flex-col gap-1', className)}>\n <div className=\"flex items-center justify-between\">\n <Small className=\"opacity-50\">{label}</Small>\n\n <CopyButton text={code} />\n </div>\n\n <div\n className={cn(\n 'bg-background/40 font-courier border border-current/20',\n 'px-3 py-2 text-[0.6875rem] leading-relaxed lowercase'\n )}\n >\n <code className=\"break-all\">{code}</code>\n </div>\n </div>\n )\n}\n\ninterface CommandBlockProps {\n className?: string\n code: string\n label: string\n}\n\ninterface CopyButtonProps {\n children?: React.ReactNode\n className?: string\n copiedLabel?: string\n label?: string\n resetDelayMs?: number\n text: string\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SVGProps } from 'react';
|
|
2
|
+
export declare function HamburgerIcon({ className, open, ...props }: HamburgerIconProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
interface HamburgerIconProps extends SVGProps<SVGSVGElement> {
|
|
4
|
+
open?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=hamburger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hamburger.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/icons/hamburger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAIrC,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,IAAY,EACZ,GAAG,KAAK,EACT,EAAE,kBAAkB,2CAuCpB;AAED,UAAU,kBAAmB,SAAQ,QAAQ,CAAC,aAAa,CAAC;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAA;CACf"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../../../utils';
|
|
3
|
+
export function HamburgerIcon({ className, open = false, ...props }) {
|
|
4
|
+
return (_jsxs("svg", { className: cn('size-5', className), fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeWidth: 1.5, viewBox: "0 0 24 24", ...props, children: [_jsx("line", { className: "origin-center transition-transform duration-200 ease-out", style: { transform: open ? 'rotate(45deg)' : 'translateY(-4px)' }, x1: 4, x2: 20, y1: 12, y2: 12 }), _jsx("line", { className: "transition-opacity duration-200 ease-out", style: { opacity: open ? 0 : 1 }, x1: 4, x2: 20, y1: 12, y2: 12 }), _jsx("line", { className: "origin-center transition-transform duration-200 ease-out", style: { transform: open ? 'rotate(-45deg)' : 'translateY(4px)' }, x1: 4, x2: 20, y1: 12, y2: 12 })] }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=hamburger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hamburger.js","sourceRoot":"","sources":["../../../../src/ui/components/icons/hamburger.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAA;AAEnC,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EACT,IAAI,GAAG,KAAK,EACZ,GAAG,KAAK,EACW;IACnB,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAClC,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,WAAW,EAAE,GAAG,EAChB,OAAO,EAAC,WAAW,KACf,KAAK,aAET,eACE,SAAS,EAAC,0DAA0D,EACpE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,kBAAkB,EAAE,EACjE,EAAE,EAAE,CAAC,EACL,EAAE,EAAE,EAAE,EACN,EAAE,EAAE,EAAE,EACN,EAAE,EAAE,EAAE,GACN,EAEF,eACE,SAAS,EAAC,0CAA0C,EACpD,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAChC,EAAE,EAAE,CAAC,EACL,EAAE,EAAE,EAAE,EACN,EAAE,EAAE,EAAE,EACN,EAAE,EAAE,EAAE,GACN,EAEF,eACE,SAAS,EAAC,0DAA0D,EACpE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,iBAAiB,EAAE,EACjE,EAAE,EAAE,CAAC,EACL,EAAE,EAAE,EAAE,EACN,EAAE,EAAE,EAAE,EACN,EAAE,EAAE,EAAE,GACN,IACE,CACP,CAAA;AACH,CAAC","sourcesContent":["import type { SVGProps } from 'react'\n\nimport { cn } from '../../../utils'\n\nexport function HamburgerIcon({\n className,\n open = false,\n ...props\n}: HamburgerIconProps) {\n return (\n <svg\n className={cn('size-5', className)}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth={1.5}\n viewBox=\"0 0 24 24\"\n {...props}\n >\n <line\n className=\"origin-center transition-transform duration-200 ease-out\"\n style={{ transform: open ? 'rotate(45deg)' : 'translateY(-4px)' }}\n x1={4}\n x2={20}\n y1={12}\n y2={12}\n />\n\n <line\n className=\"transition-opacity duration-200 ease-out\"\n style={{ opacity: open ? 0 : 1 }}\n x1={4}\n x2={20}\n y1={12}\n y2={12}\n />\n\n <line\n className=\"origin-center transition-transform duration-200 ease-out\"\n style={{ transform: open ? 'rotate(-45deg)' : 'translateY(4px)' }}\n x1={4}\n x2={20}\n y1={12}\n y2={12}\n />\n </svg>\n )\n}\n\ninterface HamburgerIconProps extends SVGProps<SVGSVGElement> {\n open?: boolean\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/icons/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/icons/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/ui/components/icons/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA","sourcesContent":["export * from './arrow'\nexport * from './chevron'\nexport * from './eye'\nexport * from './gear'\nexport * from './heart'\nexport * from './link'\nexport * from './minus'\nexport * from './search'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/ui/components/icons/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA","sourcesContent":["export * from './arrow'\nexport * from './chevron'\nexport * from './eye'\nexport * from './gear'\nexport * from './hamburger'\nexport * from './heart'\nexport * from './link'\nexport * from './minus'\nexport * from './search'\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare function ImageDistortion({ active, className, fallbackClassName, src, style, tint, tintStrength }: ImageDistortionProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
interface ImageDistortionProps {
|
|
3
|
+
active?: boolean;
|
|
4
|
+
className?: string;
|
|
5
|
+
fallbackClassName?: string;
|
|
6
|
+
src: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
tint?: string;
|
|
9
|
+
tintStrength?: {
|
|
10
|
+
active: number;
|
|
11
|
+
inactive: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=image-distortion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-distortion.d.ts","sourceRoot":"","sources":["../../../src/ui/components/image-distortion.tsx"],"names":[],"mappings":"AAoGA,wBAAgB,eAAe,CAAC,EAC9B,MAAa,EACb,SAAS,EACT,iBAAiB,EACjB,GAAG,EACH,KAAK,EACL,IAAI,EACJ,YAAY,EACb,EAAE,oBAAoB,2CA4QtB;AAED,UAAU,oBAAoB;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CACpD"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { useGpuTier } from '../../hooks/use-gpu-tier';
|
|
5
|
+
import { cn, hexToRgb } from '../../utils';
|
|
6
|
+
const NUM_BANDS = 12;
|
|
7
|
+
const VERT = `attribute vec2 a;varying vec2 vUv;void main(){vUv=vec2(a.x*.5+.5,.5-a.y*.5);gl_Position=vec4(a,0,1);}`;
|
|
8
|
+
const FRAG = `precision highp float;
|
|
9
|
+
uniform float t;
|
|
10
|
+
uniform vec2 r,imgSize,vel;
|
|
11
|
+
uniform sampler2D tex;
|
|
12
|
+
uniform float bands[${NUM_BANDS}];
|
|
13
|
+
uniform vec3 tint;
|
|
14
|
+
uniform float tintStrength;
|
|
15
|
+
varying vec2 vUv;
|
|
16
|
+
|
|
17
|
+
float h(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}
|
|
18
|
+
|
|
19
|
+
// cover-style UV: crops the image to fill the canvas, centered
|
|
20
|
+
vec2 coverUV(vec2 uv){
|
|
21
|
+
float canvasAspect=r.x/r.y;
|
|
22
|
+
float imgAspect=imgSize.x/imgSize.y;
|
|
23
|
+
vec2 scale=canvasAspect>imgAspect
|
|
24
|
+
?vec2(1.0,imgAspect/canvasAspect)
|
|
25
|
+
:vec2(canvasAspect/imgAspect,1.0);
|
|
26
|
+
return(uv-0.5)*scale+0.5;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void main(){
|
|
30
|
+
vec2 uv=coverUV(vUv);
|
|
31
|
+
float scanY=floor(vUv.y*r.y);
|
|
32
|
+
|
|
33
|
+
float bandF=vUv.y*${NUM_BANDS}.0;
|
|
34
|
+
int bandIdx=int(floor(bandF));
|
|
35
|
+
float bandFrac=fract(bandF);
|
|
36
|
+
|
|
37
|
+
float strength=0.0;
|
|
38
|
+
for(int i=0;i<${NUM_BANDS};i++){
|
|
39
|
+
if(i==bandIdx) strength=bands[i];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
float neighborStr=0.0;
|
|
43
|
+
int neighborIdx=bandFrac>.5?bandIdx+1:bandIdx-1;
|
|
44
|
+
for(int i=0;i<${NUM_BANDS};i++){
|
|
45
|
+
if(i==neighborIdx) neighborStr=bands[i];
|
|
46
|
+
}
|
|
47
|
+
float edgeBlend=abs(bandFrac-.5)*2.0;
|
|
48
|
+
edgeBlend*=edgeBlend;
|
|
49
|
+
strength=mix(strength,neighborStr,edgeBlend*.3);
|
|
50
|
+
|
|
51
|
+
float speed=length(vel);
|
|
52
|
+
float dirBlend=smoothstep(0.0,0.02,speed);
|
|
53
|
+
vec2 dir=speed>.0001?vel/speed:vec2(0);
|
|
54
|
+
dir*=dirBlend;
|
|
55
|
+
|
|
56
|
+
float rowSeed=h(vec2(scanY,floor(t*3.)+float(bandIdx)*7.));
|
|
57
|
+
float rowVar=mix(.4,1.0,rowSeed);
|
|
58
|
+
|
|
59
|
+
float ySmooth=vUv.y*6.0+t*0.7;
|
|
60
|
+
float yNoise=mix(h(vec2(floor(ySmooth),13.)),h(vec2(floor(ySmooth)+1.0,13.)),smoothstep(0.0,1.0,fract(ySmooth)));
|
|
61
|
+
float colVar=mix(.4,1.0,yNoise);
|
|
62
|
+
|
|
63
|
+
float tearShiftX=dir.x*strength*rowVar*0.15;
|
|
64
|
+
float tearShiftY=dir.y*strength*colVar*0.10;
|
|
65
|
+
|
|
66
|
+
float bandSeed=h(vec2(float(bandIdx),42.));
|
|
67
|
+
tearShiftX+=strength*(.5-bandSeed)*0.05;
|
|
68
|
+
|
|
69
|
+
float yJitter=mix(h(vec2(floor(ySmooth),73.)),h(vec2(floor(ySmooth)+1.0,73.)),smoothstep(0.0,1.0,fract(ySmooth)));
|
|
70
|
+
tearShiftY+=strength*(.5-yJitter)*0.035;
|
|
71
|
+
|
|
72
|
+
uv.x+=tearShiftX;
|
|
73
|
+
uv.y+=tearShiftY;
|
|
74
|
+
|
|
75
|
+
float sortGate=step(.5,strength)*step(.4,rowSeed);
|
|
76
|
+
uv.x+=dir.x*sortGate*strength*0.03;
|
|
77
|
+
uv.y+=dir.y*sortGate*strength*0.02;
|
|
78
|
+
|
|
79
|
+
float caX=abs(tearShiftX)*2.5+sortGate*strength*0.01;
|
|
80
|
+
float caY=abs(tearShiftY)*2.5+sortGate*strength*0.01;
|
|
81
|
+
float cr=texture2D(tex,vec2(uv.x+caX,uv.y+caY)).r;
|
|
82
|
+
float cg=texture2D(tex,uv).g;
|
|
83
|
+
float cb=texture2D(tex,vec2(uv.x-caX,uv.y-caY)).b;
|
|
84
|
+
|
|
85
|
+
vec3 col=vec3(cr,cg,cb);
|
|
86
|
+
|
|
87
|
+
col*=.97+.03*sin(vUv.y*r.y*3.14159);
|
|
88
|
+
|
|
89
|
+
float bandEdge=smoothstep(.02,.0,min(bandFrac,1.0-bandFrac));
|
|
90
|
+
col+=vec3(bandEdge*strength*.1);
|
|
91
|
+
|
|
92
|
+
col=mix(col,col*tint,tintStrength);
|
|
93
|
+
|
|
94
|
+
gl_FragColor=vec4(col,1.0);
|
|
95
|
+
}`;
|
|
96
|
+
export function ImageDistortion({ active = true, className, fallbackClassName, src, style, tint, tintStrength }) {
|
|
97
|
+
const canvasRef = useRef(null);
|
|
98
|
+
const tier = useGpuTier();
|
|
99
|
+
const [loaded, setLoaded] = useState(false);
|
|
100
|
+
const activeRef = useRef(active);
|
|
101
|
+
activeRef.current = active;
|
|
102
|
+
const tintStrengthRef = useRef(tintStrength);
|
|
103
|
+
tintStrengthRef.current = tintStrength;
|
|
104
|
+
const state = useRef({
|
|
105
|
+
bandTargets: new Float32Array(NUM_BANDS),
|
|
106
|
+
bands: new Float32Array(NUM_BANDS),
|
|
107
|
+
hoverTarget: 0,
|
|
108
|
+
imgH: 1,
|
|
109
|
+
imgW: 1,
|
|
110
|
+
mx: 0.5,
|
|
111
|
+
my: 0.5,
|
|
112
|
+
prevMx: 0.5,
|
|
113
|
+
prevMy: 0.5,
|
|
114
|
+
vx: 0,
|
|
115
|
+
vy: 0
|
|
116
|
+
});
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (tier === 0) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const c = canvasRef.current;
|
|
122
|
+
if (!c) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const gl = c.getContext('webgl');
|
|
126
|
+
if (!gl) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const compile = (type, source) => {
|
|
130
|
+
const s = gl.createShader(type);
|
|
131
|
+
gl.shaderSource(s, source);
|
|
132
|
+
gl.compileShader(s);
|
|
133
|
+
return s;
|
|
134
|
+
};
|
|
135
|
+
const prog = gl.createProgram();
|
|
136
|
+
gl.attachShader(prog, compile(gl.VERTEX_SHADER, VERT));
|
|
137
|
+
gl.attachShader(prog, compile(gl.FRAGMENT_SHADER, FRAG));
|
|
138
|
+
gl.linkProgram(prog);
|
|
139
|
+
gl.useProgram(prog);
|
|
140
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
|
141
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
142
|
+
const a = gl.getAttribLocation(prog, 'a');
|
|
143
|
+
gl.enableVertexAttribArray(a);
|
|
144
|
+
gl.vertexAttribPointer(a, 2, gl.FLOAT, false, 0, 0);
|
|
145
|
+
const uT = gl.getUniformLocation(prog, 't');
|
|
146
|
+
const uR = gl.getUniformLocation(prog, 'r');
|
|
147
|
+
const uImgSize = gl.getUniformLocation(prog, 'imgSize');
|
|
148
|
+
const uVel = gl.getUniformLocation(prog, 'vel');
|
|
149
|
+
const uTex = gl.getUniformLocation(prog, 'tex');
|
|
150
|
+
const uTint = gl.getUniformLocation(prog, 'tint');
|
|
151
|
+
const uTintStrength = gl.getUniformLocation(prog, 'tintStrength');
|
|
152
|
+
const uBands = [];
|
|
153
|
+
for (let i = 0; i < NUM_BANDS; i++) {
|
|
154
|
+
uBands.push(gl.getUniformLocation(prog, `bands[${i}]`));
|
|
155
|
+
}
|
|
156
|
+
const texture = gl.createTexture();
|
|
157
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
158
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
159
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
160
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
161
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
162
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255]));
|
|
163
|
+
const img = new Image();
|
|
164
|
+
img.crossOrigin = 'anonymous';
|
|
165
|
+
img.onload = () => {
|
|
166
|
+
state.current.imgW = img.naturalWidth;
|
|
167
|
+
state.current.imgH = img.naturalHeight;
|
|
168
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
169
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
|
|
170
|
+
setLoaded(true);
|
|
171
|
+
};
|
|
172
|
+
img.src = src;
|
|
173
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
174
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
175
|
+
gl.uniform1i(uTex, 0);
|
|
176
|
+
const resize = () => {
|
|
177
|
+
const rect = c.getBoundingClientRect();
|
|
178
|
+
const dpr = Math.min(devicePixelRatio, 2);
|
|
179
|
+
c.width = rect.width * dpr;
|
|
180
|
+
c.height = rect.height * dpr;
|
|
181
|
+
gl.viewport(0, 0, c.width, c.height);
|
|
182
|
+
};
|
|
183
|
+
resize();
|
|
184
|
+
const ro = new ResizeObserver(resize);
|
|
185
|
+
ro.observe(c);
|
|
186
|
+
const onMove = (e) => {
|
|
187
|
+
const rect = c.getBoundingClientRect();
|
|
188
|
+
state.current.mx = (e.clientX - rect.left) / rect.width;
|
|
189
|
+
state.current.my = (e.clientY - rect.top) / rect.height;
|
|
190
|
+
};
|
|
191
|
+
const onEnter = () => {
|
|
192
|
+
state.current.hoverTarget = 1;
|
|
193
|
+
};
|
|
194
|
+
const onLeave = () => {
|
|
195
|
+
state.current.hoverTarget = 0;
|
|
196
|
+
};
|
|
197
|
+
c.addEventListener('pointermove', onMove);
|
|
198
|
+
c.addEventListener('pointerenter', onEnter);
|
|
199
|
+
c.addEventListener('pointerleave', onLeave);
|
|
200
|
+
const bandEaseRates = new Float32Array(NUM_BANDS);
|
|
201
|
+
for (let i = 0; i < NUM_BANDS; i++) {
|
|
202
|
+
bandEaseRates[i] = 0.02 + Math.random() * 0.06;
|
|
203
|
+
}
|
|
204
|
+
const tintVec = tint
|
|
205
|
+
? (() => {
|
|
206
|
+
const [tr, tg, tb] = hexToRgb(tint);
|
|
207
|
+
return [tr / 255, tg / 255, tb / 255];
|
|
208
|
+
})()
|
|
209
|
+
: [1, 1, 1];
|
|
210
|
+
const t0 = performance.now();
|
|
211
|
+
let raf = 0;
|
|
212
|
+
const loop = () => {
|
|
213
|
+
raf = requestAnimationFrame(loop);
|
|
214
|
+
const s = state.current;
|
|
215
|
+
const dvx = s.mx - s.prevMx;
|
|
216
|
+
const dvy = s.my - s.prevMy;
|
|
217
|
+
s.vx += (dvx * 8 - s.vx) * 0.1;
|
|
218
|
+
s.vy += (dvy * 8 - s.vy) * 0.1;
|
|
219
|
+
s.prevMx = s.mx;
|
|
220
|
+
s.prevMy = s.my;
|
|
221
|
+
const speed = Math.sqrt(s.vx * s.vx + s.vy * s.vy);
|
|
222
|
+
for (let i = 0; i < NUM_BANDS; i++) {
|
|
223
|
+
const bandCenter = (i + 0.5) / NUM_BANDS;
|
|
224
|
+
const dist = Math.abs(s.my - bandCenter);
|
|
225
|
+
const proximity = Math.max(0, 1 - dist / 0.3);
|
|
226
|
+
const activation = s.hoverTarget * proximity * (0.4 + Math.min(speed, 1) * 0.6);
|
|
227
|
+
s.bandTargets[i] = activation;
|
|
228
|
+
}
|
|
229
|
+
for (let i = 0; i < NUM_BANDS; i++) {
|
|
230
|
+
const rate = bandEaseRates[i];
|
|
231
|
+
const current = s.bands[i] ?? 0;
|
|
232
|
+
const target = s.bandTargets[i] ?? 0;
|
|
233
|
+
s.bands[i] = current + (target - current) * rate;
|
|
234
|
+
if (s.bands[i] < 0.001) {
|
|
235
|
+
s.bands[i] = 0;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
gl.uniform1f(uT, (performance.now() - t0) / 1e3);
|
|
239
|
+
gl.uniform2f(uR, c.width, c.height);
|
|
240
|
+
gl.uniform2f(uImgSize, s.imgW, s.imgH);
|
|
241
|
+
gl.uniform2f(uVel, s.vx, s.vy);
|
|
242
|
+
gl.uniform3f(uTint, tintVec[0], tintVec[1], tintVec[2]);
|
|
243
|
+
const ts = tintStrengthRef.current;
|
|
244
|
+
const defaultStrength = tint ? 0.35 : 0;
|
|
245
|
+
const defaultInactive = tint ? 0.15 : 0;
|
|
246
|
+
gl.uniform1f(uTintStrength, activeRef.current
|
|
247
|
+
? (ts?.active ?? defaultStrength)
|
|
248
|
+
: (ts?.inactive ?? defaultInactive));
|
|
249
|
+
for (let i = 0; i < NUM_BANDS; i++) {
|
|
250
|
+
gl.uniform1f(uBands[i], s.bands[i]);
|
|
251
|
+
}
|
|
252
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
253
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
254
|
+
};
|
|
255
|
+
raf = requestAnimationFrame(loop);
|
|
256
|
+
return () => {
|
|
257
|
+
cancelAnimationFrame(raf);
|
|
258
|
+
ro.disconnect();
|
|
259
|
+
c.removeEventListener('pointermove', onMove);
|
|
260
|
+
c.removeEventListener('pointerenter', onEnter);
|
|
261
|
+
c.removeEventListener('pointerleave', onLeave);
|
|
262
|
+
gl.deleteTexture(texture);
|
|
263
|
+
gl.deleteProgram(prog);
|
|
264
|
+
setLoaded(false);
|
|
265
|
+
};
|
|
266
|
+
}, [src, tier, tint]);
|
|
267
|
+
if (tier === 0) {
|
|
268
|
+
return (
|
|
269
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
270
|
+
_jsx("img", { alt: "", className: cn('absolute inset-0 h-full w-full object-cover', fallbackClassName ?? className), src: src, style: { mixBlendMode: 'overlay', ...style } }));
|
|
271
|
+
}
|
|
272
|
+
return (_jsx("canvas", { className: cn('absolute inset-0 h-full w-full transition-opacity duration-500', className), ref: canvasRef, style: {
|
|
273
|
+
mixBlendMode: 'overlay',
|
|
274
|
+
opacity: loaded ? 1 : 0,
|
|
275
|
+
...style
|
|
276
|
+
} }));
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=image-distortion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-distortion.js","sourceRoot":"","sources":["../../../src/ui/components/image-distortion.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useEffect, useRef, useState } from 'react'\n\nimport { useGpuTier } from '../../hooks/use-gpu-tier'\nimport { cn, hexToRgb } from '../../utils'\n\nconst NUM_BANDS = 12\n\nconst VERT = `attribute vec2 a;varying vec2 vUv;void main(){vUv=vec2(a.x*.5+.5,.5-a.y*.5);gl_Position=vec4(a,0,1);}`\n\nconst FRAG = `precision highp float;\nuniform float t;\nuniform vec2 r,imgSize,vel;\nuniform sampler2D tex;\nuniform float bands[${NUM_BANDS}];\nuniform vec3 tint;\nuniform float tintStrength;\nvarying vec2 vUv;\n\nfloat h(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}\n\n// cover-style UV: crops the image to fill the canvas, centered\nvec2 coverUV(vec2 uv){\n float canvasAspect=r.x/r.y;\n float imgAspect=imgSize.x/imgSize.y;\n vec2 scale=canvasAspect>imgAspect\n ?vec2(1.0,imgAspect/canvasAspect)\n :vec2(canvasAspect/imgAspect,1.0);\n return(uv-0.5)*scale+0.5;\n}\n\nvoid main(){\n vec2 uv=coverUV(vUv);\n float scanY=floor(vUv.y*r.y);\n\n float bandF=vUv.y*${NUM_BANDS}.0;\n int bandIdx=int(floor(bandF));\n float bandFrac=fract(bandF);\n\n float strength=0.0;\n for(int i=0;i<${NUM_BANDS};i++){\n if(i==bandIdx) strength=bands[i];\n }\n\n float neighborStr=0.0;\n int neighborIdx=bandFrac>.5?bandIdx+1:bandIdx-1;\n for(int i=0;i<${NUM_BANDS};i++){\n if(i==neighborIdx) neighborStr=bands[i];\n }\n float edgeBlend=abs(bandFrac-.5)*2.0;\n edgeBlend*=edgeBlend;\n strength=mix(strength,neighborStr,edgeBlend*.3);\n\n float speed=length(vel);\n float dirBlend=smoothstep(0.0,0.02,speed);\n vec2 dir=speed>.0001?vel/speed:vec2(0);\n dir*=dirBlend;\n\n float rowSeed=h(vec2(scanY,floor(t*3.)+float(bandIdx)*7.));\n float rowVar=mix(.4,1.0,rowSeed);\n\n float ySmooth=vUv.y*6.0+t*0.7;\n float yNoise=mix(h(vec2(floor(ySmooth),13.)),h(vec2(floor(ySmooth)+1.0,13.)),smoothstep(0.0,1.0,fract(ySmooth)));\n float colVar=mix(.4,1.0,yNoise);\n\n float tearShiftX=dir.x*strength*rowVar*0.15;\n float tearShiftY=dir.y*strength*colVar*0.10;\n\n float bandSeed=h(vec2(float(bandIdx),42.));\n tearShiftX+=strength*(.5-bandSeed)*0.05;\n\n float yJitter=mix(h(vec2(floor(ySmooth),73.)),h(vec2(floor(ySmooth)+1.0,73.)),smoothstep(0.0,1.0,fract(ySmooth)));\n tearShiftY+=strength*(.5-yJitter)*0.035;\n\n uv.x+=tearShiftX;\n uv.y+=tearShiftY;\n\n float sortGate=step(.5,strength)*step(.4,rowSeed);\n uv.x+=dir.x*sortGate*strength*0.03;\n uv.y+=dir.y*sortGate*strength*0.02;\n\n float caX=abs(tearShiftX)*2.5+sortGate*strength*0.01;\n float caY=abs(tearShiftY)*2.5+sortGate*strength*0.01;\n float cr=texture2D(tex,vec2(uv.x+caX,uv.y+caY)).r;\n float cg=texture2D(tex,uv).g;\n float cb=texture2D(tex,vec2(uv.x-caX,uv.y-caY)).b;\n\n vec3 col=vec3(cr,cg,cb);\n\n col*=.97+.03*sin(vUv.y*r.y*3.14159);\n\n float bandEdge=smoothstep(.02,.0,min(bandFrac,1.0-bandFrac));\n col+=vec3(bandEdge*strength*.1);\n\n col=mix(col,col*tint,tintStrength);\n\n gl_FragColor=vec4(col,1.0);\n}`\n\nexport function ImageDistortion({\n active = true,\n className,\n fallbackClassName,\n src,\n style,\n tint,\n tintStrength\n}: ImageDistortionProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const tier = useGpuTier()\n const [loaded, setLoaded] = useState(false)\n\n const activeRef = useRef(active)\n activeRef.current = active\n const tintStrengthRef = useRef(tintStrength)\n tintStrengthRef.current = tintStrength\n\n const state = useRef({\n bandTargets: new Float32Array(NUM_BANDS),\n bands: new Float32Array(NUM_BANDS),\n hoverTarget: 0,\n imgH: 1,\n imgW: 1,\n mx: 0.5,\n my: 0.5,\n prevMx: 0.5,\n prevMy: 0.5,\n vx: 0,\n vy: 0\n })\n\n useEffect(() => {\n if (tier === 0) {\n return\n }\n\n const c = canvasRef.current\n\n if (!c) {\n return\n }\n\n const gl = c.getContext('webgl')\n\n if (!gl) {\n return\n }\n\n const compile = (type: number, source: string) => {\n const s = gl.createShader(type)!\n gl.shaderSource(s, source)\n gl.compileShader(s)\n\n return s\n }\n\n const prog = gl.createProgram()!\n gl.attachShader(prog, compile(gl.VERTEX_SHADER, VERT))\n gl.attachShader(prog, compile(gl.FRAGMENT_SHADER, FRAG))\n gl.linkProgram(prog)\n gl.useProgram(prog)\n\n gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer())\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),\n gl.STATIC_DRAW\n )\n\n const a = gl.getAttribLocation(prog, 'a')\n gl.enableVertexAttribArray(a)\n gl.vertexAttribPointer(a, 2, gl.FLOAT, false, 0, 0)\n\n const uT = gl.getUniformLocation(prog, 't')\n const uR = gl.getUniformLocation(prog, 'r')\n const uImgSize = gl.getUniformLocation(prog, 'imgSize')\n const uVel = gl.getUniformLocation(prog, 'vel')\n const uTex = gl.getUniformLocation(prog, 'tex')\n const uTint = gl.getUniformLocation(prog, 'tint')\n const uTintStrength = gl.getUniformLocation(prog, 'tintStrength')\n const uBands: (null | WebGLUniformLocation)[] = []\n\n for (let i = 0; i < NUM_BANDS; i++) {\n uBands.push(gl.getUniformLocation(prog, `bands[${i}]`))\n }\n\n const texture = gl.createTexture()!\n gl.bindTexture(gl.TEXTURE_2D, texture)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n 1,\n 1,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n new Uint8Array([0, 0, 0, 255])\n )\n\n const img = new Image()\n img.crossOrigin = 'anonymous'\n\n img.onload = () => {\n state.current.imgW = img.naturalWidth\n state.current.imgH = img.naturalHeight\n gl.bindTexture(gl.TEXTURE_2D, texture)\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n img\n )\n setLoaded(true)\n }\n\n img.src = src\n\n gl.activeTexture(gl.TEXTURE0)\n gl.bindTexture(gl.TEXTURE_2D, texture)\n gl.uniform1i(uTex, 0)\n\n const resize = () => {\n const rect = c.getBoundingClientRect()\n const dpr = Math.min(devicePixelRatio, 2)\n c.width = rect.width * dpr\n c.height = rect.height * dpr\n gl.viewport(0, 0, c.width, c.height)\n }\n\n resize()\n const ro = new ResizeObserver(resize)\n ro.observe(c)\n\n const onMove = (e: PointerEvent) => {\n const rect = c.getBoundingClientRect()\n state.current.mx = (e.clientX - rect.left) / rect.width\n state.current.my = (e.clientY - rect.top) / rect.height\n }\n\n const onEnter = () => {\n state.current.hoverTarget = 1\n }\n\n const onLeave = () => {\n state.current.hoverTarget = 0\n }\n\n c.addEventListener('pointermove', onMove)\n c.addEventListener('pointerenter', onEnter)\n c.addEventListener('pointerleave', onLeave)\n\n const bandEaseRates = new Float32Array(NUM_BANDS)\n\n for (let i = 0; i < NUM_BANDS; i++) {\n bandEaseRates[i] = 0.02 + Math.random() * 0.06\n }\n\n const tintVec: readonly [number, number, number] = tint\n ? (() => {\n const [tr, tg, tb] = hexToRgb(tint)\n\n return [tr / 255, tg / 255, tb / 255] as const\n })()\n : ([1, 1, 1] as const)\n\n const t0 = performance.now()\n let raf = 0\n\n const loop = () => {\n raf = requestAnimationFrame(loop)\n const s = state.current\n\n const dvx = s.mx - s.prevMx\n const dvy = s.my - s.prevMy\n s.vx += (dvx * 8 - s.vx) * 0.1\n s.vy += (dvy * 8 - s.vy) * 0.1\n s.prevMx = s.mx\n s.prevMy = s.my\n\n const speed = Math.sqrt(s.vx * s.vx + s.vy * s.vy)\n\n for (let i = 0; i < NUM_BANDS; i++) {\n const bandCenter = (i + 0.5) / NUM_BANDS\n const dist = Math.abs(s.my - bandCenter)\n const proximity = Math.max(0, 1 - dist / 0.3)\n const activation =\n s.hoverTarget * proximity * (0.4 + Math.min(speed, 1) * 0.6)\n s.bandTargets[i] = activation\n }\n\n for (let i = 0; i < NUM_BANDS; i++) {\n const rate = bandEaseRates[i]!\n const current = s.bands[i] ?? 0\n const target = s.bandTargets[i] ?? 0\n s.bands[i] = current + (target - current) * rate\n\n if (s.bands[i]! < 0.001) {\n s.bands[i] = 0\n }\n }\n\n gl.uniform1f(uT, (performance.now() - t0) / 1e3)\n gl.uniform2f(uR, c.width, c.height)\n gl.uniform2f(uImgSize, s.imgW, s.imgH)\n gl.uniform2f(uVel, s.vx, s.vy)\n gl.uniform3f(uTint, tintVec[0], tintVec[1], tintVec[2])\n\n const ts = tintStrengthRef.current\n const defaultStrength = tint ? 0.35 : 0\n const defaultInactive = tint ? 0.15 : 0\n gl.uniform1f(\n uTintStrength,\n activeRef.current\n ? (ts?.active ?? defaultStrength)\n : (ts?.inactive ?? defaultInactive)\n )\n\n for (let i = 0; i < NUM_BANDS; i++) {\n gl.uniform1f(uBands[i]!, s.bands[i]!)\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture)\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n }\n\n raf = requestAnimationFrame(loop)\n\n return () => {\n cancelAnimationFrame(raf)\n ro.disconnect()\n c.removeEventListener('pointermove', onMove)\n c.removeEventListener('pointerenter', onEnter)\n c.removeEventListener('pointerleave', onLeave)\n gl.deleteTexture(texture)\n gl.deleteProgram(prog)\n setLoaded(false)\n }\n }, [src, tier, tint])\n\n if (tier === 0) {\n return (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n alt=\"\"\n className={cn(\n 'absolute inset-0 h-full w-full object-cover',\n fallbackClassName ?? className\n )}\n src={src}\n style={{ mixBlendMode: 'overlay', ...style }}\n />\n )\n }\n\n return (\n <canvas\n className={cn(\n 'absolute inset-0 h-full w-full transition-opacity duration-500',\n className\n )}\n ref={canvasRef}\n style={{\n mixBlendMode: 'overlay',\n opacity: loaded ? 1 : 0,\n ...style\n }}\n />\n )\n}\n\ninterface ImageDistortionProps {\n active?: boolean\n className?: string\n fallbackClassName?: string\n src: string\n style?: React.CSSProperties\n tint?: string\n tintStrength?: { active: number; inactive: number }\n}\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare function TerminalDemo({ ariaLabel, className, height, label, loopDelayMs, outputLineDelayMs, sequence }: TerminalDemoProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
interface ClearStep {
|
|
3
|
+
type: 'clear';
|
|
4
|
+
}
|
|
5
|
+
interface OutputStep {
|
|
6
|
+
lines: string[];
|
|
7
|
+
type: 'output';
|
|
8
|
+
}
|
|
9
|
+
interface PauseStep {
|
|
10
|
+
ms: number;
|
|
11
|
+
type: 'pause';
|
|
12
|
+
}
|
|
13
|
+
interface PromptStep {
|
|
14
|
+
text: string;
|
|
15
|
+
type: 'prompt';
|
|
16
|
+
}
|
|
17
|
+
interface TerminalDemoProps {
|
|
18
|
+
ariaLabel?: string;
|
|
19
|
+
className?: string;
|
|
20
|
+
height?: number | string;
|
|
21
|
+
label?: string;
|
|
22
|
+
loopDelayMs?: number;
|
|
23
|
+
outputLineDelayMs?: number;
|
|
24
|
+
sequence: TerminalDemoStep[];
|
|
25
|
+
}
|
|
26
|
+
export type TerminalDemoStep = ClearStep | OutputStep | PauseStep | PromptStep | TypeStep;
|
|
27
|
+
interface TypeStep {
|
|
28
|
+
delay?: number;
|
|
29
|
+
text: string;
|
|
30
|
+
type: 'type';
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=terminal-demo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-demo.d.ts","sourceRoot":"","sources":["../../../src/ui/components/terminal-demo.tsx"],"names":[],"mappings":"AAUA,wBAAgB,YAAY,CAAC,EAC3B,SAA2B,EAC3B,SAAS,EACT,MAAY,EACZ,KAAkB,EAClB,WAAkB,EAClB,iBAAsB,EACtB,QAAQ,EACT,EAAE,iBAAiB,2CAgInB;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,OAAO,CAAA;CACd;AAED,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,IAAI,EAAE,QAAQ,CAAA;CACf;AAED,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,OAAO,CAAA;CACd;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,QAAQ,CAAA;CACf;AAED,UAAU,iBAAiB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC7B;AAED,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,UAAU,GACV,SAAS,GACT,UAAU,GACV,QAAQ,CAAA;AAEZ,UAAU,QAAQ;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { cn } from '../../utils';
|
|
5
|
+
function sleep(ms) {
|
|
6
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
7
|
+
}
|
|
8
|
+
export function TerminalDemo({ ariaLabel = 'Terminal Demo', className, height = 320, label = 'Terminal', loopDelayMs = 1000, outputLineDelayMs = 50, sequence }) {
|
|
9
|
+
const bodyRef = useRef(null);
|
|
10
|
+
const startedRef = useRef(false);
|
|
11
|
+
const [html, setHtml] = useState('');
|
|
12
|
+
const runDemo = useCallback(async () => {
|
|
13
|
+
if (startedRef.current) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
startedRef.current = true;
|
|
17
|
+
let content = '';
|
|
18
|
+
const render = (h) => {
|
|
19
|
+
content = h;
|
|
20
|
+
setHtml(h);
|
|
21
|
+
};
|
|
22
|
+
for (;;) {
|
|
23
|
+
for (const step of sequence) {
|
|
24
|
+
switch (step.type) {
|
|
25
|
+
case 'clear':
|
|
26
|
+
content = '';
|
|
27
|
+
render('');
|
|
28
|
+
break;
|
|
29
|
+
case 'output':
|
|
30
|
+
for (const line of step.lines) {
|
|
31
|
+
render(content + '\n' + line);
|
|
32
|
+
await sleep(outputLineDelayMs);
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
case 'pause':
|
|
36
|
+
await sleep(step.ms);
|
|
37
|
+
break;
|
|
38
|
+
case 'prompt':
|
|
39
|
+
render(content + `<span class="text-midground">${step.text}</span>`);
|
|
40
|
+
break;
|
|
41
|
+
case 'type':
|
|
42
|
+
for (const char of step.text) {
|
|
43
|
+
render(content + char);
|
|
44
|
+
await sleep(step.delay ?? 30);
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
content = '';
|
|
50
|
+
render('');
|
|
51
|
+
await sleep(loopDelayMs);
|
|
52
|
+
}
|
|
53
|
+
}, [loopDelayMs, outputLineDelayMs, sequence]);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const el = bodyRef.current?.closest('[data-demo-root]');
|
|
56
|
+
if (!el) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const observer = new IntersectionObserver(entries => {
|
|
60
|
+
entries.forEach(entry => {
|
|
61
|
+
if (entry.isIntersecting) {
|
|
62
|
+
runDemo();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}, { threshold: 0.3 });
|
|
66
|
+
observer.observe(el);
|
|
67
|
+
return () => observer.disconnect();
|
|
68
|
+
}, [runDemo]);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (bodyRef.current) {
|
|
71
|
+
bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
|
|
72
|
+
}
|
|
73
|
+
}, [html]);
|
|
74
|
+
return (_jsxs("div", { "aria-label": ariaLabel, className: cn('border-4 border-double border-inherit', className), "data-demo-root": true, role: "img", children: [_jsxs("div", { className: "flex items-center gap-3 border-b border-current/10 px-3 py-2", children: [_jsxs("div", { className: "flex gap-1.5", children: [_jsx("span", { className: "bg-midground size-2 rounded-full", style: { mixBlendMode: 'plus-lighter' } }), _jsx("span", { className: "bg-midground/60 size-2 rounded-full" }), _jsx("span", { className: "bg-midground/30 size-2 rounded-full" })] }), _jsx("span", { className: "font-courier text-[0.625rem] tracking-widest uppercase opacity-50", children: label })] }), _jsx("div", { className: cn('overflow-x-hidden overflow-y-auto whitespace-pre-wrap', 'font-courier p-4 text-[0.75rem] leading-[1.7] normal-case'), dangerouslySetInnerHTML: {
|
|
75
|
+
__html: html +
|
|
76
|
+
'<span class="blink inline-block dither ml-0.5 h-[1em] w-[1ch]"></span>'
|
|
77
|
+
}, ref: bodyRef, style: { height } })] }));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=terminal-demo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-demo.js","sourceRoot":"","sources":["../../../src/ui/components/terminal-demo.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { cn } from '../../utils'\n\nfunction sleep(ms: number) {\n return new Promise<void>(resolve => setTimeout(resolve, ms))\n}\n\nexport function TerminalDemo({\n ariaLabel = 'Terminal Demo',\n className,\n height = 320,\n label = 'Terminal',\n loopDelayMs = 1000,\n outputLineDelayMs = 50,\n sequence\n}: TerminalDemoProps) {\n const bodyRef = useRef<HTMLDivElement>(null)\n const startedRef = useRef(false)\n const [html, setHtml] = useState('')\n\n const runDemo = useCallback(async () => {\n if (startedRef.current) {\n return\n }\n\n startedRef.current = true\n let content = ''\n\n const render = (h: string) => {\n content = h\n setHtml(h)\n }\n\n for (;;) {\n for (const step of sequence) {\n switch (step.type) {\n case 'clear':\n content = ''\n render('')\n\n break\n\n case 'output':\n for (const line of step.lines) {\n render(content + '\\n' + line)\n await sleep(outputLineDelayMs)\n }\n\n break\n\n case 'pause':\n await sleep(step.ms)\n\n break\n\n case 'prompt':\n render(content + `<span class=\"text-midground\">${step.text}</span>`)\n\n break\n\n case 'type':\n for (const char of step.text) {\n render(content + char)\n await sleep(step.delay ?? 30)\n }\n\n break\n }\n }\n\n content = ''\n render('')\n await sleep(loopDelayMs)\n }\n }, [loopDelayMs, outputLineDelayMs, sequence])\n\n useEffect(() => {\n const el = bodyRef.current?.closest('[data-demo-root]')\n\n if (!el) {\n return\n }\n\n const observer = new IntersectionObserver(\n entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n runDemo()\n }\n })\n },\n { threshold: 0.3 }\n )\n\n observer.observe(el)\n\n return () => observer.disconnect()\n }, [runDemo])\n\n useEffect(() => {\n if (bodyRef.current) {\n bodyRef.current.scrollTop = bodyRef.current.scrollHeight\n }\n }, [html])\n\n return (\n <div\n aria-label={ariaLabel}\n className={cn('border-4 border-double border-inherit', className)}\n data-demo-root\n role=\"img\"\n >\n <div className=\"flex items-center gap-3 border-b border-current/10 px-3 py-2\">\n <div className=\"flex gap-1.5\">\n <span\n className=\"bg-midground size-2 rounded-full\"\n style={{ mixBlendMode: 'plus-lighter' }}\n />\n\n <span className=\"bg-midground/60 size-2 rounded-full\" />\n <span className=\"bg-midground/30 size-2 rounded-full\" />\n </div>\n\n <span className=\"font-courier text-[0.625rem] tracking-widest uppercase opacity-50\">\n {label}\n </span>\n </div>\n\n <div\n className={cn(\n 'overflow-x-hidden overflow-y-auto whitespace-pre-wrap',\n 'font-courier p-4 text-[0.75rem] leading-[1.7] normal-case'\n )}\n dangerouslySetInnerHTML={{\n __html:\n html +\n '<span class=\"blink inline-block dither ml-0.5 h-[1em] w-[1ch]\"></span>'\n }}\n ref={bodyRef}\n style={{ height }}\n />\n </div>\n )\n}\n\ninterface ClearStep {\n type: 'clear'\n}\n\ninterface OutputStep {\n lines: string[]\n type: 'output'\n}\n\ninterface PauseStep {\n ms: number\n type: 'pause'\n}\n\ninterface PromptStep {\n text: string\n type: 'prompt'\n}\n\ninterface TerminalDemoProps {\n ariaLabel?: string\n className?: string\n height?: number | string\n label?: string\n loopDelayMs?: number\n outputLineDelayMs?: number\n sequence: TerminalDemoStep[]\n}\n\nexport type TerminalDemoStep =\n | ClearStep\n | OutputStep\n | PauseStep\n | PromptStep\n | TypeStep\n\ninterface TypeStep {\n delay?: number\n text: string\n type: 'type'\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-toggle.d.ts","sourceRoot":"","sources":["../../../src/ui/components/theme-toggle.tsx"],"names":[],"mappings":"AAQA,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,gBAAgB,2CAoDjE;AAED,UAAU,gBAAgB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useStore } from '@nanostores/react';
|
|
4
|
+
import { cn } from '../../utils';
|
|
5
|
+
import { $lightMode, toggleLens } from './overlays';
|
|
6
|
+
export function ThemeToggle({ className, style }) {
|
|
7
|
+
const light = useStore($lightMode);
|
|
8
|
+
return (_jsxs("button", { "aria-label": light ? 'Switch to dark mode' : 'Switch to light mode', className: cn('relative flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full', 'border border-current/25 bg-current/8 transition-colors', 'hover:bg-current/15', className), onClick: toggleLens, style: style, type: "button", children: [_jsxs("svg", { className: "absolute left-1 size-3.5 opacity-40", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, viewBox: "0 0 24 24", children: [_jsx("circle", { cx: 12, cy: 12, r: 5 }), _jsx("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })] }), _jsx("svg", { className: "absolute right-1 size-3.5 opacity-40", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, viewBox: "0 0 24 24", children: _jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }), _jsx("span", { "aria-hidden": true, className: cn('bg-midground absolute size-4 rounded-full', 'transition-transform duration-200 ease-out'), style: { transform: `translateX(${light ? 2 : 22}px)` } })] }));
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=theme-toggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-toggle.js","sourceRoot":"","sources":["../../../src/ui/components/theme-toggle.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEnD,MAAM,UAAU,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAoB;IAChE,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;IAElC,OAAO,CACL,gCACc,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,sBAAsB,EAClE,SAAS,EAAE,EAAE,CACX,0EAA0E,EAC1E,yDAAyD,EACzD,qBAAqB,EACrB,SAAS,CACV,EACD,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAC,QAAQ,aAEb,eACE,SAAS,EAAC,qCAAqC,EAC/C,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAE,CAAC,EACd,OAAO,EAAC,WAAW,aAEnB,iBAAQ,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAI,EAEhC,eAAM,CAAC,EAAC,oHAAoH,GAAG,IAC3H,EAEN,cACE,SAAS,EAAC,sCAAsC,EAChD,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAE,CAAC,EACd,OAAO,EAAC,WAAW,YAEnB,eAAM,CAAC,EAAC,iDAAiD,GAAG,GACxD,EAEN,oCAEE,SAAS,EAAE,EAAE,CACX,2CAA2C,EAC3C,4CAA4C,CAC7C,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GACvD,IACK,CACV,CAAA;AACH,CAAC","sourcesContent":["'use client'\n\nimport { useStore } from '@nanostores/react'\n\nimport { cn } from '../../utils'\n\nimport { $lightMode, toggleLens } from './overlays'\n\nexport function ThemeToggle({ className, style }: ThemeToggleProps) {\n const light = useStore($lightMode)\n\n return (\n <button\n aria-label={light ? 'Switch to dark mode' : 'Switch to light mode'}\n className={cn(\n 'relative flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full',\n 'border border-current/25 bg-current/8 transition-colors',\n 'hover:bg-current/15',\n className\n )}\n onClick={toggleLens}\n style={style}\n type=\"button\"\n >\n <svg\n className=\"absolute left-1 size-3.5 opacity-40\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n viewBox=\"0 0 24 24\"\n >\n <circle cx={12} cy={12} r={5} />\n\n <path d=\"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42\" />\n </svg>\n\n <svg\n className=\"absolute right-1 size-3.5 opacity-40\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\" />\n </svg>\n\n <span\n aria-hidden\n className={cn(\n 'bg-midground absolute size-4 rounded-full',\n 'transition-transform duration-200 ease-out'\n )}\n style={{ transform: `translateX(${light ? 2 : 22}px)` }}\n />\n </button>\n )\n}\n\ninterface ThemeToggleProps {\n className?: string\n style?: React.CSSProperties\n}\n"]}
|