@agent-native/core 0.80.0 → 0.80.2
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +28 -0
- package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +14 -1
- package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +15 -1
- package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +15 -1
- package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +15 -1
- package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +15 -1
- package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +16 -1
- package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +14 -1
- package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +14 -1
- package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +14 -1
- package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +14 -1
- package/corpus/core/docs/content/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/template-design.mdx +14 -1
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/application-state/handlers.ts +1 -1
- package/corpus/core/src/brand-kit/index.ts +1 -1
- package/corpus/core/src/cli/skills.ts +18 -0
- package/corpus/core/src/client/AgentPanel.tsx +1 -1
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +1 -1
- package/corpus/core/src/client/extensions/portable-extension.ts +1 -1
- package/corpus/core/src/code-agents/transcript-normalizer.ts +1 -1
- package/corpus/core/src/extensions/path.ts +1 -4
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +1 -1
- package/corpus/core/src/mcp/build-server.ts +2 -2
- package/corpus/core/src/mcp/embed-app.ts +35 -1
- package/corpus/core/src/org/handlers.ts +5 -5
- package/corpus/core/src/org/plugin.ts +2 -2
- package/corpus/core/src/scripts/call-agent.ts +1 -1
- package/corpus/core/src/scripts/db/safety.ts +1 -1
- package/corpus/core/src/server/auth.ts +3 -0
- package/corpus/core/src/server/builder-design-systems.ts +308 -0
- package/corpus/core/src/server/core-routes-plugin.ts +29 -3
- package/corpus/core/src/server/index.ts +8 -0
- package/corpus/core/src/styles/agent-native.css +14 -7
- package/corpus/core/src/usage/store.ts +2 -2
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +298 -15
- package/corpus/templates/analytics/actions/get-sql-dashboard.ts +9 -4
- package/corpus/templates/analytics/actions/mutate-dashboard.ts +18 -2
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +12 -2
- package/corpus/templates/analytics/app/hooks/use-replay-storage-status.ts +66 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +37 -0
- package/corpus/templates/analytics/app/i18n-data.ts +404 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +333 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +2 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +121 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +49 -26
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +137 -36
- package/corpus/templates/analytics/changelog/2026-06-29-analytics-agents-can-now-place-new-charts-into-requested-das.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-analytics-queries-now-report-failed-source-query-errors-inst.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-charts-can-now-be-dropped-between-full-dashboard-rows-to-cre.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-dashboard-email-reports-include-the-full-dashboard-image-wit.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-main-surface-border-reaches-the-top.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-session-replay-now-records-playable-sessions-in-production-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-set-up-session-replay-storage-from-settings-connect-builder-.md +6 -0
- package/corpus/templates/analytics/scripts/cleanup-empty-session-recordings.ts +102 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +49 -26
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +81 -20
- package/corpus/templates/analytics/server/lib/replay-storage.ts +79 -0
- package/corpus/templates/analytics/server/lib/s3-upload-provider.ts +255 -0
- package/corpus/templates/analytics/server/lib/session-replay.ts +29 -8
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -2
- package/corpus/templates/analytics/server/plugins/onboarding.ts +97 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +24 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +105 -5
- package/corpus/templates/content/actions/set-image-alt-text.ts +1 -1
- package/corpus/templates/content/shared/document-export.ts +1 -1
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -18
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +17 -0
- package/corpus/templates/design/actions/add-localhost-screens.ts +32 -5
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +259 -0
- package/corpus/templates/design/actions/update-file.ts +9 -2
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +33 -75
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +72 -9
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +41 -39
- package/corpus/templates/design/app/components/design/EditPanel.tsx +1029 -249
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +450 -101
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +978 -154
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -9
- package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +133 -66
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +1234 -344
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +144 -94
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +301 -72
- package/corpus/templates/design/app/components/design/inspector/FigmaColorPicker.tsx +876 -286
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +601 -0
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +242 -0
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +30 -7
- package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +212 -155
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +423 -0
- package/corpus/templates/design/app/components/design/inspector/figma-icons.tsx +487 -107
- package/corpus/templates/design/app/components/design/inspector/index.ts +27 -0
- package/corpus/templates/design/app/global.css +29 -3
- package/corpus/templates/design/app/i18n/zh-TW.ts +13 -0
- package/corpus/templates/design/app/i18n-data.ts +239 -1
- package/corpus/templates/design/app/pages/DesignEditor.tsx +1023 -353
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +57 -221
- package/corpus/templates/design/changelog/2026-06-29-canvas-selection-no-longer-flashes-broken-prototype-html-whe.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-command-menu-selections-are-clearer-in-dark-mode.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-element-selection-now-stays-on-the-intended-layer-after-sele.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-full-view-controls-now-sit-above-frames-inst.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-tools-can-draw-shapes-create-screens-and-kee.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-now-creates-anchor-based-bezier-vectors-with-ha.md +6 -0
- package/corpus/templates/design/server/handlers/import-figma-system.ts +38 -85
- package/corpus/templates/design/server/lib/design-snapshot.ts +9 -1
- package/corpus/templates/design/shared/code-layer.ts +209 -9
- package/corpus/templates/design/shared/html-content.ts +21 -0
- package/corpus/templates/design/shared/pen-path.ts +207 -0
- package/corpus/templates/mail/app/lib/utils.ts +2 -2
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -10
- package/corpus/templates/slides/AGENTS.md +3 -2
- package/corpus/templates/slides/actions/import-file.ts +26 -17
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +259 -0
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +35 -167
- package/corpus/templates/slides/app/components/design-system/fig-import-response.ts +9 -13
- package/corpus/templates/slides/app/context/DeckContext.tsx +1 -1
- package/corpus/templates/slides/app/i18n/ar-SA.ts +9 -37
- package/corpus/templates/slides/app/i18n/de-DE.ts +10 -25
- package/corpus/templates/slides/app/i18n/en-US.ts +9 -26
- package/corpus/templates/slides/app/i18n/es-ES.ts +10 -28
- package/corpus/templates/slides/app/i18n/fr-FR.ts +10 -28
- package/corpus/templates/slides/app/i18n/hi-IN.ts +9 -26
- package/corpus/templates/slides/app/i18n/ja-JP.ts +10 -22
- package/corpus/templates/slides/app/i18n/ko-KR.ts +9 -23
- package/corpus/templates/slides/app/i18n/pt-BR.ts +10 -28
- package/corpus/templates/slides/app/i18n/zh-CN.ts +9 -22
- package/corpus/templates/slides/app/i18n/zh-TW.ts +9 -22
- package/corpus/templates/slides/server/handlers/import-figma-system.ts +44 -12
- package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
- package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +1 -1
- package/dist/application-state/handlers.js +1 -1
- package/dist/application-state/handlers.js.map +1 -1
- package/dist/brand-kit/index.d.ts +1 -1
- package/dist/brand-kit/index.js +1 -1
- package/dist/brand-kit/index.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +18 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.js +1 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +1 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts +1 -1
- package/dist/client/extensions/portable-extension.d.ts.map +1 -1
- package/dist/client/extensions/portable-extension.js.map +1 -1
- package/dist/code-agents/transcript-normalizer.js +1 -1
- package/dist/code-agents/transcript-normalizer.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/extensions/path.d.ts +1 -1
- package/dist/extensions/path.d.ts.map +1 -1
- package/dist/extensions/path.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/integrations/a2a-continuation-processor.js +1 -1
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/mcp/build-server.d.ts +1 -1
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +1 -1
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/embed-app.d.ts.map +1 -1
- package/dist/mcp/embed-app.js +35 -1
- package/dist/mcp/embed-app.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +8 -8
- package/dist/org/handlers.js +5 -5
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/plugin.js +2 -2
- package/dist/org/plugin.js.map +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/call-agent.js +1 -1
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/db/safety.js +1 -1
- package/dist/scripts/db/safety.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +3 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-design-systems.d.ts +28 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -0
- package/dist/server/builder-design-systems.js +217 -0
- package/dist/server/builder-design-systems.js.map +1 -0
- package/dist/server/core-routes-plugin.d.ts +1 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +20 -3
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/styles/agent-native.css +14 -7
- package/dist/usage/store.js +2 -2
- package/dist/usage/store.js.map +1 -1
- package/docs/content/locales/ar-SA/skills-guide.mdx +5 -0
- package/docs/content/locales/ar-SA/template-design.mdx +14 -1
- package/docs/content/locales/de-DE/skills-guide.mdx +5 -0
- package/docs/content/locales/de-DE/template-design.mdx +15 -1
- package/docs/content/locales/es-ES/skills-guide.mdx +5 -0
- package/docs/content/locales/es-ES/template-design.mdx +15 -1
- package/docs/content/locales/fr-FR/skills-guide.mdx +5 -0
- package/docs/content/locales/fr-FR/template-design.mdx +15 -1
- package/docs/content/locales/hi-IN/skills-guide.mdx +5 -0
- package/docs/content/locales/hi-IN/template-design.mdx +15 -1
- package/docs/content/locales/ja-JP/skills-guide.mdx +5 -0
- package/docs/content/locales/ja-JP/template-design.mdx +16 -1
- package/docs/content/locales/ko-KR/skills-guide.mdx +5 -0
- package/docs/content/locales/ko-KR/template-design.mdx +14 -1
- package/docs/content/locales/pt-BR/skills-guide.mdx +5 -0
- package/docs/content/locales/pt-BR/template-design.mdx +14 -1
- package/docs/content/locales/zh-CN/skills-guide.mdx +5 -0
- package/docs/content/locales/zh-CN/template-design.mdx +14 -1
- package/docs/content/locales/zh-TW/skills-guide.mdx +5 -0
- package/docs/content/locales/zh-TW/template-design.mdx +14 -1
- package/docs/content/skills-guide.mdx +5 -0
- package/docs/content/template-design.mdx +14 -1
- package/package.json +1 -1
- package/corpus/templates/design/actions/import-figma-file.ts +0 -166
- package/corpus/templates/slides/server/lib/fig-design-system.ts +0 -110
|
@@ -16,9 +16,14 @@ import {
|
|
|
16
16
|
type ShaderPresetDef,
|
|
17
17
|
type ShaderPresetName,
|
|
18
18
|
} from "@shared/shader-presets";
|
|
19
|
+
import {
|
|
20
|
+
buildFallbackGradient,
|
|
21
|
+
isWebGLAvailable,
|
|
22
|
+
prefersReducedMotion,
|
|
23
|
+
} from "@shared/shader-safety";
|
|
24
|
+
import { IconArrowLeft, IconX } from "@tabler/icons-react";
|
|
19
25
|
import { useMemo, useState } from "react";
|
|
20
26
|
|
|
21
|
-
import { Button } from "@/components/ui/button";
|
|
22
27
|
import { Label } from "@/components/ui/label";
|
|
23
28
|
import {
|
|
24
29
|
Select,
|
|
@@ -35,7 +40,7 @@ import {
|
|
|
35
40
|
} from "@/components/ui/tooltip";
|
|
36
41
|
import { cn } from "@/lib/utils";
|
|
37
42
|
|
|
38
|
-
import { ScrubInput } from "./ScrubInput";
|
|
43
|
+
import { type ScrubInputChangeMeta, ScrubInput } from "./ScrubInput";
|
|
39
44
|
|
|
40
45
|
// ---------------------------------------------------------------------------
|
|
41
46
|
// Dynamic shader component map
|
|
@@ -55,15 +60,6 @@ const SHADER_COMPONENTS: Record<ShaderPresetName, AnyShaderComponent> = {
|
|
|
55
60
|
PaperTexture: PaperTexture as AnyShaderComponent,
|
|
56
61
|
};
|
|
57
62
|
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
// Reduced-motion helper (inline, SSR-safe)
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
|
|
62
|
-
function getPreferreducedMotion(): boolean {
|
|
63
|
-
if (typeof window === "undefined") return false;
|
|
64
|
-
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
63
|
// ---------------------------------------------------------------------------
|
|
68
64
|
// ShaderPreview sub-component
|
|
69
65
|
// ---------------------------------------------------------------------------
|
|
@@ -76,6 +72,7 @@ interface ShaderPreviewProps {
|
|
|
76
72
|
function ShaderPreview({ descriptor, animated }: ShaderPreviewProps) {
|
|
77
73
|
const preset = SHADER_PRESET_MAP[descriptor.preset];
|
|
78
74
|
const ShaderComponent = SHADER_COMPONENTS[descriptor.preset];
|
|
75
|
+
const webglOk = isWebGLAvailable();
|
|
79
76
|
|
|
80
77
|
// Build props — memoized to avoid identity churn on the WebGL layer
|
|
81
78
|
const shaderProps = useMemo(() => {
|
|
@@ -92,20 +89,38 @@ function ShaderPreview({ descriptor, animated }: ShaderPreviewProps) {
|
|
|
92
89
|
}, [descriptor, animated]);
|
|
93
90
|
|
|
94
91
|
// Fallback gradient from the preset's default colors
|
|
95
|
-
const fallbackColors =
|
|
96
|
-
(preset?.defaultColors ?? preset?.defaultColorBack)
|
|
97
|
-
? [preset.defaultColorBack ?? "#555", preset.defaultColors?.[0] ?? "#888"]
|
|
98
|
-
: ["#555555", "#888888"];
|
|
99
|
-
|
|
100
92
|
const fallbackStyle = {
|
|
101
|
-
background:
|
|
93
|
+
background: buildFallbackGradient(
|
|
94
|
+
preset?.defaultColors ?? [],
|
|
95
|
+
preset?.defaultColorBack,
|
|
96
|
+
),
|
|
102
97
|
};
|
|
103
98
|
|
|
99
|
+
const fallbackEl = (
|
|
100
|
+
<Tooltip>
|
|
101
|
+
<TooltipTrigger asChild>
|
|
102
|
+
<div
|
|
103
|
+
className="w-full rounded-lg"
|
|
104
|
+
style={{ aspectRatio: "16 / 9", ...fallbackStyle }}
|
|
105
|
+
/>
|
|
106
|
+
</TooltipTrigger>
|
|
107
|
+
<TooltipContent>
|
|
108
|
+
{
|
|
109
|
+
"WebGL unavailable – showing fallback" /* i18n-ignore shader tooltip */
|
|
110
|
+
}
|
|
111
|
+
</TooltipContent>
|
|
112
|
+
</Tooltip>
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (!webglOk) {
|
|
116
|
+
return fallbackEl;
|
|
117
|
+
}
|
|
118
|
+
|
|
104
119
|
try {
|
|
105
120
|
return (
|
|
106
121
|
<div
|
|
107
|
-
className="relative overflow-hidden rounded"
|
|
108
|
-
style={{
|
|
122
|
+
className="relative w-full overflow-hidden rounded-lg"
|
|
123
|
+
style={{ aspectRatio: "16 / 9" }}
|
|
109
124
|
>
|
|
110
125
|
<ShaderComponent
|
|
111
126
|
{...shaderProps}
|
|
@@ -119,24 +134,62 @@ function ShaderPreview({ descriptor, animated }: ShaderPreviewProps) {
|
|
|
119
134
|
</div>
|
|
120
135
|
);
|
|
121
136
|
} catch {
|
|
122
|
-
return
|
|
123
|
-
<Tooltip>
|
|
124
|
-
<TooltipTrigger asChild>
|
|
125
|
-
<div
|
|
126
|
-
className="rounded"
|
|
127
|
-
style={{ width: 120, height: 80, ...fallbackStyle }}
|
|
128
|
-
/>
|
|
129
|
-
</TooltipTrigger>
|
|
130
|
-
<TooltipContent>
|
|
131
|
-
{
|
|
132
|
-
"WebGL unavailable - showing fallback" /* i18n-ignore shader tooltip */
|
|
133
|
-
}
|
|
134
|
-
</TooltipContent>
|
|
135
|
-
</Tooltip>
|
|
136
|
-
);
|
|
137
|
+
return fallbackEl;
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// Shared row wrapper: label-left, control-right, h-6 density
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
function ParamLabel({ children }: { children: React.ReactNode }) {
|
|
146
|
+
return (
|
|
147
|
+
<span className="w-[5.5rem] shrink-0 truncate text-[11px] text-muted-foreground">
|
|
148
|
+
{children}
|
|
149
|
+
</span>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// Color swatch button — Figma style: rounded rect swatch + hex label inline
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
|
|
157
|
+
interface ColorSwatchProps {
|
|
158
|
+
color: string;
|
|
159
|
+
label: string;
|
|
160
|
+
onChange: (value: string) => void;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function ColorSwatch({ color, label, onChange }: ColorSwatchProps) {
|
|
164
|
+
return (
|
|
165
|
+
<Tooltip>
|
|
166
|
+
<TooltipTrigger asChild>
|
|
167
|
+
{/* The label wraps the native color input so clicking the swatch opens the picker */}
|
|
168
|
+
<label
|
|
169
|
+
className="flex h-6 min-w-0 cursor-pointer items-center gap-1.5 rounded px-1 text-[11px] text-muted-foreground transition-colors hover:bg-[var(--design-editor-control-bg)] hover:text-foreground focus-within:bg-[var(--design-editor-control-bg)]"
|
|
170
|
+
title={label}
|
|
171
|
+
>
|
|
172
|
+
<span
|
|
173
|
+
className="inline-block size-4 shrink-0 rounded-[3px] border border-black/20 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.15)]"
|
|
174
|
+
style={{ background: color }}
|
|
175
|
+
/>
|
|
176
|
+
<span className="min-w-0 truncate font-mono uppercase">
|
|
177
|
+
{color.startsWith("#") ? color.slice(1).toUpperCase() : color}
|
|
178
|
+
</span>
|
|
179
|
+
<input
|
|
180
|
+
type="color"
|
|
181
|
+
value={color}
|
|
182
|
+
onChange={(e) => onChange(e.target.value)}
|
|
183
|
+
className="sr-only"
|
|
184
|
+
aria-label={label}
|
|
185
|
+
/>
|
|
186
|
+
</label>
|
|
187
|
+
</TooltipTrigger>
|
|
188
|
+
<TooltipContent>{label}</TooltipContent>
|
|
189
|
+
</Tooltip>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
140
193
|
// ---------------------------------------------------------------------------
|
|
141
194
|
// Param row renderers
|
|
142
195
|
// ---------------------------------------------------------------------------
|
|
@@ -159,7 +212,7 @@ function ParamRow({ paramDef, value, onChange }: ParamRowProps) {
|
|
|
159
212
|
min={min}
|
|
160
213
|
max={max}
|
|
161
214
|
step={step ?? 1}
|
|
162
|
-
onChange={(v) => onChange(key, v)}
|
|
215
|
+
onChange={(v: number, _meta: ScrubInputChangeMeta) => onChange(key, v)}
|
|
163
216
|
className="w-full"
|
|
164
217
|
/>
|
|
165
218
|
);
|
|
@@ -168,17 +221,15 @@ function ParamRow({ paramDef, value, onChange }: ParamRowProps) {
|
|
|
168
221
|
if (kind === "enum") {
|
|
169
222
|
const strVal = typeof value === "string" ? value : String(paramDef.default);
|
|
170
223
|
return (
|
|
171
|
-
<div className="flex items-center gap-
|
|
172
|
-
<
|
|
173
|
-
{label}
|
|
174
|
-
</span>
|
|
224
|
+
<div className="flex h-6 items-center gap-1.5">
|
|
225
|
+
<ParamLabel>{label}</ParamLabel>
|
|
175
226
|
<Select value={strVal} onValueChange={(v) => onChange(key, v)}>
|
|
176
|
-
<SelectTrigger className="h-
|
|
227
|
+
<SelectTrigger className="h-6 flex-1 text-[11px]">
|
|
177
228
|
<SelectValue />
|
|
178
229
|
</SelectTrigger>
|
|
179
230
|
<SelectContent>
|
|
180
231
|
{(options ?? []).map((opt: string) => (
|
|
181
|
-
<SelectItem key={opt} value={opt} className="text-
|
|
232
|
+
<SelectItem key={opt} value={opt} className="text-[11px]">
|
|
182
233
|
{opt}
|
|
183
234
|
</SelectItem>
|
|
184
235
|
))}
|
|
@@ -193,15 +244,15 @@ function ParamRow({ paramDef, value, onChange }: ParamRowProps) {
|
|
|
193
244
|
typeof value === "boolean" ? value : Boolean(paramDef.default);
|
|
194
245
|
const switchId = `shader-param-${key}`;
|
|
195
246
|
return (
|
|
196
|
-
<div className="flex items-center justify-between gap-
|
|
197
|
-
<Label htmlFor={switchId} className="text-
|
|
247
|
+
<div className="flex h-6 items-center justify-between gap-1.5">
|
|
248
|
+
<Label htmlFor={switchId} className="text-[11px] text-muted-foreground">
|
|
198
249
|
{label}
|
|
199
250
|
</Label>
|
|
200
251
|
<Switch
|
|
201
252
|
id={switchId}
|
|
202
253
|
checked={boolVal}
|
|
203
254
|
onCheckedChange={(checked) => onChange(key, checked)}
|
|
204
|
-
className="scale-
|
|
255
|
+
className="origin-right scale-[0.8]"
|
|
205
256
|
/>
|
|
206
257
|
</div>
|
|
207
258
|
);
|
|
@@ -210,23 +261,13 @@ function ParamRow({ paramDef, value, onChange }: ParamRowProps) {
|
|
|
210
261
|
if (kind === "color") {
|
|
211
262
|
const strVal = typeof value === "string" ? value : String(paramDef.default);
|
|
212
263
|
return (
|
|
213
|
-
<div className="flex items-center gap-
|
|
214
|
-
<
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
type="color"
|
|
221
|
-
value={strVal}
|
|
222
|
-
onChange={(e) => onChange(key, e.target.value)}
|
|
223
|
-
className="h-7 w-8 cursor-pointer rounded border border-border bg-transparent p-0.5"
|
|
224
|
-
aria-label={label}
|
|
225
|
-
/>
|
|
226
|
-
</TooltipTrigger>
|
|
227
|
-
<TooltipContent>{label}</TooltipContent>
|
|
228
|
-
</Tooltip>
|
|
229
|
-
<span className="text-[10px] text-muted-foreground">{strVal}</span>
|
|
264
|
+
<div className="flex h-6 items-center gap-1.5">
|
|
265
|
+
<ParamLabel>{label}</ParamLabel>
|
|
266
|
+
<ColorSwatch
|
|
267
|
+
color={strVal}
|
|
268
|
+
label={label}
|
|
269
|
+
onChange={(v) => onChange(key, v)}
|
|
270
|
+
/>
|
|
230
271
|
</div>
|
|
231
272
|
);
|
|
232
273
|
}
|
|
@@ -238,28 +279,24 @@ function ParamRow({ paramDef, value, onChange }: ParamRowProps) {
|
|
|
238
279
|
const limit = maxCount ?? 10;
|
|
239
280
|
return (
|
|
240
281
|
<div className="flex flex-col gap-1">
|
|
241
|
-
|
|
242
|
-
<
|
|
282
|
+
{/* Section label sits at the top of the stop list */}
|
|
283
|
+
<span className="text-[11px] text-muted-foreground">{label}</span>
|
|
284
|
+
{/* Color stop rows — each a swatch + hex + remove button */}
|
|
285
|
+
<div className="flex flex-col gap-0.5">
|
|
243
286
|
{arrVal.map((color, i) => {
|
|
244
287
|
const colorLabel = `Color ${i + 1}`;
|
|
245
288
|
return (
|
|
246
|
-
<div key={i} className="flex items-center gap-
|
|
247
|
-
<
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
className="h-6 w-6 cursor-pointer rounded border border-border bg-transparent p-0"
|
|
258
|
-
aria-label={colorLabel}
|
|
259
|
-
/>
|
|
260
|
-
</TooltipTrigger>
|
|
261
|
-
<TooltipContent>{colorLabel}</TooltipContent>
|
|
262
|
-
</Tooltip>
|
|
289
|
+
<div key={i} className="flex h-6 items-center gap-1">
|
|
290
|
+
<ColorSwatch
|
|
291
|
+
color={color}
|
|
292
|
+
label={colorLabel}
|
|
293
|
+
onChange={(v) => {
|
|
294
|
+
const next = [...arrVal];
|
|
295
|
+
next[i] = v;
|
|
296
|
+
onChange(key, next);
|
|
297
|
+
}}
|
|
298
|
+
/>
|
|
299
|
+
<span className="flex-1" />
|
|
263
300
|
{arrVal.length > 1 && (
|
|
264
301
|
<Tooltip>
|
|
265
302
|
<TooltipTrigger asChild>
|
|
@@ -269,12 +306,12 @@ function ParamRow({ paramDef, value, onChange }: ParamRowProps) {
|
|
|
269
306
|
const next = arrVal.filter((_, idx) => idx !== i);
|
|
270
307
|
onChange(key, next);
|
|
271
308
|
}}
|
|
272
|
-
className="
|
|
309
|
+
className="flex size-4 items-center justify-center rounded text-muted-foreground hover:text-destructive focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
273
310
|
aria-label={
|
|
274
311
|
"Remove color" /* i18n-ignore shader tooltip */
|
|
275
312
|
}
|
|
276
313
|
>
|
|
277
|
-
|
|
314
|
+
<IconX className="size-2.5" />
|
|
278
315
|
</button>
|
|
279
316
|
</TooltipTrigger>
|
|
280
317
|
<TooltipContent>
|
|
@@ -286,14 +323,18 @@ function ParamRow({ paramDef, value, onChange }: ParamRowProps) {
|
|
|
286
323
|
);
|
|
287
324
|
})}
|
|
288
325
|
{arrVal.length < limit && (
|
|
289
|
-
<
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
className="h-6 px-2 text-[10px]"
|
|
326
|
+
<button
|
|
327
|
+
type="button"
|
|
328
|
+
className="flex h-6 items-center gap-1.5 rounded px-1 text-[11px] text-muted-foreground hover:bg-[var(--design-editor-control-bg)] hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
293
329
|
onClick={() => onChange(key, [...arrVal, "#ffffff"])}
|
|
294
330
|
>
|
|
295
|
-
|
|
296
|
-
|
|
331
|
+
<span className="flex size-4 shrink-0 items-center justify-center rounded-[3px] border border-dashed border-muted-foreground/50 text-[10px]">
|
|
332
|
+
+
|
|
333
|
+
</span>
|
|
334
|
+
<span>
|
|
335
|
+
{"Add color" /* i18n-ignore shader compact add button */}
|
|
336
|
+
</span>
|
|
337
|
+
</button>
|
|
297
338
|
)}
|
|
298
339
|
</div>
|
|
299
340
|
</div>
|
|
@@ -310,18 +351,21 @@ function ParamRow({ paramDef, value, onChange }: ParamRowProps) {
|
|
|
310
351
|
export interface ShaderControlsProps {
|
|
311
352
|
descriptor: ShaderDescriptor;
|
|
312
353
|
onChange: (descriptor: ShaderDescriptor) => void;
|
|
354
|
+
/** Optional callback to navigate back to the preset browser. */
|
|
355
|
+
onBack?: () => void;
|
|
313
356
|
className?: string;
|
|
314
357
|
}
|
|
315
358
|
|
|
316
359
|
export function ShaderControls({
|
|
317
360
|
descriptor,
|
|
318
361
|
onChange,
|
|
362
|
+
onBack,
|
|
319
363
|
className,
|
|
320
364
|
}: ShaderControlsProps) {
|
|
321
|
-
const
|
|
365
|
+
const reducedMotion = prefersReducedMotion();
|
|
322
366
|
|
|
323
367
|
const [animated, setAnimated] = useState(
|
|
324
|
-
() => (descriptor.speed ?? 0) !== 0 && !
|
|
368
|
+
() => (descriptor.speed ?? 0) !== 0 && !reducedMotion,
|
|
325
369
|
);
|
|
326
370
|
|
|
327
371
|
const preset = SHADER_PRESET_MAP[descriptor.preset];
|
|
@@ -397,31 +441,43 @@ export function ShaderControls({
|
|
|
397
441
|
}
|
|
398
442
|
}
|
|
399
443
|
|
|
400
|
-
function handleSpeedChange(v: number) {
|
|
444
|
+
function handleSpeedChange(v: number, _meta: ScrubInputChangeMeta) {
|
|
401
445
|
onChange({ ...descriptor, speed: v });
|
|
402
446
|
}
|
|
403
447
|
|
|
404
448
|
const animateSwitchId = "shader-animate";
|
|
405
449
|
|
|
406
450
|
return (
|
|
407
|
-
<div
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
451
|
+
<div className={cn("flex flex-col gap-0", className)}>
|
|
452
|
+
{/* ── Live preview ─ full-width, rounded, sits at top ─────────────── */}
|
|
453
|
+
<div className="px-3 pb-2 pt-1">
|
|
454
|
+
<ShaderPreview descriptor={descriptor} animated={animated} />
|
|
455
|
+
</div>
|
|
456
|
+
|
|
457
|
+
{/* ── "Back to presets" affordance ─────────────────────────────────── */}
|
|
458
|
+
{onBack && (
|
|
459
|
+
<div className="px-3 pb-1.5">
|
|
460
|
+
<button
|
|
461
|
+
type="button"
|
|
462
|
+
onClick={onBack}
|
|
463
|
+
className="flex h-6 items-center gap-1 rounded px-1 text-[11px] text-muted-foreground hover:bg-[var(--design-editor-control-bg)] hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
464
|
+
>
|
|
465
|
+
<IconArrowLeft className="size-3" />
|
|
466
|
+
<span>{"Back to presets" /* i18n-ignore shader nav */}</span>
|
|
467
|
+
</button>
|
|
468
|
+
</div>
|
|
411
469
|
)}
|
|
412
|
-
|
|
413
|
-
{/* Preset picker */}
|
|
414
|
-
<div className="flex
|
|
415
|
-
<
|
|
416
|
-
Preset
|
|
417
|
-
</span>
|
|
470
|
+
|
|
471
|
+
{/* ── Preset picker ────────────────────────────────────────────────── */}
|
|
472
|
+
<div className="flex h-6 items-center gap-1.5 px-3">
|
|
473
|
+
<ParamLabel>{"Preset" /* i18n-ignore */}</ParamLabel>
|
|
418
474
|
<Select value={descriptor.preset} onValueChange={handlePresetChange}>
|
|
419
|
-
<SelectTrigger className="h-
|
|
475
|
+
<SelectTrigger className="h-6 flex-1 text-[11px]">
|
|
420
476
|
<SelectValue />
|
|
421
477
|
</SelectTrigger>
|
|
422
478
|
<SelectContent>
|
|
423
479
|
{(SHADER_PRESETS as readonly ShaderPresetDef[]).map((p) => (
|
|
424
|
-
<SelectItem key={p.name} value={p.name} className="text-
|
|
480
|
+
<SelectItem key={p.name} value={p.name} className="text-[11px]">
|
|
425
481
|
{p.label}
|
|
426
482
|
</SelectItem>
|
|
427
483
|
))}
|
|
@@ -429,85 +485,86 @@ export function ShaderControls({
|
|
|
429
485
|
</Select>
|
|
430
486
|
</div>
|
|
431
487
|
|
|
432
|
-
{/*
|
|
433
|
-
<div className="flex justify-
|
|
434
|
-
<ShaderPreview descriptor={descriptor} animated={animated} />
|
|
435
|
-
</div>
|
|
436
|
-
|
|
437
|
-
{/* Animate toggle */}
|
|
438
|
-
<div className="flex items-center justify-between gap-2">
|
|
488
|
+
{/* ── Animate toggle ───────────────────────────────────────────────── */}
|
|
489
|
+
<div className="flex h-6 items-center justify-between gap-1.5 px-3 pt-1">
|
|
439
490
|
<Label
|
|
440
491
|
htmlFor={animateSwitchId}
|
|
441
492
|
className={cn(
|
|
442
|
-
"text-
|
|
443
|
-
|
|
493
|
+
"text-[11px] text-muted-foreground",
|
|
494
|
+
reducedMotion && "opacity-50",
|
|
444
495
|
)}
|
|
445
496
|
>
|
|
446
|
-
Animate
|
|
447
|
-
{
|
|
448
|
-
<span className="ml-1 text-[10px]">
|
|
497
|
+
{"Animate" /* i18n-ignore shader label */}
|
|
498
|
+
{reducedMotion && (
|
|
499
|
+
<span className="ml-1 text-[10px]">
|
|
500
|
+
{"(reduced motion)" /* i18n-ignore */}
|
|
501
|
+
</span>
|
|
449
502
|
)}
|
|
450
503
|
</Label>
|
|
451
504
|
<Switch
|
|
452
505
|
id={animateSwitchId}
|
|
453
506
|
checked={animated}
|
|
454
507
|
onCheckedChange={handleAnimatedChange}
|
|
455
|
-
disabled={
|
|
456
|
-
className="scale-
|
|
508
|
+
disabled={reducedMotion}
|
|
509
|
+
className="origin-right scale-[0.8]"
|
|
457
510
|
/>
|
|
458
511
|
</div>
|
|
459
512
|
|
|
460
|
-
{/* Speed scrub — only when animating */}
|
|
513
|
+
{/* ── Speed scrub — only when animating ───────────────────────────── */}
|
|
461
514
|
{animated && (
|
|
462
|
-
<
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
515
|
+
<div className="px-3 pt-1">
|
|
516
|
+
<ScrubInput
|
|
517
|
+
label="Speed"
|
|
518
|
+
value={descriptor.speed ?? 1}
|
|
519
|
+
min={-5}
|
|
520
|
+
max={5}
|
|
521
|
+
step={0.1}
|
|
522
|
+
onChange={handleSpeedChange}
|
|
523
|
+
className="w-full"
|
|
524
|
+
/>
|
|
525
|
+
</div>
|
|
471
526
|
)}
|
|
472
527
|
|
|
473
|
-
{/* Shader-specific params */}
|
|
528
|
+
{/* ── Shader-specific params ───────────────────────────────────────── */}
|
|
474
529
|
{preset && preset.params.length > 0 && (
|
|
475
|
-
|
|
476
|
-
<
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
530
|
+
<>
|
|
531
|
+
<div className="mx-3 mb-1 mt-2 border-t border-border/40" />
|
|
532
|
+
<div className="flex flex-col gap-1 px-3 pb-2">
|
|
533
|
+
{preset.params.map((paramDef: ParamDef) => {
|
|
534
|
+
if (paramDef.kind === "colors") {
|
|
535
|
+
// Resolve the current color array
|
|
536
|
+
const val: string[] =
|
|
537
|
+
descriptor.colors ?? preset.defaultColors ?? [];
|
|
538
|
+
return (
|
|
539
|
+
<ParamRow
|
|
540
|
+
key={paramDef.key}
|
|
541
|
+
paramDef={paramDef}
|
|
542
|
+
value={val}
|
|
543
|
+
onChange={(k, v) =>
|
|
544
|
+
handleColorsParamChange(k, v as string[])
|
|
545
|
+
}
|
|
546
|
+
/>
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const val = descriptor.params[paramDef.key] ?? paramDef.default;
|
|
551
|
+
|
|
484
552
|
return (
|
|
485
553
|
<ParamRow
|
|
486
554
|
key={paramDef.key}
|
|
487
555
|
paramDef={paramDef}
|
|
488
|
-
value={val}
|
|
489
|
-
onChange={
|
|
556
|
+
value={val as number | boolean | string}
|
|
557
|
+
onChange={handleParamChange}
|
|
490
558
|
/>
|
|
491
559
|
);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
return (
|
|
497
|
-
<ParamRow
|
|
498
|
-
key={paramDef.key}
|
|
499
|
-
paramDef={paramDef}
|
|
500
|
-
value={val as number | boolean | string}
|
|
501
|
-
onChange={handleParamChange}
|
|
502
|
-
/>
|
|
503
|
-
);
|
|
504
|
-
})}
|
|
505
|
-
</div>
|
|
560
|
+
})}
|
|
561
|
+
</div>
|
|
562
|
+
</>
|
|
506
563
|
)}
|
|
507
564
|
|
|
508
|
-
{/* Expensive param performance warning */}
|
|
565
|
+
{/* ── Expensive param performance warning ─────────────────────────── */}
|
|
509
566
|
{hasExpensiveParam && (
|
|
510
|
-
<p className="rounded bg-yellow-950/50 px-2 py-1 text-[10px] text-yellow-400">
|
|
567
|
+
<p className="mx-3 mb-2 rounded bg-yellow-950/50 px-2 py-1 text-[10px] text-yellow-400">
|
|
511
568
|
{
|
|
512
569
|
"grainMixer / grainOverlay may impact performance on mobile" /* i18n-ignore shader performance warning */
|
|
513
570
|
}
|