@ctrl-ui/react 0.8.7 → 0.8.8
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.
- package/dist/action-bar.d.ts +15 -7
- package/dist/action-bar.js +40 -20
- package/dist/activity.js +8 -16
- package/dist/audio-recorder.d.ts +14 -4
- package/dist/audio-recorder.js +82 -29
- package/dist/audio-visualizer.js +1 -1
- package/dist/blocks/coding-agent.js +39 -39
- package/dist/blocks/design-canvas-inspector.js +2 -2
- package/dist/blocks/design-canvas.d.ts +5 -1
- package/dist/blocks/design-canvas.js +200 -94
- package/dist/blocks/discussion.d.ts +28 -0
- package/dist/blocks/discussion.js +67 -0
- package/dist/blocks/file-explorer-data.d.ts +1 -0
- package/dist/blocks/file-explorer-data.js +4 -1
- package/dist/blocks/file-explorer.d.ts +9 -1
- package/dist/blocks/file-explorer.js +461 -192
- package/dist/blocks/settings.d.ts +2 -1
- package/dist/blocks/settings.js +102 -80
- package/dist/blocks/team-chat.d.ts +12 -0
- package/dist/blocks/team-chat.js +26 -0
- package/dist/blocks/theme-toggle.js +23 -31
- package/dist/chat-composer-attachment.d.ts +4 -1
- package/dist/chat-composer-attachment.js +35 -10
- package/dist/chat-composer-editor/extensions/mention.d.ts +5 -1
- package/dist/chat-composer-editor/extensions/mention.js +58 -27
- package/dist/chat-composer-editor/ghost.js +2 -4
- package/dist/chat-composer-editor/types.d.ts +5 -0
- package/dist/chat-composer-editor.d.ts +1 -1
- package/dist/chat-composer-editor.js +57 -30
- package/dist/chat-composer.d.ts +13 -32
- package/dist/chat-composer.js +53 -13
- package/dist/chat-layout.d.ts +19 -0
- package/dist/chat-layout.js +91 -40
- package/dist/chat-message/social.d.ts +26 -0
- package/dist/chat-message/social.js +122 -0
- package/dist/chat-message.d.ts +28 -29
- package/dist/chat-message.js +106 -25
- package/dist/context.d.ts +2 -2
- package/dist/context.js +39 -24
- package/dist/dynamic-notification-canvas-loop.d.ts +24 -0
- package/dist/dynamic-notification-canvas-loop.js +113 -0
- package/dist/dynamic-notification-glass.js +23 -114
- package/dist/dynamic-notification-liquid.js +14 -118
- package/dist/dynamic-notification.d.ts +16 -8
- package/dist/dynamic-notification.js +86 -23
- package/dist/email/email-brand.d.ts +7 -4
- package/dist/email/email-brand.js +9 -6
- package/dist/email/email-code.d.ts +3 -2
- package/dist/email/email-code.js +11 -9
- package/dist/email/email-footer.d.ts +5 -3
- package/dist/email/email-footer.js +11 -5
- package/dist/email/email.d.ts +31 -9
- package/dist/email/email.js +50 -26
- package/dist/email/templates.d.ts +10 -9
- package/dist/email/templates.js +102 -38
- package/dist/email/theme.js +1 -1
- package/dist/environment-variables.d.ts +4 -2
- package/dist/environment-variables.js +52 -32
- package/dist/filter-bar/editor.js +20 -8
- package/dist/filter-bar/model.d.ts +1 -0
- package/dist/filter-bar/model.js +10 -1
- package/dist/filter-bar/motion.js +4 -4
- package/dist/filter-bar/parts.js +20 -9
- package/dist/filter-bar/types.d.ts +1 -0
- package/dist/filter-bar.js +20 -14
- package/dist/hooks/use-audio-recorder.js +12 -6
- package/dist/hooks/use-chat-composer.d.ts +19 -7
- package/dist/hooks/use-chat-composer.js +32 -5
- package/dist/hooks/use-chat-message.d.ts +28 -2
- package/dist/hooks/use-chat-message.js +41 -10
- package/dist/hooks/use-chat-thread-scroll.js +43 -7
- package/dist/hooks/use-color-area.d.ts +3 -3
- package/dist/hooks/use-color-area.js +13 -12
- package/dist/hooks/use-copy-to-clipboard.d.ts +2 -1
- package/dist/hooks/use-copy-to-clipboard.js +20 -20
- package/dist/hooks/use-dynamic-notification.d.ts +6 -2
- package/dist/hooks/use-dynamic-notification.js +26 -10
- package/dist/hooks/use-mobile.d.ts +3 -2
- package/dist/hooks/use-mobile.js +8 -4
- package/dist/hooks/use-textarea-trigger-menu.js +2 -1
- package/dist/hooks/use-trigger-menu.d.ts +54 -0
- package/dist/hooks/use-trigger-menu.js +102 -47
- package/dist/hooks/use-user-ask.d.ts +2 -0
- package/dist/hooks/use-user-ask.js +35 -41
- package/dist/inline-attachment.d.ts +6 -2
- package/dist/inline-attachment.js +36 -15
- package/dist/inline-citation.d.ts +12 -5
- package/dist/inline-citation.js +26 -17
- package/dist/knob-contracts/audio-recorder-knobs.d.ts +1 -1
- package/dist/knob-contracts/audio-recorder-knobs.js +2 -1
- package/dist/knob-contracts/audio-visualizer-knobs.d.ts +1 -1
- package/dist/knob-contracts/audio-visualizer-knobs.js +2 -1
- package/dist/knob-contracts/avatar-knobs.d.ts +1 -1
- package/dist/knob-contracts/avatar-knobs.js +6 -1
- package/dist/knob-contracts/badge-knobs.d.ts +1 -1
- package/dist/knob-contracts/badge-knobs.js +2 -1
- package/dist/knob-contracts/breadcrumb-knobs.d.ts +4 -0
- package/dist/knob-contracts/breadcrumb-knobs.js +8 -0
- package/dist/knob-contracts/button-knobs.d.ts +1 -1
- package/dist/knob-contracts/button-knobs.js +1 -0
- package/dist/knob-contracts/chat-message-knobs.d.ts +1 -1
- package/dist/knob-contracts/chat-message-knobs.js +8 -1
- package/dist/knob-contracts/code-diff-knobs.d.ts +1 -1
- package/dist/knob-contracts/code-diff-knobs.js +2 -0
- package/dist/knob-contracts/code-knobs.d.ts +1 -1
- package/dist/knob-contracts/code-knobs.js +2 -1
- package/dist/knob-contracts/dynamic-notification-knobs.d.ts +1 -1
- package/dist/knob-contracts/dynamic-notification-knobs.js +2 -0
- package/dist/knob-contracts/emoji-picker-knobs.d.ts +4 -0
- package/dist/knob-contracts/emoji-picker-knobs.js +10 -0
- package/dist/knob-contracts/field-knobs.d.ts +1 -1
- package/dist/knob-contracts/field-knobs.js +5 -1
- package/dist/knob-contracts/filter-bar-knobs.d.ts +1 -1
- package/dist/knob-contracts/filter-bar-knobs.js +1 -2
- package/dist/knob-contracts/markdown-knobs.d.ts +1 -1
- package/dist/knob-contracts/markdown-knobs.js +3 -1
- package/dist/knob-contracts/page-layout-knobs.d.ts +1 -1
- package/dist/knob-contracts/page-layout-knobs.js +2 -1
- package/dist/knob-contracts/popup-knobs.d.ts +1 -1
- package/dist/knob-contracts/popup-knobs.js +27 -0
- package/dist/knob-contracts/range-knobs.d.ts +1 -1
- package/dist/knob-contracts/range-knobs.js +1 -0
- package/dist/knob-contracts/rich-tooltip-knobs.d.ts +1 -1
- package/dist/knob-contracts/rich-tooltip-knobs.js +2 -1
- package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
- package/dist/knob-contracts/sidebar-knobs.js +27 -2
- package/dist/knob-contracts/spinner-knobs.d.ts +1 -1
- package/dist/knob-contracts/spinner-knobs.js +1 -1
- package/dist/knob-contracts/stepper-knobs.d.ts +1 -1
- package/dist/knob-contracts/stepper-knobs.js +4 -1
- package/dist/knob-contracts/switch-knobs.d.ts +1 -1
- package/dist/knob-contracts/switch-knobs.js +5 -0
- package/dist/knob-contracts/table-of-contents-knobs.d.ts +1 -1
- package/dist/knob-contracts/table-of-contents-knobs.js +2 -1
- package/dist/knob-contracts/tabs-knobs.d.ts +1 -1
- package/dist/knob-contracts/tabs-knobs.js +1 -0
- package/dist/knob-contracts/tree-knobs.d.ts +1 -1
- package/dist/knob-contracts/tree-knobs.js +2 -1
- package/dist/lib/cn.js +0 -4
- package/dist/lib/contrast.d.ts +1 -0
- package/dist/lib/contrast.js +17 -5
- package/dist/lib/dropzone-validation.js +41 -28
- package/dist/lib/env-file.d.ts +1 -1
- package/dist/lib/env-file.js +5 -5
- package/dist/lib/motion.d.ts +4 -0
- package/dist/lib/motion.js +15 -0
- package/dist/lib/phone-input-format.js +1 -1
- package/dist/lib/trigger-detect.js +6 -8
- package/dist/markdown-block.js +2 -1
- package/dist/popup-parts.d.ts +8 -0
- package/dist/popup-parts.js +43 -0
- package/dist/source-badge.js +3 -1
- package/dist/styles/code.css +0 -2
- package/dist/styles/effects.css +6 -32
- package/dist/styles/index.css +10 -5
- package/dist/styles/recipes/accordion.css +9 -6
- package/dist/styles/recipes/action-bar.css +0 -15
- package/dist/styles/recipes/activity.css +5 -11
- package/dist/styles/recipes/alert.css +4 -4
- package/dist/styles/recipes/audio-recorder.css +15 -3
- package/dist/styles/recipes/audio-visualizer.css +13 -2
- package/dist/styles/recipes/avatar.css +78 -1
- package/dist/styles/recipes/badge.css +14 -4
- package/dist/styles/recipes/breadcrumb.css +77 -0
- package/dist/styles/recipes/button-group.css +5 -7
- package/dist/styles/recipes/button-states.css +66 -0
- package/dist/styles/recipes/button.css +24 -83
- package/dist/styles/recipes/calendar.css +17 -23
- package/dist/styles/recipes/card.css +2 -2
- package/dist/styles/recipes/chat-composer-attachment.css +9 -3
- package/dist/styles/recipes/chat-composer.css +7 -10
- package/dist/styles/recipes/chat-layout.css +35 -0
- package/dist/styles/recipes/chat-message-social.css +123 -0
- package/dist/styles/recipes/chat-message.css +157 -37
- package/dist/styles/recipes/choice.css +18 -21
- package/dist/styles/recipes/code-diff.css +46 -33
- package/dist/styles/recipes/code.css +36 -16
- package/dist/styles/recipes/collapsible.css +7 -2
- package/dist/styles/recipes/color-picker-details.css +3 -4
- package/dist/styles/recipes/color-picker-values.css +9 -8
- package/dist/styles/recipes/color-picker.css +11 -2
- package/dist/styles/recipes/context.css +3 -3
- package/dist/styles/recipes/dockable-panel.css +7 -4
- package/dist/styles/recipes/dropzone.css +7 -8
- package/dist/styles/recipes/dynamic-notification-input.css +8 -5
- package/dist/styles/recipes/dynamic-notification-motion.css +12 -21
- package/dist/styles/recipes/dynamic-notification.css +40 -26
- package/dist/styles/recipes/emoji-picker.css +132 -0
- package/dist/styles/recipes/empty.css +5 -4
- package/dist/styles/recipes/environment-variables.css +4 -15
- package/dist/styles/recipes/field-parts.css +30 -24
- package/dist/styles/recipes/field.css +61 -26
- package/dist/styles/recipes/filter-bar.css +18 -31
- package/dist/styles/recipes/gradient-editor.css +18 -7
- package/dist/styles/recipes/infinite-canvas.css +0 -1
- package/dist/styles/recipes/inline-attachment.css +3 -3
- package/dist/styles/recipes/inline-citation.css +10 -4
- package/dist/styles/recipes/item.css +23 -9
- package/dist/styles/recipes/markdown-block.css +5 -4
- package/dist/styles/recipes/markdown.css +68 -26
- package/dist/styles/recipes/morphing-panel.css +8 -8
- package/dist/styles/recipes/page-layout.css +20 -12
- package/dist/styles/recipes/pagination.css +4 -5
- package/dist/styles/recipes/phone-input.css +12 -8
- package/dist/styles/recipes/popup-controls.css +166 -33
- package/dist/styles/recipes/popup-drawer.css +3 -14
- package/dist/styles/recipes/popup-lists.css +128 -27
- package/dist/styles/recipes/popup-motion.css +4 -45
- package/dist/styles/recipes/popup-toast.css +55 -26
- package/dist/styles/recipes/popup.css +139 -141
- package/dist/styles/recipes/range.css +54 -18
- package/dist/styles/recipes/resizable.css +2 -7
- package/dist/styles/recipes/rich-tooltip.css +24 -34
- package/dist/styles/recipes/scroll-area.css +8 -1
- package/dist/styles/recipes/sidebar-menu.css +149 -34
- package/dist/styles/recipes/sidebar-parts.css +154 -0
- package/dist/styles/recipes/sidebar.css +187 -128
- package/dist/styles/recipes/source-badge.css +1 -1
- package/dist/styles/recipes/spinner.css +8 -1
- package/dist/styles/recipes/stepper.css +31 -13
- package/dist/styles/recipes/switch.css +68 -23
- package/dist/styles/recipes/table-of-contents.css +9 -1
- package/dist/styles/recipes/table.css +14 -10
- package/dist/styles/recipes/tabs.css +17 -12
- package/dist/styles/recipes/task-list.css +7 -14
- package/dist/styles/recipes/thread-rail.css +42 -19
- package/dist/styles/recipes/timeline.css +2 -0
- package/dist/styles/recipes/toolbar.css +27 -25
- package/dist/styles/recipes/track-highlight.css +10 -7
- package/dist/styles/recipes/tree.css +31 -4
- package/dist/styles/recipes/user-ask-details.css +0 -1
- package/dist/styles/recipes/user-ask.css +4 -4
- package/dist/styles/theme.css +37 -16
- package/dist/task-list.d.ts +4 -1
- package/dist/task-list.js +24 -8
- package/dist/thread-rail.d.ts +1 -1
- package/dist/thread-rail.js +61 -19
- package/dist/transcript-divider.js +2 -1
- package/dist/ui/alert-dialog.js +1 -1
- package/dist/ui/alert.d.ts +3 -1
- package/dist/ui/alert.js +14 -8
- package/dist/ui/autocomplete.js +4 -2
- package/dist/ui/avatar.d.ts +8 -0
- package/dist/ui/avatar.js +23 -3
- package/dist/ui/badge.js +1 -1
- package/dist/ui/breadcrumb.d.ts +27 -0
- package/dist/ui/breadcrumb.js +88 -0
- package/dist/ui/button.d.ts +2 -1
- package/dist/ui/button.js +3 -3
- package/dist/ui/calendar.js +2 -2
- package/dist/ui/card.d.ts +3 -1
- package/dist/ui/card.js +12 -7
- package/dist/ui/checkbox.d.ts +2 -0
- package/dist/ui/code-diff.d.ts +1 -1
- package/dist/ui/code-diff.js +72 -28
- package/dist/ui/code.d.ts +5 -3
- package/dist/ui/code.js +28 -29
- package/dist/ui/collapsible.js +1 -1
- package/dist/ui/color-picker.d.ts +5 -2
- package/dist/ui/color-picker.js +85 -37
- package/dist/ui/combobox-disabled-selection.d.ts +1 -2
- package/dist/ui/combobox-disabled-selection.js +7 -9
- package/dist/ui/combobox.js +14 -6
- package/dist/ui/command.d.ts +8 -2
- package/dist/ui/command.js +30 -14
- package/dist/ui/context-menu.js +4 -1
- package/dist/ui/dialog.d.ts +2 -1
- package/dist/ui/dialog.js +4 -23
- package/dist/ui/dockable-panel-geometry.d.ts +1 -0
- package/dist/ui/dockable-panel-geometry.js +7 -1
- package/dist/ui/dockable-panel.d.ts +9 -6
- package/dist/ui/dockable-panel.js +63 -23
- package/dist/ui/drawer.js +1 -1
- package/dist/ui/dropdown-menu.js +5 -4
- package/dist/ui/dropzone.d.ts +2 -2
- package/dist/ui/dropzone.js +75 -16
- package/dist/ui/emoji-picker.d.ts +18 -0
- package/dist/ui/emoji-picker.js +136 -0
- package/dist/ui/empty.d.ts +3 -1
- package/dist/ui/empty.js +12 -7
- package/dist/ui/gradient-editor.d.ts +1 -1
- package/dist/ui/gradient-editor.js +37 -21
- package/dist/ui/hover-card.js +1 -1
- package/dist/ui/infinite-canvas.d.ts +3 -2
- package/dist/ui/infinite-canvas.js +63 -19
- package/dist/ui/input-group.d.ts +0 -3
- package/dist/ui/input-group.js +4 -14
- package/dist/ui/input-otp.d.ts +1 -1
- package/dist/ui/input-otp.js +32 -15
- package/dist/ui/input.js +4 -4
- package/dist/ui/item.d.ts +2 -1
- package/dist/ui/item.js +12 -8
- package/dist/ui/live-status.d.ts +7 -0
- package/dist/ui/live-status.js +17 -0
- package/dist/ui/markdown-elements.d.ts +6 -0
- package/dist/ui/markdown-elements.js +31 -1
- package/dist/ui/menubar.js +3 -3
- package/dist/ui/morphing-panel.js +3 -2
- package/dist/ui/native-select.d.ts +1 -1
- package/dist/ui/native-select.js +24 -11
- package/dist/ui/navigation-menu.js +1 -1
- package/dist/ui/page-layout.d.ts +2 -2
- package/dist/ui/page-layout.js +2 -4
- package/dist/ui/pagination.d.ts +7 -5
- package/dist/ui/pagination.js +19 -13
- package/dist/ui/phone-input.d.ts +1 -0
- package/dist/ui/phone-input.js +58 -60
- package/dist/ui/popover.js +1 -1
- package/dist/ui/radio-group.d.ts +2 -0
- package/dist/ui/resizable.d.ts +3 -2
- package/dist/ui/resizable.js +5 -3
- package/dist/ui/responsive-dialog.d.ts +1 -1
- package/dist/ui/responsive-dialog.js +4 -21
- package/dist/ui/rich-tooltip.d.ts +10 -4
- package/dist/ui/rich-tooltip.js +82 -34
- package/dist/ui/scroll-area.d.ts +1 -1
- package/dist/ui/scroll-area.js +43 -28
- package/dist/ui/select.js +1 -1
- package/dist/ui/sheet.js +1 -1
- package/dist/ui/sidebar-menu.d.ts +5 -1
- package/dist/ui/sidebar-menu.js +32 -34
- package/dist/ui/sidebar-provider.d.ts +10 -1
- package/dist/ui/sidebar-provider.js +39 -14
- package/dist/ui/sidebar-resize-rail.js +8 -4
- package/dist/ui/sidebar.d.ts +11 -6
- package/dist/ui/sidebar.js +47 -24
- package/dist/ui/slider.js +31 -22
- package/dist/ui/spinner.d.ts +3 -2
- package/dist/ui/spinner.js +3 -2
- package/dist/ui/stepper.d.ts +8 -1
- package/dist/ui/stepper.js +74 -25
- package/dist/ui/switch.d.ts +1 -0
- package/dist/ui/table-of-contents.d.ts +2 -2
- package/dist/ui/table-of-contents.js +20 -8
- package/dist/ui/table.js +4 -2
- package/dist/ui/textarea.d.ts +1 -1
- package/dist/ui/textarea.js +20 -9
- package/dist/ui/timeline.d.ts +3 -1
- package/dist/ui/timeline.js +17 -9
- package/dist/ui/toast.d.ts +11 -5
- package/dist/ui/toast.js +101 -55
- package/dist/ui/toolbar.d.ts +3 -2
- package/dist/ui/toolbar.js +4 -2
- package/dist/ui/tooltip.js +4 -21
- package/dist/ui/tree.js +121 -81
- package/dist/ui/trigger-menu.js +2 -1
- package/dist/user-ask.d.ts +10 -5
- package/dist/user-ask.js +32 -12
- package/package.json +5 -1
- package/dist/hooks/use-keyboard-navigation.d.ts +0 -3
- package/dist/hooks/use-keyboard-navigation.js +0 -22
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Button } from "../ui/button.js";
|
|
3
3
|
import { InputGroup, InputGroupAddon } from "../ui/input-group.js";
|
|
4
|
-
import { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from "../ui/empty.js";
|
|
5
|
-
import { Separator } from "../ui/separator.js";
|
|
6
4
|
import { resizeDesignCanvasLayer } from "./design-canvas-data.js";
|
|
7
5
|
import { NumberField, NumberFieldGroup, NumberFieldInput, NumberFieldScrubArea } from "../ui/number-field.js";
|
|
8
6
|
import { ColorPicker, ColorPickerArea, ColorPickerContent, ColorPickerEyeDropper, ColorPickerHue, ColorPickerInput, ColorPickerTrigger } from "../ui/color-picker.js";
|
|
7
|
+
import { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from "../ui/empty.js";
|
|
8
|
+
import { Separator } from "../ui/separator.js";
|
|
9
9
|
import { Toggle } from "../ui/toggle.js";
|
|
10
10
|
import { useState } from "react";
|
|
11
11
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -11,7 +11,11 @@ export type DesignCanvasBlockProps = Omit<ComponentProps<"div">, "children" | "d
|
|
|
11
11
|
onSelectedLayerIdChange?: (layerId: string | null) => void;
|
|
12
12
|
defaultTransform?: InfiniteCanvasTransform;
|
|
13
13
|
layout?: "viewport" | "contained";
|
|
14
|
+
layersLabel?: string;
|
|
15
|
+
propertiesLabel?: string;
|
|
16
|
+
openLayersLabel?: string;
|
|
17
|
+
openPropertiesLabel?: string;
|
|
14
18
|
};
|
|
15
|
-
export declare function DesignCanvasBlock({ layers, defaultLayers, onLayersChange, selectedLayerId, defaultSelectedLayerId, onSelectedLayerIdChange, defaultTransform, layout, className, ...props }: DesignCanvasBlockProps): import("react").JSX.Element;
|
|
19
|
+
export declare function DesignCanvasBlock({ layers, defaultLayers, onLayersChange, selectedLayerId, defaultSelectedLayerId, onSelectedLayerIdChange, defaultTransform, layout, layersLabel, propertiesLabel, openLayersLabel, openPropertiesLabel, className, ...props }: DesignCanvasBlockProps): import("react").JSX.Element;
|
|
16
20
|
//#endregion
|
|
17
21
|
export type { DesignCanvasFill, DesignCanvasLayer, DesignCanvasLayerKind, DesignCanvasTool };
|
|
@@ -3,14 +3,15 @@ import { cn } from "../lib/cn.js";
|
|
|
3
3
|
import { Button } from "../ui/button.js";
|
|
4
4
|
import { ScrollArea } from "../ui/scroll-area.js";
|
|
5
5
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip.js";
|
|
6
|
-
import { InfiniteCanvas, InfiniteCanvasContent, InfiniteCanvasControls, InfiniteCanvasItem } from "../ui/infinite-canvas.js";
|
|
7
|
-
import { ResizableFloatingPanel } from "../ui/resizable.js";
|
|
8
|
-
import { Toolbar, ToolbarButton, ToolbarGroup } from "../ui/toolbar.js";
|
|
9
6
|
import { createDesignCanvasLayer, designCanvasFillColor, drawnDesignCanvasBounds } from "./design-canvas-data.js";
|
|
10
7
|
import { DesignCanvasInspector } from "./design-canvas-inspector.js";
|
|
8
|
+
import { Drawer, DrawerContent, DrawerTitle } from "../ui/drawer.js";
|
|
9
|
+
import { InfiniteCanvas, InfiniteCanvasContent, InfiniteCanvasControls, InfiniteCanvasItem } from "../ui/infinite-canvas.js";
|
|
10
|
+
import { ResizableFloatingPanel } from "../ui/resizable.js";
|
|
11
|
+
import { Toolbar, ToolbarButton, ToolbarGroup, ToolbarSeparator } from "../ui/toolbar.js";
|
|
11
12
|
import { useRef, useState } from "react";
|
|
12
13
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
-
import { CircleIcon, FrameIcon, MousePointer2Icon, SquareIcon, TypeIcon } from "lucide-react";
|
|
14
|
+
import { CircleIcon, FrameIcon, LayersIcon, MousePointer2Icon, SlidersHorizontalIcon, SquareIcon, TypeIcon } from "lucide-react";
|
|
14
15
|
//#region src/blocks/design-canvas.tsx
|
|
15
16
|
const TOOLS = [
|
|
16
17
|
{
|
|
@@ -74,6 +75,9 @@ const DEFAULT_TRANSFORM = {
|
|
|
74
75
|
scale: 1
|
|
75
76
|
};
|
|
76
77
|
const CLICK_TOLERANCE_PX = 4;
|
|
78
|
+
const DELETE_KEYS = /* @__PURE__ */ new Set(["Delete", "Backspace"]);
|
|
79
|
+
const CANVAS_KEY_SHORTCUTS = `${TOOLS.map((entry) => entry.shortcut).join(" ")} Enter Delete Backspace Escape`;
|
|
80
|
+
const LAYER_KEY_SHORTCUTS = "Enter Space ArrowLeft ArrowRight ArrowUp ArrowDown Delete Backspace";
|
|
77
81
|
function newLayerId(kind) {
|
|
78
82
|
return `${kind}-${Math.random().toString(36).slice(2, 8)}`;
|
|
79
83
|
}
|
|
@@ -83,12 +87,14 @@ function toolForShortcut(key) {
|
|
|
83
87
|
function layerFromDraft(draft, id) {
|
|
84
88
|
return createDesignCanvasLayer(draft.kind, drawnDesignCanvasBounds(draft.kind, draft.start, draft.end, draft.clickTolerance), id);
|
|
85
89
|
}
|
|
86
|
-
function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selectedLayerId, defaultSelectedLayerId = null, onSelectedLayerIdChange, defaultTransform = DEFAULT_TRANSFORM, layout = "viewport", className, ...props }) {
|
|
90
|
+
function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selectedLayerId, defaultSelectedLayerId = null, onSelectedLayerIdChange, defaultTransform = DEFAULT_TRANSFORM, layout = "viewport", layersLabel = "Layers", propertiesLabel = "Properties", openLayersLabel = "Show layers", openPropertiesLabel = "Show properties", className, ...props }) {
|
|
87
91
|
const [internalLayers, setInternalLayers] = useState(defaultLayers);
|
|
88
92
|
const [internalSelectedLayerId, setInternalSelectedLayerId] = useState(defaultSelectedLayerId);
|
|
89
93
|
const transformRef = useRef(defaultTransform);
|
|
90
94
|
const [tool, setTool] = useState("move");
|
|
91
95
|
const [draft, setDraft] = useState(null);
|
|
96
|
+
const [layersOpen, setLayersOpen] = useState(false);
|
|
97
|
+
const [propertiesOpen, setPropertiesOpen] = useState(false);
|
|
92
98
|
const currentLayers = layers ?? internalLayers;
|
|
93
99
|
const currentSelectedLayerId = selectedLayerId === void 0 ? internalSelectedLayerId : selectedLayerId;
|
|
94
100
|
const selectedLayer = currentLayers.find((layer) => layer.id === currentSelectedLayerId);
|
|
@@ -103,14 +109,33 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
|
|
|
103
109
|
function replaceLayer(next) {
|
|
104
110
|
changeLayers(currentLayers.map((layer) => layer.id === next.id ? next : layer));
|
|
105
111
|
}
|
|
106
|
-
function
|
|
107
|
-
|
|
112
|
+
function addLayer(layer) {
|
|
113
|
+
changeLayers([...currentLayers, layer]);
|
|
114
|
+
selectLayer(layer.id);
|
|
115
|
+
setTool("move");
|
|
116
|
+
}
|
|
117
|
+
function toWorldPoint(local) {
|
|
108
118
|
const { x, y, scale } = transformRef.current;
|
|
109
119
|
return {
|
|
110
|
-
x: (
|
|
111
|
-
y: (
|
|
120
|
+
x: (local.x - x) / scale,
|
|
121
|
+
y: (local.y - y) / scale
|
|
112
122
|
};
|
|
113
123
|
}
|
|
124
|
+
function worldPointAt(event) {
|
|
125
|
+
const bounds = event.currentTarget.getBoundingClientRect();
|
|
126
|
+
return toWorldPoint({
|
|
127
|
+
x: event.clientX - bounds.left,
|
|
128
|
+
y: event.clientY - bounds.top
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function addLayerAtViewportCenter(kind, canvas) {
|
|
132
|
+
const center = toWorldPoint({
|
|
133
|
+
x: canvas.clientWidth / 2,
|
|
134
|
+
y: canvas.clientHeight / 2
|
|
135
|
+
});
|
|
136
|
+
const bounds = drawnDesignCanvasBounds(kind, center, center, CLICK_TOLERANCE_PX / transformRef.current.scale);
|
|
137
|
+
addLayer(createDesignCanvasLayer(kind, bounds, newLayerId(kind)));
|
|
138
|
+
}
|
|
114
139
|
function beginDrawOrDeselect(event) {
|
|
115
140
|
if (event.defaultPrevented || event.target !== event.currentTarget) return;
|
|
116
141
|
if (tool === "move") {
|
|
@@ -138,48 +163,63 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
|
|
|
138
163
|
}
|
|
139
164
|
function commitDraft(event) {
|
|
140
165
|
if (draft?.pointerId !== event.pointerId) return;
|
|
141
|
-
const layer = layerFromDraft(draft, newLayerId(draft.kind));
|
|
142
166
|
setDraft(null);
|
|
143
|
-
|
|
144
|
-
selectLayer(layer.id);
|
|
145
|
-
setTool("move");
|
|
167
|
+
addLayer(layerFromDraft(draft, newLayerId(draft.kind)));
|
|
146
168
|
}
|
|
147
169
|
function cancelDraft(event) {
|
|
148
170
|
if (draft?.pointerId === event.pointerId) setDraft(null);
|
|
149
171
|
}
|
|
150
|
-
function
|
|
151
|
-
if (!selectedLayer) return false;
|
|
172
|
+
function editLayerWithKey(layer, event) {
|
|
152
173
|
const nudge = NUDGE_DIRECTIONS[event.key];
|
|
153
|
-
if (
|
|
154
|
-
changeLayers(currentLayers.filter((
|
|
155
|
-
selectLayer(null);
|
|
174
|
+
if (DELETE_KEYS.has(event.key)) {
|
|
175
|
+
changeLayers(currentLayers.filter((entry) => entry.id !== layer.id));
|
|
176
|
+
if (layer.id === currentSelectedLayerId) selectLayer(null);
|
|
156
177
|
} else if (nudge) {
|
|
157
178
|
const distance = event.shiftKey ? 10 : 1;
|
|
158
179
|
replaceLayer({
|
|
159
|
-
...
|
|
160
|
-
x:
|
|
161
|
-
y:
|
|
180
|
+
...layer,
|
|
181
|
+
x: layer.x + nudge.x * distance,
|
|
182
|
+
y: layer.y + nudge.y * distance
|
|
162
183
|
});
|
|
163
184
|
} else return false;
|
|
164
185
|
return true;
|
|
165
186
|
}
|
|
166
|
-
function
|
|
187
|
+
function handleLayerKey(layer, event) {
|
|
167
188
|
if (event.metaKey || event.ctrlKey || event.altKey) return;
|
|
189
|
+
if (event.key === "Enter" || event.key === " ") selectLayer(layer.id);
|
|
190
|
+
else if (!editLayerWithKey(layer, event)) return;
|
|
191
|
+
event.preventDefault();
|
|
192
|
+
if (DELETE_KEYS.has(event.key)) event.currentTarget.closest("[data-control-family=\"infinite-canvas\"][data-slot=\"root\"]")?.focus();
|
|
193
|
+
}
|
|
194
|
+
function handleShortcut(event) {
|
|
195
|
+
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.altKey) return;
|
|
168
196
|
const shortcutTool = toolForShortcut(event.key);
|
|
169
197
|
if (shortcutTool) setTool(shortcutTool);
|
|
170
198
|
else if (event.key === "Escape") {
|
|
171
199
|
setDraft(null);
|
|
172
200
|
setTool("move");
|
|
173
201
|
selectLayer(null);
|
|
174
|
-
} else if (
|
|
202
|
+
} else if (event.key === "Enter" && tool !== "move" && event.target === event.currentTarget) addLayerAtViewportCenter(tool, event.currentTarget);
|
|
203
|
+
else if (!selectedLayer || !editLayerWithKey(selectedLayer, event)) return;
|
|
175
204
|
event.preventDefault();
|
|
176
205
|
}
|
|
206
|
+
const layerList = /* @__PURE__ */ jsx(DesignCanvasLayerList, {
|
|
207
|
+
layers: currentLayers,
|
|
208
|
+
selectedLayerId: currentSelectedLayerId,
|
|
209
|
+
onSelect: selectLayer
|
|
210
|
+
});
|
|
211
|
+
const inspector = /* @__PURE__ */ jsx(DesignCanvasInspector, {
|
|
212
|
+
layer: selectedLayer,
|
|
213
|
+
onLayerChange: replaceLayer
|
|
214
|
+
});
|
|
215
|
+
const propertiesTitle = selectedLayer?.name ?? "Design";
|
|
177
216
|
return /* @__PURE__ */ jsxs("div", {
|
|
178
217
|
className: cn("@container/design-canvas relative isolate overflow-hidden bg-background text-foreground", layout === "contained" ? "h-full min-h-0" : "h-svh", className),
|
|
179
218
|
...props,
|
|
180
219
|
children: [
|
|
181
220
|
/* @__PURE__ */ jsxs(InfiniteCanvas, {
|
|
182
221
|
"aria-label": "Design canvas",
|
|
222
|
+
"aria-keyshortcuts": CANVAS_KEY_SHORTCUTS,
|
|
183
223
|
defaultTransform,
|
|
184
224
|
onTransformChange: (next) => {
|
|
185
225
|
transformRef.current = next;
|
|
@@ -202,12 +242,13 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
|
|
|
202
242
|
layer,
|
|
203
243
|
selected: layer.id === currentSelectedLayerId,
|
|
204
244
|
onSelect: () => selectLayer(layer.id),
|
|
245
|
+
onKeyDown: (event) => handleLayerKey(layer, event),
|
|
205
246
|
onLayerChange: replaceLayer
|
|
206
247
|
}, layer.id)), draft ? /* @__PURE__ */ jsx(DesignCanvasLayerNode, {
|
|
207
248
|
layer: layerFromDraft(draft, "draft"),
|
|
208
249
|
selected: true
|
|
209
250
|
}) : null]
|
|
210
|
-
}), /* @__PURE__ */ jsx(InfiniteCanvasControls, { className: "
|
|
251
|
+
}), /* @__PURE__ */ jsx(InfiniteCanvasControls, { className: "start-3 end-auto top-3 bottom-auto w-max @4xl/design-canvas:inset-x-0 @4xl/design-canvas:mx-auto" })]
|
|
211
252
|
}),
|
|
212
253
|
/* @__PURE__ */ jsx(ResizableFloatingPanel, {
|
|
213
254
|
side: "left",
|
|
@@ -215,30 +256,10 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
|
|
|
215
256
|
minSize: 180,
|
|
216
257
|
maxSize: 360,
|
|
217
258
|
className: "hidden @4xl/design-canvas:flex",
|
|
218
|
-
children: /* @__PURE__ */
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
children:
|
|
222
|
-
className: "flex h-11 shrink-0 items-center border-b px-3 text-caption font-medium",
|
|
223
|
-
children: "Layers"
|
|
224
|
-
}), /* @__PURE__ */ jsx(ScrollArea, {
|
|
225
|
-
className: "min-h-0 flex-1",
|
|
226
|
-
children: /* @__PURE__ */ jsx("ul", {
|
|
227
|
-
className: "flex flex-col gap-0.5 p-2",
|
|
228
|
-
children: currentLayers.toReversed().map((layer) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(Button, {
|
|
229
|
-
variant: "ghost",
|
|
230
|
-
size: "sm",
|
|
231
|
-
active: layer.id === currentSelectedLayerId,
|
|
232
|
-
"aria-pressed": layer.id === currentSelectedLayerId,
|
|
233
|
-
className: "w-full justify-start [&_svg]:size-3.5 [&_svg]:text-muted-foreground",
|
|
234
|
-
onClick: () => selectLayer(layer.id),
|
|
235
|
-
children: [LAYER_ICONS[layer.kind], /* @__PURE__ */ jsx("span", {
|
|
236
|
-
className: "truncate",
|
|
237
|
-
children: layer.name
|
|
238
|
-
})]
|
|
239
|
-
}) }, layer.id))
|
|
240
|
-
})
|
|
241
|
-
})]
|
|
259
|
+
children: /* @__PURE__ */ jsx(DesignCanvasPanel, {
|
|
260
|
+
label: layersLabel,
|
|
261
|
+
title: layersLabel,
|
|
262
|
+
children: layerList
|
|
242
263
|
})
|
|
243
264
|
}),
|
|
244
265
|
/* @__PURE__ */ jsx(ResizableFloatingPanel, {
|
|
@@ -246,37 +267,133 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
|
|
|
246
267
|
minSize: 256,
|
|
247
268
|
maxSize: 440,
|
|
248
269
|
className: "hidden @xl/design-canvas:flex",
|
|
249
|
-
children: /* @__PURE__ */
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
children:
|
|
253
|
-
className: "flex h-11 shrink-0 items-center border-b px-3 text-caption font-medium",
|
|
254
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
255
|
-
className: "truncate",
|
|
256
|
-
children: selectedLayer?.name ?? "Design"
|
|
257
|
-
})
|
|
258
|
-
}), /* @__PURE__ */ jsx(ScrollArea, {
|
|
259
|
-
className: "min-h-0 flex-1",
|
|
260
|
-
children: /* @__PURE__ */ jsx(DesignCanvasInspector, {
|
|
261
|
-
layer: selectedLayer,
|
|
262
|
-
onLayerChange: replaceLayer
|
|
263
|
-
})
|
|
264
|
-
})]
|
|
270
|
+
children: /* @__PURE__ */ jsx(DesignCanvasPanel, {
|
|
271
|
+
label: propertiesLabel,
|
|
272
|
+
title: propertiesTitle,
|
|
273
|
+
children: inspector
|
|
265
274
|
})
|
|
266
275
|
}),
|
|
267
|
-
/* @__PURE__ */ jsx(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
276
|
+
/* @__PURE__ */ jsx(Drawer, {
|
|
277
|
+
side: "left",
|
|
278
|
+
open: layersOpen,
|
|
279
|
+
onOpenChange: setLayersOpen,
|
|
280
|
+
children: /* @__PURE__ */ jsx(DrawerContent, {
|
|
281
|
+
side: "left",
|
|
282
|
+
className: "gap-0 p-0",
|
|
283
|
+
children: /* @__PURE__ */ jsx(DesignCanvasPanel, {
|
|
284
|
+
label: layersLabel,
|
|
285
|
+
title: layersLabel,
|
|
286
|
+
inDrawer: true,
|
|
287
|
+
children: layerList
|
|
288
|
+
})
|
|
289
|
+
})
|
|
290
|
+
}),
|
|
291
|
+
/* @__PURE__ */ jsx(Drawer, {
|
|
292
|
+
side: "right",
|
|
293
|
+
open: propertiesOpen,
|
|
294
|
+
onOpenChange: setPropertiesOpen,
|
|
295
|
+
children: /* @__PURE__ */ jsx(DrawerContent, {
|
|
296
|
+
side: "right",
|
|
297
|
+
className: "gap-0 p-0",
|
|
298
|
+
children: /* @__PURE__ */ jsx(DesignCanvasPanel, {
|
|
299
|
+
label: propertiesLabel,
|
|
300
|
+
title: propertiesTitle,
|
|
301
|
+
inDrawer: true,
|
|
302
|
+
children: inspector
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
}),
|
|
306
|
+
/* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Toolbar, {
|
|
307
|
+
variant: "floating",
|
|
308
|
+
"aria-label": "Design tools",
|
|
309
|
+
className: "absolute start-4 bottom-4 w-max @4xl/design-canvas:inset-x-0 @4xl/design-canvas:mx-auto",
|
|
310
|
+
children: [
|
|
311
|
+
/* @__PURE__ */ jsx(ToolbarGroup, {
|
|
312
|
+
"aria-label": "Tools",
|
|
313
|
+
children: TOOLS.map((entry) => /* @__PURE__ */ jsx(DesignCanvasToolbarButton, {
|
|
314
|
+
label: entry.label,
|
|
315
|
+
hint: `${entry.label} · ${entry.shortcut}`,
|
|
316
|
+
pressed: tool === entry.tool,
|
|
317
|
+
onClick: () => setTool(entry.tool),
|
|
318
|
+
children: entry.icon
|
|
319
|
+
}, entry.tool))
|
|
320
|
+
}),
|
|
321
|
+
/* @__PURE__ */ jsx(ToolbarSeparator, { className: "@4xl/design-canvas:hidden" }),
|
|
322
|
+
/* @__PURE__ */ jsxs(ToolbarGroup, {
|
|
323
|
+
className: "@4xl/design-canvas:hidden",
|
|
324
|
+
children: [/* @__PURE__ */ jsx(DesignCanvasToolbarButton, {
|
|
325
|
+
label: openLayersLabel,
|
|
326
|
+
hint: openLayersLabel,
|
|
327
|
+
"aria-haspopup": "dialog",
|
|
328
|
+
"aria-expanded": layersOpen,
|
|
329
|
+
onClick: () => setLayersOpen(true),
|
|
330
|
+
children: /* @__PURE__ */ jsx(LayersIcon, {})
|
|
331
|
+
}), /* @__PURE__ */ jsx(DesignCanvasToolbarButton, {
|
|
332
|
+
label: openPropertiesLabel,
|
|
333
|
+
hint: openPropertiesLabel,
|
|
334
|
+
"aria-haspopup": "dialog",
|
|
335
|
+
"aria-expanded": propertiesOpen,
|
|
336
|
+
className: "@xl/design-canvas:hidden",
|
|
337
|
+
onClick: () => setPropertiesOpen(true),
|
|
338
|
+
children: /* @__PURE__ */ jsx(SlidersHorizontalIcon, {})
|
|
339
|
+
})]
|
|
340
|
+
})
|
|
341
|
+
]
|
|
342
|
+
}) })
|
|
271
343
|
]
|
|
272
344
|
});
|
|
273
345
|
}
|
|
274
|
-
function
|
|
346
|
+
function DesignCanvasPanel({ label, title, inDrawer = false, children }) {
|
|
347
|
+
const titleClassName = "flex h-11 shrink-0 items-center border-b px-3 text-caption font-medium";
|
|
348
|
+
const titleText = /* @__PURE__ */ jsx("span", {
|
|
349
|
+
className: "truncate",
|
|
350
|
+
title,
|
|
351
|
+
children: title
|
|
352
|
+
});
|
|
353
|
+
return /* @__PURE__ */ jsxs("aside", {
|
|
354
|
+
"aria-label": label,
|
|
355
|
+
className: "flex min-h-0 flex-1 flex-col",
|
|
356
|
+
children: [inDrawer ? /* @__PURE__ */ jsx(DrawerTitle, {
|
|
357
|
+
className: titleClassName,
|
|
358
|
+
children: titleText
|
|
359
|
+
}) : /* @__PURE__ */ jsx("h2", {
|
|
360
|
+
className: titleClassName,
|
|
361
|
+
children: titleText
|
|
362
|
+
}), /* @__PURE__ */ jsx(ScrollArea, {
|
|
363
|
+
className: "min-h-0 flex-1",
|
|
364
|
+
children
|
|
365
|
+
})]
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
function DesignCanvasLayerList({ layers, selectedLayerId, onSelect }) {
|
|
369
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
370
|
+
className: "flex flex-col gap-0.5 p-2",
|
|
371
|
+
children: layers.toReversed().map((layer) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(Button, {
|
|
372
|
+
variant: "ghost",
|
|
373
|
+
size: "sm",
|
|
374
|
+
active: layer.id === selectedLayerId,
|
|
375
|
+
"aria-pressed": layer.id === selectedLayerId,
|
|
376
|
+
className: "w-full justify-start [&_svg]:size-3.5 [&_svg]:text-muted-foreground",
|
|
377
|
+
onClick: () => onSelect(layer.id),
|
|
378
|
+
children: [LAYER_ICONS[layer.kind], /* @__PURE__ */ jsx("span", {
|
|
379
|
+
className: "truncate",
|
|
380
|
+
title: layer.name,
|
|
381
|
+
children: layer.name
|
|
382
|
+
})]
|
|
383
|
+
}) }, layer.id))
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
function DesignCanvasLayerNode({ layer, selected, onSelect, onKeyDown, onLayerChange }) {
|
|
275
387
|
const fillColor = designCanvasFillColor(layer.fill);
|
|
388
|
+
const interactive = onSelect !== void 0;
|
|
276
389
|
return /* @__PURE__ */ jsxs(InfiniteCanvasItem, {
|
|
277
390
|
x: layer.x,
|
|
278
391
|
y: layer.y,
|
|
279
392
|
"aria-label": layer.name,
|
|
393
|
+
role: interactive ? "button" : void 0,
|
|
394
|
+
tabIndex: interactive ? 0 : void 0,
|
|
395
|
+
"aria-pressed": interactive ? selected : void 0,
|
|
396
|
+
"aria-keyshortcuts": interactive ? LAYER_KEY_SHORTCUTS : void 0,
|
|
280
397
|
"data-selected": selected || void 0,
|
|
281
398
|
className: "outline-primary data-selected:outline-2",
|
|
282
399
|
style: {
|
|
@@ -286,6 +403,7 @@ function DesignCanvasLayerNode({ layer, selected, onSelect, onLayerChange }) {
|
|
|
286
403
|
opacity: layer.opacity / 100
|
|
287
404
|
},
|
|
288
405
|
onPointerDown: onSelect,
|
|
406
|
+
onKeyDown,
|
|
289
407
|
onPositionChange: onLayerChange && ((position) => onLayerChange({
|
|
290
408
|
...layer,
|
|
291
409
|
x: Math.round(position.x),
|
|
@@ -293,7 +411,7 @@ function DesignCanvasLayerNode({ layer, selected, onSelect, onLayerChange }) {
|
|
|
293
411
|
})),
|
|
294
412
|
children: [
|
|
295
413
|
layer.kind === "frame" ? /* @__PURE__ */ jsx("span", {
|
|
296
|
-
className: "absolute bottom-full
|
|
414
|
+
className: "absolute start-0 bottom-full mb-1 whitespace-nowrap text-caption text-muted-foreground",
|
|
297
415
|
children: layer.name
|
|
298
416
|
}) : null,
|
|
299
417
|
layer.kind === "text" ? /* @__PURE__ */ jsx("p", {
|
|
@@ -308,7 +426,7 @@ function DesignCanvasLayerNode({ layer, selected, onSelect, onLayerChange }) {
|
|
|
308
426
|
}
|
|
309
427
|
}),
|
|
310
428
|
selected ? /* @__PURE__ */ jsxs("span", {
|
|
311
|
-
className: "absolute top-full
|
|
429
|
+
className: "absolute inset-x-0 top-full mx-auto mt-1.5 w-max rounded-sm bg-primary px-1 text-micro whitespace-nowrap text-primary-foreground tabular-nums",
|
|
312
430
|
children: [
|
|
313
431
|
layer.width,
|
|
314
432
|
" × ",
|
|
@@ -318,29 +436,17 @@ function DesignCanvasLayerNode({ layer, selected, onSelect, onLayerChange }) {
|
|
|
318
436
|
]
|
|
319
437
|
});
|
|
320
438
|
}
|
|
321
|
-
function
|
|
322
|
-
return /* @__PURE__ */
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
"aria-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
"aria-pressed": tool === entry.tool,
|
|
333
|
-
"data-pressed": tool === entry.tool ? "" : void 0,
|
|
334
|
-
onClick: () => onToolChange(entry.tool)
|
|
335
|
-
}),
|
|
336
|
-
children: entry.icon
|
|
337
|
-
}), /* @__PURE__ */ jsxs(TooltipContent, { children: [
|
|
338
|
-
entry.label,
|
|
339
|
-
" · ",
|
|
340
|
-
entry.shortcut
|
|
341
|
-
] })] }, entry.tool))
|
|
342
|
-
})
|
|
343
|
-
}) });
|
|
439
|
+
function DesignCanvasToolbarButton({ label, hint, pressed, children, ...props }) {
|
|
440
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
441
|
+
render: /* @__PURE__ */ jsx(ToolbarButton, {
|
|
442
|
+
...props,
|
|
443
|
+
"aria-label": label,
|
|
444
|
+
iconOnly: true,
|
|
445
|
+
"aria-pressed": pressed,
|
|
446
|
+
"data-pressed": pressed ? "" : void 0
|
|
447
|
+
}),
|
|
448
|
+
children
|
|
449
|
+
}), /* @__PURE__ */ jsx(TooltipContent, { children: hint })] });
|
|
344
450
|
}
|
|
345
451
|
//#endregion
|
|
346
452
|
export { DesignCanvasBlock };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ChatComposer } from "../chat-composer.js";
|
|
2
|
+
import { ChatMessage } from "../chat-message.js";
|
|
3
|
+
import { ComponentProps, ReactNode } from "react";
|
|
4
|
+
//#region src/blocks/discussion.d.ts
|
|
5
|
+
export type DiscussionComposerProps = Omit<ComponentProps<typeof ChatComposer>, "submitKey" | "children"> & {
|
|
6
|
+
label: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
submitLabel?: ReactNode;
|
|
9
|
+
secondaryAction?: ReactNode;
|
|
10
|
+
hint?: ReactNode;
|
|
11
|
+
autoFocus?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare function DiscussionComposer({ label, placeholder, submitLabel, secondaryAction, hint, autoFocus, ...props }: DiscussionComposerProps): import("react").JSX.Element;
|
|
14
|
+
export type DiscussionCommentProps = Omit<ComponentProps<typeof ChatMessage>, "from" | "layout" | "authorLabel" | "children"> & {
|
|
15
|
+
author: string;
|
|
16
|
+
avatar?: ReactNode;
|
|
17
|
+
sentAt: string;
|
|
18
|
+
timeLabel: ReactNode;
|
|
19
|
+
edited?: boolean;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
actions?: ReactNode;
|
|
22
|
+
onReply?: () => void;
|
|
23
|
+
replyLabel?: ReactNode;
|
|
24
|
+
replies?: ReactNode;
|
|
25
|
+
replyComposer?: ReactNode;
|
|
26
|
+
};
|
|
27
|
+
export declare function DiscussionComment({ author, avatar, sentAt, timeLabel, edited, children, actions, onReply, replyLabel, replies, replyComposer, ...props }: DiscussionCommentProps): import("react").JSX.Element;
|
|
28
|
+
//#endregion
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Button } from "../ui/button.js";
|
|
3
|
+
import { ChatComposer, ChatComposerShell, ChatComposerSubmit, ChatComposerTextarea, ChatComposerToolbar } from "../chat-composer.js";
|
|
4
|
+
import { ChatMessageReplies } from "../chat-message/social.js";
|
|
5
|
+
import { ChatMessage, ChatMessageActions, ChatMessageAuthor, ChatMessageAvatar, ChatMessageBody, ChatMessageContent, ChatMessageFooter, ChatMessageHeader, ChatMessageRow, ChatMessageTime } from "../chat-message.js";
|
|
6
|
+
import { Kbd, KbdGroup } from "../ui/kbd.js";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { CornerDownRightIcon } from "lucide-react";
|
|
9
|
+
//#region src/blocks/discussion.tsx
|
|
10
|
+
function DiscussionComposer({ label, placeholder, submitLabel = "Post", secondaryAction, hint = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(KbdGroup, { children: [/* @__PURE__ */ jsx(Kbd, { children: "⌘" }), /* @__PURE__ */ jsx(Kbd, { children: "Enter" })] }), /* @__PURE__ */ jsx("span", { children: "to post" })] }), autoFocus, ...props }) {
|
|
11
|
+
return /* @__PURE__ */ jsx(ChatComposer, {
|
|
12
|
+
submitKey: "mod-enter",
|
|
13
|
+
...props,
|
|
14
|
+
children: /* @__PURE__ */ jsxs(ChatComposerShell, { children: [/* @__PURE__ */ jsx(ChatComposerTextarea, {
|
|
15
|
+
"aria-label": label,
|
|
16
|
+
placeholder,
|
|
17
|
+
autoFocus,
|
|
18
|
+
"aria-keyshortcuts": "Meta+Enter Control+Enter"
|
|
19
|
+
}), /* @__PURE__ */ jsxs(ChatComposerToolbar, { children: [/* @__PURE__ */ jsx("span", {
|
|
20
|
+
className: "flex min-w-0 items-center gap-1.5 text-caption text-muted-foreground",
|
|
21
|
+
children: hint
|
|
22
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
23
|
+
className: "flex items-center gap-2",
|
|
24
|
+
children: [secondaryAction, /* @__PURE__ */ jsx(ChatComposerSubmit, { children: submitLabel })]
|
|
25
|
+
})] })] })
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function initials(name) {
|
|
29
|
+
return name.split(/\s+/).slice(0, 2).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
30
|
+
}
|
|
31
|
+
function DiscussionComment({ author, avatar, sentAt, timeLabel, edited = false, children, actions, onReply, replyLabel = "Reply", replies, replyComposer, ...props }) {
|
|
32
|
+
const hasReplies = Boolean(replies) || Boolean(replyComposer);
|
|
33
|
+
return /* @__PURE__ */ jsx(ChatMessage, {
|
|
34
|
+
from: "participant",
|
|
35
|
+
layout: "flat",
|
|
36
|
+
authorLabel: author,
|
|
37
|
+
...props,
|
|
38
|
+
children: /* @__PURE__ */ jsxs(ChatMessageRow, { children: [
|
|
39
|
+
/* @__PURE__ */ jsx(ChatMessageAvatar, { children: avatar ?? /* @__PURE__ */ jsx("span", {
|
|
40
|
+
"aria-hidden": "true",
|
|
41
|
+
children: initials(author)
|
|
42
|
+
}) }),
|
|
43
|
+
/* @__PURE__ */ jsxs(ChatMessageBody, { children: [
|
|
44
|
+
/* @__PURE__ */ jsxs(ChatMessageHeader, { children: [
|
|
45
|
+
/* @__PURE__ */ jsx(ChatMessageAuthor, { children: author }),
|
|
46
|
+
/* @__PURE__ */ jsx(ChatMessageTime, {
|
|
47
|
+
dateTime: sentAt,
|
|
48
|
+
children: timeLabel
|
|
49
|
+
}),
|
|
50
|
+
edited ? /* @__PURE__ */ jsx("span", { children: "(edited)" }) : null
|
|
51
|
+
] }),
|
|
52
|
+
/* @__PURE__ */ jsx(ChatMessageContent, { children }),
|
|
53
|
+
onReply ? /* @__PURE__ */ jsx(ChatMessageFooter, { children: /* @__PURE__ */ jsxs(Button, {
|
|
54
|
+
variant: "ghost",
|
|
55
|
+
size: "xs",
|
|
56
|
+
onClick: onReply,
|
|
57
|
+
className: "-ms-2",
|
|
58
|
+
children: [/* @__PURE__ */ jsx(CornerDownRightIcon, { "aria-hidden": "true" }), replyLabel]
|
|
59
|
+
}) }) : null,
|
|
60
|
+
hasReplies ? /* @__PURE__ */ jsxs(ChatMessageReplies, { children: [replies, replyComposer] }) : null
|
|
61
|
+
] }),
|
|
62
|
+
actions ? /* @__PURE__ */ jsx(ChatMessageActions, { children: actions }) : null
|
|
63
|
+
] })
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { DiscussionComment, DiscussionComposer };
|
|
@@ -52,5 +52,6 @@ export declare function groupFileExplorerItems<T extends {
|
|
|
52
52
|
label: string;
|
|
53
53
|
items: T[];
|
|
54
54
|
}[];
|
|
55
|
+
export declare function orderFileExplorerEntries(entries: readonly FileExplorerEntry[]): FileExplorerEntry[];
|
|
55
56
|
export declare function searchFileExplorer(location: FileExplorerLocation, query: string): readonly FileExplorerSearchResult[];
|
|
56
57
|
//#endregion
|
|
@@ -52,6 +52,9 @@ function groupFileExplorerItems(items) {
|
|
|
52
52
|
items: groupedItems
|
|
53
53
|
}));
|
|
54
54
|
}
|
|
55
|
+
function orderFileExplorerEntries(entries) {
|
|
56
|
+
return groupFileExplorerItems(entries).flatMap((group) => group.items);
|
|
57
|
+
}
|
|
55
58
|
function searchFileExplorer(location, query) {
|
|
56
59
|
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
57
60
|
if (!normalizedQuery) return [];
|
|
@@ -71,4 +74,4 @@ function searchFileExplorer(location, query) {
|
|
|
71
74
|
return results;
|
|
72
75
|
}
|
|
73
76
|
//#endregion
|
|
74
|
-
export { groupFileExplorerItems, resolveFileExplorer, searchFileExplorer };
|
|
77
|
+
export { groupFileExplorerItems, orderFileExplorerEntries, resolveFileExplorer, searchFileExplorer };
|
|
@@ -16,9 +16,17 @@ export type FileExplorerBlockProps = Omit<ComponentProps<"div">, "children" | "d
|
|
|
16
16
|
sidebarTop?: ReactNode;
|
|
17
17
|
sidebarFooter?: ReactNode;
|
|
18
18
|
headerActions?: ReactNode;
|
|
19
|
+
headerMenuItems?: ReactNode;
|
|
19
20
|
searchPlaceholder?: string | false;
|
|
21
|
+
searchLabel?: string;
|
|
22
|
+
clearSearchLabel?: string;
|
|
23
|
+
searchResultsLabel?: string;
|
|
24
|
+
searchStatusLabel?: (count: number, query: string) => string;
|
|
25
|
+
backLabel?: string;
|
|
26
|
+
moreActionsLabel?: string;
|
|
27
|
+
detailsLabel?: string;
|
|
20
28
|
layout?: "viewport" | "contained";
|
|
21
29
|
};
|
|
22
|
-
export declare function FileExplorerBlock({ locations, activeLocationId, defaultActiveLocationId, selectedPath, defaultSelectedPath, searchValue, defaultSearchValue, onActiveLocationChange, onSelectedPathChange, onSearchValueChange, onOpenEntry, sidebarTop, sidebarFooter, headerActions, searchPlaceholder, layout, className, style, ...props }: FileExplorerBlockProps): import("react").JSX.Element;
|
|
30
|
+
export declare function FileExplorerBlock({ locations, activeLocationId, defaultActiveLocationId, selectedPath, defaultSelectedPath, searchValue, defaultSearchValue, onActiveLocationChange, onSelectedPathChange, onSearchValueChange, onOpenEntry, sidebarTop, sidebarFooter, headerActions, headerMenuItems, searchPlaceholder, searchLabel, clearSearchLabel, searchResultsLabel, searchStatusLabel, backLabel, moreActionsLabel, detailsLabel, layout, className, style, ...props }: FileExplorerBlockProps): import("react").JSX.Element;
|
|
23
31
|
//#endregion
|
|
24
32
|
export type { FileExplorerBreadcrumb, FileExplorerColumn, FileExplorerEntry, FileExplorerEntryDetail, FileExplorerLocation, FileExplorerResolution, FileExplorerSearchResult };
|