@agent-native/core 0.84.56 → 0.84.58
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 +1 -1
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/docs/content/locales/ar-SA/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/ar-SA/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/de-DE/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/de-DE/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/es-ES/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/es-ES/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/fr-FR/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/fr-FR/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/hi-IN/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/hi-IN/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/ja-JP/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/ja-JP/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/ko-KR/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/ko-KR/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/pt-BR/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/pt-BR/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-CN/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-CN/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-TW/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-TW/template-clips.mdx +2 -0
- package/corpus/core/docs/content/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/template-clips.mdx +22 -10
- package/corpus/core/docs/content/tracking.mdx +2 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/action.ts +11 -0
- package/corpus/core/src/agent/production-agent.ts +24 -46
- package/corpus/core/src/client/AssistantChat.tsx +69 -12
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +1 -1
- package/corpus/core/src/client/conversation/use-near-bottom-autoscroll.ts +45 -2
- package/corpus/core/src/coding-tools/run-code.ts +1 -0
- package/corpus/core/src/integrations/webhook-handler.ts +10 -9
- package/corpus/core/src/server/action-discovery.ts +3 -0
- package/corpus/core/src/server/credential-provider.ts +11 -6
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +8 -0
- package/corpus/templates/analytics/AGENTS.md +5 -0
- package/corpus/templates/analytics/actions/create-session-replay-agent-link.ts +31 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/analytics/app/i18n-data.ts +20 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +65 -3
- package/corpus/templates/analytics/changelog/2026-07-02-session-replays-can-be-copied-as-temporary-private-links-for-agents.md +6 -0
- package/corpus/templates/analytics/server/handlers/session-replay.ts +78 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +29 -0
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +313 -0
- package/corpus/templates/analytics/server/lib/session-replay.ts +198 -3
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +9 -1
- package/corpus/templates/analytics/server/routes/[...page].get.ts +104 -1
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-context.json.get.ts +48 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-events.json.get.ts +63 -0
- package/corpus/templates/analytics/shared/session-replay-agent-access.ts +10 -0
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +14 -8
- package/corpus/templates/clips/AGENTS.md +3 -2
- package/corpus/templates/clips/actions/create-recording-agent-link.ts +90 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +43 -46
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +5 -3
- package/corpus/templates/clips/app/i18n/ar-SA.ts +1 -1
- package/corpus/templates/clips/app/i18n/de-DE.ts +1 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -1
- package/corpus/templates/clips/app/i18n/es-ES.ts +1 -1
- package/corpus/templates/clips/app/i18n/fr-FR.ts +1 -1
- package/corpus/templates/clips/app/i18n/hi-IN.ts +1 -1
- package/corpus/templates/clips/app/i18n/ja-JP.ts +1 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +1 -1
- package/corpus/templates/clips/app/i18n/pt-BR.ts +1 -1
- package/corpus/templates/clips/app/i18n/zh-CN.ts +1 -1
- package/corpus/templates/clips/app/i18n/zh-TW.ts +1 -1
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +100 -46
- package/corpus/templates/clips/changelog/2026-07-02-private-recordings-can-be-shared-with-agents-through-temporary-links-without-making-them-public.md +6 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +26 -13
- package/corpus/templates/clips/server/routes/api/agent-context.json.get.ts +2 -1
- package/corpus/templates/clips/server/routes/api/agent-frame.jpg.get.ts +2 -1
- package/corpus/templates/clips/server/routes/api/agent-transcript.json.get.ts +2 -1
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +7 -2
- package/corpus/templates/clips/shared/agent-context.ts +5 -0
- package/corpus/templates/design/actions/list-design-extensions.ts +2 -2
- package/corpus/templates/design/app/components/design/CodeWorkbenchHost.tsx +11 -89
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +314 -181
- package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +92 -134
- package/corpus/templates/design/app/components/design/EditPanel.tsx +93 -19
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +18 -26
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +220 -192
- package/corpus/templates/design/app/components/design/code-workbench-theme.ts +150 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +5 -7
- package/corpus/templates/design/app/i18n-data.ts +61 -77
- package/corpus/templates/design/app/lib/design-import.ts +4 -1
- package/corpus/templates/design/app/pages/DesignEditor.tsx +97 -48
- package/corpus/templates/design/changelog/2026-07-02-design-inspector-and-canvas-controls-stay-consistent-when-se.md +6 -0
- package/corpus/templates/design/changelog/2026-07-02-fixed-a-crash-when-opening-the-code-editor.md +6 -0
- package/corpus/templates/design/changelog/2026-07-02-fixed-motion-drawer-open-transition.md +6 -0
- package/corpus/templates/design/changelog/2026-07-02-improved-design-assets-panel.md +6 -0
- package/dist/action.d.ts +8 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +3 -0
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +10 -11
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +21 -44
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +1 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +61 -11
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +1 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.js +43 -2
- package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
- package/dist/coding-tools/run-code.d.ts.map +1 -1
- package/dist/coding-tools/run-code.js +1 -0
- package/dist/coding-tools/run-code.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/integrations/webhook-handler.d.ts +1 -0
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +9 -9
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +3 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/credential-provider.d.ts +4 -0
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +13 -7
- package/dist/server/credential-provider.js.map +1 -1
- package/docs/content/locales/ar-SA/template-analytics.mdx +2 -0
- package/docs/content/locales/ar-SA/template-clips.mdx +2 -0
- package/docs/content/locales/de-DE/template-analytics.mdx +2 -0
- package/docs/content/locales/de-DE/template-clips.mdx +2 -0
- package/docs/content/locales/es-ES/template-analytics.mdx +2 -0
- package/docs/content/locales/es-ES/template-clips.mdx +2 -0
- package/docs/content/locales/fr-FR/template-analytics.mdx +2 -0
- package/docs/content/locales/fr-FR/template-clips.mdx +2 -0
- package/docs/content/locales/hi-IN/template-analytics.mdx +2 -0
- package/docs/content/locales/hi-IN/template-clips.mdx +2 -0
- package/docs/content/locales/ja-JP/template-analytics.mdx +2 -0
- package/docs/content/locales/ja-JP/template-clips.mdx +2 -0
- package/docs/content/locales/ko-KR/template-analytics.mdx +2 -0
- package/docs/content/locales/ko-KR/template-clips.mdx +2 -0
- package/docs/content/locales/pt-BR/template-analytics.mdx +2 -0
- package/docs/content/locales/pt-BR/template-clips.mdx +2 -0
- package/docs/content/locales/zh-CN/template-analytics.mdx +2 -0
- package/docs/content/locales/zh-CN/template-clips.mdx +2 -0
- package/docs/content/locales/zh-TW/template-analytics.mdx +2 -0
- package/docs/content/locales/zh-TW/template-clips.mdx +2 -0
- package/docs/content/template-analytics.mdx +2 -0
- package/docs/content/template-clips.mdx +22 -10
- package/docs/content/tracking.mdx +2 -0
- package/package.json +1 -1
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
IconChevronDown,
|
|
20
20
|
IconExternalLink,
|
|
21
21
|
IconLock,
|
|
22
|
+
IconLayoutGrid,
|
|
22
23
|
IconMessageCircle,
|
|
23
24
|
IconPalette,
|
|
24
25
|
IconPhoto,
|
|
@@ -34,6 +35,7 @@ import {
|
|
|
34
35
|
useRef,
|
|
35
36
|
useState,
|
|
36
37
|
type FormEvent,
|
|
38
|
+
type DragEvent as ReactDragEvent,
|
|
37
39
|
} from "react";
|
|
38
40
|
import { toast } from "sonner";
|
|
39
41
|
|
|
@@ -150,6 +152,7 @@ type FirstPartyRow = {
|
|
|
150
152
|
|
|
151
153
|
const DEFAULT_ASSETS_PICKER_URL =
|
|
152
154
|
"https://assets.agent-native.com/library?__an_picker=1&mediaType=image&layout=vertical";
|
|
155
|
+
const SHOW_FIGMA_ASSET_TAB = true;
|
|
153
156
|
|
|
154
157
|
interface PickedAssetPayload {
|
|
155
158
|
url?: unknown;
|
|
@@ -368,11 +371,11 @@ function ToolFilterMenu<T extends string>({
|
|
|
368
371
|
type="button"
|
|
369
372
|
variant="outline"
|
|
370
373
|
size="sm"
|
|
371
|
-
className="h-
|
|
374
|
+
className="h-7 cursor-pointer gap-1 rounded-md bg-transparent px-2 !text-[11px] font-medium"
|
|
372
375
|
>
|
|
373
|
-
<IconAdjustmentsHorizontal className="size-
|
|
376
|
+
<IconAdjustmentsHorizontal className="size-3 text-muted-foreground" />
|
|
374
377
|
<span>{triggerLabel}</span>
|
|
375
|
-
<IconChevronDown className="size-3
|
|
378
|
+
<IconChevronDown className="size-3 text-muted-foreground" />
|
|
376
379
|
</Button>
|
|
377
380
|
</DropdownMenuTrigger>
|
|
378
381
|
<DropdownMenuContent align="start" className="min-w-36">
|
|
@@ -451,7 +454,12 @@ const NATIVE_ASSET_CATEGORY_LABELS: Record<
|
|
|
451
454
|
};
|
|
452
455
|
|
|
453
456
|
export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
457
|
+
const panelRef = useRef<HTMLDivElement | null>(null);
|
|
454
458
|
const [assetPickerReady, setAssetPickerReady] = useState(false);
|
|
459
|
+
const [nativeSearchQuery, setNativeSearchQuery] = useState("");
|
|
460
|
+
const [draggedNativeAsset, setDraggedNativeAsset] =
|
|
461
|
+
useState<DesignNativeAsset | null>(null);
|
|
462
|
+
const [dropOverlayLeft, setDropOverlayLeft] = useState<number | null>(null);
|
|
455
463
|
const [figmaFileInput, setFigmaFileInput] = useState("");
|
|
456
464
|
const [figmaQueryInput, setFigmaQueryInput] = useState("");
|
|
457
465
|
const [figmaRequest, setFigmaRequest] = useState<{
|
|
@@ -476,6 +484,24 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
476
484
|
: undefined,
|
|
477
485
|
{ enabled: Boolean(figmaRequest) },
|
|
478
486
|
);
|
|
487
|
+
const filteredNativeAssets = useMemo(() => {
|
|
488
|
+
const assets = nativeAssets.data?.assets ?? [];
|
|
489
|
+
const query = nativeSearchQuery.trim().toLowerCase();
|
|
490
|
+
if (!query) return assets;
|
|
491
|
+
return assets.filter((asset) =>
|
|
492
|
+
[
|
|
493
|
+
asset.title,
|
|
494
|
+
asset.description,
|
|
495
|
+
asset.componentName,
|
|
496
|
+
asset.category,
|
|
497
|
+
NATIVE_ASSET_CATEGORY_LABELS[asset.category],
|
|
498
|
+
]
|
|
499
|
+
.join(" ")
|
|
500
|
+
.toLowerCase()
|
|
501
|
+
.includes(query),
|
|
502
|
+
);
|
|
503
|
+
}, [nativeAssets.data?.assets, nativeSearchQuery]);
|
|
504
|
+
const canInsertNativeAssets = Boolean(context.activeFileId);
|
|
479
505
|
const notifyAssetInserted = useCallback(
|
|
480
506
|
(result: unknown, title: string) => {
|
|
481
507
|
if (!result || typeof result !== "object") return;
|
|
@@ -553,23 +579,68 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
553
579
|
[context.designId, context.activeFileId, insertAsset, notifyAssetInserted],
|
|
554
580
|
);
|
|
555
581
|
|
|
556
|
-
const handleInsertNativeAsset = (
|
|
557
|
-
|
|
558
|
-
{
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
582
|
+
const handleInsertNativeAsset = useCallback(
|
|
583
|
+
(asset: DesignNativeAsset) => {
|
|
584
|
+
if (!context.activeFileId) {
|
|
585
|
+
toast.error("Open a design screen first to insert assets.");
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
insertNativeAsset.mutate(
|
|
589
|
+
{
|
|
590
|
+
kind: asset.kind,
|
|
591
|
+
designId: context.designId || undefined,
|
|
592
|
+
fileId: context.activeFileId || undefined,
|
|
567
593
|
},
|
|
568
|
-
|
|
569
|
-
|
|
594
|
+
{
|
|
595
|
+
onSuccess: (result) => {
|
|
596
|
+
notifyAssetInserted(result, asset.title);
|
|
597
|
+
toast.success(`${asset.title} inserted into design.`);
|
|
598
|
+
},
|
|
599
|
+
onError: (error) => {
|
|
600
|
+
toast.error(error.message || "Failed to insert Design asset.");
|
|
601
|
+
},
|
|
570
602
|
},
|
|
571
|
-
|
|
572
|
-
|
|
603
|
+
);
|
|
604
|
+
},
|
|
605
|
+
[
|
|
606
|
+
context.activeFileId,
|
|
607
|
+
context.designId,
|
|
608
|
+
insertNativeAsset,
|
|
609
|
+
notifyAssetInserted,
|
|
610
|
+
],
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
const clearNativeAssetDrag = useCallback(() => {
|
|
614
|
+
setDraggedNativeAsset(null);
|
|
615
|
+
setDropOverlayLeft(null);
|
|
616
|
+
}, []);
|
|
617
|
+
|
|
618
|
+
useEffect(() => {
|
|
619
|
+
if (!draggedNativeAsset) return;
|
|
620
|
+
window.addEventListener("dragend", clearNativeAssetDrag);
|
|
621
|
+
return () => window.removeEventListener("dragend", clearNativeAssetDrag);
|
|
622
|
+
}, [clearNativeAssetDrag, draggedNativeAsset]);
|
|
623
|
+
|
|
624
|
+
const handleNativeAssetDragStart = (
|
|
625
|
+
event: ReactDragEvent<HTMLDivElement>,
|
|
626
|
+
asset: DesignNativeAsset,
|
|
627
|
+
) => {
|
|
628
|
+
if (!canInsertNativeAssets || insertNativeAsset.isPending) {
|
|
629
|
+
event.preventDefault();
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
setDraggedNativeAsset(asset);
|
|
633
|
+
setDropOverlayLeft(panelRef.current?.getBoundingClientRect().right ?? 0);
|
|
634
|
+
event.dataTransfer.effectAllowed = "copy";
|
|
635
|
+
event.dataTransfer.setData("text/plain", asset.title);
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
const handleNativeAssetDrop = (event: ReactDragEvent<HTMLDivElement>) => {
|
|
639
|
+
event.preventDefault();
|
|
640
|
+
event.stopPropagation();
|
|
641
|
+
if (!draggedNativeAsset) return;
|
|
642
|
+
handleInsertNativeAsset(draggedNativeAsset);
|
|
643
|
+
clearNativeAssetDrag();
|
|
573
644
|
};
|
|
574
645
|
|
|
575
646
|
const handleBrowseFigma = (event: FormEvent<HTMLFormElement>) => {
|
|
@@ -612,22 +683,32 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
612
683
|
};
|
|
613
684
|
|
|
614
685
|
return (
|
|
615
|
-
<div className="flex min-h-0 flex-1 flex-col">
|
|
686
|
+
<div ref={panelRef} className="flex min-h-0 flex-1 flex-col">
|
|
616
687
|
<Tabs defaultValue="native" className="flex min-h-0 flex-1 flex-col">
|
|
617
688
|
<div className="border-b border-border/60 px-2 py-1.5">
|
|
618
|
-
<TabsList
|
|
689
|
+
<TabsList
|
|
690
|
+
className={cn(
|
|
691
|
+
"grid h-7 w-full rounded-md p-0.5",
|
|
692
|
+
SHOW_FIGMA_ASSET_TAB ? "grid-cols-3" : "grid-cols-2",
|
|
693
|
+
)}
|
|
694
|
+
>
|
|
619
695
|
<TabsTrigger value="native" className="h-6 gap-1 px-2 !text-[11px]">
|
|
620
|
-
<
|
|
621
|
-
|
|
696
|
+
<IconLayoutGrid className="size-3" />
|
|
697
|
+
Design
|
|
622
698
|
</TabsTrigger>
|
|
623
699
|
<TabsTrigger value="media" className="h-6 gap-1 px-2 !text-[11px]">
|
|
624
700
|
<IconPhoto className="size-3" />
|
|
625
701
|
Media
|
|
626
702
|
</TabsTrigger>
|
|
627
|
-
|
|
628
|
-
<
|
|
629
|
-
|
|
630
|
-
|
|
703
|
+
{SHOW_FIGMA_ASSET_TAB ? (
|
|
704
|
+
<TabsTrigger
|
|
705
|
+
value="figma"
|
|
706
|
+
className="h-6 gap-1 px-2 !text-[11px]"
|
|
707
|
+
>
|
|
708
|
+
<IconBrandFigma className="size-3" />
|
|
709
|
+
Figma
|
|
710
|
+
</TabsTrigger>
|
|
711
|
+
) : null}
|
|
631
712
|
</TabsList>
|
|
632
713
|
</div>
|
|
633
714
|
|
|
@@ -650,35 +731,67 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
650
731
|
)}
|
|
651
732
|
|
|
652
733
|
{!nativeAssets.isLoading && nativeAssets.data && (
|
|
653
|
-
<div className="space-y-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
734
|
+
<div className="space-y-2">
|
|
735
|
+
<p className="text-[10px] leading-snug text-muted-foreground">
|
|
736
|
+
Drag Design elements into the canvas to add them to the current
|
|
737
|
+
screen.
|
|
738
|
+
</p>
|
|
739
|
+
<div className="relative">
|
|
740
|
+
<IconSearch className="pointer-events-none absolute left-2 top-1/2 size-3 -translate-y-1/2 text-muted-foreground" />
|
|
741
|
+
<Input
|
|
742
|
+
value={nativeSearchQuery}
|
|
743
|
+
onChange={(event) => setNativeSearchQuery(event.target.value)}
|
|
744
|
+
placeholder="Search Design assets"
|
|
745
|
+
className="h-7 bg-muted/50 pl-7 !text-[11px] shadow-none md:!text-[11px]"
|
|
746
|
+
/>
|
|
747
|
+
</div>
|
|
748
|
+
{filteredNativeAssets.length === 0 ? (
|
|
749
|
+
<p className="rounded border border-border bg-muted/30 px-2 py-1.5 text-[10px] leading-snug text-muted-foreground">
|
|
750
|
+
No Design assets match this search.
|
|
751
|
+
</p>
|
|
752
|
+
) : (
|
|
753
|
+
<div role="list" className="space-y-1.5">
|
|
754
|
+
{filteredNativeAssets.map((asset) => (
|
|
755
|
+
<div
|
|
756
|
+
key={asset.kind}
|
|
757
|
+
role="listitem"
|
|
758
|
+
aria-disabled={
|
|
759
|
+
!canInsertNativeAssets || insertNativeAsset.isPending
|
|
760
|
+
}
|
|
761
|
+
draggable={
|
|
762
|
+
canInsertNativeAssets && !insertNativeAsset.isPending
|
|
763
|
+
}
|
|
764
|
+
onDragStart={(event) =>
|
|
765
|
+
handleNativeAssetDragStart(event, asset)
|
|
766
|
+
}
|
|
767
|
+
onDragEnd={clearNativeAssetDrag}
|
|
768
|
+
className={cn(
|
|
769
|
+
"group flex w-full items-start gap-2 rounded-md border border-border bg-background px-2 py-2 text-left transition hover:border-primary/50 hover:bg-accent/30",
|
|
770
|
+
canInsertNativeAssets && !insertNativeAsset.isPending
|
|
771
|
+
? "cursor-grab active:cursor-grabbing"
|
|
772
|
+
: "cursor-not-allowed opacity-55",
|
|
773
|
+
)}
|
|
774
|
+
>
|
|
775
|
+
<span className="mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-md border border-border/70 bg-muted/50 text-muted-foreground group-hover:text-foreground">
|
|
776
|
+
<IconLayoutGrid className="size-4" />
|
|
671
777
|
</span>
|
|
672
|
-
<span className="
|
|
673
|
-
|
|
778
|
+
<span className="min-w-0 flex-1">
|
|
779
|
+
<span className="flex items-center gap-1.5">
|
|
780
|
+
<span className="truncate !text-[11px] font-medium leading-tight text-foreground">
|
|
781
|
+
{asset.title}
|
|
782
|
+
</span>
|
|
783
|
+
<span className="shrink-0 rounded border border-border/70 px-1 py-0.5 text-[9px] leading-none text-muted-foreground">
|
|
784
|
+
{NATIVE_ASSET_CATEGORY_LABELS[asset.category]}
|
|
785
|
+
</span>
|
|
786
|
+
</span>
|
|
787
|
+
<span className="mt-1 line-clamp-2 text-[10px] leading-snug text-muted-foreground">
|
|
788
|
+
{asset.description}
|
|
789
|
+
</span>
|
|
674
790
|
</span>
|
|
675
|
-
</
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
</span>
|
|
680
|
-
</button>
|
|
681
|
-
))}
|
|
791
|
+
</div>
|
|
792
|
+
))}
|
|
793
|
+
</div>
|
|
794
|
+
)}
|
|
682
795
|
</div>
|
|
683
796
|
)}
|
|
684
797
|
</TabsContent>
|
|
@@ -704,136 +817,156 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
704
817
|
</div>
|
|
705
818
|
</TabsContent>
|
|
706
819
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
<
|
|
713
|
-
value={figmaFileInput}
|
|
714
|
-
onChange={(event) => setFigmaFileInput(event.target.value)}
|
|
715
|
-
placeholder="Figma file URL or key"
|
|
716
|
-
className="h-7 !text-[11px] md:!text-[11px]"
|
|
717
|
-
/>
|
|
718
|
-
<div className="flex gap-1.5">
|
|
820
|
+
{SHOW_FIGMA_ASSET_TAB ? (
|
|
821
|
+
<TabsContent
|
|
822
|
+
value="figma"
|
|
823
|
+
className="design-inspector-scroll m-0 min-h-0 flex-1 overflow-y-auto p-2.5"
|
|
824
|
+
>
|
|
825
|
+
<form className="space-y-1.5" onSubmit={handleBrowseFigma}>
|
|
719
826
|
<Input
|
|
720
|
-
value={
|
|
721
|
-
onChange={(event) =>
|
|
722
|
-
placeholder="
|
|
723
|
-
className="h-7
|
|
827
|
+
value={figmaFileInput}
|
|
828
|
+
onChange={(event) => setFigmaFileInput(event.target.value)}
|
|
829
|
+
placeholder="Figma file URL or key"
|
|
830
|
+
className="h-7 !text-[11px] md:!text-[11px]"
|
|
724
831
|
/>
|
|
725
|
-
<
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
{figmaAssets.isFetching && (
|
|
744
|
-
<div className="mt-2 grid grid-cols-2 gap-1.5">
|
|
745
|
-
{Array.from({ length: 4 }).map((_, index) => (
|
|
746
|
-
<Skeleton key={index} className="aspect-square rounded-md" />
|
|
747
|
-
))}
|
|
748
|
-
</div>
|
|
749
|
-
)}
|
|
832
|
+
<div className="flex gap-1.5">
|
|
833
|
+
<Input
|
|
834
|
+
value={figmaQueryInput}
|
|
835
|
+
onChange={(event) => setFigmaQueryInput(event.target.value)}
|
|
836
|
+
placeholder="Search components"
|
|
837
|
+
className="h-7 min-w-0 flex-1 !text-[11px] md:!text-[11px]"
|
|
838
|
+
/>
|
|
839
|
+
<Button
|
|
840
|
+
type="submit"
|
|
841
|
+
size="sm"
|
|
842
|
+
className="h-7 cursor-pointer gap-1 px-2 !text-[11px]"
|
|
843
|
+
disabled={!figmaFileInput.trim() || figmaAssets.isFetching}
|
|
844
|
+
>
|
|
845
|
+
<IconSearch className="size-3" />
|
|
846
|
+
{figmaAssets.isFetching ? "Loading" : "Browse"}
|
|
847
|
+
</Button>
|
|
848
|
+
</div>
|
|
849
|
+
</form>
|
|
750
850
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
<p className="mt-2 rounded border border-border bg-muted/30 px-2 py-1.5 text-[10px] leading-snug text-muted-foreground">
|
|
755
|
-
No components matched this Figma file and search.
|
|
851
|
+
{figmaAssets.isError && (
|
|
852
|
+
<p className="mt-2 rounded border border-destructive/30 bg-destructive/5 px-2 py-1.5 text-[10px] leading-snug text-destructive">
|
|
853
|
+
{figmaAssets.error.message}
|
|
756
854
|
</p>
|
|
757
855
|
)}
|
|
758
856
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
857
|
+
{figmaAssets.isFetching && (
|
|
858
|
+
<div className="mt-2 grid grid-cols-2 gap-1.5">
|
|
859
|
+
{Array.from({ length: 4 }).map((_, index) => (
|
|
860
|
+
<Skeleton key={index} className="aspect-square rounded-md" />
|
|
861
|
+
))}
|
|
862
|
+
</div>
|
|
863
|
+
)}
|
|
864
|
+
|
|
865
|
+
{!figmaAssets.isFetching &&
|
|
866
|
+
figmaAssets.data &&
|
|
867
|
+
figmaAssets.data.assets.length === 0 && (
|
|
868
|
+
<p className="mt-2 rounded border border-border bg-muted/30 px-2 py-1.5 text-[10px] leading-snug text-muted-foreground">
|
|
869
|
+
No components matched this Figma file and search.
|
|
870
|
+
</p>
|
|
871
|
+
)}
|
|
872
|
+
|
|
873
|
+
{!figmaAssets.isFetching &&
|
|
874
|
+
figmaAssets.data &&
|
|
875
|
+
figmaAssets.data.assets.length > 0 && (
|
|
876
|
+
<div className="mt-2 space-y-1.5">
|
|
877
|
+
<div className="flex items-center justify-between gap-2 text-[10px] text-muted-foreground">
|
|
878
|
+
<span>
|
|
879
|
+
{figmaAssets.data.returned} of {figmaAssets.data.total}
|
|
880
|
+
</span>
|
|
881
|
+
<span className="truncate">{figmaAssets.data.fileKey}</span>
|
|
882
|
+
</div>
|
|
883
|
+
<div className="grid grid-cols-2 gap-1.5">
|
|
884
|
+
{figmaAssets.data.assets.map((asset) => {
|
|
885
|
+
const preview = asset.thumbnailUrl ?? asset.renderUrl;
|
|
886
|
+
const canInsert = Boolean(
|
|
887
|
+
context.activeFileId &&
|
|
888
|
+
(asset.insertUrl ??
|
|
889
|
+
asset.renderUrl ??
|
|
890
|
+
asset.thumbnailUrl),
|
|
891
|
+
);
|
|
892
|
+
return (
|
|
893
|
+
<div
|
|
894
|
+
key={asset.id}
|
|
895
|
+
className="overflow-hidden rounded-md border border-border bg-background"
|
|
788
896
|
>
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
</span>
|
|
807
|
-
{asset.sourceUrl && (
|
|
808
|
-
<a
|
|
809
|
-
href={asset.sourceUrl}
|
|
810
|
-
target="_blank"
|
|
811
|
-
rel="noreferrer"
|
|
812
|
-
className="shrink-0 text-muted-foreground hover:text-foreground"
|
|
813
|
-
aria-label="Open in Figma"
|
|
814
|
-
>
|
|
815
|
-
<IconExternalLink className="size-3" />
|
|
816
|
-
</a>
|
|
897
|
+
<button
|
|
898
|
+
type="button"
|
|
899
|
+
className="block aspect-square w-full cursor-pointer bg-muted/30"
|
|
900
|
+
disabled={!canInsert || insertFigmaAsset.isPending}
|
|
901
|
+
onClick={() => handleInsertFigmaAsset(asset)}
|
|
902
|
+
>
|
|
903
|
+
{preview ? (
|
|
904
|
+
<img
|
|
905
|
+
src={preview}
|
|
906
|
+
alt={asset.name}
|
|
907
|
+
className="size-full object-contain p-2"
|
|
908
|
+
loading="lazy"
|
|
909
|
+
/>
|
|
910
|
+
) : (
|
|
911
|
+
<span className="flex size-full items-center justify-center text-muted-foreground">
|
|
912
|
+
<IconLayoutGrid className="size-5" />
|
|
913
|
+
</span>
|
|
817
914
|
)}
|
|
915
|
+
</button>
|
|
916
|
+
<div className="border-t border-border/70 px-1.5 py-1">
|
|
917
|
+
<div className="flex items-center gap-1">
|
|
918
|
+
<span className="min-w-0 flex-1 truncate text-[10px] font-medium leading-tight">
|
|
919
|
+
{asset.name}
|
|
920
|
+
</span>
|
|
921
|
+
{asset.sourceUrl && (
|
|
922
|
+
<a
|
|
923
|
+
href={asset.sourceUrl}
|
|
924
|
+
target="_blank"
|
|
925
|
+
rel="noreferrer"
|
|
926
|
+
className="shrink-0 text-muted-foreground hover:text-foreground"
|
|
927
|
+
aria-label="Open in Figma"
|
|
928
|
+
>
|
|
929
|
+
<IconExternalLink className="size-3" />
|
|
930
|
+
</a>
|
|
931
|
+
)}
|
|
932
|
+
</div>
|
|
933
|
+
<p className="mt-0.5 truncate text-[9px] text-muted-foreground">
|
|
934
|
+
{asset.kind === "component_set"
|
|
935
|
+
? "Component set"
|
|
936
|
+
: "Component"}
|
|
937
|
+
{asset.containingFrame?.name
|
|
938
|
+
? ` · ${asset.containingFrame.name}`
|
|
939
|
+
: ""}
|
|
940
|
+
</p>
|
|
818
941
|
</div>
|
|
819
|
-
<p className="mt-0.5 truncate text-[9px] text-muted-foreground">
|
|
820
|
-
{asset.kind === "component_set"
|
|
821
|
-
? "Component set"
|
|
822
|
-
: "Component"}
|
|
823
|
-
{asset.containingFrame?.name
|
|
824
|
-
? ` · ${asset.containingFrame.name}`
|
|
825
|
-
: ""}
|
|
826
|
-
</p>
|
|
827
942
|
</div>
|
|
828
|
-
|
|
829
|
-
)
|
|
830
|
-
|
|
943
|
+
);
|
|
944
|
+
})}
|
|
945
|
+
</div>
|
|
831
946
|
</div>
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
947
|
+
)}
|
|
948
|
+
</TabsContent>
|
|
949
|
+
) : null}
|
|
835
950
|
</Tabs>
|
|
836
951
|
|
|
952
|
+
{draggedNativeAsset && dropOverlayLeft !== null ? (
|
|
953
|
+
<div
|
|
954
|
+
className="fixed bottom-0 right-0 top-0 z-[120] cursor-copy"
|
|
955
|
+
style={{ left: dropOverlayLeft }}
|
|
956
|
+
onDragOver={(event) => {
|
|
957
|
+
event.preventDefault();
|
|
958
|
+
event.dataTransfer.dropEffect = "copy";
|
|
959
|
+
}}
|
|
960
|
+
onDrop={handleNativeAssetDrop}
|
|
961
|
+
>
|
|
962
|
+
<div className="pointer-events-none absolute inset-3 flex items-center justify-center rounded-xl border border-dashed border-primary/50 bg-primary/5 text-primary shadow-[inset_0_0_0_1px_rgba(255,255,255,0.18)]">
|
|
963
|
+
<div className="rounded-md border border-border bg-background/95 px-3 py-2 text-xs font-medium shadow-sm">
|
|
964
|
+
Drop to add {draggedNativeAsset.title} to this design
|
|
965
|
+
</div>
|
|
966
|
+
</div>
|
|
967
|
+
</div>
|
|
968
|
+
) : null}
|
|
969
|
+
|
|
837
970
|
{!context.activeFileId && (
|
|
838
971
|
<p className="border-t border-border/60 px-2.5 py-1.5 text-[10px] text-amber-600 dark:text-amber-400">
|
|
839
972
|
Open a design screen first to insert assets.
|
|
@@ -1310,8 +1443,8 @@ export function DesignExtensionsPanel({
|
|
|
1310
1443
|
|
|
1311
1444
|
return (
|
|
1312
1445
|
<div className={cn("flex min-h-0 flex-1 flex-col", className)}>
|
|
1313
|
-
<div className="flex h-
|
|
1314
|
-
<h3 className="min-w-0 flex-1 truncate text-
|
|
1446
|
+
<div className="flex min-h-8 shrink-0 items-center gap-2 border-b border-border/60 px-3">
|
|
1447
|
+
<h3 className="min-w-0 flex-1 truncate text-xs font-semibold text-foreground">
|
|
1315
1448
|
{title ?? t("designEditor.extensions")}
|
|
1316
1449
|
</h3>
|
|
1317
1450
|
<CreateExtensionPopover
|
|
@@ -1321,18 +1454,18 @@ export function DesignExtensionsPanel({
|
|
|
1321
1454
|
/>
|
|
1322
1455
|
</div>
|
|
1323
1456
|
|
|
1324
|
-
<div className="design-inspector-scroll min-h-0 flex-1 overflow-y-auto overscroll-contain px-
|
|
1325
|
-
<div className="relative mb-
|
|
1326
|
-
<IconSearch className="pointer-events-none absolute left-2
|
|
1457
|
+
<div className="design-inspector-scroll min-h-0 flex-1 overflow-y-auto overscroll-contain px-3 pb-4 pt-3">
|
|
1458
|
+
<div className="relative mb-3">
|
|
1459
|
+
<IconSearch className="pointer-events-none absolute left-2 top-1/2 size-3 -translate-y-1/2 text-muted-foreground" />
|
|
1327
1460
|
<Input
|
|
1328
1461
|
value={searchQuery}
|
|
1329
1462
|
onChange={(event) => setSearchQuery(event.target.value)}
|
|
1330
1463
|
placeholder="Search all tools"
|
|
1331
|
-
className="h-
|
|
1464
|
+
className="h-7 border-0 bg-muted/70 pl-7 !text-[11px] shadow-none focus-visible:ring-1 md:!text-[11px]"
|
|
1332
1465
|
/>
|
|
1333
1466
|
</div>
|
|
1334
1467
|
|
|
1335
|
-
<div className="mb-
|
|
1468
|
+
<div className="mb-4 flex flex-wrap gap-1.5">
|
|
1336
1469
|
<ToolFilterMenu
|
|
1337
1470
|
label="Source"
|
|
1338
1471
|
value={sourceFilter}
|
|
@@ -1367,7 +1500,7 @@ export function DesignExtensionsPanel({
|
|
|
1367
1500
|
<>
|
|
1368
1501
|
{visibleInstalls.length > 0 ? (
|
|
1369
1502
|
<div className="mb-6">
|
|
1370
|
-
<p className="mb-
|
|
1503
|
+
<p className="mb-2 text-xs font-medium text-muted-foreground">
|
|
1371
1504
|
Recents
|
|
1372
1505
|
</p>
|
|
1373
1506
|
<div className="space-y-2">
|
|
@@ -1387,7 +1520,7 @@ export function DesignExtensionsPanel({
|
|
|
1387
1520
|
|
|
1388
1521
|
{visibleFirstPartyRows.length > 0 ? (
|
|
1389
1522
|
<div className="mb-6">
|
|
1390
|
-
<p className="mb-
|
|
1523
|
+
<p className="mb-2 text-xs font-medium text-muted-foreground">
|
|
1391
1524
|
Suggested
|
|
1392
1525
|
</p>
|
|
1393
1526
|
<div className="space-y-1">
|
|
@@ -1411,7 +1544,7 @@ export function DesignExtensionsPanel({
|
|
|
1411
1544
|
|
|
1412
1545
|
{visibleInstallable.length > 0 ? (
|
|
1413
1546
|
<div className="border-t border-border/60 pt-4">
|
|
1414
|
-
<p className="mb-
|
|
1547
|
+
<p className="mb-2 text-xs font-medium text-muted-foreground">
|
|
1415
1548
|
Available
|
|
1416
1549
|
</p>
|
|
1417
1550
|
<div className="space-y-1">
|
|
@@ -1498,7 +1631,7 @@ function CreateExtensionPopover({
|
|
|
1498
1631
|
type="button"
|
|
1499
1632
|
variant="outline"
|
|
1500
1633
|
size="sm"
|
|
1501
|
-
className="h-
|
|
1634
|
+
className="h-6 cursor-pointer rounded-md bg-transparent px-2 !text-[11px] font-medium"
|
|
1502
1635
|
aria-label={t("designEditor.addExtension")}
|
|
1503
1636
|
>
|
|
1504
1637
|
Create
|