2025-11-21 07:51:00 +00:00
|
|
|
import React from "react";
|
2025-11-21 07:04:30 +00:00
|
|
|
import { StatusIcon } from "@/components/atoms/StatusIcon";
|
2025-11-21 07:51:00 +00:00
|
|
|
import { LucideIconModal } from "./LucideIconModal";
|
|
|
|
|
import { App } from "obsidian";
|
|
|
|
|
import { Input } from "@/components/atoms/Input";
|
|
|
|
|
|
|
|
|
|
const getAppInstance = (): App | undefined => {
|
|
|
|
|
return (window as typeof window & { app?: App }).app;
|
|
|
|
|
};
|
2025-11-21 07:04:30 +00:00
|
|
|
|
|
|
|
|
export interface LucideIconPickerProps {
|
|
|
|
|
value?: string;
|
|
|
|
|
onChange: (value: string) => void;
|
2025-11-21 07:33:25 +00:00
|
|
|
placeholder?: string;
|
|
|
|
|
allowTextInput?: boolean;
|
|
|
|
|
allowClear?: boolean;
|
2025-11-21 07:04:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const LucideIconPicker: React.FC<LucideIconPickerProps> = ({
|
|
|
|
|
value = "",
|
|
|
|
|
onChange,
|
2025-11-21 07:51:00 +00:00
|
|
|
placeholder = "Choose Lucide icon",
|
2025-11-21 07:33:25 +00:00
|
|
|
allowTextInput = false,
|
|
|
|
|
allowClear = true,
|
2025-11-21 07:04:30 +00:00
|
|
|
}) => {
|
2025-11-21 07:51:00 +00:00
|
|
|
const openModal = () => {
|
|
|
|
|
const app = getAppInstance();
|
|
|
|
|
if (!app) {
|
|
|
|
|
console.warn("Cannot open Lucide icon modal without Obsidian app");
|
|
|
|
|
return;
|
2025-11-21 07:04:30 +00:00
|
|
|
}
|
2025-11-21 07:51:00 +00:00
|
|
|
const modal = new LucideIconModal(app, {
|
|
|
|
|
initialValue: value,
|
|
|
|
|
onSelect: (icon) => onChange(icon),
|
|
|
|
|
});
|
|
|
|
|
modal.open();
|
2025-11-21 07:04:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleClear = () => {
|
|
|
|
|
onChange("");
|
2025-11-21 07:33:25 +00:00
|
|
|
};
|
|
|
|
|
|
2025-11-21 07:04:30 +00:00
|
|
|
return (
|
2025-11-21 07:51:00 +00:00
|
|
|
<div className="lucide-icon-picker">
|
2025-11-21 07:33:25 +00:00
|
|
|
{allowTextInput && (
|
2025-11-21 07:04:30 +00:00
|
|
|
<Input
|
|
|
|
|
variant="text"
|
2025-11-21 07:33:25 +00:00
|
|
|
value={value}
|
2025-11-21 07:51:00 +00:00
|
|
|
onChange={(val) => onChange(val)}
|
2025-11-21 07:33:25 +00:00
|
|
|
placeholder="Emoji or icon name"
|
|
|
|
|
className="lucide-icon-picker__text-input"
|
2025-11-21 07:04:30 +00:00
|
|
|
/>
|
2025-11-21 07:33:25 +00:00
|
|
|
)}
|
2025-11-21 07:51:00 +00:00
|
|
|
<div className="lucide-icon-picker__row">
|
2025-11-21 07:33:25 +00:00
|
|
|
<button
|
|
|
|
|
type="button"
|
2025-11-21 07:51:00 +00:00
|
|
|
className="lucide-icon-picker__modal-button"
|
|
|
|
|
onClick={openModal}
|
2025-11-21 07:33:25 +00:00
|
|
|
>
|
2025-11-21 07:51:00 +00:00
|
|
|
<span className="lucide-icon-picker__preview">
|
|
|
|
|
<StatusIcon icon={value} lucideIcon={value} size={18} />
|
2025-11-21 07:33:25 +00:00
|
|
|
</span>
|
2025-11-21 07:51:00 +00:00
|
|
|
<span className="lucide-icon-picker__label">
|
2025-11-21 07:33:25 +00:00
|
|
|
{value || placeholder}
|
|
|
|
|
</span>
|
|
|
|
|
</button>
|
|
|
|
|
{allowClear && value && (
|
2025-11-21 07:04:30 +00:00
|
|
|
<button
|
|
|
|
|
type="button"
|
2025-11-21 07:33:25 +00:00
|
|
|
className="lucide-icon-picker__clear-trigger"
|
2025-11-21 07:04:30 +00:00
|
|
|
onClick={handleClear}
|
|
|
|
|
>
|
|
|
|
|
Clear
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|