@heyramzi/ui 3.1.0 → 3.3.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.
- package/dist/lib/sliding-pill.js +2 -2
- package/dist/record/measure-clamp.js +23 -0
- package/dist/shadcn/button-group/index.js +6 -0
- package/dist/shadcn/checkbox/checkbox-box.js +3 -0
- package/dist/shadcn/drawer/index.js +14 -0
- package/dist/shadcn/input-group/index.js +9 -0
- package/dist/shadcn/item/index.js +13 -0
- package/dist/shadcn/native-select/index.js +6 -0
- package/dist/shadcn/pagination/index.js +12 -0
- package/package.json +7 -2
- package/scripts/sync-shadcn.mjs +0 -6
- package/src/ai/generation-progress/GenerationProgress.svelte +14 -12
- package/src/canvas/pen/PenOverlay.svelte +1 -30
- package/src/canvas/screen/PartView.svelte +13 -8
- package/src/canvas/screen/ScreenBody.svelte +18 -11
- package/src/canvas/ui/BarTooltip.svelte +46 -0
- package/src/canvas/ui/BarTooltip.svelte.d.ts +17 -0
- package/src/canvas/ui/CanvasToolbar.svelte +170 -156
- package/src/canvas/ui/StylePanel.svelte +179 -102
- package/src/canvas/ui/canvas-ui.css +12 -76
- package/src/charts/dashboard/data-table.svelte +80 -80
- package/src/charts/dashboard/hint.svelte +34 -0
- package/src/charts/dashboard/hint.svelte.d.ts +10 -0
- package/src/charts/dashboard/rating-chip.svelte +4 -3
- package/src/charts/legend.css +0 -8
- package/src/charts/legend.svelte +26 -30
- package/src/components/copy/copy-button.svelte +10 -2
- package/src/components/copy/copy-button.test.ts +7 -0
- package/src/components/data-table/table-skeleton.svelte +15 -7
- package/src/components/data-table/table-skeleton.svelte.d.ts +4 -0
- package/src/components/docs/on-this-page.svelte +2 -2
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +2 -1
- package/src/components/list-page/filter-item.svelte +20 -7
- package/src/components/list-page/filter-popover.svelte +41 -16
- package/src/components/list-page/filter-popover.svelte.d.ts +1 -1
- package/src/components/list-page/grouped-list.svelte +41 -23
- package/src/components/picker/picker.svelte +8 -3
- package/src/components/picker/picker.svelte.d.ts +2 -1
- package/src/components/segmented/segmented-filter.svelte +19 -10
- package/src/components/segmented/segmented-track.svelte +11 -3
- package/src/components/table-view/table-view.svelte +22 -6
- package/src/components/tags-input/tags-input.svelte +94 -77
- package/src/components/toolbar/toolbar.svelte +2 -1
- package/src/components/toolbar/toolbar.test.ts +5 -4
- package/src/components/work-parts/group-head.svelte +28 -9
- package/src/components/work-parts/group-head.svelte.d.ts +5 -2
- package/src/editor/editor-toolbar.svelte +223 -193
- package/src/editor/editor.svelte +56 -38
- package/src/editor/image-toolbar.svelte +99 -37
- package/src/editor/image-toolbar.svelte.d.ts +4 -5
- package/src/editor/url-dialog.svelte +96 -0
- package/src/editor/url-dialog.svelte.d.ts +15 -0
- package/src/effects/theme-toggle/ThemeToggle.css +8 -8
- package/src/effects/theme-toggle/ThemeToggle.svelte +20 -6
- package/src/inbox/thread-inbox.svelte +9 -1
- package/src/lib/live-region.svelte +12 -4
- package/src/lib/live-region.svelte.d.ts +5 -1
- package/src/lib/sliding-pill.ts +3 -2
- package/src/record/info-list.svelte +33 -59
- package/src/record/measure-clamp.ts +31 -0
- package/src/record/record-shell.svelte +38 -39
- package/src/record/record-timeline.svelte +10 -5
- package/src/record/steps-rail.svelte +50 -36
- package/src/record/where-we-are.svelte +5 -19
- package/src/shadcn/button-group/button-group-separator.svelte +23 -0
- package/src/shadcn/button-group/button-group-separator.svelte.d.ts +13 -0
- package/src/shadcn/button-group/button-group-text.svelte +28 -0
- package/src/shadcn/button-group/button-group-text.svelte.d.ts +11 -0
- package/src/shadcn/button-group/button-group.svelte +46 -0
- package/src/shadcn/button-group/button-group.svelte.d.ts +16 -0
- package/src/shadcn/button-group/index.ts +15 -0
- package/src/shadcn/checkbox/checkbox-box.ts +4 -0
- package/src/shadcn/checkbox/checkbox.svelte +2 -4
- package/src/shadcn/drawer/drawer-close.svelte +7 -0
- package/src/shadcn/drawer/drawer-close.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer-content.svelte +36 -0
- package/src/shadcn/drawer/drawer-content.svelte.d.ts +10 -0
- package/src/shadcn/drawer/drawer-description.svelte +17 -0
- package/src/shadcn/drawer/drawer-description.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer-footer.svelte +20 -0
- package/src/shadcn/drawer/drawer-footer.svelte.d.ts +5 -0
- package/src/shadcn/drawer/drawer-header.svelte +23 -0
- package/src/shadcn/drawer/drawer-header.svelte.d.ts +5 -0
- package/src/shadcn/drawer/drawer-nested.svelte +12 -0
- package/src/shadcn/drawer/drawer-nested.svelte.d.ts +3 -0
- package/src/shadcn/drawer/drawer-overlay.svelte +20 -0
- package/src/shadcn/drawer/drawer-overlay.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer-portal.svelte +7 -0
- package/src/shadcn/drawer/drawer-portal.svelte.d.ts +3 -0
- package/src/shadcn/drawer/drawer-title.svelte +17 -0
- package/src/shadcn/drawer/drawer-title.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer-trigger.svelte +7 -0
- package/src/shadcn/drawer/drawer-trigger.svelte.d.ts +4 -0
- package/src/shadcn/drawer/drawer.svelte +12 -0
- package/src/shadcn/drawer/drawer.svelte.d.ts +3 -0
- package/src/shadcn/drawer/index.ts +38 -0
- package/src/shadcn/input-group/index.ts +22 -0
- package/src/shadcn/input-group/input-group-addon.svelte +51 -0
- package/src/shadcn/input-group/input-group-addon.svelte.d.ts +18 -0
- package/src/shadcn/input-group/input-group-button.svelte +49 -0
- package/src/shadcn/input-group/input-group-button.svelte.d.ts +18 -0
- package/src/shadcn/input-group/input-group-input.svelte +20 -0
- package/src/shadcn/input-group/input-group-input.svelte.d.ts +11 -0
- package/src/shadcn/input-group/input-group-text.svelte +19 -0
- package/src/shadcn/input-group/input-group-text.svelte.d.ts +5 -0
- package/src/shadcn/input-group/input-group-textarea.svelte +20 -0
- package/src/shadcn/input-group/input-group-textarea.svelte.d.ts +3 -0
- package/src/shadcn/input-group/input-group.svelte +24 -0
- package/src/shadcn/input-group/input-group.svelte.d.ts +5 -0
- package/src/shadcn/item/index.ts +34 -0
- package/src/shadcn/item/item-actions.svelte +20 -0
- package/src/shadcn/item/item-actions.svelte.d.ts +5 -0
- package/src/shadcn/item/item-content.svelte +23 -0
- package/src/shadcn/item/item-content.svelte.d.ts +5 -0
- package/src/shadcn/item/item-description.svelte +23 -0
- package/src/shadcn/item/item-description.svelte.d.ts +5 -0
- package/src/shadcn/item/item-footer.svelte +20 -0
- package/src/shadcn/item/item-footer.svelte.d.ts +5 -0
- package/src/shadcn/item/item-group.svelte +21 -0
- package/src/shadcn/item/item-group.svelte.d.ts +5 -0
- package/src/shadcn/item/item-header.svelte +20 -0
- package/src/shadcn/item/item-header.svelte.d.ts +5 -0
- package/src/shadcn/item/item-media.svelte +42 -0
- package/src/shadcn/item/item-media.svelte.d.ts +17 -0
- package/src/shadcn/item/item-separator.svelte +19 -0
- package/src/shadcn/item/item-separator.svelte.d.ts +13 -0
- package/src/shadcn/item/item-title.svelte +20 -0
- package/src/shadcn/item/item-title.svelte.d.ts +5 -0
- package/src/shadcn/item/item.svelte +61 -0
- package/src/shadcn/item/item.svelte.d.ts +28 -0
- package/src/shadcn/native-select/index.ts +13 -0
- package/src/shadcn/native-select/native-select-opt-group.svelte +20 -0
- package/src/shadcn/native-select/native-select-opt-group.svelte.d.ts +5 -0
- package/src/shadcn/native-select/native-select-option.svelte +20 -0
- package/src/shadcn/native-select/native-select-option.svelte.d.ts +5 -0
- package/src/shadcn/native-select/native-select.svelte +45 -0
- package/src/shadcn/native-select/native-select.svelte.d.ts +8 -0
- package/src/shadcn/pagination/index.ts +31 -0
- package/src/shadcn/pagination/pagination-content.svelte +20 -0
- package/src/shadcn/pagination/pagination-content.svelte.d.ts +5 -0
- package/src/shadcn/pagination/pagination-ellipsis.svelte +22 -0
- package/src/shadcn/pagination/pagination-ellipsis.svelte.d.ts +5 -0
- package/src/shadcn/pagination/pagination-item.svelte +14 -0
- package/src/shadcn/pagination/pagination-item.svelte.d.ts +5 -0
- package/src/shadcn/pagination/pagination-link.svelte +41 -0
- package/src/shadcn/pagination/pagination-link.svelte.d.ts +9 -0
- package/src/shadcn/pagination/pagination-next-button.svelte +34 -0
- package/src/shadcn/pagination/pagination-next-button.svelte.d.ts +4 -0
- package/src/shadcn/pagination/pagination-next.svelte +26 -0
- package/src/shadcn/pagination/pagination-next.svelte.d.ts +4 -0
- package/src/shadcn/pagination/pagination-prev-button.svelte +34 -0
- package/src/shadcn/pagination/pagination-prev-button.svelte.d.ts +4 -0
- package/src/shadcn/pagination/pagination-previous.svelte +30 -0
- package/src/shadcn/pagination/pagination-previous.svelte.d.ts +4 -0
- package/src/shadcn/pagination/pagination.svelte +27 -0
- package/src/shadcn/pagination/pagination.svelte.d.ts +4 -0
- package/src/slides/Controls.svelte +39 -36
- package/src/slides/Deck.svelte +11 -8
- package/src/thread/thread.svelte +15 -8
- package/src/work/detail/task-detail.svelte +1 -1
- package/src/work/gantt/gantt-task-row.svelte +3 -6
- package/src/work/inbox/inbox-card.svelte +7 -5
- package/src/work/inbox/inbox-trace.svelte +14 -10
- package/src/work/kanban-board.svelte +40 -25
- package/src/work/kanban-hidden-rail.svelte +67 -65
- package/src/work/task-list.svelte +145 -124
- package/src/work/task-list.svelte.test.ts +5 -2
- package/src/work/time/time-tracker.svelte +35 -10
|
@@ -17,11 +17,14 @@
|
|
|
17
17
|
// IMPORTS
|
|
18
18
|
// =========================
|
|
19
19
|
import { Panel } from "@xyflow/svelte";
|
|
20
|
+
import { mergeProps, Toolbar } from "bits-ui";
|
|
20
21
|
import type { Snippet } from "svelte";
|
|
21
22
|
import "../pen/pen.css";
|
|
22
23
|
import { PEN_COLORS } from "../pen/types.js";
|
|
23
24
|
import "./canvas-ui.css";
|
|
24
25
|
import ToolIcon from "../components/icons/ToolIcon.svelte";
|
|
26
|
+
import BarTooltip from "./BarTooltip.svelte";
|
|
27
|
+
import * as Tooltip from "../../shadcn/tooltip/index.js";
|
|
25
28
|
import {
|
|
26
29
|
hasBrush,
|
|
27
30
|
hasColor,
|
|
@@ -63,6 +66,9 @@
|
|
|
63
66
|
// =========================
|
|
64
67
|
let lastShape = $state<"rectangle" | "ellipse" | "diamond">("rectangle");
|
|
65
68
|
let lastBrush = $state<BrushTool>("pen");
|
|
69
|
+
let styleBar = $state<HTMLElement | null>(null);
|
|
70
|
+
/** The value of the style bar item that had focus when its layout changed, or null when focus was elsewhere. */
|
|
71
|
+
let refocus: string | null = null;
|
|
66
72
|
|
|
67
73
|
// =========================
|
|
68
74
|
// DERIVED
|
|
@@ -70,10 +76,17 @@
|
|
|
70
76
|
const BRUSHES = ["pen", "highlighter", "eraser"] as const;
|
|
71
77
|
const SHAPES = ["rectangle", "ellipse", "diamond"] as const;
|
|
72
78
|
const BRUSH_DOT = [4, 7, 11] as const;
|
|
79
|
+
const SINGLE_TOOLS = ["select", "hand", "connect"] as const;
|
|
73
80
|
|
|
74
81
|
let shapeActive = $derived(isShapeTool(tool));
|
|
75
82
|
let brushActive = $derived(isBrushTool(tool));
|
|
76
83
|
let showStyle = $derived(brushActive || shapeActive || hasColor(tool));
|
|
84
|
+
/** The brush and shape buttons stand for a family of tools, so the rail's pick is the family. */
|
|
85
|
+
let railValue = $derived(brushActive ? "brush" : shapeActive ? "shapes" : tool);
|
|
86
|
+
// Roving focus remembers its tab stop by element, so a bar whose items change is rebuilt fresh.
|
|
87
|
+
let styleLayout = $derived(
|
|
88
|
+
`${brushActive ? "brush" : shapeActive ? "shape" : "none"}-${hasColor(tool)}-${hasBrush(tool)}`,
|
|
89
|
+
);
|
|
77
90
|
|
|
78
91
|
// =========================
|
|
79
92
|
// EFFECTS
|
|
@@ -83,175 +96,176 @@
|
|
|
83
96
|
if (isBrushTool(tool)) lastBrush = tool;
|
|
84
97
|
});
|
|
85
98
|
|
|
99
|
+
$effect.pre(() => {
|
|
100
|
+
void styleLayout;
|
|
101
|
+
const active = document.activeElement;
|
|
102
|
+
refocus =
|
|
103
|
+
active instanceof HTMLElement && styleBar?.contains(active)
|
|
104
|
+
? (active.dataset.value ?? "")
|
|
105
|
+
: null;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
$effect(() => {
|
|
109
|
+
void styleLayout;
|
|
110
|
+
if (refocus === null || !styleBar) return;
|
|
111
|
+
const items = [...styleBar.querySelectorAll<HTMLElement>("[data-toolbar-item]")];
|
|
112
|
+
(items.find((item) => item.dataset.value === refocus) ?? items[0])?.focus();
|
|
113
|
+
refocus = null;
|
|
114
|
+
});
|
|
115
|
+
|
|
86
116
|
// =========================
|
|
87
117
|
// FUNCTIONS
|
|
88
118
|
// =========================
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
119
|
+
// A single-select group sends "" when its pressed item is pressed again. A tool stays picked.
|
|
120
|
+
function pickRail(value: string) {
|
|
121
|
+
if (value === "brush") tool = lastBrush;
|
|
122
|
+
else if (value === "shapes") tool = lastShape;
|
|
123
|
+
else if (value) tool = value as CanvasTool;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Svelte Flow blurs a node a frame after Esc deselects it, which stops the tool letters.
|
|
127
|
+
// A later frame refocuses it. On the window, so it runs after the node's delegated handler.
|
|
128
|
+
function keepNodeFocus(panel: HTMLElement) {
|
|
129
|
+
const flow = panel.closest<HTMLElement>(".svelte-flow");
|
|
130
|
+
if (!flow) return;
|
|
131
|
+
const onkeydown = (event: KeyboardEvent) => {
|
|
132
|
+
const node = event.target;
|
|
133
|
+
if (event.key !== "Escape" || !(node instanceof HTMLElement)) return;
|
|
134
|
+
if (!node.matches(".svelte-flow__node") || !flow.contains(node)) return;
|
|
135
|
+
requestAnimationFrame(() => node.isConnected && node.focus());
|
|
136
|
+
};
|
|
137
|
+
window.addEventListener("keydown", onkeydown);
|
|
138
|
+
return () => window.removeEventListener("keydown", onkeydown);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function pickTool(value: string) {
|
|
142
|
+
if (value) tool = value as CanvasTool;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function pickColor(value: string) {
|
|
146
|
+
if (value) color = value as PenColor;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function pickLevel(value: string) {
|
|
150
|
+
if (value) level = Number(value) as BrushLevel;
|
|
92
151
|
}
|
|
93
152
|
</script>
|
|
94
153
|
|
|
95
154
|
<!-- =========================== -->
|
|
96
155
|
<!-- MARKUP -->
|
|
97
156
|
<!-- =========================== -->
|
|
98
|
-
<Panel position="center-left" class="cv-dock">
|
|
99
|
-
<
|
|
100
|
-
<div
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<button
|
|
107
|
-
type="button"
|
|
108
|
-
class="cv-btn"
|
|
109
|
-
aria-pressed={tool === "select"}
|
|
110
|
-
aria-label={labels.tools.select}
|
|
111
|
-
data-tip={tip("select")}
|
|
112
|
-
onclick={() => (tool = "select")}
|
|
113
|
-
>
|
|
114
|
-
<ToolIcon name="select" />
|
|
115
|
-
</button>
|
|
116
|
-
<button
|
|
117
|
-
type="button"
|
|
118
|
-
class="cv-btn"
|
|
119
|
-
aria-pressed={tool === "hand"}
|
|
120
|
-
aria-label={labels.tools.hand}
|
|
121
|
-
data-tip={tip("hand")}
|
|
122
|
-
onclick={() => (tool = "hand")}
|
|
123
|
-
>
|
|
124
|
-
<ToolIcon name="hand" />
|
|
125
|
-
</button>
|
|
126
|
-
<button
|
|
127
|
-
type="button"
|
|
128
|
-
class="cv-btn"
|
|
129
|
-
aria-pressed={tool === "connect"}
|
|
130
|
-
aria-label={labels.tools.connect}
|
|
131
|
-
data-tip={tip("connect")}
|
|
132
|
-
onclick={() => (tool = "connect")}
|
|
133
|
-
>
|
|
134
|
-
<ToolIcon name="connect" />
|
|
135
|
-
</button>
|
|
136
|
-
<button
|
|
137
|
-
type="button"
|
|
138
|
-
class="cv-btn"
|
|
139
|
-
aria-pressed={brushActive}
|
|
140
|
-
aria-label={labels.tools[lastBrush]}
|
|
141
|
-
data-tip={tip(lastBrush)}
|
|
142
|
-
onclick={() => (tool = lastBrush)}
|
|
143
|
-
>
|
|
144
|
-
<ToolIcon name={brushActive ? (tool as BrushTool) : lastBrush} />
|
|
145
|
-
</button>
|
|
146
|
-
<button
|
|
147
|
-
type="button"
|
|
148
|
-
class="cv-btn"
|
|
149
|
-
aria-pressed={tool === "text"}
|
|
150
|
-
aria-label={labels.tools.text}
|
|
151
|
-
data-tip={tip("text")}
|
|
152
|
-
onclick={() => (tool = "text")}
|
|
153
|
-
>
|
|
154
|
-
<ToolIcon name="text" />
|
|
155
|
-
</button>
|
|
156
|
-
<button
|
|
157
|
-
type="button"
|
|
158
|
-
class="cv-btn"
|
|
159
|
-
aria-pressed={shapeActive}
|
|
160
|
-
aria-label={labels.tools.shapes}
|
|
161
|
-
data-tip={tip("rectangle", labels.tools.shapes)}
|
|
162
|
-
onclick={() => (tool = lastShape)}
|
|
157
|
+
<Panel position="center-left" class="cv-dock" {@attach keepNodeFocus}>
|
|
158
|
+
<Tooltip.Provider>
|
|
159
|
+
<div class="cv-row">
|
|
160
|
+
<Toolbar.Root
|
|
161
|
+
class="cv-bar cv-rail"
|
|
162
|
+
orientation="vertical"
|
|
163
|
+
aria-orientation="vertical"
|
|
164
|
+
aria-label={labels.toolbar}
|
|
163
165
|
>
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
type="button"
|
|
168
|
-
class="cv-btn"
|
|
169
|
-
aria-pressed={tool === "frame"}
|
|
170
|
-
aria-label={labels.tools.frame}
|
|
171
|
-
data-tip={tip("frame")}
|
|
172
|
-
onclick={() => (tool = "frame")}
|
|
173
|
-
>
|
|
174
|
-
<ToolIcon name="frame" />
|
|
175
|
-
</button>
|
|
176
|
-
{#if onNote}
|
|
177
|
-
<button
|
|
178
|
-
type="button"
|
|
179
|
-
class="cv-btn"
|
|
180
|
-
aria-label={labels.tools.note}
|
|
181
|
-
data-tip="{labels.tools.note} N"
|
|
182
|
-
onclick={onNote}
|
|
183
|
-
>
|
|
184
|
-
<ToolIcon name="note" />
|
|
185
|
-
</button>
|
|
186
|
-
{/if}
|
|
187
|
-
|
|
188
|
-
{#if extra}
|
|
189
|
-
<span class="cv-gap" aria-hidden="true"></span>
|
|
190
|
-
{@render extra()}
|
|
191
|
-
{/if}
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
{#if showStyle}
|
|
195
|
-
<div class="cv-bar t-enter" role="toolbar" aria-label={labels.style}>
|
|
196
|
-
{#if brushActive}
|
|
197
|
-
{#each BRUSHES as brush (brush)}
|
|
198
|
-
<button
|
|
199
|
-
type="button"
|
|
200
|
-
class="cv-btn"
|
|
201
|
-
aria-pressed={tool === brush}
|
|
202
|
-
aria-label={labels.tools[brush]}
|
|
203
|
-
data-tip={tip(brush)}
|
|
204
|
-
onclick={() => (tool = brush)}
|
|
205
|
-
>
|
|
206
|
-
<ToolIcon name={brush} />
|
|
207
|
-
</button>
|
|
208
|
-
{/each}
|
|
209
|
-
{:else if shapeActive}
|
|
210
|
-
{#each SHAPES as shape (shape)}
|
|
211
|
-
<button
|
|
212
|
-
type="button"
|
|
213
|
-
class="cv-btn"
|
|
214
|
-
aria-pressed={tool === shape}
|
|
215
|
-
aria-label={labels.tools[shape]}
|
|
216
|
-
data-tip={tip(shape)}
|
|
217
|
-
onclick={() => (tool = shape)}
|
|
218
|
-
>
|
|
219
|
-
<ToolIcon name={shape} />
|
|
220
|
-
</button>
|
|
166
|
+
<Toolbar.Group type="single" class="cv-group" bind:value={() => railValue, pickRail}>
|
|
167
|
+
{#each SINGLE_TOOLS as id (id)}
|
|
168
|
+
{@render railItem(id, labels.tools[id], keyForTool(id), id)}
|
|
221
169
|
{/each}
|
|
170
|
+
{@render railItem(
|
|
171
|
+
"brush",
|
|
172
|
+
labels.tools[lastBrush],
|
|
173
|
+
keyForTool(lastBrush),
|
|
174
|
+
brushActive ? (tool as BrushTool) : lastBrush,
|
|
175
|
+
)}
|
|
176
|
+
{@render railItem("text", labels.tools.text, keyForTool("text"), "text")}
|
|
177
|
+
{@render railItem(
|
|
178
|
+
"shapes",
|
|
179
|
+
labels.tools.shapes,
|
|
180
|
+
keyForTool("rectangle"),
|
|
181
|
+
shapeActive ? (tool as typeof lastShape) : lastShape,
|
|
182
|
+
)}
|
|
183
|
+
{@render railItem("frame", labels.tools.frame, keyForTool("frame"), "frame")}
|
|
184
|
+
</Toolbar.Group>
|
|
185
|
+
{#if onNote}
|
|
186
|
+
<BarTooltip label={labels.tools.note} shortcut="N" side="right">
|
|
187
|
+
{#snippet child({ props })}
|
|
188
|
+
<Toolbar.Button {...mergeProps(props, { onclick: onNote })} class="cv-btn">
|
|
189
|
+
<ToolIcon name="note" />
|
|
190
|
+
</Toolbar.Button>
|
|
191
|
+
{/snippet}
|
|
192
|
+
</BarTooltip>
|
|
222
193
|
{/if}
|
|
223
194
|
|
|
224
|
-
{#if
|
|
225
|
-
{#if brushActive || shapeActive}<span class="cv-gap" aria-hidden="true"></span>{/if}
|
|
226
|
-
{#each PEN_COLORS as swatch (swatch)}
|
|
227
|
-
<button
|
|
228
|
-
type="button"
|
|
229
|
-
class="cv-swatch"
|
|
230
|
-
aria-pressed={color === swatch}
|
|
231
|
-
aria-label={labels.colors[swatch]}
|
|
232
|
-
data-tip={labels.colors[swatch]}
|
|
233
|
-
style:--swatch="var(--pen-{swatch})"
|
|
234
|
-
onclick={() => (color = swatch)}
|
|
235
|
-
></button>
|
|
236
|
-
{/each}
|
|
237
|
-
{/if}
|
|
238
|
-
|
|
239
|
-
{#if hasBrush(tool)}
|
|
195
|
+
{#if extra}
|
|
240
196
|
<span class="cv-gap" aria-hidden="true"></span>
|
|
241
|
-
{
|
|
242
|
-
<button
|
|
243
|
-
type="button"
|
|
244
|
-
class="cv-btn"
|
|
245
|
-
aria-pressed={level === index}
|
|
246
|
-
aria-label={labels.sizes[index]}
|
|
247
|
-
data-tip={labels.sizes[index]}
|
|
248
|
-
onclick={() => (level = index as BrushLevel)}
|
|
249
|
-
>
|
|
250
|
-
<span class="cv-dot" style:--dot="{dot}px"></span>
|
|
251
|
-
</button>
|
|
252
|
-
{/each}
|
|
197
|
+
{@render extra()}
|
|
253
198
|
{/if}
|
|
254
|
-
</
|
|
255
|
-
|
|
256
|
-
|
|
199
|
+
</Toolbar.Root>
|
|
200
|
+
|
|
201
|
+
{#if showStyle}
|
|
202
|
+
<div class="cv-bar t-enter" bind:this={styleBar}>
|
|
203
|
+
{#key styleLayout}
|
|
204
|
+
<Toolbar.Root class="cv-group" aria-label={labels.style}>
|
|
205
|
+
{#if brushActive || shapeActive}
|
|
206
|
+
<Toolbar.Group type="single" class="cv-group" bind:value={() => tool, pickTool}>
|
|
207
|
+
{#each brushActive ? BRUSHES : SHAPES as kind (kind)}
|
|
208
|
+
<BarTooltip label={labels.tools[kind]} shortcut={keyForTool(kind)}>
|
|
209
|
+
{#snippet child({ props })}
|
|
210
|
+
<Toolbar.GroupItem {...props} value={kind} class="cv-btn">
|
|
211
|
+
<ToolIcon name={kind} />
|
|
212
|
+
</Toolbar.GroupItem>
|
|
213
|
+
{/snippet}
|
|
214
|
+
</BarTooltip>
|
|
215
|
+
{/each}
|
|
216
|
+
</Toolbar.Group>
|
|
217
|
+
{/if}
|
|
218
|
+
|
|
219
|
+
{#if hasColor(tool)}
|
|
220
|
+
{#if brushActive || shapeActive}<span class="cv-gap" aria-hidden="true"></span>{/if}
|
|
221
|
+
<Toolbar.Group type="single" class="cv-group" bind:value={() => color, pickColor}>
|
|
222
|
+
{#each PEN_COLORS as swatch (swatch)}
|
|
223
|
+
<BarTooltip label={labels.colors[swatch]}>
|
|
224
|
+
{#snippet child({ props })}
|
|
225
|
+
<Toolbar.GroupItem
|
|
226
|
+
{...props}
|
|
227
|
+
value={swatch}
|
|
228
|
+
class="cv-swatch"
|
|
229
|
+
style="--swatch: var(--pen-{swatch})"
|
|
230
|
+
/>
|
|
231
|
+
{/snippet}
|
|
232
|
+
</BarTooltip>
|
|
233
|
+
{/each}
|
|
234
|
+
</Toolbar.Group>
|
|
235
|
+
{/if}
|
|
236
|
+
|
|
237
|
+
{#if hasBrush(tool)}
|
|
238
|
+
<span class="cv-gap" aria-hidden="true"></span>
|
|
239
|
+
<Toolbar.Group
|
|
240
|
+
type="single"
|
|
241
|
+
class="cv-group"
|
|
242
|
+
bind:value={() => String(level), pickLevel}
|
|
243
|
+
>
|
|
244
|
+
{#each BRUSH_DOT as dot, index (index)}
|
|
245
|
+
<BarTooltip label={labels.sizes[index]}>
|
|
246
|
+
{#snippet child({ props })}
|
|
247
|
+
<Toolbar.GroupItem {...props} value={String(index)} class="cv-btn">
|
|
248
|
+
<span class="cv-dot" style:--dot="{dot}px"></span>
|
|
249
|
+
</Toolbar.GroupItem>
|
|
250
|
+
{/snippet}
|
|
251
|
+
</BarTooltip>
|
|
252
|
+
{/each}
|
|
253
|
+
</Toolbar.Group>
|
|
254
|
+
{/if}
|
|
255
|
+
</Toolbar.Root>
|
|
256
|
+
{/key}
|
|
257
|
+
</div>
|
|
258
|
+
{/if}
|
|
259
|
+
</div>
|
|
260
|
+
</Tooltip.Provider>
|
|
257
261
|
</Panel>
|
|
262
|
+
|
|
263
|
+
{#snippet railItem(value: string, label: string, shortcut: string, icon: CanvasTool)}
|
|
264
|
+
<BarTooltip {label} {shortcut} side="right">
|
|
265
|
+
{#snippet child({ props })}
|
|
266
|
+
<Toolbar.GroupItem {...props} {value} class="cv-btn">
|
|
267
|
+
<ToolIcon name={icon} />
|
|
268
|
+
</Toolbar.GroupItem>
|
|
269
|
+
{/snippet}
|
|
270
|
+
</BarTooltip>
|
|
271
|
+
{/snippet}
|