@moldable-ai/ui 0.2.25 → 0.2.26

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.
Files changed (62) hide show
  1. package/dist/catalog/core-foundation-stories.d.ts.map +1 -1
  2. package/dist/catalog/core-foundation-stories.js +2 -2
  3. package/dist/components/chat/chat-input.d.ts.map +1 -1
  4. package/dist/components/chat/chat-input.js +1 -1
  5. package/dist/components/chat/chat-message.js +1 -1
  6. package/dist/components/chat/index.d.ts +1 -0
  7. package/dist/components/chat/index.d.ts.map +1 -1
  8. package/dist/components/chat/index.js +1 -0
  9. package/dist/components/chat/orb-materials.d.ts +14 -0
  10. package/dist/components/chat/orb-materials.d.ts.map +1 -0
  11. package/dist/components/chat/orb-materials.js +340 -0
  12. package/dist/components/chat/voice-orb-shaders.d.ts +1 -1
  13. package/dist/components/chat/voice-orb-shaders.d.ts.map +1 -1
  14. package/dist/components/chat/voice-orb-shaders.js +11 -162
  15. package/dist/components/chat/voice-orb.d.ts.map +1 -1
  16. package/dist/components/chat/voice-orb.js +2 -1
  17. package/dist/components/native-capabilities/shortcut-recorder.js +1 -1
  18. package/dist/components/rich-media-player.js +1 -1
  19. package/dist/components/ui/app-frame.d.ts +1 -1
  20. package/dist/components/ui/app-frame.d.ts.map +1 -1
  21. package/dist/components/ui/app-frame.js +7 -39
  22. package/dist/components/ui/button-group.d.ts +1 -1
  23. package/dist/components/ui/button-group.js +1 -1
  24. package/dist/components/ui/button.d.ts +2 -2
  25. package/dist/components/ui/button.d.ts.map +1 -1
  26. package/dist/components/ui/checkbox.js +1 -1
  27. package/dist/components/ui/collapsible.js +1 -1
  28. package/dist/components/ui/combobox.js +1 -1
  29. package/dist/components/ui/command.d.ts.map +1 -1
  30. package/dist/components/ui/command.js +10 -2
  31. package/dist/components/ui/date-field.d.ts +1 -1
  32. package/dist/components/ui/date-field.js +1 -1
  33. package/dist/components/ui/input-group.d.ts +2 -2
  34. package/dist/components/ui/input-group.d.ts.map +1 -1
  35. package/dist/components/ui/input-otp.js +1 -1
  36. package/dist/components/ui/input.js +1 -1
  37. package/dist/components/ui/inspector.js +3 -3
  38. package/dist/components/ui/menubar.js +1 -1
  39. package/dist/components/ui/number-input.js +1 -1
  40. package/dist/components/ui/panel.d.ts +2 -2
  41. package/dist/components/ui/panel.js +2 -2
  42. package/dist/components/ui/radio-group.js +1 -1
  43. package/dist/components/ui/select.js +1 -1
  44. package/dist/components/ui/switch.js +1 -1
  45. package/dist/components/ui/toolbar.d.ts +15 -4
  46. package/dist/components/ui/toolbar.d.ts.map +1 -1
  47. package/dist/components/ui/toolbar.js +16 -5
  48. package/dist/components/ui/window-titlebar.d.ts +8 -0
  49. package/dist/components/ui/window-titlebar.d.ts.map +1 -0
  50. package/dist/components/ui/window-titlebar.js +40 -0
  51. package/dist/index.d.ts +1 -1
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +1 -1
  54. package/dist/lib/commands.d.ts +29 -0
  55. package/dist/lib/commands.d.ts.map +1 -1
  56. package/dist/lib/commands.js +28 -0
  57. package/docs/app-anatomy.md +9 -7
  58. package/docs/standalone-app-windows.md +12 -8
  59. package/package.json +2 -2
  60. package/src/components/ui/app-frame.md +6 -8
  61. package/src/components/ui/toolbar.md +14 -1
  62. package/src/styles/index.css +28 -0
@@ -1 +1 @@
1
- {"version":3,"file":"core-foundation-stories.d.ts","sourceRoot":"","sources":["../../src/catalog/core-foundation-stories.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AAE/D,eAAO,MAAM,qBAAqB,EAAE,wBA6InC,CAAA"}
1
+ {"version":3,"file":"core-foundation-stories.d.ts","sourceRoot":"","sources":["../../src/catalog/core-foundation-stories.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AAE/D,eAAO,MAAM,qBAAqB,EAAE,wBA2InC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ChevronLeftIcon, ChevronRightIcon, LocateFixedIcon, PlusIcon, } from 'lucide-react';
3
- import { AppFrame, AppFrameContent, AppFrameTitlebar, AppFrameToolbar, } from '../components/ui/app-frame.js';
3
+ import { AppFrame, AppFrameContent, } from '../components/ui/app-frame.js';
4
4
  import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '../components/ui/card.js';
5
5
  import { IconButton } from '../components/ui/icon-button.js';
6
6
  import { Material, MaterialGroup } from '../components/ui/material.js';
@@ -16,7 +16,7 @@ export const coreFoundationSection = {
16
16
  title: 'App frame',
17
17
  components: ['app-frame'],
18
18
  interactions: ['rest', 'empty'],
19
- render: ({ interaction }) => (_jsxs(AppFrame, { mode: "window", className: "rounded-container h-56 border", children: [_jsx(AppFrameTitlebar, { children: _jsx(AppFrameToolbar, { children: _jsx("strong", { className: "text-sm", children: "Calendar" }) }) }), _jsx(AppFrameContent, { className: "grid place-items-center p-4", children: _jsx("span", { className: "text-muted-foreground text-sm", children: interaction === 'empty' ? 'No events yet' : 'App-owned canvas' }) })] })),
19
+ render: ({ interaction }) => (_jsxs(AppFrame, { mode: "window", className: "rounded-container h-56 border", children: [_jsx(Toolbar, { position: "top", children: _jsx(ToolbarTitle, { children: "Today" }) }), _jsx(AppFrameContent, { className: "grid place-items-center p-4", children: _jsx("span", { className: "text-muted-foreground text-sm", children: interaction === 'empty' ? 'No events yet' : 'App-owned canvas' }) })] })),
20
20
  },
21
21
  {
22
22
  id: 'adaptive-material',
@@ -1 +1 @@
1
- {"version":3,"file":"chat-input.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-input.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAGT,SAAS,EACT,SAAS,EACV,MAAM,OAAO,CAAA;AAKd,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAA;AAE7C,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAA;IAC5D,QAAQ,EAAE,CACR,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,EACzC,IAAI,CAAC,EAAE,cAAc,KAClB,IAAI,CAAA;IACT,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAA;IAChD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAA;IACxC,uBAAuB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9C,mBAAmB,CAAC,EAAE,SAAS,CAAA;IAC/B,cAAc,CAAC,EAAE,SAAS,CAAA;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,sBAAsB,EAAE,CAAA;IACxC,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,CAAA;CACjE,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,WAA+B,EAC/B,QAAQ,EACR,MAAM,EACN,OAAe,EACf,gBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,EACnB,cAAc,EACd,cAAsB,EACtB,aAAkB,EAClB,oBAAoB,GACrB,EAAE,cAAc,2CA2KhB"}
1
+ {"version":3,"file":"chat-input.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-input.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAGT,SAAS,EACT,SAAS,EACV,MAAM,OAAO,CAAA;AAKd,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAA;AAE7C,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAA;IAC5D,QAAQ,EAAE,CACR,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,EACzC,IAAI,CAAC,EAAE,cAAc,KAClB,IAAI,CAAA;IACT,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAA;IAChD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAA;IACxC,uBAAuB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9C,mBAAmB,CAAC,EAAE,SAAS,CAAA;IAC/B,cAAc,CAAC,EAAE,SAAS,CAAA;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,sBAAsB,EAAE,CAAA;IACxC,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,CAAA;CACjE,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,WAA+B,EAC/B,QAAQ,EACR,MAAM,EACN,OAAe,EACf,gBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,EACnB,cAAc,EACd,cAAsB,EACtB,aAAkB,EAClB,oBAAoB,GACrB,EAAE,cAAc,2CA4KhB"}
@@ -47,7 +47,7 @@ export function ChatInput({ input, onInputChange, onSubmit, isResponding, placeh
47
47
  return;
48
48
  }
49
49
  onSubmit(e, isResponding ? 'queue' : 'send');
50
- }, children: _jsxs("div", { className: cn('bg-background rounded-container relative flex w-full flex-col border', compact && !hasAttachments && 'h-14'), children: [!compact && slashCommands.length > 0 && (_jsx("div", { className: "border-border bg-popover text-popover-foreground rounded-container absolute bottom-full left-4 right-4 z-20 mb-2 overflow-hidden border shadow-lg", children: slashCommands.map((command) => (_jsxs("button", { type: "button", className: "hover:bg-accent hover:text-accent-foreground flex min-h-12 w-full cursor-pointer items-center gap-3 px-3 py-2.5 text-left transition-colors", onMouseDown: (event) => {
50
+ }, children: _jsxs("div", { className: cn('bg-background relative flex w-full flex-col border', compact ? 'rounded-pill' : 'rounded-container', compact && !hasAttachments && 'h-14'), children: [!compact && slashCommands.length > 0 && (_jsx("div", { className: "border-border bg-popover text-popover-foreground rounded-container absolute bottom-full left-4 right-4 z-20 mb-2 overflow-hidden border shadow-lg", children: slashCommands.map((command) => (_jsxs("button", { type: "button", className: "hover:bg-accent hover:text-accent-foreground flex min-h-12 w-full cursor-pointer items-center gap-3 px-3 py-2.5 text-left transition-colors", onMouseDown: (event) => {
51
51
  event.preventDefault();
52
52
  onSlashCommandSelect?.(command);
53
53
  }, children: [_jsxs("span", { className: "bg-muted text-muted-foreground rounded-control text-ui-caption px-1.5 py-0.5 font-mono", children: ["/", command.name] }), _jsx("span", { className: "text-ui-caption min-w-0", children: command.description })] }, command.id))) })), !compact && hasAttachments && (_jsx("div", { className: "flex max-h-32 gap-2 overflow-x-auto px-3 pt-3", children: imageAttachments.map((attachment) => (_jsxs("div", { className: "bg-muted/70 border-border rounded-container flex max-w-48 shrink-0 items-center gap-2 border p-1.5 pr-2", children: [_jsx("div", { className: "bg-background rounded-container flex size-9 shrink-0 items-center justify-center overflow-hidden border", children: attachment.previewUrl ? (_jsx("img", { src: attachment.previewUrl, alt: "", className: "size-full object-cover", draggable: false })) : (_jsx(ImageIcon, { className: "text-muted-foreground size-4" })) }), _jsx("span", { className: "text-ui-caption min-w-0 truncate font-medium", title: attachment.path, children: attachment.name }), onRemoveImageAttachment && (_jsx("button", { type: "button", onClick: () => onRemoveImageAttachment(attachment.id), className: "text-muted-foreground hover:bg-accent hover:text-foreground rounded-control flex size-6 shrink-0 cursor-pointer items-center justify-center transition-colors", "aria-label": `Remove ${attachment.name}`, children: _jsx(X, { className: "size-3.5" }) }))] }, attachment.id))) })), _jsx("div", { className: cn('w-full px-5', compact ? 'py-4' : 'pb-2 pt-4'), children: _jsx(Textarea, { ref: inputRef, value: input, placeholder: placeholder, onChange: onInputChange, onKeyDown: handleKeyDown, className: cn('text-ui-body max-h-32 min-h-[24px] resize-none rounded-none border-0 !bg-transparent p-0 shadow-none focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:!bg-transparent', compact && 'max-h-6 min-h-6') }) }), !compact && (_jsxs("div", { className: "flex min-h-11 items-center justify-between gap-3 px-3 pb-3", children: [_jsx("div", { className: "flex min-w-0 shrink-0 items-center justify-start gap-1", children: footerStartControls }), _jsx("div", { className: "min-w-0 flex-1" }), _jsx("div", { className: "flex min-w-0 shrink-0 items-center justify-end gap-0.5", children: footerControls }), _jsxs(Button, { type: showStopButton ? 'button' : 'submit', size: "icon", className: "bg-primary text-primary-foreground rounded-pill size-8 cursor-pointer hover:opacity-70 disabled:opacity-30", disabled: !canSubmit && !isResponding, onClick: handleButtonClick, children: [showStopButton ? (_jsx(Square, { className: "fill-primary-foreground size-4 animate-pulse" })) : (_jsx(ArrowUp, { className: "size-4" })), _jsx("span", { className: "sr-only", children: showStopButton
@@ -723,7 +723,7 @@ function PureMessage({ message, isLast = false, isStreaming = false, animateEntr
723
723
  });
724
724
  return next;
725
725
  });
726
- }, className: "mb-1 w-full", "data-ai-reasoning": true, "data-message-scroll-anchor": item.id, children: [_jsxs(CollapsibleTrigger, { className: cn('text-ui-body group flex max-w-full cursor-pointer items-center gap-1 py-0.5 font-normal leading-5 transition-colors', 'text-muted-foreground/75 hover:text-foreground/80 min-w-0'), children: [_jsx("span", { className: "flex-1 truncate", children: titleForTrigger }), _jsx(ChevronDown, { className: cn('size-3 shrink-0 opacity-0 transition-all duration-200 group-hover:opacity-70', isOpen && 'rotate-180 opacity-50') })] }), _jsx(CollapsibleContent, { className: "text-muted-foreground/75 text-ui-body min-w-0 overflow-hidden pb-1.5 pl-3 pt-0 leading-5", children: _jsx("div", { className: "max-h-72 space-y-0.5 overflow-y-auto pr-2", children: group.entries.map((entry) => (_jsx("div", { className: cn('min-w-0', entry.allowOverflow
726
+ }, className: "mb-1 w-full", "data-ai-reasoning": true, "data-message-scroll-anchor": item.id, children: [_jsxs(CollapsibleTrigger, { className: cn('group flex max-w-full cursor-pointer items-center gap-1 py-0.5 text-[10px] font-normal leading-4 transition-colors', 'text-muted-foreground/75 hover:text-foreground/80 min-w-0'), children: [_jsx("span", { className: "flex-1 truncate", children: titleForTrigger }), _jsx(ChevronDown, { className: cn('size-3 shrink-0 opacity-0 transition-all duration-200 group-hover:opacity-70', isOpen && 'rotate-180 opacity-50') })] }), _jsx(CollapsibleContent, { className: "text-muted-foreground/75 text-ui-body min-w-0 overflow-hidden pb-1.5 pl-3 pt-0 leading-5", children: _jsx("div", { className: "max-h-72 space-y-0.5 overflow-y-auto pr-2", children: group.entries.map((entry) => (_jsx("div", { className: cn('min-w-0', entry.allowOverflow
727
727
  ? 'overflow-visible'
728
728
  : 'overflow-hidden truncate', entry.isError && 'text-destructive'), children: entry.content }, entry.id))) }) })] }, item.id));
729
729
  }
@@ -1,3 +1,4 @@
1
+ export { classicOrbMaterialGlsl, DEFAULT_ORB_MATERIAL_ID, defaultOrbMaterialGlsl, getOrbMaterial, orbMaterials, type OrbMaterialDefinition, } from './orb-materials.js';
1
2
  export { ChatInput, type ChatImageAttachment, type ChatSlashCommandOption, type ChatSubmitMode, } from './chat-input.js';
2
3
  export { CompactingMessage, Message, ThinkingMessage, type ChatMessage, type ChatMessagePart, } from './chat-message.js';
3
4
  export { Messages, type MessageCheckpoint } from './chat-messages.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/chat/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC/E,OAAO,EACL,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAClE,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,6BAA6B,CAAA;AACpC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,oBAAoB,GACrB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,mBAAmB,GACpB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,4BAA4B,EAC5B,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/chat/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,cAAc,EACd,YAAY,EACZ,KAAK,qBAAqB,GAC3B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,SAAS,EACT,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC/E,OAAO,EACL,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAClE,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,6BAA6B,CAAA;AACpC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,oBAAoB,GACrB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,mBAAmB,GACpB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,4BAA4B,EAC5B,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAA"}
@@ -1,3 +1,4 @@
1
+ export { classicOrbMaterialGlsl, DEFAULT_ORB_MATERIAL_ID, defaultOrbMaterialGlsl, getOrbMaterial, orbMaterials, } from './orb-materials.js';
1
2
  export { ChatInput, } from './chat-input.js';
2
3
  export { CompactingMessage, Message, ThinkingMessage, } from './chat-message.js';
3
4
  export { Messages } from './chat-messages.js';
@@ -0,0 +1,14 @@
1
+ export interface OrbMaterialDefinition {
2
+ id: string;
3
+ label: string;
4
+ glsl: string;
5
+ /** CSS color for the component's halo, matched to the palette. */
6
+ glow: string;
7
+ }
8
+ export declare const classicOrbMaterialGlsl: string;
9
+ export declare const orbMaterials: OrbMaterialDefinition[];
10
+ export declare function getOrbMaterial(id: string): OrbMaterialDefinition;
11
+ export declare const DEFAULT_ORB_MATERIAL_ID = "creamish-red-blue";
12
+ export declare const defaultOrbMaterialGlsl: string;
13
+ export declare const defaultOrbMaterialGlow: string;
14
+ //# sourceMappingURL=orb-materials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orb-materials.d.ts","sourceRoot":"","sources":["../../../src/components/chat/orb-materials.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAA;CACb;AAiND,eAAO,MAAM,sBAAsB,QAAoC,CAAA;AAwJvE,eAAO,MAAM,YAAY,EAAE,qBAAqB,EAa/C,CAAA;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,CAEhE;AAID,eAAO,MAAM,uBAAuB,sBAAsB,CAAA;AAE1D,eAAO,MAAM,sBAAsB,QAE7B,CAAA;AAEN,eAAO,MAAM,sBAAsB,QAE7B,CAAA"}
@@ -0,0 +1,340 @@
1
+ // Orb MATERIAL registry (Rob, 2026-07-27): every entry is a GLSL chunk
2
+ // defining `vec3 orbMaterial(vec2 uvStart)` — the SINGLE SOURCE for the
3
+ // orb's surface everywhere: the production VoiceOrb composes its
4
+ // fragment shader from the classic chunk, and the desktop's liquid
5
+ // field renderer compiles whichever chunk it is handed (idle previews,
6
+ // birth mother and daughter, raindrop blooms). Main orb and spawn
7
+ // bodies can never drift apart — they are the same function.
8
+ //
9
+ // Chunk contract — the renderer's prelude provides:
10
+ // uniforms u_time, u_motionScale, u_micLevel, u_audio,
11
+ // u_cumulativeAudio, u_stateMuted, u_stateError
12
+ // helpers PI, rand(vec2), noise(vec2), fbm(vec2), cnoise(vec3),
13
+ // blendLinearBurn(vec3, vec3, float)
14
+ // uvStart 0..1 across the body's disc, y increasing UPWARD
15
+ // (pre-flip convention; classic flips internally).
16
+ // Every chunk should end with the muted/error mixes so voice states
17
+ // read consistently across materials.
18
+ // The classic pipeline is THE template: recolored materials swap only
19
+ // these palette stops — structure, motion, and texture stay identical
20
+ // (Rob, 2026-07-27: "use the same classic one but change colors").
21
+ function buildClassicChunk(palette) {
22
+ return `
23
+ vec3 orbMaterial(vec2 uvStart) {
24
+ float sound = max(max(u_audio.x, u_audio.y), max(u_audio.z, u_audio.w));
25
+ float audioEnergy = smoothstep(0.08, 0.72, max(sound, u_micLevel));
26
+ float animatedTime = u_time * u_motionScale;
27
+ vec2 uv = uvStart;${palette.flip ? '\n uv.y = 1.0 - uv.y;' : ''}
28
+ float soundScale = 1.0 + audioEnergy * 0.22;
29
+ float time = animatedTime * 0.34;
30
+ float noiseX = cnoise(vec3(
31
+ uv + vec2(0.0, 74.8572),
32
+ (time + u_cumulativeAudio.x * 0.05 * soundScale) * 0.3
33
+ ));
34
+ float noiseY = cnoise(vec3(
35
+ uv + vec2(203.91282, 10.0),
36
+ (time + u_cumulativeAudio.z * 0.05 * soundScale) * 0.3
37
+ ));
38
+ uv += vec2(noiseX * 2.0, noiseY) * 0.19;
39
+
40
+ float voiceWarpX = cnoise(vec3(
41
+ uv * 3.1 + vec2(0.0, 17.3),
42
+ u_cumulativeAudio.x * 0.085 + u_cumulativeAudio.z * 0.035
43
+ ));
44
+ float voiceWarpY = cnoise(vec3(
45
+ uv * 3.4 + vec2(31.7, 0.0),
46
+ u_cumulativeAudio.y * 0.075 + u_cumulativeAudio.w * 0.045
47
+ ));
48
+ uv += vec2(voiceWarpX, voiceWarpY) * audioEnergy * 0.04;
49
+ uv.y +=
50
+ sin(uv.x * 5.4 + u_cumulativeAudio.w * 0.19) *
51
+ audioEnergy *
52
+ 0.016;
53
+
54
+ float watercolor =
55
+ cnoise(vec3(uv * 18.0 + vec2(344.91282, 0.0), time * 0.3)) +
56
+ cnoise(vec3(uv * 39.6 + vec2(723.937, 0.0), time * 0.4)) * 0.5;
57
+ uv += watercolor * 0.006;
58
+
59
+ float textureA = noise(
60
+ uv * 22.0 + vec2(time * 0.08, u_cumulativeAudio.x * 0.025)
61
+ );
62
+ float textureB = noise(
63
+ vec2(1.0 - uv.x, uv.y) * 41.0 +
64
+ vec2(u_cumulativeAudio.z * 0.018, -time * 0.11)
65
+ );
66
+ float texture = mix(
67
+ textureA,
68
+ textureB,
69
+ sin(time + u_cumulativeAudio.w * 0.12) * 0.5 + 0.5
70
+ ) - 0.5;
71
+ uv += texture * (0.012 + audioEnergy * 0.004);
72
+
73
+ uv.y = 1.0 - uv.y;
74
+ vec2 centeredUv = uv - 0.5;
75
+ float angle = -0.16;
76
+ uv = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * centeredUv + 0.5;
77
+ uv.y -= 0.03;
78
+
79
+ vec2 stNoise = uv * 1.25;
80
+ vec2 q = vec2(
81
+ fbm(
82
+ stNoise * 0.5 +
83
+ 0.075 * (time + u_cumulativeAudio.w * 0.175 * soundScale)
84
+ ),
85
+ fbm(
86
+ stNoise * 0.5 +
87
+ 0.075 * (time + u_cumulativeAudio.x * 0.136 * soundScale)
88
+ )
89
+ );
90
+ vec2 r = vec2(
91
+ fbm(
92
+ stNoise + q + vec2(0.3, 9.2) +
93
+ 0.15 * (time + u_cumulativeAudio.y * 0.234 * soundScale)
94
+ ),
95
+ fbm(
96
+ stNoise + q + vec2(8.3, 0.8) +
97
+ 0.126 * (time + u_cumulativeAudio.z * 0.165 * soundScale)
98
+ )
99
+ );
100
+ float field = fbm(stNoise + r - q);
101
+ float fullField = pow(
102
+ ((field + 0.6 * field * field + 0.7 * field) + 0.5) * 0.5,
103
+ 0.55
104
+ );
105
+
106
+ vec3 mainColor = mix(
107
+ ${palette.mainA},
108
+ ${palette.mainB},
109
+ u_micLevel
110
+ );
111
+ vec3 lowColor = ${palette.low};
112
+ vec3 midColor = mix(
113
+ ${palette.midA},
114
+ ${palette.midB},
115
+ u_micLevel
116
+ );
117
+ vec3 highColor = ${palette.high};
118
+
119
+ vec3 offsets = vec3(
120
+ u_cumulativeAudio.x * 0.15 * soundScale,
121
+ -u_cumulativeAudio.y * 0.5 * soundScale,
122
+ u_cumulativeAudio.z * 1.5 * soundScale
123
+ );
124
+
125
+ vec2 lowUv = uv + vec2((fullField - 0.5) * 1.2, 0.025);
126
+ float lowNoise = noise(
127
+ lowUv * 2.0 + vec2(sin(offsets.x * 0.25), time * 0.5 + offsets.x)
128
+ ) * 2.0;
129
+ float lowMask = smoothstep(
130
+ lowNoise - 1.8,
131
+ lowNoise + 1.8,
132
+ ((lowUv.y - 0.5) * (5.0 - u_audio.x * 0.05 * soundScale)) + 0.5
133
+ );
134
+
135
+ vec2 midUv = uv + vec2((fullField - 0.5) * 0.85, 0.025);
136
+ float midNoise = noise(
137
+ midUv * 4.0 +
138
+ vec2(sin(offsets.y * 0.15) * 2.4 + 293.0, time + offsets.y * 0.5)
139
+ ) * 2.0;
140
+ float midMask = smoothstep(
141
+ midNoise - ((0.9 + u_audio.y * 0.4) * 1.5),
142
+ midNoise + ((0.9 + u_audio.y * 0.8) * 1.5),
143
+ ((midUv.y - 0.6) * (5.0 - u_audio.y * 0.75)) + 0.5
144
+ );
145
+
146
+ vec2 highUv = uv + vec2((fullField - 0.5) * 1.1);
147
+ float highNoise = noise(
148
+ highUv * 6.0 +
149
+ vec2(sin(offsets.z * 0.1) * 2.4 + 153.0, time * 1.2 + offsets.z * 0.8)
150
+ ) * 2.0;
151
+ float highMask = smoothstep(
152
+ highNoise - 1.05,
153
+ highNoise + 1.05,
154
+ ((highUv.y - 0.9) * 6.0) + 0.5
155
+ );
156
+
157
+ lowMask = pow(lowMask, 0.8);
158
+ midMask = pow(midMask, 0.9);
159
+ vec3 color = blendLinearBurn(mainColor, lowColor, 1.0 - lowMask);
160
+ color = blendLinearBurn(
161
+ color,
162
+ mix(mainColor, midColor, 1.0 - midMask),
163
+ lowMask
164
+ );
165
+ color = mix(
166
+ color,
167
+ mix(mainColor, highColor, 1.0 - highMask),
168
+ lowMask * midMask
169
+ );
170
+
171
+ float fineNoise = fbm(
172
+ uv * 12.0 + vec2(time * 0.13, -time * 0.09) + r * 0.4
173
+ );
174
+ color = mix(
175
+ color,
176
+ highColor,
177
+ smoothstep(0.58, 0.9, fineNoise) * (0.035 + audioEnergy * 0.025)
178
+ );
179
+ color = mix(
180
+ color,
181
+ lowColor,
182
+ smoothstep(0.42, 0.12, fineNoise) * 0.018
183
+ );
184
+
185
+ float luminance = dot(color, vec3(0.299, 0.587, 0.114));
186
+ color = mix(color, vec3(luminance), u_stateMuted * 0.72);
187
+ color = mix(color, vec3(1.0, 0.35, 0.31), u_stateError * 0.58);
188
+ return color;
189
+ }
190
+ `;
191
+ }
192
+ const classicPalette = {
193
+ mainA: 'vec3(0.94, 0.965, 1.0)',
194
+ mainB: 'vec3(1.0, 0.99, 0.96)',
195
+ low: 'vec3(0.36, 0.34, 0.96)',
196
+ midA: 'vec3(0.57, 0.64, 1.0)',
197
+ midB: 'vec3(0.96, 0.92, 1.0)',
198
+ high: 'vec3(1.0, 0.99, 0.97)',
199
+ };
200
+ export const classicOrbMaterialGlsl = buildClassicChunk(classicPalette);
201
+ function component(value) {
202
+ const rounded = Math.round(value * 1000) / 1000;
203
+ return Number.isInteger(rounded) ? rounded.toFixed(1) : String(rounded);
204
+ }
205
+ function vec3Literal(color) {
206
+ return `vec3(${component(color[0])}, ${component(color[1])}, ${component(color[2])})`;
207
+ }
208
+ function warmed(color) {
209
+ const warmWhite = [1.0, 0.99, 0.96];
210
+ return [
211
+ color[0] + (warmWhite[0] - color[0]) * 0.3,
212
+ color[1] + (warmWhite[1] - color[1]) * 0.3,
213
+ color[2] + (warmWhite[2] - color[2]) * 0.3,
214
+ ];
215
+ }
216
+ // Classic composes lows/mids through blendLinearBurn(main, c) = main +
217
+ // c - 1. Feed it the INVERSE of the target so the reference's field
218
+ // colors actually appear on screen instead of collapsing to black.
219
+ function burnInverse(target, main) {
220
+ return [
221
+ Math.min(1, Math.max(0, target[0] + 1 - main[0])),
222
+ Math.min(1, Math.max(0, target[1] + 1 - main[1])),
223
+ Math.min(1, Math.max(0, target[2] + 1 - main[2])),
224
+ ];
225
+ }
226
+ function buildRecolorChunk(params) {
227
+ return buildClassicChunk({
228
+ mainA: vec3Literal(params.main),
229
+ mainB: vec3Literal(warmed(params.main)),
230
+ low: vec3Literal(burnInverse(params.low, params.main)),
231
+ midA: vec3Literal(burnInverse(params.mid, params.main)),
232
+ midB: vec3Literal(warmed(burnInverse(params.mid, params.main))),
233
+ high: vec3Literal(params.high),
234
+ flip: params.flip,
235
+ });
236
+ }
237
+ // Palettes sampled from the reference images (~/Desktop/orbs/<id>.png).
238
+ const recolorMaterials = [
239
+ {
240
+ id: 'blueish-green',
241
+ label: 'Monet',
242
+ main: [0.94, 0.92, 0.7],
243
+ low: [0.08, 0.33, 0.62],
244
+ mid: [0.26, 0.7, 0.48],
245
+ high: [1.0, 0.98, 0.88],
246
+ },
247
+ {
248
+ id: 'blueish-red',
249
+ label: 'Matisse',
250
+ main: [0.98, 0.86, 0.84],
251
+ low: [0.93, 0.3, 0.26],
252
+ mid: [0.95, 0.62, 0.62],
253
+ high: [0.5, 0.76, 0.78],
254
+ },
255
+ {
256
+ id: 'creamish-red-blue',
257
+ label: 'Dawn',
258
+ main: [0.96, 0.85, 0.66],
259
+ low: [0.95, 0.38, 0.3],
260
+ mid: [0.97, 0.6, 0.45],
261
+ high: [1.0, 0.93, 0.8],
262
+ flip: true,
263
+ },
264
+ {
265
+ id: 'gold-blue',
266
+ label: 'Dusk',
267
+ main: [0.98, 0.84, 0.56],
268
+ low: [0.18, 0.24, 0.58],
269
+ mid: [0.92, 0.58, 0.24],
270
+ high: [1.0, 0.93, 0.75],
271
+ },
272
+ {
273
+ id: 'greenish',
274
+ label: 'Meadow',
275
+ main: [0.95, 0.93, 0.62],
276
+ low: [0.12, 0.55, 0.38],
277
+ mid: [0.55, 0.72, 0.85],
278
+ high: [1.0, 0.98, 0.85],
279
+ },
280
+ {
281
+ id: 'pinky',
282
+ label: 'Blush',
283
+ main: [0.99, 0.8, 0.76],
284
+ low: [0.66, 0.56, 0.82],
285
+ mid: [0.93, 0.55, 0.62],
286
+ high: [0.98, 0.55, 0.45],
287
+ flip: true,
288
+ },
289
+ {
290
+ id: 'purplish',
291
+ label: 'Fever',
292
+ main: [0.99, 0.74, 0.6],
293
+ low: [0.58, 0.42, 0.86],
294
+ mid: [0.95, 0.44, 0.62],
295
+ high: [1.0, 0.85, 0.72],
296
+ },
297
+ {
298
+ id: 'reddish-orange',
299
+ label: 'Ember',
300
+ main: [0.98, 0.84, 0.64],
301
+ low: [0.7, 0.18, 0.13],
302
+ mid: [0.95, 0.55, 0.2],
303
+ high: [1.0, 0.92, 0.7],
304
+ },
305
+ {
306
+ id: 'sunny',
307
+ label: 'Marigold',
308
+ main: [1.0, 0.87, 0.25],
309
+ low: [0.93, 0.4, 0.02],
310
+ mid: [0.98, 0.62, 0.05],
311
+ high: [1.0, 0.95, 0.5],
312
+ },
313
+ ];
314
+ // Halo tint derived from the palette's mid stop, lifted toward white.
315
+ function cssGlow(color) {
316
+ const lift = (value) => Math.round(Math.min(1, value * 0.65 + 0.35) * 255);
317
+ return `rgb(${lift(color[0])} ${lift(color[1])} ${lift(color[2])} / 55%)`;
318
+ }
319
+ export const orbMaterials = [
320
+ {
321
+ id: 'classic',
322
+ label: 'Classic',
323
+ glsl: classicOrbMaterialGlsl,
324
+ glow: 'rgb(154 154 249 / 55%)',
325
+ },
326
+ ...recolorMaterials.map((params) => ({
327
+ id: params.id,
328
+ label: params.label,
329
+ glsl: buildRecolorChunk(params),
330
+ glow: cssGlow(params.mid),
331
+ })),
332
+ ];
333
+ export function getOrbMaterial(id) {
334
+ return orbMaterials.find((material) => material.id === id) ?? orbMaterials[0];
335
+ }
336
+ // Dawn is the shipped default (Rob, 2026-07-27): the production
337
+ // VoiceOrb and the spawn renderer both compose from this chunk.
338
+ export const DEFAULT_ORB_MATERIAL_ID = 'creamish-red-blue';
339
+ export const defaultOrbMaterialGlsl = getOrbMaterial(DEFAULT_ORB_MATERIAL_ID).glsl;
340
+ export const defaultOrbMaterialGlow = getOrbMaterial(DEFAULT_ORB_MATERIAL_ID).glow;
@@ -1,3 +1,3 @@
1
1
  export declare const voiceOrbVertexShader = "\nattribute vec2 a_position;\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = (a_position + 1.0) * 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n";
2
- export declare const voiceOrbFragmentShader = "\nprecision highp float;\n\nvarying vec2 v_uv;\n\nuniform vec2 u_resolution;\nuniform float u_time;\nuniform float u_micLevel;\nuniform float u_outputLevel;\nuniform float u_stateListen;\nuniform float u_stateThink;\nuniform float u_stateSpeak;\nuniform float u_stateMuted;\nuniform float u_stateError;\nuniform float u_motionScale;\nuniform vec4 u_audio;\nuniform vec4 u_cumulativeAudio;\n\n#define PI 3.141592653589793\n#define NUM_OCTAVES 5\n\nfloat rand(vec2 n) {\n return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);\n}\n\nfloat noise(vec2 p) {\n vec2 ip = floor(p);\n vec2 u = fract(p);\n u = u * u * (3.0 - 2.0 * u);\n float value = mix(\n mix(rand(ip), rand(ip + vec2(1.0, 0.0)), u.x),\n mix(rand(ip + vec2(0.0, 1.0)), rand(ip + vec2(1.0, 1.0)), u.x),\n u.y\n );\n return value * value;\n}\n\nfloat fbm(vec2 point) {\n float value = 0.0;\n float amplitude = 0.5;\n vec2 shift = vec2(100.0);\n mat2 rotation = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5));\n for (int index = 0; index < NUM_OCTAVES; index++) {\n value += amplitude * noise(point);\n point = rotation * point * 2.0 + shift;\n amplitude *= 0.5;\n }\n return value;\n}\n\nvec3 blendLinearBurn(vec3 base, vec3 blend, float opacity) {\n vec3 burned = max(base + blend - vec3(1.0), vec3(0.0));\n return burned * opacity + base * (1.0 - opacity);\n}\n\nvec4 permute(vec4 value) {\n return mod((value * 34.0 + 1.0) * value, 289.0);\n}\n\nvec4 taylorInvSqrt(vec4 value) {\n return 1.79284291400159 - 0.85373472095314 * value;\n}\n\nvec3 fade(vec3 value) {\n return value * value * value * (value * (value * 6.0 - 15.0) + 10.0);\n}\n\nfloat cnoise(vec3 point) {\n vec3 cell0 = floor(point);\n vec3 cell1 = cell0 + vec3(1.0);\n cell0 = mod(cell0, 289.0);\n cell1 = mod(cell1, 289.0);\n vec3 offset0 = fract(point);\n vec3 offset1 = offset0 - vec3(1.0);\n vec4 x = vec4(cell0.x, cell1.x, cell0.x, cell1.x);\n vec4 y = vec4(cell0.yy, cell1.yy);\n vec4 z0 = vec4(cell0.z);\n vec4 z1 = vec4(cell1.z);\n vec4 xy = permute(permute(x) + y);\n vec4 xy0 = permute(xy + z0);\n vec4 xy1 = permute(xy + z1);\n\n vec4 gx0 = xy0 / 7.0;\n vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;\n gx0 = fract(gx0);\n vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);\n vec4 sz0 = step(gz0, vec4(0.0));\n gx0 -= sz0 * (step(vec4(0.0), gx0) - 0.5);\n gy0 -= sz0 * (step(vec4(0.0), gy0) - 0.5);\n\n vec4 gx1 = xy1 / 7.0;\n vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;\n gx1 = fract(gx1);\n vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);\n vec4 sz1 = step(gz1, vec4(0.0));\n gx1 -= sz1 * (step(vec4(0.0), gx1) - 0.5);\n gy1 -= sz1 * (step(vec4(0.0), gy1) - 0.5);\n\n vec3 g000 = vec3(gx0.x, gy0.x, gz0.x);\n vec3 g100 = vec3(gx0.y, gy0.y, gz0.y);\n vec3 g010 = vec3(gx0.z, gy0.z, gz0.z);\n vec3 g110 = vec3(gx0.w, gy0.w, gz0.w);\n vec3 g001 = vec3(gx1.x, gy1.x, gz1.x);\n vec3 g101 = vec3(gx1.y, gy1.y, gz1.y);\n vec3 g011 = vec3(gx1.z, gy1.z, gz1.z);\n vec3 g111 = vec3(gx1.w, gy1.w, gz1.w);\n\n vec4 norm0 = taylorInvSqrt(\n vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))\n );\n g000 *= norm0.x;\n g010 *= norm0.y;\n g100 *= norm0.z;\n g110 *= norm0.w;\n vec4 norm1 = taylorInvSqrt(\n vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))\n );\n g001 *= norm1.x;\n g011 *= norm1.y;\n g101 *= norm1.z;\n g111 *= norm1.w;\n\n float n000 = dot(g000, offset0);\n float n100 = dot(g100, vec3(offset1.x, offset0.yz));\n float n010 = dot(g010, vec3(offset0.x, offset1.y, offset0.z));\n float n110 = dot(g110, vec3(offset1.xy, offset0.z));\n float n001 = dot(g001, vec3(offset0.xy, offset1.z));\n float n101 = dot(g101, vec3(offset1.x, offset0.y, offset1.z));\n float n011 = dot(g011, vec3(offset0.x, offset1.yz));\n float n111 = dot(g111, offset1);\n\n vec3 fadePoint = fade(offset0);\n vec4 noiseZ = mix(\n vec4(n000, n100, n010, n110),\n vec4(n001, n101, n011, n111),\n fadePoint.z\n );\n vec2 noiseYZ = mix(noiseZ.xy, noiseZ.zw, fadePoint.y);\n return 2.2 * mix(noiseYZ.x, noiseYZ.y, fadePoint.x);\n}\n\nvoid main() {\n vec2 st = v_uv - 0.5;\n st.x *= u_resolution.x / u_resolution.y;\n\n float sound = max(max(u_audio.x, u_audio.y), max(u_audio.z, u_audio.w));\n float stateAmount = max(\n max(u_stateListen, u_stateThink),\n max(u_stateSpeak, max(u_stateMuted, u_stateError))\n );\n float audioEnergy = smoothstep(0.08, 0.72, max(sound, u_micLevel));\n float outputEnergy = smoothstep(0.04, 0.46, u_outputLevel);\n float animatedTime = u_time * u_motionScale;\n float breath = sin(animatedTime * PI * 0.34) * 0.5 + 0.5;\n float entry = smoothstep(0.0, 0.9, stateAmount);\n float maxRadius = min(\n 0.36,\n min(0.5, 0.5 * u_resolution.x / u_resolution.y) - 0.16\n );\n float baseRadius = mix(maxRadius * 0.88, maxRadius * 0.94, u_stateThink);\n float radius = baseRadius * mix(0.82, 1.0, entry);\n radius += outputEnergy * maxRadius * 0.12;\n radius +=\n (1.0 - u_stateThink) *\n (1.0 - outputEnergy) *\n breath *\n maxRadius *\n 0.01;\n radius = min(maxRadius, radius);\n\n vec2 drift = vec2(\n sin(animatedTime * 0.43) * 0.0028,\n sin(animatedTime * 0.36 + 1.7) * 0.0035\n );\n vec2 lifted = st - drift;\n float distanceToEdge = length(lifted) - radius;\n float edgeWidth = max(1.25 / min(u_resolution.x, u_resolution.y), 0.0014);\n if (distanceToEdge > edgeWidth) discard;\n float edge = 1.0 - smoothstep(-edgeWidth, edgeWidth, distanceToEdge);\n\n vec2 uv = lifted / (2.0 * radius) + 0.5;\n float soundScale = 1.0 + audioEnergy * 0.22;\n float time = animatedTime * 0.34;\n float noiseX = cnoise(vec3(\n uv + vec2(0.0, 74.8572),\n (time + u_cumulativeAudio.x * 0.05 * soundScale) * 0.3\n ));\n float noiseY = cnoise(vec3(\n uv + vec2(203.91282, 10.0),\n (time + u_cumulativeAudio.z * 0.05 * soundScale) * 0.3\n ));\n uv += vec2(noiseX * 2.0, noiseY) * 0.19;\n\n float voiceWarpX = cnoise(vec3(\n uv * 3.1 + vec2(0.0, 17.3),\n u_cumulativeAudio.x * 0.085 + u_cumulativeAudio.z * 0.035\n ));\n float voiceWarpY = cnoise(vec3(\n uv * 3.4 + vec2(31.7, 0.0),\n u_cumulativeAudio.y * 0.075 + u_cumulativeAudio.w * 0.045\n ));\n uv += vec2(voiceWarpX, voiceWarpY) * audioEnergy * 0.04;\n uv.y +=\n sin(uv.x * 5.4 + u_cumulativeAudio.w * 0.19) *\n audioEnergy *\n 0.016;\n\n float watercolor =\n cnoise(vec3(uv * 18.0 + vec2(344.91282, 0.0), time * 0.3)) +\n cnoise(vec3(uv * 39.6 + vec2(723.937, 0.0), time * 0.4)) * 0.5;\n uv += watercolor * 0.006;\n\n float textureA = noise(\n uv * 22.0 + vec2(time * 0.08, u_cumulativeAudio.x * 0.025)\n );\n float textureB = noise(\n vec2(1.0 - uv.x, uv.y) * 41.0 +\n vec2(u_cumulativeAudio.z * 0.018, -time * 0.11)\n );\n float texture = mix(\n textureA,\n textureB,\n sin(time + u_cumulativeAudio.w * 0.12) * 0.5 + 0.5\n ) - 0.5;\n uv += texture * (0.012 + audioEnergy * 0.004);\n\n uv.y = 1.0 - uv.y;\n vec2 centeredUv = uv - 0.5;\n float angle = -0.16;\n uv = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * centeredUv + 0.5;\n uv.y -= 0.03;\n\n vec2 stNoise = uv * 1.25;\n vec2 q = vec2(\n fbm(\n stNoise * 0.5 +\n 0.075 * (time + u_cumulativeAudio.w * 0.175 * soundScale)\n ),\n fbm(\n stNoise * 0.5 +\n 0.075 * (time + u_cumulativeAudio.x * 0.136 * soundScale)\n )\n );\n vec2 r = vec2(\n fbm(\n stNoise + q + vec2(0.3, 9.2) +\n 0.15 * (time + u_cumulativeAudio.y * 0.234 * soundScale)\n ),\n fbm(\n stNoise + q + vec2(8.3, 0.8) +\n 0.126 * (time + u_cumulativeAudio.z * 0.165 * soundScale)\n )\n );\n float field = fbm(stNoise + r - q);\n float fullField = pow(\n ((field + 0.6 * field * field + 0.7 * field) + 0.5) * 0.5,\n 0.55\n );\n\n vec3 mainColor = mix(\n vec3(0.94, 0.965, 1.0),\n vec3(1.0, 0.99, 0.96),\n u_micLevel\n );\n vec3 lowColor = vec3(0.36, 0.34, 0.96);\n vec3 midColor = mix(\n vec3(0.57, 0.64, 1.0),\n vec3(0.96, 0.92, 1.0),\n u_micLevel\n );\n vec3 highColor = vec3(1.0, 0.99, 0.97);\n\n vec3 offsets = vec3(\n u_cumulativeAudio.x * 0.15 * soundScale,\n -u_cumulativeAudio.y * 0.5 * soundScale,\n u_cumulativeAudio.z * 1.5 * soundScale\n );\n\n vec2 lowUv = uv + vec2((fullField - 0.5) * 1.2, 0.025);\n float lowNoise = noise(\n lowUv * 2.0 + vec2(sin(offsets.x * 0.25), time * 0.5 + offsets.x)\n ) * 2.0;\n float lowMask = smoothstep(\n lowNoise - 1.8,\n lowNoise + 1.8,\n ((lowUv.y - 0.5) * (5.0 - u_audio.x * 0.05 * soundScale)) + 0.5\n );\n\n vec2 midUv = uv + vec2((fullField - 0.5) * 0.85, 0.025);\n float midNoise = noise(\n midUv * 4.0 +\n vec2(sin(offsets.y * 0.15) * 2.4 + 293.0, time + offsets.y * 0.5)\n ) * 2.0;\n float midMask = smoothstep(\n midNoise - ((0.9 + u_audio.y * 0.4) * 1.5),\n midNoise + ((0.9 + u_audio.y * 0.8) * 1.5),\n ((midUv.y - 0.6) * (5.0 - u_audio.y * 0.75)) + 0.5\n );\n\n vec2 highUv = uv + vec2((fullField - 0.5) * 1.1);\n float highNoise = noise(\n highUv * 6.0 +\n vec2(sin(offsets.z * 0.1) * 2.4 + 153.0, time * 1.2 + offsets.z * 0.8)\n ) * 2.0;\n float highMask = smoothstep(\n highNoise - 1.05,\n highNoise + 1.05,\n ((highUv.y - 0.9) * 6.0) + 0.5\n );\n\n lowMask = pow(lowMask, 0.8);\n midMask = pow(midMask, 0.9);\n vec3 color = blendLinearBurn(mainColor, lowColor, 1.0 - lowMask);\n color = blendLinearBurn(\n color,\n mix(mainColor, midColor, 1.0 - midMask),\n lowMask\n );\n color = mix(\n color,\n mix(mainColor, highColor, 1.0 - highMask),\n lowMask * midMask\n );\n\n float fineNoise = fbm(\n uv * 12.0 + vec2(time * 0.13, -time * 0.09) + r * 0.4\n );\n color = mix(\n color,\n highColor,\n smoothstep(0.58, 0.9, fineNoise) * (0.035 + audioEnergy * 0.025)\n );\n color = mix(\n color,\n lowColor,\n smoothstep(0.42, 0.12, fineNoise) * 0.018\n );\n\n float luminance = dot(color, vec3(0.299, 0.587, 0.114));\n color = mix(color, vec3(luminance), u_stateMuted * 0.72);\n color = mix(color, vec3(1.0, 0.35, 0.31), u_stateError * 0.58);\n\n float alpha = edge * smoothstep(0.0, 0.18, stateAmount + 0.3);\n gl_FragColor = vec4(color, alpha);\n}\n";
2
+ export declare const voiceOrbFragmentShader: string;
3
3
  //# sourceMappingURL=voice-orb-shaders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"voice-orb-shaders.d.ts","sourceRoot":"","sources":["../../../src/components/chat/voice-orb-shaders.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,4JAQhC,CAAA;AAED,eAAO,MAAM,sBAAsB,g/TAyVlC,CAAA"}
1
+ {"version":3,"file":"voice-orb-shaders.d.ts","sourceRoot":"","sources":["../../../src/components/chat/voice-orb-shaders.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB,4JAQhC,CAAA;AAsMD,eAAO,MAAM,sBAAsB,QACsC,CAAA"}