feat: add bookmark widget (#964)
* feat: add bookmark widget * fix: item component type issue, widget-ordered-object-list-input item component issue * feat: add button in items list * wip * wip: bookmark options dnd * wip: improve widget sortable item list * feat: add sortable item list input to widget edit modal * feat: implement bookmark widget * chore: address pull request feedback * fix: format issues * fix: lockfile not up to date * fix: import configuration missing and apps not imported * fix: bookmark items not sorted * feat: add flex layouts to bookmark widget * fix: deepsource issue * fix: add missing layout bookmarks old-import options mapping --------- Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
import type React from "react";
|
||||
import type { DraggableAttributes, UniqueIdentifier } from "@dnd-kit/core";
|
||||
import type { ActionIconProps } from "@mantine/core";
|
||||
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import type { IntegrationKind, WidgetKind } from "@homarr/definitions";
|
||||
import type { ZodType } from "@homarr/validation";
|
||||
@@ -21,6 +25,19 @@ interface MultiSelectInput<TOptions extends SelectOption[]>
|
||||
searchable?: boolean;
|
||||
}
|
||||
|
||||
interface SortableItemListInput<TItem, TOptionValue extends UniqueIdentifier>
|
||||
extends Omit<CommonInput<TOptionValue[]>, "withDescription"> {
|
||||
AddButton: (props: { addItem: (item: TItem) => void; values: TOptionValue[] }) => React.ReactNode;
|
||||
ItemComponent: (props: {
|
||||
item: TItem;
|
||||
removeItem: () => void;
|
||||
rootAttributes: DraggableAttributes;
|
||||
handle: (props: Partial<Pick<ActionIconProps, "size" | "color" | "variant">>) => React.ReactNode;
|
||||
}) => React.ReactNode;
|
||||
uniqueIdentifier: (item: TItem) => TOptionValue;
|
||||
useData: (values: TOptionValue[]) => { data: TItem[] | undefined; isLoading: boolean; error: unknown };
|
||||
}
|
||||
|
||||
interface SelectInput<TOptions extends readonly SelectOption[]>
|
||||
extends CommonInput<inferSelectOptionValue<TOptions[number]>> {
|
||||
options: TOptions;
|
||||
@@ -109,10 +126,26 @@ const optionsFactory = {
|
||||
defaultValue: "",
|
||||
withDescription: false,
|
||||
}),
|
||||
sortableItemList: <const TItem, const TOptionValue extends UniqueIdentifier>(
|
||||
input: SortableItemListInput<TItem, TOptionValue>,
|
||||
) => ({
|
||||
type: "sortableItemList" as const,
|
||||
defaultValue: [] as TOptionValue[],
|
||||
itemComponent: input.ItemComponent,
|
||||
addButton: input.AddButton,
|
||||
uniqueIdentifier: input.uniqueIdentifier,
|
||||
useData: input.useData,
|
||||
withDescription: false,
|
||||
}),
|
||||
};
|
||||
|
||||
type WidgetOptionFactory = typeof optionsFactory;
|
||||
export type WidgetOptionDefinition = ReturnType<WidgetOptionFactory[keyof WidgetOptionFactory]>;
|
||||
|
||||
export type WidgetOptionDefinition =
|
||||
| ReturnType<WidgetOptionFactory[Exclude<keyof WidgetOptionFactory, "sortableItemList">]>
|
||||
// We allow any here as it's already type guarded with Record<string, unknown> and it still infers the correct type
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ReturnType<typeof optionsFactory.sortableItemList<any, any>>;
|
||||
export type WidgetOptionsRecord = Record<string, WidgetOptionDefinition>;
|
||||
export type WidgetOptionType = WidgetOptionDefinition["type"];
|
||||
export type WidgetOptionOfType<TType extends WidgetOptionType> = Extract<WidgetOptionDefinition, { type: TType }>;
|
||||
|
||||
Reference in New Issue
Block a user