fix(custom-widgets): address review feedback

This commit is contained in:
Thomas Camlong committed 2026-07-12 15:08:59 +02:00
1 parent c43836e85a
commit c5703e7e53
9 files changed
+93 -63

No files matched your search

@@ -18,14 +18,13 @@ export const WidgetCustomWidgetSelectInput = ({
const t = useWidgetInputTranslation(kind, property);
const form = useFormContext();
const board = useOptionalBoard();
const currentValue = form.values.options[property] as string;
const { data, isLoading } = clientApi.customWidget.available.useQuery(
{ boardId: board?.id ?? "" },
{ boardId: board?.id ?? "", currentId: currentValue || undefined },
{ enabled: board !== null },
);
const [search, setSearch] = useState("");
const currentValue = form.values.options[property] as string;
const definitions = useMemo(() => (data ?? []).map((def) => ({ value: def.id, label: def.name })), [data]);
const filteredOptions = useMemo(
@@ -20,7 +20,7 @@ function appendParseError(prev: string[], message: string): string[] {
return [...prev, message];
}
const METHOD_COLORS: Record<string, string> = {
export const CUSTOM_JSX_METHOD_COLORS: Record<string, string> = {
GET: "blue",
POST: "orange",
PUT: "yellow",
@@ -173,7 +173,7 @@ export default function CustomJsxDisplay({ data }: { data: Record<string, unknow
{capability.id}
</Text>
<Group gap={4} wrap="nowrap">
<Badge size="xs" color={METHOD_COLORS[capability.method] ?? "gray"} variant="light">
<Badge size="xs" color={CUSTOM_JSX_METHOD_COLORS[capability.method] ?? "gray"} variant="light">
{capability.method}
</Badge>
<Badge size="xs" color="gray" variant="outline">
@@ -185,7 +185,7 @@ export function SubFetch({
const result = query.data as RequestResult | undefined;
const requestError =
(query.error ? t("requestFailed") : null) ??
(query.error && !result ? t("requestFailed") : null) ??
(!result?.ok ? (result?.error ?? `${t("requestFailed")} (${result?.status ?? 0})`) : null);
if (!result && query.isPending) {
@@ -239,13 +239,25 @@ function isSafeUrl(url: unknown): boolean {
function SafeAnchor(props: Record<string, unknown>) {
const href = props.href;
const safeHref = href && isSafeUrl(href) ? href : undefined;
return createElement(Anchor as never, { ...sanitizeCustomJsxProps(props), href: safeHref });
const sanitized = sanitizeCustomJsxProps(props);
const opensNewWindow = sanitized.target === "_blank";
return createElement(Anchor as never, {
...sanitized,
href: safeHref,
rel: opensNewWindow ? "noopener noreferrer" : sanitized.rel,
});
}
function SafeNavLink(props: Record<string, unknown>) {
const href = props.href;
const safeHref = href && isSafeUrl(href) ? href : undefined;
return createElement(NavLink as never, { ...sanitizeCustomJsxProps(props), href: safeHref });
const sanitized = sanitizeCustomJsxProps(props);
const opensNewWindow = sanitized.target === "_blank";
return createElement(NavLink as never, {
...sanitized,
href: safeHref,
rel: opensNewWindow ? "noopener noreferrer" : sanitized.rel,
});
}
function SafeButton(props: Record<string, unknown>) {
@@ -301,7 +313,13 @@ function SafeCalendar(props: Record<string, unknown>) {
}
function SafeMiniCalendar(props: Record<string, unknown>) {
return createElement(MiniCalendar as never, { ...sanitizeCustomJsxProps(props), static: true });
return createElement(MiniCalendar as never, {
...sanitizeCustomJsxProps(props),
style: { pointerEvents: "none" },
previousControlProps: { disabled: true, tabIndex: -1 },
nextControlProps: { disabled: true, tabIndex: -1 },
getDayProps: () => ({ disabled: true, tabIndex: -1 }),
});
}
function SafeTree(props: Record<string, unknown>) {
@@ -309,7 +327,12 @@ function SafeTree(props: Record<string, unknown>) {
}
function SafeDatePicker(props: Record<string, unknown>) {
return createElement(DatePicker as never, { ...sanitizeCustomJsxProps(props), static: true });
return createElement(DatePicker as never, {
...sanitizeCustomJsxProps(props),
style: { pointerEvents: "none" },
enableKeyboardNavigation: false,
getDayProps: () => ({ disabled: true, tabIndex: -1 }),
});
}
function createSafeDateComponent(component: ComponentType<never>) {
@@ -730,7 +753,7 @@ safeDate.toLocaleTimeString = createSafeCallable((v: string | number, locale?: s
safeDate.getTime = createSafeCallable((v: string | number) => new Date(v).getTime());
safeDate.getYear = createSafeCallable((v: string | number) => new Date(v).getFullYear());
safeDate.getMonth = createSafeCallable((v: string | number) => new Date(v).getMonth());
safeDate.getDay = createSafeCallable((v: string | number) => new Date(v).getDay());
safeDate.getDay = createSafeCallable((v: string | number) => new Date(v).getUTCDay());
Object.freeze(safeDate);
export const SAFE_BINDINGS = (apiData: unknown) => ({
@@ -838,7 +838,7 @@ class Interpreter {
case "charAt":
return { handled: true, value: receiver.charAt(numericArgument(args[0], 0)) };
case "split": {
const limit = Math.max(0, Math.min(2_000, numericArgument(args[1], 100)));
const limit = Math.max(0, Math.min(2_000, numericArgument(args[1], 2_000)));
const split = args[0] === undefined ? [receiver] : receiver.split(String(args[0]), limit);
this.budget.collection(split.length);
return { handled: true, value: split };