@datum-cloud/datum-ui 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/assistant/index.mjs +996 -0
  2. package/dist/components/features/assistant/components/assistant-workspace.d.ts +53 -0
  3. package/dist/components/features/assistant/components/brain-glyph.d.ts +8 -0
  4. package/dist/components/features/assistant/components/composer/equalizer.d.ts +6 -0
  5. package/dist/components/features/assistant/components/composer/index.d.ts +3 -0
  6. package/dist/components/features/assistant/components/composer/model-selector.d.ts +10 -0
  7. package/dist/components/features/assistant/components/composer/prompt-card.d.ts +21 -0
  8. package/dist/components/features/assistant/components/conversation/conversation.d.ts +15 -0
  9. package/dist/components/features/assistant/components/conversation/index.d.ts +3 -0
  10. package/dist/components/features/assistant/components/conversation/scroll-to-bottom-button.d.ts +5 -0
  11. package/dist/components/features/assistant/components/conversation/turn-rail.d.ts +12 -0
  12. package/dist/components/features/assistant/components/empty-state.d.ts +10 -0
  13. package/dist/components/features/assistant/components/message/assistant-message.d.ts +9 -0
  14. package/dist/components/features/assistant/components/message/index.d.ts +4 -0
  15. package/dist/components/features/assistant/components/message/loading-dots.d.ts +4 -0
  16. package/dist/components/features/assistant/components/message/thinking-block.d.ts +4 -0
  17. package/dist/components/features/assistant/components/message/user-message.d.ts +4 -0
  18. package/dist/components/features/assistant/components/sidebar/chat-rail.d.ts +7 -0
  19. package/dist/components/features/assistant/components/sidebar/history-panel.d.ts +16 -0
  20. package/dist/components/features/assistant/components/sidebar/index.d.ts +2 -0
  21. package/dist/components/features/assistant/context/assistant-config.d.ts +19 -0
  22. package/dist/components/features/assistant/context/index.d.ts +1 -0
  23. package/dist/components/features/assistant/hooks/index.d.ts +1 -0
  24. package/dist/components/features/assistant/hooks/use-turn-rail.d.ts +16 -0
  25. package/dist/components/features/assistant/index.d.ts +11 -0
  26. package/dist/components/features/assistant/types.d.ts +66 -0
  27. package/dist/components/features/assistant/utils/format-relative-time.d.ts +2 -0
  28. package/dist/components/features/assistant/utils/index.d.ts +2 -0
  29. package/dist/components/features/assistant/utils/sanitize-html.d.ts +2 -0
  30. package/dist/dropdown-menu-b8zY5Cs6.mjs +82 -0
  31. package/dist/index.mjs +1 -1
  32. package/dist/{layers-CGp0ceSG.mjs → layers-DJYz6fyE.mjs} +2 -78
  33. package/dist/map/index.mjs +1 -1
  34. package/package.json +21 -1
@@ -0,0 +1,53 @@
1
+ import type { Editor } from '@tiptap/react';
2
+ import type { UIMessage } from 'ai';
3
+ import type { MouseEvent as ReactMouseEvent, ReactNode, RefObject } from 'react';
4
+ import type { AssistantConfig, ChatSummary, EffortId } from '../types';
5
+ /**
6
+ * Presentational, props-driven assistant layout: left rail + collapsible
7
+ * history + (empty state | conversation) + composer. The host owns all state
8
+ * and transport (via its own chat hook) and feeds it in here, so staff and
9
+ * cloud reuse the exact same layout. Shell-agnostic — it fills its container.
10
+ */
11
+ export interface AssistantWorkspaceProps {
12
+ /** Host-specific configuration (copy, suggestions, tool labels, models, …). */
13
+ config?: Partial<AssistantConfig>;
14
+ /** Display name for the greeting; the host reads it from its own user context. */
15
+ userName?: string;
16
+ /** Header title for the active conversation. */
17
+ title: string;
18
+ messages: UIMessage[];
19
+ status: string;
20
+ error?: Error;
21
+ isReady: boolean;
22
+ chatList: ChatSummary[];
23
+ currentChatId: string;
24
+ /**
25
+ * Optional block pinned above the history search input, naming the scope the
26
+ * listed chats belong to (cloud-portal shows the current project).
27
+ */
28
+ sidebarHeader?: ReactNode;
29
+ editor: Editor | null;
30
+ /** Sanitized HTML per user message index (for exact-render of the user's input). */
31
+ htmlByUserMsgIndex: RefObject<string[]>;
32
+ bottomRef: RefObject<HTMLDivElement | null>;
33
+ containerRef: (node: HTMLDivElement | null) => void;
34
+ userScrolledUpRef: RefObject<boolean>;
35
+ onSend: () => void;
36
+ onStop: () => void;
37
+ onRetry: () => void;
38
+ onNewChat: () => void;
39
+ onLoadChat: (chat: ChatSummary) => void;
40
+ onDeleteChat: (e: ReactMouseEvent, chatId: string) => void;
41
+ onSuggestion: (text: string) => void;
42
+ modelId: string;
43
+ effortId: EffortId;
44
+ onModelChange: (id: string) => void;
45
+ onEffortChange: (id: EffortId) => void;
46
+ micSupported?: boolean;
47
+ micListening?: boolean;
48
+ micFrequencyData?: number[];
49
+ onMicToggle?: () => void;
50
+ historyOpen: boolean;
51
+ onToggleHistory: () => void;
52
+ }
53
+ export declare function AssistantWorkspace({ config, userName, title, messages, status, error, isReady, chatList, currentChatId, sidebarHeader, editor, htmlByUserMsgIndex, bottomRef, containerRef, userScrolledUpRef, onSend, onStop, onRetry, onNewChat, onLoadChat, onDeleteChat, onSuggestion, modelId, effortId, onModelChange, onEffortChange, micSupported, micListening, micFrequencyData, onMicToggle, historyOpen, onToggleHistory, }: AssistantWorkspaceProps): import("react").JSX.Element;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Decorative brain/sunburst glyph for the assistant empty-state greeting (per
3
+ * Figma). Follows the Datum logo's theming: canyon-clay (#bf9595) in light,
4
+ * aurora-moss (#e6f59f) in dark. Size is driven by the passed `className`.
5
+ */
6
+ export declare function BrainGlyph({ className }: {
7
+ className?: string;
8
+ }): import("react").JSX.Element;
@@ -0,0 +1,6 @@
1
+ interface EqualizerProps {
2
+ frequencyData: number[];
3
+ className?: string;
4
+ }
5
+ export declare function Equalizer({ frequencyData, className }: EqualizerProps): import("react").JSX.Element;
6
+ export {};
@@ -0,0 +1,3 @@
1
+ export * from './equalizer';
2
+ export * from './model-selector';
3
+ export * from './prompt-card';
@@ -0,0 +1,10 @@
1
+ import type { EffortId } from '../../types';
2
+ interface ModelSelectorProps {
3
+ modelId: string;
4
+ effortId: EffortId;
5
+ onModelChange: (id: string) => void;
6
+ onEffortChange: (id: EffortId) => void;
7
+ disabled?: boolean;
8
+ }
9
+ export declare function ModelSelector({ modelId, effortId, onModelChange, onEffortChange, disabled, }: ModelSelectorProps): import("react").JSX.Element | null;
10
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { Editor } from '@tiptap/react';
2
+ import type { EffortId } from '../../types';
3
+ interface PromptCardProps {
4
+ editor: Editor | null;
5
+ isReady: boolean;
6
+ canRetry: boolean;
7
+ onSend: () => void;
8
+ onStop: () => void;
9
+ onRetry: () => void;
10
+ modelId: string;
11
+ effortId: EffortId;
12
+ onModelChange: (id: string) => void;
13
+ onEffortChange: (id: EffortId) => void;
14
+ speechSupported?: boolean;
15
+ isListening?: boolean;
16
+ frequencyData?: number[];
17
+ onMicToggle?: () => void;
18
+ className?: string;
19
+ }
20
+ export declare function PromptCard({ editor, isReady, canRetry, onSend, onStop, onRetry, modelId, effortId, onModelChange, onEffortChange, speechSupported, isListening, frequencyData, onMicToggle, className, }: PromptCardProps): import("react").JSX.Element;
21
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { UIMessage } from 'ai';
2
+ import type { RefObject } from 'react';
3
+ interface ConversationProps {
4
+ messages: UIMessage[];
5
+ status: string;
6
+ error?: Error;
7
+ htmlByUserMsgIndex: RefObject<string[]>;
8
+ containerRef: (node: HTMLDivElement | null) => void;
9
+ bottomRef: RefObject<HTMLDivElement | null>;
10
+ userScrolledUpRef: RefObject<boolean>;
11
+ /** The docked prompt card, pinned to the bottom. */
12
+ footer: React.ReactNode;
13
+ }
14
+ export declare function Conversation({ messages, status, error, htmlByUserMsgIndex, containerRef, bottomRef, userScrolledUpRef, footer, }: ConversationProps): import("react").JSX.Element;
15
+ export {};
@@ -0,0 +1,3 @@
1
+ export * from './conversation';
2
+ export * from './scroll-to-bottom-button';
3
+ export * from './turn-rail';
@@ -0,0 +1,5 @@
1
+ /** Floating chevron above the composer; jumps to the latest message. */
2
+ export declare function ScrollToBottomButton({ show, onClick }: {
3
+ show: boolean;
4
+ onClick: () => void;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import type { Turn } from '../../types';
2
+ interface TurnRailProps {
3
+ turns: Turn[];
4
+ activeId: string | null;
5
+ onJump: (id: string) => void;
6
+ }
7
+ /**
8
+ * Right-edge rail: ticks (one per submitted prompt) when idle; morphs into a
9
+ * compact, clickable prompt list on hover. The in-view turn is highlighted.
10
+ */
11
+ export declare function TurnRail({ turns, activeId, onJump }: TurnRailProps): import("react").JSX.Element | null;
12
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from 'react';
2
+ interface EmptyStateProps {
3
+ name?: string;
4
+ isReady: boolean;
5
+ onSuggestion: (text: string) => void;
6
+ /** The shared prompt card. */
7
+ children: ReactNode;
8
+ }
9
+ export declare function EmptyState({ name, isReady, onSuggestion, children }: EmptyStateProps): import("react").JSX.Element;
10
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { UIMessage } from 'ai';
2
+ import 'streamdown/styles.css';
3
+ interface AssistantMessageProps {
4
+ msg: UIMessage;
5
+ isLastMessage: boolean;
6
+ status: string;
7
+ }
8
+ export declare function AssistantMessage({ msg, isLastMessage, status }: AssistantMessageProps): import("react").JSX.Element;
9
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from './assistant-message';
2
+ export * from './loading-dots';
3
+ export * from './thinking-block';
4
+ export * from './user-message';
@@ -0,0 +1,4 @@
1
+ /** Three bouncing dots — the assistant's "thinking" indicator. */
2
+ export declare function LoadingDots({ className }: {
3
+ className?: string;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare function ThinkingBlock({ text, isStreaming, }: {
2
+ text: string;
3
+ isStreaming?: boolean;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ /** A user's message — a right-aligned bubble rendering the sanitized input HTML. */
2
+ export declare function UserMessage({ html }: {
3
+ html: string;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ interface ChatRailProps {
2
+ historyOpen: boolean;
3
+ onNewChat: () => void;
4
+ onToggleHistory: () => void;
5
+ }
6
+ export declare function ChatRail({ historyOpen, onNewChat, onToggleHistory }: ChatRailProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { ChatSummary } from '../../types';
3
+ interface HistoryPanelProps {
4
+ chatList: ChatSummary[];
5
+ currentChatId: string;
6
+ onLoadChat: (chat: ChatSummary) => void;
7
+ onDeleteChat: (e: React.MouseEvent, chatId: string) => void;
8
+ /**
9
+ * Optional host-supplied block pinned above the search input, naming the scope
10
+ * the listed chats belong to — cloud-portal shows the current project. Hosts
11
+ * whose history isn't scoped to anything (staff-portal) omit it.
12
+ */
13
+ header?: ReactNode;
14
+ }
15
+ export declare function HistoryPanel({ chatList, currentChatId, onLoadChat, onDeleteChat, header, }: HistoryPanelProps): import("react").JSX.Element;
16
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './chat-rail';
2
+ export * from './history-panel';
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { AssistantConfig, LinkRenderProps } from '../types';
3
+ /**
4
+ * Framework-agnostic link renderer: internal routes (`/…`) render as a plain
5
+ * same-tab anchor, everything else opens in a new tab. Hosts override
6
+ * `renderLink` to add routing (e.g. a router `<Link>`) or icons (e.g. a Sentry
7
+ * glyph) — see the host config.
8
+ */
9
+ export declare function defaultRenderLink({ href, children }: LinkRenderProps): ReactNode;
10
+ /**
11
+ * Neutral fallback so leaf components render without a host having wired a full
12
+ * config. Host apps override via `<AssistantConfigProvider config={…}>`.
13
+ */
14
+ export declare const DEFAULT_ASSISTANT_CONFIG: AssistantConfig;
15
+ export declare function AssistantConfigProvider({ config, children, }: {
16
+ config?: Partial<AssistantConfig>;
17
+ children: ReactNode;
18
+ }): import("react").JSX.Element;
19
+ export declare function useAssistantConfig(): AssistantConfig;
@@ -0,0 +1 @@
1
+ export { AssistantConfigProvider, DEFAULT_ASSISTANT_CONFIG, defaultRenderLink, useAssistantConfig, } from './assistant-config';
@@ -0,0 +1 @@
1
+ export { useTurnRail } from './use-turn-rail';
@@ -0,0 +1,16 @@
1
+ import type { UIMessage } from 'ai';
2
+ import type { RefObject } from 'react';
3
+ import type { Turn } from '../types';
4
+ /**
5
+ * Tracks conversation "turns" (submitted prompts) for the right-edge rail:
6
+ * derives the turn list, follows which turn is in view as you scroll, and
7
+ * scrolls a chosen turn to the top. Owns a node ref to the scroll container,
8
+ * composed with the caller's own container ref callback.
9
+ */
10
+ export declare function useTurnRail(messages: UIMessage[], containerRef: (node: HTMLDivElement | null) => void, userScrolledUpRef: RefObject<boolean>): {
11
+ turns: Turn[];
12
+ activeTurnId: string | null;
13
+ setScrollEl: (node: HTMLDivElement | null) => void;
14
+ handleScroll: (el: HTMLDivElement) => boolean;
15
+ scrollToTurn: (id: string) => void;
16
+ };
@@ -0,0 +1,11 @@
1
+ export { AssistantWorkspace, type AssistantWorkspaceProps } from './components/assistant-workspace';
2
+ export { BrainGlyph } from './components/brain-glyph';
3
+ export * from './components/composer';
4
+ export * from './components/conversation';
5
+ export { EmptyState } from './components/empty-state';
6
+ export * from './components/message';
7
+ export * from './components/sidebar';
8
+ export { AssistantConfigProvider, DEFAULT_ASSISTANT_CONFIG, defaultRenderLink, useAssistantConfig, } from './context';
9
+ export { useTurnRail } from './hooks';
10
+ export type { AssistantConfig, ChatSummary, EffortId, EffortOption, LinkRenderProps, ModelOption, ModelSelectorConfig, Turn, } from './types';
11
+ export { formatRelativeTime, sanitizeUserHtml } from './utils';
@@ -0,0 +1,66 @@
1
+ import type { DynamicToolUIPart, ToolUIPart, UIMessage } from 'ai';
2
+ import type { ReactNode } from 'react';
3
+ export type EffortId = 'low' | 'medium' | 'high';
4
+ export interface ModelOption {
5
+ /** Stable id sent to the server; must match the allowlist in server/routes/assistant.ts. */
6
+ id: string;
7
+ label: string;
8
+ }
9
+ export interface EffortOption {
10
+ id: EffortId;
11
+ label: string;
12
+ }
13
+ /** One submitted prompt — the unit tracked by the right-edge turn rail. */
14
+ export interface Turn {
15
+ id: string;
16
+ text: string;
17
+ }
18
+ /** Props passed to a `renderLink` implementation (a link in the assistant's markdown). */
19
+ export interface LinkRenderProps {
20
+ href?: string;
21
+ children?: ReactNode;
22
+ }
23
+ export interface ModelSelectorConfig {
24
+ models: ModelOption[];
25
+ efforts: EffortOption[];
26
+ defaultModelId: string;
27
+ defaultEffortId: EffortId;
28
+ }
29
+ /**
30
+ * Everything that differs between host apps (staff vs cloud). Supplied once at
31
+ * the workspace root and read by leaf components via `useAssistantConfig()`, so
32
+ * the presentational pieces stay generic and shell-agnostic.
33
+ */
34
+ export interface AssistantConfig {
35
+ /** Greeting line on the empty state, e.g. "Hey there, Jacob". */
36
+ greeting: (name?: string) => string;
37
+ /** Starter prompts on the empty state. */
38
+ suggestions: string[];
39
+ /** Whether to render the assistant's reasoning ("thinking") blocks. */
40
+ showReasoning: boolean;
41
+ /** Model + effort picker config, or `false` to hide the control. */
42
+ modelSelector: ModelSelectorConfig | false;
43
+ /** Tool name → progress label ("Searching users…"). Host-specific tool set. */
44
+ toolLabels: Record<string, string>;
45
+ /** Renders links inside the assistant's markdown (internal routes, external, host-specific icons). */
46
+ renderLink: (props: LinkRenderProps) => ReactNode;
47
+ /** Override the per-message action toolbar (defaults to copy + download). */
48
+ messageActions?: (msg: UIMessage) => ReactNode;
49
+ /**
50
+ * Renders a completed tool call inline, in message order. Return a falsy value
51
+ * to leave that tool invisible — the default for every tool, since most only
52
+ * feed the model. Hosts use this to surface a result as UI (cloud-portal turns
53
+ * an `openSupportTicket` result into a button).
54
+ */
55
+ renderToolOutput?: (part: ToolUIPart | DynamicToolUIPart, msg: UIMessage) => ReactNode;
56
+ }
57
+ /**
58
+ * Minimal shape the history list needs. Host apps pass their own richer chat
59
+ * objects (they're structurally compatible) — persistence lives in the host.
60
+ */
61
+ export interface ChatSummary {
62
+ id: string;
63
+ title: string;
64
+ updatedAt: number;
65
+ messages: UIMessage[];
66
+ }
@@ -0,0 +1,2 @@
1
+ /** Human-friendly relative timestamp for the chat history list. */
2
+ export declare function formatRelativeTime(timestamp: number): string;
@@ -0,0 +1,2 @@
1
+ export { formatRelativeTime } from './format-relative-time';
2
+ export { sanitizeUserHtml } from './sanitize-html';
@@ -0,0 +1,2 @@
1
+ /** Whitelist-sanitize the tiptap-authored HTML of a user message before render. */
2
+ export declare function sanitizeUserHtml(raw: string): string;
@@ -0,0 +1,82 @@
1
+ import { t as cn } from "./utils-Bu32wN-x.mjs";
2
+ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
3
+ import * as React from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
6
+ //#region ../shadcn/ui/dropdown-menu.tsx
7
+ /**
8
+ * Vanilla shadcn/ui DropdownMenu Component
9
+ * Pure shadcn dropdown without Datum customizations
10
+ * For Datum-specific features (destructive MenuItem), import from @/modules/datum-ui
11
+ */
12
+ const DropdownMenu = DropdownMenuPrimitive.Root;
13
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
14
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
15
+ const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.SubTrigger, {
16
+ ref,
17
+ className: cn("focus:bg-accent data-[state=open]:bg-accent flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", className),
18
+ ...props,
19
+ children: [children, /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto" })]
20
+ }));
21
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
22
+ const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.SubContent, {
23
+ ref,
24
+ className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg", className),
25
+ ...props
26
+ }));
27
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
28
+ const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.Content, {
29
+ ref,
30
+ sideOffset,
31
+ className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md", className),
32
+ ...props
33
+ }) }));
34
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
35
+ const DropdownMenuItem = React.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Item, {
36
+ ref,
37
+ className: cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", className),
38
+ ...props
39
+ }));
40
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
41
+ const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.CheckboxItem, {
42
+ ref,
43
+ className: cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
44
+ checked,
45
+ ...props,
46
+ children: [/* @__PURE__ */ jsx("span", {
47
+ className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
48
+ children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" }) })
49
+ }), children]
50
+ }));
51
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
52
+ const DropdownMenuRadioItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.RadioItem, {
53
+ ref,
54
+ className: cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
55
+ ...props,
56
+ children: [/* @__PURE__ */ jsx("span", {
57
+ className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
58
+ children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CircleIcon, { className: "h-2 w-2 fill-current" }) })
59
+ }), children]
60
+ }));
61
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
62
+ const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Label, {
63
+ ref,
64
+ className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
65
+ ...props
66
+ }));
67
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
68
+ const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Separator, {
69
+ ref,
70
+ className: cn("bg-muted -mx-1 my-1 h-px", className),
71
+ ...props
72
+ }));
73
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
74
+ function DropdownMenuShortcut({ className, ...props }) {
75
+ return /* @__PURE__ */ jsx("span", {
76
+ className: cn("ml-auto text-xs tracking-widest opacity-60", className),
77
+ ...props
78
+ });
79
+ }
80
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
81
+ //#endregion
82
+ export { DropdownMenuRadioGroup as a, DropdownMenuTrigger as c, DropdownMenuLabel as i, DropdownMenuCheckboxItem as n, DropdownMenuRadioItem as o, DropdownMenuContent as r, DropdownMenuSeparator as s, DropdownMenu as t };
package/dist/index.mjs CHANGED
@@ -23,7 +23,7 @@ import { t as Input } from "./input-j4tbmYYz.mjs";
23
23
  import { a as InputGroupText, i as InputGroupInput, n as InputGroupAddon, o as InputGroupTextarea, r as InputGroupButton, t as InputGroup } from "./input-group-DieA8aBt.mjs";
24
24
  import { t as Label } from "./label-Bk6FXsju.mjs";
25
25
  import { t as Spinner } from "./spinner-C5Xv-i2C.mjs";
26
- import { A as useLeaflet, C as MapMarkerClusterGroup, D as MapRectangle, E as MapPopup, O as MapTooltip, S as MapMarker, T as MapPolyline, _ as MapLocateControl, a as MapTileLayer, b as MapCircle, c as MapDrawDelete, d as MapDrawPolygon, f as MapDrawPolyline, g as MapFullscreenControl, h as MapControlContainer, i as MapLayersControl, j as PlaceAutocomplete, k as Map, l as MapDrawEdit, m as MapDrawUndo, n as MapLayerGroup, o as MapDrawCircle, p as MapDrawRectangle, r as MapLayers, s as MapDrawControl, t as MapFeatureGroup, u as MapDrawMarker, v as MapSearchControl, w as MapPolygon, x as MapCircleMarker, y as MapZoomControl } from "./layers-CGp0ceSG.mjs";
26
+ import { A as useLeaflet, C as MapMarkerClusterGroup, D as MapRectangle, E as MapPopup, O as MapTooltip, S as MapMarker, T as MapPolyline, _ as MapLocateControl, a as MapTileLayer, b as MapCircle, c as MapDrawDelete, d as MapDrawPolygon, f as MapDrawPolyline, g as MapFullscreenControl, h as MapControlContainer, i as MapLayersControl, j as PlaceAutocomplete, k as Map, l as MapDrawEdit, m as MapDrawUndo, n as MapLayerGroup, o as MapDrawCircle, p as MapDrawRectangle, r as MapLayers, s as MapDrawControl, t as MapFeatureGroup, u as MapDrawMarker, v as MapSearchControl, w as MapPolygon, x as MapCircleMarker, y as MapZoomControl } from "./layers-DJYz6fyE.mjs";
27
27
  import { i as useInSheet, n as MobileSheet, r as InSheetContext, t as ResponsiveSheetTrigger } from "./mobile-sheet-D9L-JOee.mjs";
28
28
  import { a as SheetHeader, i as SheetFooter, o as SheetTitle, r as SheetDescription, s as SheetTrigger } from "./sheet-DXCZyMHI.mjs";
29
29
  import { i as SheetOverlay, n as SheetClose, r as SheetContent, t as Sheet } from "./sheet-BZViad2U.mjs";
@@ -4,12 +4,12 @@ import { t as Button } from "./button-CsdF61EI.mjs";
4
4
  import { i as CommandGroup, o as CommandItem, r as CommandEmpty, s as CommandList, t as Command } from "./command-C0aGIYnQ.mjs";
5
5
  import { i as InputGroupInput, n as InputGroupAddon, t as InputGroup } from "./input-group-DieA8aBt.mjs";
6
6
  import { t as Spinner } from "./spinner-C5Xv-i2C.mjs";
7
- import { CheckIcon, ChevronRightIcon, CircleIcon, LayersIcon, LoaderCircleIcon, MapPinIcon, MaximizeIcon, MinimizeIcon, MinusIcon, NavigationIcon, PenLineIcon, PentagonIcon, PlusIcon, SearchIcon, SquareIcon, Trash2Icon, Undo2Icon, WaypointsIcon } from "lucide-react";
7
+ import { a as DropdownMenuRadioGroup, c as DropdownMenuTrigger, i as DropdownMenuLabel, n as DropdownMenuCheckboxItem, o as DropdownMenuRadioItem, r as DropdownMenuContent, s as DropdownMenuSeparator, t as DropdownMenu } from "./dropdown-menu-b8zY5Cs6.mjs";
8
+ import { CircleIcon, LayersIcon, LoaderCircleIcon, MapPinIcon, MaximizeIcon, MinimizeIcon, MinusIcon, NavigationIcon, PenLineIcon, PentagonIcon, PlusIcon, SearchIcon, SquareIcon, Trash2Icon, Undo2Icon, WaypointsIcon } from "lucide-react";
8
9
  import * as React from "react";
9
10
  import { Suspense, createContext, lazy, useContext, useEffect, useRef, useState } from "react";
10
11
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
12
  import { renderToString } from "react-dom/server.browser";
12
- import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
13
13
  //#region ../shadcn/ui/place-autocomplete.tsx
14
14
  function formatAddress(properties) {
15
15
  const parts = [];
@@ -913,82 +913,6 @@ function useTheme() {
913
913
  return { resolvedTheme };
914
914
  }
915
915
  //#endregion
916
- //#region ../shadcn/ui/dropdown-menu.tsx
917
- /**
918
- * Vanilla shadcn/ui DropdownMenu Component
919
- * Pure shadcn dropdown without Datum customizations
920
- * For Datum-specific features (destructive MenuItem), import from @/modules/datum-ui
921
- */
922
- const DropdownMenu = DropdownMenuPrimitive.Root;
923
- const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
924
- const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
925
- const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.SubTrigger, {
926
- ref,
927
- className: cn("focus:bg-accent data-[state=open]:bg-accent flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", className),
928
- ...props,
929
- children: [children, /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto" })]
930
- }));
931
- DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
932
- const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.SubContent, {
933
- ref,
934
- className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg", className),
935
- ...props
936
- }));
937
- DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
938
- const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.Content, {
939
- ref,
940
- sideOffset,
941
- className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md", className),
942
- ...props
943
- }) }));
944
- DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
945
- const DropdownMenuItem = React.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Item, {
946
- ref,
947
- className: cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", inset && "pl-8", className),
948
- ...props
949
- }));
950
- DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
951
- const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.CheckboxItem, {
952
- ref,
953
- className: cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
954
- checked,
955
- ...props,
956
- children: [/* @__PURE__ */ jsx("span", {
957
- className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
958
- children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" }) })
959
- }), children]
960
- }));
961
- DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
962
- const DropdownMenuRadioItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DropdownMenuPrimitive.RadioItem, {
963
- ref,
964
- className: cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
965
- ...props,
966
- children: [/* @__PURE__ */ jsx("span", {
967
- className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
968
- children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CircleIcon, { className: "h-2 w-2 fill-current" }) })
969
- }), children]
970
- }));
971
- DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
972
- const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Label, {
973
- ref,
974
- className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
975
- ...props
976
- }));
977
- DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
978
- const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Separator, {
979
- ref,
980
- className: cn("bg-muted -mx-1 my-1 h-px", className),
981
- ...props
982
- }));
983
- DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
984
- function DropdownMenuShortcut({ className, ...props }) {
985
- return /* @__PURE__ */ jsx("span", {
986
- className: cn("ml-auto text-xs tracking-widest opacity-60", className),
987
- ...props
988
- });
989
- }
990
- DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
991
- //#endregion
992
916
  //#region ../shadcn/ui/map/layers.tsx
993
917
  const MapLayersContext = createContext(null);
994
918
  function useMapLayersContext() {
@@ -1,2 +1,2 @@
1
- import { A as useLeaflet, C as MapMarkerClusterGroup, D as MapRectangle, E as MapPopup, O as MapTooltip, S as MapMarker, T as MapPolyline, _ as MapLocateControl, a as MapTileLayer, b as MapCircle, c as MapDrawDelete, d as MapDrawPolygon, f as MapDrawPolyline, g as MapFullscreenControl, h as MapControlContainer, i as MapLayersControl, j as PlaceAutocomplete, k as Map, l as MapDrawEdit, m as MapDrawUndo, n as MapLayerGroup, o as MapDrawCircle, p as MapDrawRectangle, r as MapLayers, s as MapDrawControl, t as MapFeatureGroup, u as MapDrawMarker, v as MapSearchControl, w as MapPolygon, x as MapCircleMarker, y as MapZoomControl } from "../layers-CGp0ceSG.mjs";
1
+ import { A as useLeaflet, C as MapMarkerClusterGroup, D as MapRectangle, E as MapPopup, O as MapTooltip, S as MapMarker, T as MapPolyline, _ as MapLocateControl, a as MapTileLayer, b as MapCircle, c as MapDrawDelete, d as MapDrawPolygon, f as MapDrawPolyline, g as MapFullscreenControl, h as MapControlContainer, i as MapLayersControl, j as PlaceAutocomplete, k as Map, l as MapDrawEdit, m as MapDrawUndo, n as MapLayerGroup, o as MapDrawCircle, p as MapDrawRectangle, r as MapLayers, s as MapDrawControl, t as MapFeatureGroup, u as MapDrawMarker, v as MapSearchControl, w as MapPolygon, x as MapCircleMarker, y as MapZoomControl } from "../layers-DJYz6fyE.mjs";
2
2
  export { Map, MapCircle, MapCircleMarker, MapControlContainer, MapDrawCircle, MapDrawControl, MapDrawDelete, MapDrawEdit, MapDrawMarker, MapDrawPolygon, MapDrawPolyline, MapDrawRectangle, MapDrawUndo, MapFeatureGroup, MapFullscreenControl, MapLayerGroup, MapLayers, MapLayersControl, MapLocateControl, MapMarker, MapMarkerClusterGroup, MapPolygon, MapPolyline, MapPopup, MapRectangle, MapSearchControl, MapTileLayer, MapTooltip, MapZoomControl, PlaceAutocomplete, useLeaflet };