Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2c4e0ee
chore: fieldlocation fetch completed
SahilCs15 Jun 29, 2025
26a70f4
chore: rendered the fieldmodifier apps added an event listner to send…
SahilCs15 Jun 30, 2025
c394b1f
chore: added test cases for the field location data
SahilCs15 Jul 1, 2025
bf2cc68
fix: undo unneccsary changes
SahilCs15 Jul 1, 2025
a0ff5b0
fix: resolved the issues
SahilCs15 Jul 3, 2025
000168e
feat: hovertoolbar component and rendering
csAyushDubey Jul 4, 2025
d9a0d09
chore: talismanrc update
csAyushDubey Jul 4, 2025
bc21aae
test: fieldlabelwrapper
csAyushDubey Jul 4, 2025
d2c1c70
Merge pull request #449 from contentstack/Field-modifiers-in-canvas
sairaj-cs Jul 7, 2025
88a81a4
redner the app on dom
SahilCs15 Jul 9, 2025
19f865a
Merge pull request #450 from contentstack/VE-6701-Hover-Toolbar-Support
csAyushDubey Jul 9, 2025
1cae0c3
fix: disable scroll when field modifer is active
SahilCs15 Jul 9, 2025
42c1576
feat: fieldLabelWrapper changes
csAyushDubey Jul 9, 2025
bab4171
fix: tooltip arrow change
csAyushDubey Jul 10, 2025
bfd84b7
Merge pull request #453 from contentstack/VE-6698-reference-map-sync
csAyushDubey Jul 10, 2025
8478bbc
fix: missed rendering case
csAyushDubey Jul 10, 2025
14ba432
fix:removed uncessary changes
SahilCs15 Jul 11, 2025
764fc0b
Merge branch 'render-field-modifier-in-canvas' into disable-scroll-wh…
SahilCs15 Jul 11, 2025
12be298
fix: addresed the requested cahnges
SahilCs15 Jul 14, 2025
51204af
chore: cleanup commit
csAyushDubey Jul 15, 2025
71f24d8
fix: tests
csAyushDubey Jul 15, 2025
8830f3c
chore: increased test timeout for CI
csAyushDubey Jul 15, 2025
eb2d72f
chore: incresed hook timeout for CI
csAyushDubey Jul 15, 2025
abfd640
chore: added retry to vitest
csAyushDubey Jul 15, 2025
da638dd
chore: increased timeout further
csAyushDubey Jul 15, 2025
cd63458
Merge pull request #458 from contentstack/disable-scroll-when-field-m…
SahilCs15 Jul 15, 2025
0d36fbc
Merge pull request #455 from contentstack/VE-6600-Hover-Toolbar-Support
csAyushDubey Jul 16, 2025
aa16fa2
Merge branch 'develop_v3' into VE-5474-Field-Modifier-support-for-can…
SahilCs15 Jul 16, 2025
c8e3a35
fix: fixed conficts
SahilCs15 Jul 16, 2025
435a028
fix: fixed the required changes
SahilCs15 Jul 16, 2025
37dccb8
fix: removed not requied changes
SahilCs15 Jul 16, 2025
366fc87
Merge pull request #460 from contentstack/VE-5474-Field-Modifier-supp…
SahilCs15 Jul 16, 2025
a80d08d
fix: no hovertoolbar when focussed
csAyushDubey Jul 16, 2025
69328d4
Merge pull request #461 from contentstack/VE-6600-Hover-Toolbar-Support
csAyushDubey Jul 16, 2025
cc71759
fix: changed order in tooltip and customcursor hiding
csAyushDubey Jul 18, 2025
565d56d
Merge pull request #464 from contentstack/VE-6600-Hover-Toolbar-Support
csAyushDubey Jul 18, 2025
b43682d
fix: modified the way we were handling fieldlocation data fetch (#462)
SahilCs15 Jul 18, 2025
ac4fdb3
fix: field parent clickability
csAyushDubey Jul 22, 2025
3b897a4
Merge pull request #467 from contentstack/VE-7005-hover-toolbar-click…
csAyushDubey Jul 22, 2025
95fb850
Merge pull request #474 from contentstack/stage_v3
sairaj-cs Jul 24, 2025
6b83664
chore(VE-6918/error-text): warning message improved
csAdityaPachauri Jul 15, 2025
ec3ccab
chore(VE-6918/error-text): component name changed to title case
csAdityaPachauri Jul 23, 2025
7ecfb19
chore(VE-6918/error-text): unit test file added
csAdityaPachauri Jul 25, 2025
3d5afdc
Merge branch 'main' of https://github.com/contentstack/live-preview-s…
csAdityaPachauri Jul 30, 2025
baea843
Merge pull request #475 from contentstack/VE-6918/error-text-main
csAdityaPachauri Jul 30, 2025
4c06df4
fix: removed edit icon when the click is on the container
SahilCs15 Aug 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 209 additions & 0 deletions src/visualBuilder/components/FieldLocationAppList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import React, { useState, useEffect, useMemo } from "preact/compat";
import { EmptyAppIcon } from "./icons/EmptyAppIcon";
import { VisualBuilderPostMessageEvents } from "../utils/types/postMessage.types";
import visualBuilderPostMessage from "../utils/visualBuilderPostMessage";
import { visualBuilderStyles } from "../visualBuilder.style";
import classNames from "classnames";
import { CslpData } from "../../utils/cslpdata";

interface App {
app_installation_uid: string;
app_uid: string;
contentTypeUid: string;
entryUid: string;
fieldDataType: string;
fieldDisplayName: string;
fieldPath: string;
icon?: string;
locale: string;
manifest: {
uid: string;
name: string;
description: string;
icon: string;
visibility: string;
};
title: string;
uid: string;
}

interface FieldLocationAppListProps {
apps: App[];
position: "left" | "right";
toolbarRef: React.RefObject<HTMLDivElement>;
domEditStack:CslpData[]
setDisplayAllApps: (displayAllApps: boolean) => void;
displayAllApps: boolean;
}

const normalize = (text: string) =>
text
.toLowerCase()
.replace(/[^a-z0-9 ]/gi, "")
.trim();

export const FieldLocationAppList = ({
apps,
position,
toolbarRef,
domEditStack,
setDisplayAllApps,
}: FieldLocationAppListProps) => {
const remainingApps = apps.filter((app, index) => index !== 0);
const [search, setSearch] = useState("");

const filteredApps = useMemo(() => {
if (!search.trim()) return remainingApps;

const normalizedSearch = normalize(search);
return remainingApps.filter((app) => {
return (
normalize(app.title).includes(normalizedSearch)
);
});
}, [search, remainingApps]);

const handleAppClick = (app: App) => {
visualBuilderPostMessage?.send(
VisualBuilderPostMessageEvents.FIELD_LOCATION_SELECTED_APP,
{
app: app,
position: toolbarRef.current?.getBoundingClientRect(),
DomEditStack:domEditStack
}
);
setDisplayAllApps(false);
};

return (
<div
className={classNames(
visualBuilderStyles()[
"visual-builder__field-location-app-list"
],
{
[visualBuilderStyles()[
"visual-builder__field-location-app-list--left"
]]: position === "left",
[visualBuilderStyles()[
"visual-builder__field-location-app-list--right"
]]: position === "right",
}
)}
>
<div
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__search-container"
]
}
>
<svg
width="14"
height="14"
viewBox="0 0 14 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={classNames(
"Search__search-icon Icon--mini",
visualBuilderStyles()[
"visual-builder__field-location-app-list__search-icon"
]
)}
>
<path
d="M12.438 12.438L9.624 9.624M6.25 10.75a4.5 4.5 0 100-9 4.5 4.5 0 000 9z"
stroke="#A9B6CB"
strokeWidth="2"
strokeMiterlimit="10"
strokeLinecap="round"
strokeLinejoin="round"
></path>
</svg>
<input
type="text"
value={search}
onInput={(e) =>
setSearch((e.target as HTMLInputElement).value)
}
placeholder="Search for Apps"
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__search-input"
]
}
/>
</div>

<div
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__content"
]
}
>
{filteredApps.length === 0 && (
<div
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__no-results"
]
}
>
<span
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__no-results-text"
]
}
>
No matching results found!
</span>
</div>
)}
{filteredApps.map((app) => (
<div
key={app.uid}
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__item"
]
}
onClick={() => handleAppClick(app)}
>
<div
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__item-icon-container"
]
}
>
{app.icon ? (
<img
src={app.icon}
alt={app.title}
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__item-icon"
]
}
/>
) : (
<EmptyAppIcon id={app.app_installation_uid} />
)}
</div>
<span
className={
visualBuilderStyles()[
"visual-builder__field-location-app-list__item-title"
]
}
>
{app.title}
</span>
</div>
))}
</div>
</div>
);
};
95 changes: 95 additions & 0 deletions src/visualBuilder/components/FieldLocationIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import classNames from "classnames";
import { visualBuilderStyles } from "../visualBuilder.style";
import { EmptyAppIcon } from "./icons/EmptyAppIcon";
import { MoreIcon } from "./icons";
import React, { useRef } from "preact/compat";
import { LoadingIcon } from "./icons/loading";
import { VisualBuilderPostMessageEvents } from "../utils/types/postMessage.types";
import visualBuilderPostMessage from "../utils/visualBuilderPostMessage";
import { CslpData } from "../../utils/cslpdata";

export const FieldLocationIcon = ({
fieldLocationData,
multipleFieldToolbarButtonClasses,
handleMoreIconClick,
moreButtonRef,
toolbarRef,
domEditStack
}: {
fieldLocationData: any;
multipleFieldToolbarButtonClasses: any;
handleMoreIconClick: () => void;
moreButtonRef: any;
toolbarRef: any;
domEditStack:CslpData[]
}) => {



if (!fieldLocationData?.apps || fieldLocationData?.apps?.length === 0) {
return null;
}

const handleAppClick = (app: any) => {
if(!toolbarRef.current) return
visualBuilderPostMessage?.send(VisualBuilderPostMessageEvents.FIELD_LOCATION_SELECTED_APP, {
app,
position: toolbarRef.current?.getBoundingClientRect(),
DomEditStack:domEditStack
});
};

return (
<div
ref={toolbarRef}
className={classNames(
visualBuilderStyles()[
"visual-builder__field-location-icons-container"
]
)}
>
<hr
className={visualBuilderStyles()["visual-builder__field-location-icons-container__divider"]}
/>
<button
key={`${fieldLocationData.apps[0].uid}`}
title={fieldLocationData.apps[0].title}
className={multipleFieldToolbarButtonClasses}
data-tooltip={fieldLocationData.apps[0].title}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleAppClick(fieldLocationData.apps[0]);
}}
data-testid="field-location-icon"
>
{fieldLocationData.apps[0].icon ? (
<img
src={fieldLocationData.apps[0].icon}
alt={fieldLocationData.apps[0].title}
className={visualBuilderStyles()["visual-builder__field-location-icons-container__app-icon"]}
/>
) : (
<EmptyAppIcon
id={fieldLocationData.apps[0].app_installation_uid}
/>
)}
</button>


{
fieldLocationData.apps.length > 1 && (
<button
ref={moreButtonRef}
className={multipleFieldToolbarButtonClasses}
data-tooltip={"More"}
onClick={handleMoreIconClick}
data-testid="field-location-more-button"
>
<MoreIcon />
</button>
)
}
</div>
);
};
Loading
Loading