diff --git a/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesLayersPanel.tsx b/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesLayersPanel.tsx
new file mode 100644
index 0000000..16cb533
--- /dev/null
+++ b/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesLayersPanel.tsx
@@ -0,0 +1,22 @@
+import { type Image } from "@tissuumaps/core";
+
+import { cn } from "@/lib/utils";
+
+import { Fieldset, FieldsetLegend } from "../../common/fieldset";
+
+export type ImagesLayersPanelProps = {
+ image: Image;
+ className?: string;
+};
+
+export function ImagesLayersPanel({ className }: ImagesLayersPanelProps) {
+ return (
+
+ );
+}
diff --git a/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesPanelItem.tsx b/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesPanelItem.tsx
deleted file mode 100644
index 289c139..0000000
--- a/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesPanelItem.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { type Image } from "@tissuumaps/core";
-
-import { ImagesPanelItemSettings } from "./ImagesPanelItemSettings";
-
-export type ImagesPanelItemProps = {
- image: Image;
-};
-
-export function ImagesPanelItem({ image }: ImagesPanelItemProps) {
- return (
- <>
-
- >
- );
-}
diff --git a/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesSettingsPanel.tsx b/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesSettingsPanel.tsx
new file mode 100644
index 0000000..3c74a4b
--- /dev/null
+++ b/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesSettingsPanel.tsx
@@ -0,0 +1,70 @@
+import { type Image } from "@tissuumaps/core";
+
+import { Input } from "@/components/ui/input";
+import { Switch } from "@/components/ui/switch";
+import { cn } from "@/lib/utils";
+
+import { useTissUUmaps } from "../../../store";
+import { Field, FieldLabel } from "../../common/field";
+import { Fieldset, FieldsetLegend } from "../../common/fieldset";
+
+export type ImagesSettingsPanelProps = {
+ image: Image;
+ className?: string;
+};
+
+export function ImagesSettingsPanel({
+ image,
+ className,
+}: ImagesSettingsPanelProps) {
+ const updateImage = useTissUUmaps((state) => state.updateImage);
+
+ return (
+
+ );
+}
diff --git a/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesPanelItemSettings.tsx b/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesSourcePanel.tsx
similarity index 50%
rename from apps/tissuumaps/src/components/panels/ImagesPanel/ImagesPanelItemSettings.tsx
rename to apps/tissuumaps/src/components/panels/ImagesPanel/ImagesSourcePanel.tsx
index 4f78b69..4b460b1 100644
--- a/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesPanelItemSettings.tsx
+++ b/apps/tissuumaps/src/components/panels/ImagesPanel/ImagesSourcePanel.tsx
@@ -1,22 +1,29 @@
import { JsonForms } from "@jsonforms/react";
+import { EditIcon } from "lucide-react";
import { useMemo } from "react";
-import { type Image, type ImageDataSource } from "@tissuumaps/core";
+import { type Image } from "@tissuumaps/core";
+
+import { Input } from "@/components/ui/input";
+import { cn } from "@/lib/utils";
import { useTissUUmaps } from "../../../store";
+import { Field, FieldLabel } from "../../common/field";
+import { Fieldset, FieldsetLegend } from "../../common/fieldset";
import { cells, renderers } from "../../jsonforms";
-export type ImagesPanelItemSettingsProps = {
+export type ImagesSourcePanelProps = {
image: Image;
+ className?: string;
};
-export function ImagesPanelItemSettings({
+export function ImagesSourcePanel({
image,
-}: ImagesPanelItemSettingsProps) {
+ className,
+}: ImagesSourcePanelProps) {
const imageDataStorageRegistry = useTissUUmaps(
(state) => state.imageDataStorageRegistry,
);
- const updateImage = useTissUUmaps((state) => state.updateImage);
const { dataSourceSchema, dataSourceUISchema } = useMemo(() => {
const value = imageDataStorageRegistry.get(image.dataSource.type);
@@ -29,25 +36,25 @@ export function ImagesPanelItemSettings({
}, [imageDataStorageRegistry, image.dataSource.type]);
return (
-
- {/* Data source */}
+
+
);
}
diff --git a/apps/tissuumaps/src/components/panels/ImagesPanel/index.tsx b/apps/tissuumaps/src/components/panels/ImagesPanel/index.tsx
index eb1d060..42ebd0d 100644
--- a/apps/tissuumaps/src/components/panels/ImagesPanel/index.tsx
+++ b/apps/tissuumaps/src/components/panels/ImagesPanel/index.tsx
@@ -1,9 +1,16 @@
import { DragDropProvider } from "@dnd-kit/react";
import { isSortable, useSortable } from "@dnd-kit/react/sortable";
-import { GripVertical } from "lucide-react";
+import { EyeIcon, EyeOffIcon, GripVertical, Trash2Icon } from "lucide-react";
import { type Image } from "@tissuumaps/core";
+import { Button } from "@/components/ui/button";
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/components/ui/input-group";
+
import { useTissUUmaps } from "../../../store";
import {
Accordion,
@@ -13,7 +20,9 @@ import {
AccordionTrigger,
AccordionTriggerUpDownIcon,
} from "../../common/accordion";
-import { ImagesPanelItem } from "./ImagesPanelItem";
+import { ImagesLayersPanel } from "./ImagesLayersPanel";
+import { ImagesSettingsPanel } from "./ImagesSettingsPanel";
+import { ImagesSourcePanel } from "./ImagesSourcePanel";
export type ImagesPanelProps = {
className?: string;
@@ -49,18 +58,71 @@ type ImageAccordionItemProps = {
};
function ImageAccordionItem({ image, index }: ImageAccordionItemProps) {
+ const updateImage = useTissUUmaps((state) => state.updateImage);
+ const deleteImage = useTissUUmaps((state) => state.deleteImage);
+
const { ref, handleRef } = useSortable({ id: image.id, index });
return (
- }>
-
-
- {image.name}
-
-
-
-
-
-
+
+
+
+
+
+
+
+ OPA
+ {
+ const opacity = event.target.valueAsNumber;
+ if (Number.isFinite(opacity)) {
+ updateImage(image.id, {
+ opacity: Math.min(Math.max(0, opacity), 1),
+ });
+ }
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsLayersPanel.tsx b/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsLayersPanel.tsx
new file mode 100644
index 0000000..40cacdd
--- /dev/null
+++ b/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsLayersPanel.tsx
@@ -0,0 +1,22 @@
+import { type Labels } from "@tissuumaps/core";
+
+import { cn } from "@/lib/utils";
+
+import { Fieldset, FieldsetLegend } from "../../common/fieldset";
+
+export type LabelsLayersPanelProps = {
+ labels: Labels;
+ className?: string;
+};
+
+export function LabelsLayersPanel({ className }: LabelsLayersPanelProps) {
+ return (
+
+ );
+}
diff --git a/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsPanelItem.tsx b/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsPanelItem.tsx
deleted file mode 100644
index d207233..0000000
--- a/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsPanelItem.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { type Labels } from "@tissuumaps/core";
-
-import { LabelsPanelItemSettings } from "./LabelsPanelItemSettings";
-
-export type LabelsPanelItemProps = {
- labels: Labels;
-};
-
-export function LabelsPanelItem({ labels }: LabelsPanelItemProps) {
- return (
- <>
-
- >
- );
-}
diff --git a/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsPanelItemSettings.tsx b/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsSettingsPanel.tsx
similarity index 54%
rename from apps/tissuumaps/src/components/panels/LabelsPanel/LabelsPanelItemSettings.tsx
rename to apps/tissuumaps/src/components/panels/LabelsPanel/LabelsSettingsPanel.tsx
index 7837e4c..6aaa121 100644
--- a/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsPanelItemSettings.tsx
+++ b/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsSettingsPanel.tsx
@@ -1,14 +1,14 @@
-import { JsonForms } from "@jsonforms/react";
-import { useMemo, useState } from "react";
-
import {
type Labels,
- type LabelsDataSource,
defaultLabelColor,
defaultLabelOpacity,
defaultLabelVisibility,
} from "@tissuumaps/core";
+import { Input } from "@/components/ui/input";
+import { Switch } from "@/components/ui/switch";
+import { cn } from "@/lib/utils";
+
import { useTissUUmaps } from "../../../store";
import {
Accordion,
@@ -18,6 +18,8 @@ import {
AccordionTrigger,
AccordionTriggerRightDownIcon,
} from "../../common/accordion";
+import { Field, FieldLabel } from "../../common/field";
+import { Fieldset, FieldsetLegend } from "../../common/fieldset";
import {
ColorConfigControl,
ColorConfigSourceToggleGroup,
@@ -33,41 +35,18 @@ import {
VisibilityConfigSourceToggleGroup,
} from "../../controls/VisibilityConfigControl";
import { useVisibilityConfigControl } from "../../controls/VisibilityConfigControl/useVisibilityConfigControl";
-import { cells, renderers } from "../../jsonforms";
-
-const ConfigControl = {
- labelColor: "labelColor",
- labelVisibility: "labelVisibility",
- labelOpacity: "labelOpacity",
-} as const;
-type ConfigControl = (typeof ConfigControl)[keyof typeof ConfigControl];
-
-export type LabelsPanelItemSettingsProps = {
+export type LabelsSettingsPanelProps = {
labels: Labels;
+ className?: string;
};
-export function LabelsPanelItemSettings({
+export function LabelsSettingsPanel({
labels,
-}: LabelsPanelItemSettingsProps) {
- const [expandedConfigControl, setExpandedConfigControl] =
- useState(null);
-
- const labelsDataStorageRegistry = useTissUUmaps(
- (state) => state.labelsDataStorageRegistry,
- );
+ className,
+}: LabelsSettingsPanelProps) {
const updateLabels = useTissUUmaps((state) => state.updateLabels);
- const { dataSourceSchema, dataSourceUISchema } = useMemo(() => {
- const value = labelsDataStorageRegistry.get(labels.dataSource.type);
- if (value === undefined) {
- throw new Error(
- `No labels data storage adapter registered for data source type "${labels.dataSource.type}"`,
- );
- }
- return value;
- }, [labelsDataStorageRegistry, labels.dataSource.type]);
-
const labelColorConfigControlState = useColorConfigControl(
labels.labelColor,
(newColorConfig) => updateLabels(labels.id, { labelColor: newColorConfig }),
@@ -87,43 +66,68 @@ export function LabelsPanelItemSettings({
);
return (
-
- {/* Data source */}
-
{
- if (errors === undefined || errors.length === 0) {
- updateLabels(labels.id, {
- dataSource: {
- ...labels.dataSource,
- ...(data as LabelsDataSource),
- },
- });
- }
- }}
- renderers={renderers}
- cells={cells}
- />
- {/* Label settings */}
-
- setExpandedConfigControl(
- (value[0] as ConfigControl | undefined) ?? null,
- )
- }
- >
+
+
);
}
diff --git a/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsSourcePanel.tsx b/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsSourcePanel.tsx
new file mode 100644
index 0000000..a3884e3
--- /dev/null
+++ b/apps/tissuumaps/src/components/panels/LabelsPanel/LabelsSourcePanel.tsx
@@ -0,0 +1,60 @@
+import { JsonForms } from "@jsonforms/react";
+import { EditIcon } from "lucide-react";
+import { useMemo } from "react";
+
+import { type Labels } from "@tissuumaps/core";
+
+import { Input } from "@/components/ui/input";
+import { cn } from "@/lib/utils";
+
+import { useTissUUmaps } from "../../../store";
+import { Field, FieldLabel } from "../../common/field";
+import { Fieldset, FieldsetLegend } from "../../common/fieldset";
+import { cells, renderers } from "../../jsonforms";
+
+export type LabelsSourcePanelProps = {
+ labels: Labels;
+ className?: string;
+};
+
+export function LabelsSourcePanel({
+ labels,
+ className,
+}: LabelsSourcePanelProps) {
+ const labelsDataStorageRegistry = useTissUUmaps(
+ (state) => state.labelsDataStorageRegistry,
+ );
+
+ const { dataSourceSchema, dataSourceUISchema } = useMemo(() => {
+ const value = labelsDataStorageRegistry.get(labels.dataSource.type);
+ if (value === undefined) {
+ throw new Error(
+ `No labels data Storage registered for data source type "${labels.dataSource.type}"`,
+ );
+ }
+ return value;
+ }, [labelsDataStorageRegistry, labels.dataSource.type]);
+
+ return (
+
+ );
+}
diff --git a/apps/tissuumaps/src/components/panels/LabelsPanel/index.tsx b/apps/tissuumaps/src/components/panels/LabelsPanel/index.tsx
index 1443360..be0173e 100644
--- a/apps/tissuumaps/src/components/panels/LabelsPanel/index.tsx
+++ b/apps/tissuumaps/src/components/panels/LabelsPanel/index.tsx
@@ -1,9 +1,16 @@
import { DragDropProvider } from "@dnd-kit/react";
import { isSortable, useSortable } from "@dnd-kit/react/sortable";
-import { GripVertical } from "lucide-react";
+import { EyeIcon, EyeOffIcon, GripVertical, Trash2Icon } from "lucide-react";
import { type Labels } from "@tissuumaps/core";
+import { Button } from "@/components/ui/button";
+import {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupInput,
+} from "@/components/ui/input-group";
+
import { useTissUUmaps } from "../../../store";
import {
Accordion,
@@ -13,7 +20,9 @@ import {
AccordionTrigger,
AccordionTriggerUpDownIcon,
} from "../../common/accordion";
-import { LabelsPanelItem } from "./LabelsPanelItem";
+import { LabelsLayersPanel } from "./LabelsLayersPanel";
+import { LabelsSettingsPanel } from "./LabelsSettingsPanel";
+import { LabelsSourcePanel } from "./LabelsSourcePanel";
export type LabelsPanelProps = {
className?: string;
@@ -28,8 +37,6 @@ export function LabelsPanel({ className }: LabelsPanelProps) {
onDragEnd={(event) => {
const { source, canceled } = event.operation;
if (isSortable(source) && !canceled) {
- // dnd-kit optimistically updates the DOM
- // https://github.com/clauderic/dnd-kit/issues/1564
moveLabels(source.id as string, source.index);
}
}}
@@ -53,18 +60,70 @@ type LabelsAccordionItemProps = {
};
function LabelsAccordionItem({ labels, index }: LabelsAccordionItemProps) {
+ const updateLabels = useTissUUmaps((state) => state.updateLabels);
+ const deleteLabels = useTissUUmaps((state) => state.deleteLabels);
+
const { ref, handleRef } = useSortable({ id: labels.id, index });
return (
-
+
- {labels.name}
-
+
+
+
+ OPA
+ {
+ const opacity = event.target.valueAsNumber;
+ if (Number.isFinite(opacity)) {
+ updateLabels(labels.id, {
+ opacity: Math.min(Math.max(0, opacity), 1),
+ });
+ }
+ }}
+ />
+
+
+
+
+
-
-
+
+
+
+
diff --git a/apps/tissuumaps/src/components/panels/TablesPanel/TablesPanelItem.tsx b/apps/tissuumaps/src/components/panels/TablesPanel/TablesPanelItem.tsx
deleted file mode 100644
index d6144bf..0000000
--- a/apps/tissuumaps/src/components/panels/TablesPanel/TablesPanelItem.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { type Table } from "@tissuumaps/core";
-
-import { TablesPanelItemSettings } from "./TablesPanelItemSettings";
-
-export type TablesPanelItemProps = {
- table: Table;
-};
-
-export function TablesPanelItem({ table }: TablesPanelItemProps) {
- return (
- <>
-
- >
- );
-}
diff --git a/apps/tissuumaps/src/components/panels/TablesPanel/TablesSettingsPanel.tsx b/apps/tissuumaps/src/components/panels/TablesPanel/TablesSettingsPanel.tsx
new file mode 100644
index 0000000..3bd73cd
--- /dev/null
+++ b/apps/tissuumaps/src/components/panels/TablesPanel/TablesSettingsPanel.tsx
@@ -0,0 +1,39 @@
+import { type Table } from "@tissuumaps/core";
+
+import { Input } from "@/components/ui/input";
+import { cn } from "@/lib/utils";
+
+import { useTissUUmaps } from "../../../store";
+import { Field, FieldLabel } from "../../common/field";
+import { Fieldset, FieldsetLegend } from "../../common/fieldset";
+
+export type TablesSettingsPanelProps = {
+ table: Table;
+ className?: string;
+};
+
+export function TablesSettingsPanel({
+ table,
+ className,
+}: TablesSettingsPanelProps) {
+ const updateTable = useTissUUmaps((state) => state.updateTable);
+
+ return (
+
+ );
+}
diff --git a/apps/tissuumaps/src/components/panels/TablesPanel/TablesPanelItemSettings.tsx b/apps/tissuumaps/src/components/panels/TablesPanel/TablesSourcePanel.tsx
similarity index 54%
rename from apps/tissuumaps/src/components/panels/TablesPanel/TablesPanelItemSettings.tsx
rename to apps/tissuumaps/src/components/panels/TablesPanel/TablesSourcePanel.tsx
index 51d8b01..21e3332 100644
--- a/apps/tissuumaps/src/components/panels/TablesPanel/TablesPanelItemSettings.tsx
+++ b/apps/tissuumaps/src/components/panels/TablesPanel/TablesSourcePanel.tsx
@@ -1,18 +1,26 @@
import { JsonForms } from "@jsonforms/react";
+import { EditIcon } from "lucide-react";
import { useMemo } from "react";
import { type Table } from "@tissuumaps/core";
+import { Input } from "@/components/ui/input";
+import { cn } from "@/lib/utils";
+
import { useTissUUmaps } from "../../../store";
+import { Field, FieldLabel } from "../../common/field";
+import { Fieldset, FieldsetLegend } from "../../common/fieldset";
import { cells, renderers } from "../../jsonforms";
-export type TablesPanelItemSettingsProps = {
+export type TablesSourcePanelProps = {
table: Table;
+ className?: string;
};
-export function TablesPanelItemSettings({
+export function TablesSourcePanel({
table,
-}: TablesPanelItemSettingsProps) {
+ className,
+}: TablesSourcePanelProps) {
const tableDataStorageRegistry = useTissUUmaps(
(state) => state.tableDataStorageRegistry,
);
@@ -28,8 +36,17 @@ export function TablesPanelItemSettings({
}, [tableDataStorageRegistry, table.dataSource.type]);
return (
-
- {/* Data source */}
+
+
);
}
diff --git a/apps/tissuumaps/src/components/panels/TablesPanel/index.tsx b/apps/tissuumaps/src/components/panels/TablesPanel/index.tsx
index 8700121..18a3aad 100644
--- a/apps/tissuumaps/src/components/panels/TablesPanel/index.tsx
+++ b/apps/tissuumaps/src/components/panels/TablesPanel/index.tsx
@@ -1,3 +1,11 @@
+import { DragDropProvider } from "@dnd-kit/react";
+import { isSortable, useSortable } from "@dnd-kit/react/sortable";
+import { GripVertical, Trash2Icon } from "lucide-react";
+
+import { type Table } from "@tissuumaps/core";
+
+import { Button } from "@/components/ui/button";
+
import { useTissUUmaps } from "../../../store";
import {
Accordion,
@@ -7,7 +15,8 @@ import {
AccordionTrigger,
AccordionTriggerUpDownIcon,
} from "../../common/accordion";
-import { TablesPanelItem } from "./TablesPanelItem";
+import { TablesSettingsPanel } from "./TablesSettingsPanel";
+import { TablesSourcePanel } from "./TablesSourcePanel";
export type TablesPanelProps = {
className?: string;
@@ -15,20 +24,68 @@ export type TablesPanelProps = {
export function TablesPanel({ className }: TablesPanelProps) {
const tables = useTissUUmaps((state) => state.tables);
+ const moveTable = useTissUUmaps((state) => state.moveTable);
+
+ return (
+ {
+ const { source, canceled } = event.operation;
+ if (isSortable(source) && !canceled) {
+ moveTable(source.id as string, source.index);
+ }
+ }}
+ >
+
+ {tables.map((table, index) => (
+
+ ))}
+
+
+ );
+}
+
+type TableAccordionItemProps = {
+ table: Table;
+ index: number;
+};
+
+function TableAccordionItem({ table, index }: TableAccordionItemProps) {
+ const deleteTable = useTissUUmaps((state) => state.deleteTable);
+
+ const { ref, handleRef } = useSortable({ id: table.id, index });
return (
-
- {tables.map((table) => (
-
-
- {table.name}
-
-
-
-
-
-
- ))}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}