@heyramzi/ui 2.1.0 → 2.2.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/package.json +7 -8
- package/scripts/sync-shadcn.mjs +3 -4
- package/src/agents/agent-avatar.svelte +604 -575
- package/src/agents/agent-cast.svelte +179 -183
- package/src/agents/demo.svelte +125 -113
- package/src/agents/helpers.ts +23 -17
- package/src/agents/index.ts +4 -4
- package/src/agents/page-state.ts +6 -6
- package/src/agents/types.ts +6 -6
- package/src/ai/ai-button/AiButton.svelte +4 -12
- package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
- package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
- package/src/ai/response/Response.css +2 -3
- package/src/animations/avatar-group-hover.css +2 -16
- package/src/animations/card-tilt.css +3 -6
- package/src/animations/digit-pop-in.css +2 -15
- package/src/animations/dropdown.css +4 -17
- package/src/animations/input-clear-dissolve.css +5 -18
- package/src/animations/input-shake.css +9 -41
- package/src/animations/learn-more-hover.css +17 -9
- package/src/animations/like-button.css +2 -4
- package/src/animations/page-side-by-side.css +2 -10
- package/src/animations/plus-menu-morph.css +2 -5
- package/src/animations/shimmer-text.css +5 -18
- package/src/animations/spinning-counter.css +2 -6
- package/src/animations/success-check.css +2 -15
- package/src/animations/thinking-states.css +2 -7
- package/src/brand/brand.test.ts +21 -5
- package/src/brand/index.ts +4 -10
- package/src/canvas/card/card-frame.svelte +43 -39
- package/src/canvas/card/resize-handles.svelte +89 -80
- package/src/canvas/chrome/chrome-zoom.svelte +101 -100
- package/src/canvas/chrome/lock-badge.svelte +8 -8
- package/src/canvas/chrome/side-handles.svelte +24 -19
- package/src/canvas/chrome/size-chip.svelte +30 -30
- package/src/canvas/chrome/snap-guides.svelte +20 -20
- package/src/canvas/components/icons/ToolIcon.svelte +8 -8
- package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
- package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
- package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
- package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
- package/src/canvas/edges/bend-handle.svelte +46 -46
- package/src/canvas/edges/edge-gradient.svelte +10 -10
- package/src/canvas/edges/gradient-edge.svelte +45 -29
- package/src/canvas/editor/lock.test.ts +6 -1
- package/src/canvas/editor/style.ts +7 -1
- package/src/canvas/headless/svg-figure.test.ts +5 -1
- package/src/canvas/lod/lod-switch.svelte +111 -106
- package/src/canvas/pen/PenField.svelte +87 -81
- package/src/canvas/pen/PenOverlay.svelte +127 -127
- package/src/canvas/pen/ShapeNode.svelte +31 -32
- package/src/canvas/pen/TextNode.svelte +54 -53
- package/src/canvas/pen/host-field.test.svelte +7 -7
- package/src/canvas/pen/shapes.ts +7 -1
- package/src/canvas/screen/GlyphIcon.svelte +22 -17
- package/src/canvas/screen/PartView.svelte +138 -72
- package/src/canvas/screen/ScreenBody.svelte +81 -60
- package/src/canvas/screen/ScreenCard.svelte +20 -20
- package/src/canvas/ui/CanvasToolbar.svelte +173 -85
- package/src/canvas/ui/FrameLayer.svelte +59 -59
- package/src/canvas/ui/PenLayer.svelte +39 -30
- package/src/canvas/ui/StylePanel.svelte +119 -102
- package/src/canvas/ui/canvas-grid.svelte +137 -129
- package/src/charts/animated-value.svelte +1 -1
- package/src/charts/area-chart.css +2 -5
- package/src/charts/area-chart.svelte +1 -1
- package/src/charts/bar-chart.css +2 -3
- package/src/charts/bar-chart.svelte +1 -1
- package/src/charts/charts.css +5 -17
- package/src/charts/crosshair.svelte +1 -1
- package/src/charts/dashboard/dashboard-empty.svelte +25 -25
- package/src/charts/dashboard/dashboard-section.svelte +24 -24
- package/src/charts/dashboard/data-panel.svelte +50 -50
- package/src/charts/dashboard/data-sort-head.svelte +56 -56
- package/src/charts/dashboard/data-table.svelte +138 -138
- package/src/charts/dashboard/panel-grid.svelte +30 -30
- package/src/charts/dashboard/period-filter.svelte +25 -25
- package/src/charts/dashboard/rating-chip.svelte +19 -19
- package/src/charts/dashboard/stat-band.svelte +32 -32
- package/src/charts/dashboard/stat-tile.svelte +106 -99
- package/src/charts/donut-chart.svelte +1 -1
- package/src/charts/edge-fade.svelte +1 -1
- package/src/charts/figure.svelte +1 -1
- package/src/charts/gauge-chart.css +4 -7
- package/src/charts/gauge-chart.svelte +1 -1
- package/src/charts/hover-focus.svelte +1 -1
- package/src/charts/legend.css +1 -3
- package/src/charts/legend.svelte +1 -1
- package/src/charts/line-chart.svelte +1 -1
- package/src/charts/number-chart.css +6 -9
- package/src/charts/number-chart.svelte +1 -1
- package/src/charts/reference-line.svelte +19 -19
- package/src/charts/reveal.svelte +1 -1
- package/src/charts/ring-chart.css +2 -4
- package/src/charts/ring-chart.svelte +1 -1
- package/src/charts/sparkline.svelte +5 -2
- package/src/charts/stat-card.svelte +1 -1
- package/src/charts/time-series-chart.css +2 -5
- package/src/charts/trend-pill.css +2 -4
- package/src/charts/trend-pill.svelte +1 -1
- package/src/components/copy/copy-button.svelte +93 -98
- package/src/components/copy/copy-button.test.ts +10 -2
- package/src/components/data-table/infinite-scroll.svelte +42 -42
- package/src/components/data-table/pagination.svelte +34 -22
- package/src/components/data-table/row-arrow.svelte +19 -16
- package/src/components/data-table/row-context-menu.svelte +52 -52
- package/src/components/data-table/sortable-head.svelte +25 -25
- package/src/components/data-table/table-skeleton.svelte +41 -36
- package/src/components/docs/doc-page.svelte +18 -9
- package/src/components/docs/on-this-page.svelte +16 -3
- package/src/components/docs/scroll-spy.svelte.ts +2 -3
- package/src/components/field-row/field-row.svelte +10 -8
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
- package/src/components/icon/icon.svelte +14 -14
- package/src/components/language-flag/language-flag.svelte +3 -1
- package/src/components/list-page/detail-empty.svelte +34 -34
- package/src/components/list-page/detail-header.svelte +55 -47
- package/src/components/list-page/detail-panel.svelte +51 -59
- package/src/components/list-page/detail-row.svelte +19 -19
- package/src/components/list-page/detail-stack.svelte +21 -21
- package/src/components/list-page/empty-state.svelte +30 -30
- package/src/components/list-page/filter-item.svelte +20 -20
- package/src/components/list-page/filter-popover.svelte +60 -55
- package/src/components/list-page/grouped-list.svelte +4 -2
- package/src/components/list-page/index.ts +5 -1
- package/src/components/list-page/list-page-shell.svelte +2 -5
- package/src/components/list-page/master-detail.svelte +87 -88
- package/src/components/list-page/notice-bar.svelte +38 -38
- package/src/components/list-page/prev-next.svelte +63 -63
- package/src/components/list-page/rail-body.svelte +18 -18
- package/src/components/list-page/rail-empty.svelte +23 -30
- package/src/components/list-page/rail-head.svelte +24 -24
- package/src/components/list-page/rail-row.svelte +77 -73
- package/src/components/list-page/section-host.ts +2 -3
- package/src/components/locale-switch/locale-switch.svelte +41 -41
- package/src/components/mark/mark.svelte +34 -38
- package/src/components/open-in/index.ts +1 -5
- package/src/components/open-in/open-in.svelte +40 -40
- package/src/components/picker/mark-picker.svelte +49 -49
- package/src/components/picker/picker.svelte +5 -3
- package/src/components/section-header/section-header.test.ts +7 -1
- package/src/components/section-header/section-label.svelte +20 -20
- package/src/components/segmented/animated-tabs.svelte +31 -2
- package/src/components/segmented/collapse.test.ts +2 -1
- package/src/components/segmented/index.ts +2 -0
- package/src/components/segmented/segment.svelte +52 -49
- package/src/components/segmented/segmented-filter.svelte +79 -80
- package/src/components/segmented/segmented-nav.svelte +34 -40
- package/src/components/segmented/segmented-overflow.svelte +53 -50
- package/src/components/segmented/segmented-track.svelte +62 -46
- package/src/components/segmented/segmented.ts +2 -3
- package/src/components/star-rating-input/star-rating-input.svelte +103 -103
- package/src/components/svg/svg.svelte +4 -4
- package/src/components/table-view/table-view.svelte +17 -2
- package/src/components/table-view/table-view.test.ts +7 -1
- package/src/components/table-view/types.ts +11 -11
- package/src/components/tags-input/index.ts +13 -0
- package/src/components/tags-input/tags-input.svelte +305 -0
- package/src/components/tags-input/tags.test.ts +64 -0
- package/src/components/tags-input/tags.ts +142 -0
- package/src/components/theme/index.ts +2 -4
- package/src/components/theme/theme-provider.svelte +1 -3
- package/src/components/toolbar/toolbar-search.svelte +25 -25
- package/src/components/toolbar/toolbar.svelte +11 -7
- package/src/components/toolbar/toolbar.test.ts +10 -1
- package/src/design/index.css +21 -78
- package/src/design/polish.css +26 -35
- package/src/editor/editor-toolbar.svelte +104 -99
- package/src/editor/editor.svelte +296 -266
- package/src/editor/image-toolbar.svelte +20 -22
- package/src/editor/index.ts +1 -4
- package/src/editor/inline-editor.svelte +280 -238
- package/src/editor/markdown.ts +15 -15
- package/src/editor/renderer.svelte +71 -71
- package/src/editor/slash-menu.svelte +24 -27
- package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
- package/src/effects/image-comparison/ImageComparison.svelte +11 -1
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
- package/src/effects/magic-card/MagicCard.css +14 -7
- package/src/effects/marquee/Marquee.svelte +3 -5
- package/src/effects/reveal/observe.ts +0 -3
- package/src/effects/spotlight/Spotlight.svelte +1 -1
- package/src/effects/theme-toggle/ThemeToggle.css +25 -22
- package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
- package/src/gallery.test.ts +14 -4
- package/src/inbox/README.md +1 -3
- package/src/inbox/inbox.test.ts +181 -138
- package/src/inbox/index.ts +20 -20
- package/src/inbox/logic.ts +114 -111
- package/src/inbox/thread-inbox.svelte +227 -151
- package/src/inbox/types.ts +130 -108
- package/src/lib/theme-transition.ts +2 -4
- package/src/lib/tone.ts +2 -4
- package/src/lib/utils.ts +2 -2
- package/src/modules.test.ts +79 -69
- package/src/onboarding/define-tours.test.ts +55 -40
- package/src/onboarding/define-tours.ts +23 -23
- package/src/onboarding/demo.svelte +24 -5
- package/src/onboarding/index.ts +1 -8
- package/src/onboarding/onboarding-provider.svelte +19 -7
- package/src/onboarding/onboarding.svelte.ts +16 -16
- package/src/onboarding/pick.test.ts +61 -52
- package/src/onboarding/pick.ts +16 -13
- package/src/onboarding/stores.test.ts +80 -80
- package/src/onboarding/stores.ts +41 -39
- package/src/onboarding/tour-card.svelte +30 -5
- package/src/onboarding/tour-runner.svelte +12 -3
- package/src/onboarding/types.ts +20 -12
- package/src/onboarding/wait.ts +22 -22
- package/src/panel/side-panel.svelte +94 -93
- package/src/record/demo-data.ts +291 -225
- package/src/record/field-section.svelte +38 -34
- package/src/record/fields.ts +148 -96
- package/src/record/format.ts +63 -56
- package/src/record/index.ts +49 -35
- package/src/record/info-list.svelte +145 -114
- package/src/record/kinds.ts +31 -31
- package/src/record/logic.ts +216 -214
- package/src/record/next-up.svelte +45 -34
- package/src/record/project-list.svelte +56 -50
- package/src/record/record-demo.svelte +130 -110
- package/src/record/record-header.svelte +37 -28
- package/src/record/record-shell.svelte +54 -54
- package/src/record/record-stats.svelte +25 -25
- package/src/record/record-timeline.svelte +134 -114
- package/src/record/record.test.ts +430 -309
- package/src/record/steps-rail.svelte +225 -216
- package/src/record/types.ts +234 -215
- package/src/record/where-we-are.svelte +62 -58
- package/src/shadcn/button/button.svelte +1 -1
- package/src/shadcn/card/card-title.svelte +1 -5
- package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
- package/src/shadcn/sheet/sheet-content.svelte +2 -4
- package/src/shadcn/table/table-cell.svelte +2 -3
- package/src/shadcn/utilities.css +3 -8
- package/src/slides/Controls.svelte +150 -124
- package/src/slides/Deck.svelte +243 -238
- package/src/slides/Fragment.svelte +64 -57
- package/src/slides/Overview.svelte +106 -101
- package/src/slides/Presenter.svelte +300 -266
- package/src/slides/Slide.svelte +185 -170
- package/src/slides/SlideList.svelte +16 -12
- package/src/slides/ambient.d.ts +1 -1
- package/src/slides/bridges.ts +42 -23
- package/src/slides/deck-controller.svelte.ts +47 -35
- package/src/slides/demo-slides.svelte +330 -306
- package/src/slides/demo.svelte +164 -160
- package/src/slides/export/capture.ts +20 -16
- package/src/slides/export/ffmpeg.ts +43 -38
- package/src/slides/export/index.ts +5 -5
- package/src/slides/export/launch.ts +3 -1
- package/src/slides/export/pdf.ts +30 -27
- package/src/slides/export/types.ts +10 -8
- package/src/slides/index.ts +11 -11
- package/src/slides/labels.ts +22 -19
- package/src/slides/layout.ts +9 -2
- package/src/slides/model.ts +4 -4
- package/src/slides/navigation.ts +43 -31
- package/src/slides/theme.css +5 -7
- package/src/slides/types.ts +9 -10
- package/src/status/define-statuses.ts +17 -24
- package/src/status/index.ts +5 -5
- package/src/status/status-badge.svelte +3 -1
- package/src/status/status-dot.svelte +1 -3
- package/src/status/status-icon.svelte +1 -1
- package/src/status/status-types.ts +21 -21
- package/src/tasks/board-order.ts +2 -4
- package/src/tasks/demo.svelte +189 -31
- package/src/tasks/detail/detail-demo.svelte +73 -13
- package/src/tasks/detail/detail-types.ts +45 -45
- package/src/tasks/detail/task-detail.svelte +40 -10
- package/src/tasks/detail/task-property.svelte +8 -2
- package/src/tasks/detail/task-thread.svelte +53 -12
- package/src/tasks/gantt/gantt-bar.svelte +17 -6
- package/src/tasks/gantt/gantt-grid.svelte +40 -9
- package/src/tasks/gantt/gantt-group-row.svelte +8 -2
- package/src/tasks/gantt/gantt-header.svelte +9 -3
- package/src/tasks/gantt/gantt-task-row.svelte +26 -6
- package/src/tasks/gantt/gantt.css +2 -1
- package/src/tasks/gantt/gantt.test.ts +3 -1
- package/src/tasks/gantt/logic.test.ts +110 -20
- package/src/tasks/gantt/logic.ts +42 -6
- package/src/tasks/inbox/inbox-card.svelte +13 -5
- package/src/tasks/inbox/inbox-draft.svelte +1 -1
- package/src/tasks/inbox/inbox-logic.ts +6 -40
- package/src/tasks/inbox/inbox-statuses.ts +23 -23
- package/src/tasks/inbox/inbox-trace.svelte +9 -3
- package/src/tasks/inbox/inbox-types.ts +54 -58
- package/src/tasks/inbox/index.ts +22 -21
- package/src/tasks/index.ts +49 -52
- package/src/tasks/kanban-board.svelte +16 -12
- package/src/tasks/kanban-types.ts +2 -3
- package/src/tasks/presets/sales.ts +6 -6
- package/src/tasks/task-gantt.svelte +28 -8
- package/src/tasks/task-list.svelte +41 -17
- package/src/tasks/time/duration.ts +40 -40
- package/src/tasks/time/time-chip.svelte +9 -2
- package/src/tasks/time/time-dot.svelte +1 -1
- package/src/tasks/time/time-ring.svelte +11 -3
- package/src/tasks/time/time-tracker.svelte +57 -15
- package/src/tasks/time/time-types.ts +57 -57
- package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
- package/src/thread/index.ts +7 -7
- package/src/thread/logic.ts +36 -33
- package/src/thread/thread.svelte +82 -16
- package/src/thread/thread.test.ts +58 -47
- package/src/thread/types.ts +68 -68
- package/src/tokens/craft.css +17 -53
- package/src/tokens/index.css +3 -13
- package/src/tokens/palette.css +13 -11
- package/src/tokens/primitives.css +10 -23
- package/src/tasks/inbox/inbox.svelte +0 -203
|
@@ -1,43 +1,59 @@
|
|
|
1
1
|
<svelte:options namespace="svg" />
|
|
2
2
|
|
|
3
3
|
<script lang="ts">
|
|
4
|
-
// =========================
|
|
5
|
-
// IMPORTS
|
|
6
|
-
// =========================
|
|
7
|
-
import { BaseEdge } from "@xyflow/svelte";
|
|
8
|
-
import EdgeGradient from "./edge-gradient.svelte";
|
|
4
|
+
// =========================
|
|
5
|
+
// IMPORTS
|
|
6
|
+
// =========================
|
|
7
|
+
import { BaseEdge } from "@xyflow/svelte";
|
|
8
|
+
import EdgeGradient from "./edge-gradient.svelte";
|
|
9
9
|
|
|
10
|
-
// =========================
|
|
11
|
-
// TYPES
|
|
12
|
-
// =========================
|
|
13
|
-
interface Props {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
10
|
+
// =========================
|
|
11
|
+
// TYPES
|
|
12
|
+
// =========================
|
|
13
|
+
interface Props {
|
|
14
|
+
id: string;
|
|
15
|
+
path: string;
|
|
16
|
+
from: { x: number; y: number };
|
|
17
|
+
to: { x: number; y: number };
|
|
18
|
+
fromColor: string;
|
|
19
|
+
toColor?: string;
|
|
20
|
+
markerEnd?: string;
|
|
21
|
+
/** The edge's own style. A stroke set here beats the gradient. */
|
|
22
|
+
style?: string;
|
|
23
|
+
class?: string;
|
|
24
|
+
}
|
|
25
25
|
|
|
26
|
-
// =========================
|
|
27
|
-
// PROPS
|
|
28
|
-
// =========================
|
|
29
|
-
let {
|
|
26
|
+
// =========================
|
|
27
|
+
// PROPS
|
|
28
|
+
// =========================
|
|
29
|
+
let {
|
|
30
|
+
id,
|
|
31
|
+
path,
|
|
32
|
+
from,
|
|
33
|
+
to,
|
|
34
|
+
fromColor,
|
|
35
|
+
toColor = fromColor,
|
|
36
|
+
markerEnd,
|
|
37
|
+
style = "",
|
|
38
|
+
class: className = "",
|
|
39
|
+
}: Props = $props();
|
|
30
40
|
|
|
31
|
-
// =========================
|
|
32
|
-
// DERIVED
|
|
33
|
-
// =========================
|
|
34
|
-
let gradientId = $derived(`canvas-gradient-${id.replace(/[^\w-]/g, "_")}`);
|
|
41
|
+
// =========================
|
|
42
|
+
// DERIVED
|
|
43
|
+
// =========================
|
|
44
|
+
let gradientId = $derived(`canvas-gradient-${id.replace(/[^\w-]/g, "_")}`);
|
|
35
45
|
</script>
|
|
36
46
|
|
|
37
47
|
<!-- =========================== -->
|
|
38
48
|
<!-- MARKUP -->
|
|
39
49
|
<!-- =========================== -->
|
|
40
50
|
<EdgeGradient id={gradientId} {from} {to} {fromColor} {toColor} />
|
|
41
|
-
<BaseEdge
|
|
51
|
+
<BaseEdge
|
|
52
|
+
{id}
|
|
53
|
+
{path}
|
|
54
|
+
{markerEnd}
|
|
55
|
+
class="canvas-edge {className}"
|
|
56
|
+
style="stroke: url(#{gradientId}); {style}"
|
|
57
|
+
/>
|
|
42
58
|
<!-- Hidden until a test run crosses this link; the canvas stylesheet draws the moving dashes. -->
|
|
43
59
|
<path d={path} class="canvas-edge-flow" fill="none" aria-hidden="true" />
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { describe, expect, it } from "vite-plus/test";
|
|
2
2
|
import type { Node } from "@xyflow/svelte";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
deletableIds,
|
|
5
|
+
refuseLockedOps,
|
|
6
|
+
toggleLock,
|
|
7
|
+
withLockFlags,
|
|
8
|
+
} from "./lock.js";
|
|
4
9
|
|
|
5
10
|
function card(id: string, data: Record<string, unknown> = {}, extra: Partial<Node> = {}): Node {
|
|
6
11
|
return { id, type: "note", position: { x: 0, y: 0 }, data, ...extra };
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
// A change is one patchNode per card, so it is one undo step.
|
|
3
3
|
|
|
4
4
|
import type { CanvasOp } from "../ops/ops.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
PEN_COLORS,
|
|
7
|
+
SHAPE_NODE,
|
|
8
|
+
STROKE_NODE,
|
|
9
|
+
TEXT_NODE,
|
|
10
|
+
type PenColor,
|
|
11
|
+
} from "../pen/types.js";
|
|
6
12
|
|
|
7
13
|
export type FillValue = PenColor | "none";
|
|
8
14
|
export type FontWeight = "regular" | "bold";
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { describe, expect, it } from "vite-plus/test";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
figureBoxHeight,
|
|
4
|
+
figureRatio,
|
|
5
|
+
sanitizeFigureSvg,
|
|
6
|
+
} from "./svg-figure.js";
|
|
3
7
|
|
|
4
8
|
describe("sanitizeFigureSvg", () => {
|
|
5
9
|
it("keeps the shapes, the text and the geometry", () => {
|
|
@@ -1,81 +1,82 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import type { Snippet } from "svelte";
|
|
6
|
-
import { useStore } from "@xyflow/svelte";
|
|
7
|
-
import SideHandles from "../chrome/side-handles.svelte";
|
|
8
|
-
import { lodMode } from "./lod-mode.svelte.js";
|
|
9
|
-
import { renderAll } from "./render-all.svelte.js";
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
import { useStore } from "@xyflow/svelte";
|
|
7
|
+
import SideHandles from "../chrome/side-handles.svelte";
|
|
8
|
+
import { lodMode } from "./lod-mode.svelte.js";
|
|
9
|
+
import { renderAll } from "./render-all.svelte.js";
|
|
10
10
|
|
|
11
|
-
// Zoomed out, a card is a box at its measured size, so no arrow moves.
|
|
12
|
-
// Never measured, selected, dragged or exported: full.
|
|
11
|
+
// Zoomed out, a card is a box at its measured size, so no arrow moves.
|
|
12
|
+
// Never measured, selected, dragged or exported: full.
|
|
13
13
|
|
|
14
|
-
// =========================
|
|
15
|
-
// TYPES
|
|
16
|
-
// =========================
|
|
17
|
-
interface Props {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
14
|
+
// =========================
|
|
15
|
+
// TYPES
|
|
16
|
+
// =========================
|
|
17
|
+
interface Props {
|
|
18
|
+
id: string;
|
|
19
|
+
selected?: boolean;
|
|
20
|
+
dragging?: boolean;
|
|
21
|
+
/** A CSS colour: the card's own, for the box's border and icon well. */
|
|
22
|
+
tone: string;
|
|
23
|
+
title: string;
|
|
24
|
+
/** The full card. */
|
|
25
|
+
children: Snippet;
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
// =========================
|
|
29
|
-
// PROPS
|
|
30
|
-
// =========================
|
|
31
|
-
let { id, selected = false, dragging = false, tone, title, children }: Props = $props();
|
|
28
|
+
// =========================
|
|
29
|
+
// PROPS
|
|
30
|
+
// =========================
|
|
31
|
+
let { id, selected = false, dragging = false, tone, title, children }: Props = $props();
|
|
32
32
|
|
|
33
|
-
// =========================
|
|
34
|
-
// STATE
|
|
35
|
-
// =========================
|
|
36
|
-
const store = useStore();
|
|
37
|
-
const mode = lodMode(store);
|
|
38
|
-
let probe = $state<HTMLElement>();
|
|
39
|
-
// xyflow keeps the size of a card that scrolled away, so it comes back as a box.
|
|
40
|
-
let size = $state<{ width: number; height: number } | null>(measured());
|
|
41
|
-
// Plain on purpose: only the observer below reads it.
|
|
42
|
-
let boxed = false;
|
|
33
|
+
// =========================
|
|
34
|
+
// STATE
|
|
35
|
+
// =========================
|
|
36
|
+
const store = useStore();
|
|
37
|
+
const mode = lodMode(store);
|
|
38
|
+
let probe = $state<HTMLElement>();
|
|
39
|
+
// xyflow keeps the size of a card that scrolled away, so it comes back as a box.
|
|
40
|
+
let size = $state<{ width: number; height: number } | null>(measured());
|
|
41
|
+
// Plain on purpose: only the observer below reads it.
|
|
42
|
+
let boxed = false;
|
|
43
43
|
|
|
44
|
-
// =========================
|
|
45
|
-
// DERIVED
|
|
46
|
-
// =========================
|
|
47
|
-
let simple = $derived(mode.low && size !== null && !selected && !dragging && !renderAll.on);
|
|
44
|
+
// =========================
|
|
45
|
+
// DERIVED
|
|
46
|
+
// =========================
|
|
47
|
+
let simple = $derived(mode.low && size !== null && !selected && !dragging && !renderAll.on);
|
|
48
48
|
|
|
49
|
-
// =========================
|
|
50
|
-
// EFFECTS
|
|
51
|
-
// =========================
|
|
52
|
-
// Sizes the simple box from the full card. The observer's first call carries it, so a mount forces no layout.
|
|
53
|
-
$effect(() => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
// =========================
|
|
50
|
+
// EFFECTS
|
|
51
|
+
// =========================
|
|
52
|
+
// Sizes the simple box from the full card. The observer's first call carries it, so a mount forces no layout.
|
|
53
|
+
$effect(() => {
|
|
54
|
+
const node = probe?.closest<HTMLElement>(".svelte-flow__node");
|
|
55
|
+
if (!node) return;
|
|
56
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
57
|
+
if (boxed) return;
|
|
58
|
+
const box = entry.borderBoxSize[0];
|
|
59
|
+
const width = Math.round(box.inlineSize);
|
|
60
|
+
const height = Math.round(box.blockSize);
|
|
61
|
+
if (width && height && (width !== size?.width || height !== size?.height))
|
|
62
|
+
size = { width, height };
|
|
63
|
+
});
|
|
64
|
+
observer.observe(node);
|
|
65
|
+
return () => observer.disconnect();
|
|
62
66
|
});
|
|
63
|
-
observer.observe(node);
|
|
64
|
-
return () => observer.disconnect();
|
|
65
|
-
});
|
|
66
67
|
|
|
67
|
-
// Set after the render that swaps the box in, so the read above never sees the box's own size.
|
|
68
|
-
$effect(() => {
|
|
69
|
-
|
|
70
|
-
});
|
|
68
|
+
// Set after the render that swaps the box in, so the read above never sees the box's own size.
|
|
69
|
+
$effect(() => {
|
|
70
|
+
boxed = simple;
|
|
71
|
+
});
|
|
71
72
|
|
|
72
|
-
// =========================
|
|
73
|
-
// FUNCTIONS
|
|
74
|
-
// =========================
|
|
75
|
-
function measured(): { width: number; height: number } | null {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
73
|
+
// =========================
|
|
74
|
+
// FUNCTIONS
|
|
75
|
+
// =========================
|
|
76
|
+
function measured(): { width: number; height: number } | null {
|
|
77
|
+
const known = store.nodeLookup.get(id)?.measured;
|
|
78
|
+
return known?.width && known.height ? { width: known.width, height: known.height } : null;
|
|
79
|
+
}
|
|
79
80
|
</script>
|
|
80
81
|
|
|
81
82
|
<!-- =========================== -->
|
|
@@ -83,7 +84,11 @@ function measured(): { width: number; height: number } | null {
|
|
|
83
84
|
<!-- =========================== -->
|
|
84
85
|
<span class="cv-lod-probe" bind:this={probe} hidden></span>
|
|
85
86
|
{#if simple && size}
|
|
86
|
-
<div
|
|
87
|
+
<div
|
|
88
|
+
class="cv-lod-box"
|
|
89
|
+
style="width: {size.width}px; height: {size.height}px; --cv-lod-tone: {tone}"
|
|
90
|
+
data-lod="simple"
|
|
91
|
+
>
|
|
87
92
|
<span class="cv-lod-well"></span>
|
|
88
93
|
<span class="cv-lod-title">{title}</span>
|
|
89
94
|
</div>
|
|
@@ -96,45 +101,45 @@ function measured(): { width: number; height: number } | null {
|
|
|
96
101
|
<!-- STYLES -->
|
|
97
102
|
<!-- =========================== -->
|
|
98
103
|
<style>
|
|
99
|
-
:global([data-cv-every-card] .svelte-flow__node) {
|
|
100
|
-
|
|
101
|
-
}
|
|
104
|
+
:global([data-cv-every-card] .svelte-flow__node) {
|
|
105
|
+
animation: none;
|
|
106
|
+
}
|
|
102
107
|
|
|
103
|
-
/* A dot on a zoomed-out box is too small to link from; unpainted, it keeps its place for the links. */
|
|
104
|
-
:global(.cv-lod-handle) {
|
|
105
|
-
|
|
106
|
-
}
|
|
108
|
+
/* A dot on a zoomed-out box is too small to link from; unpainted, it keeps its place for the links. */
|
|
109
|
+
:global(.cv-lod-handle) {
|
|
110
|
+
visibility: hidden;
|
|
111
|
+
}
|
|
107
112
|
|
|
108
|
-
/* The architecture card's own frame and layout (architecture-node.svelte), so selecting a card doesn't change how it looks. */
|
|
109
|
-
.cv-lod-box {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
113
|
+
/* The architecture card's own frame and layout (architecture-node.svelte), so selecting a card doesn't change how it looks. */
|
|
114
|
+
.cv-lod-box {
|
|
115
|
+
position: relative;
|
|
116
|
+
box-sizing: border-box;
|
|
117
|
+
display: flex;
|
|
118
|
+
align-items: flex-start;
|
|
119
|
+
gap: 10px;
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
padding: var(--card-pad, 12px);
|
|
122
|
+
border: 1px solid color-mix(in oklab, var(--cv-lod-tone) 20%, transparent);
|
|
123
|
+
border-radius: var(--card-radius, 12px);
|
|
124
|
+
background: var(--card, var(--cv-chrome-surface, #fff));
|
|
125
|
+
color: var(--cv-ink, var(--foreground, #1a1a1f));
|
|
126
|
+
contain: strict;
|
|
127
|
+
}
|
|
123
128
|
|
|
124
|
-
/* The icon well, without the icon. */
|
|
125
|
-
.cv-lod-well {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
129
|
+
/* The icon well, without the icon. */
|
|
130
|
+
.cv-lod-well {
|
|
131
|
+
flex: none;
|
|
132
|
+
width: 32px;
|
|
133
|
+
height: 32px;
|
|
134
|
+
border-radius: 9999px;
|
|
135
|
+
background: color-mix(in oklab, var(--cv-lod-tone) 10%, transparent);
|
|
136
|
+
}
|
|
132
137
|
|
|
133
|
-
.cv-lod-title {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
138
|
+
.cv-lod-title {
|
|
139
|
+
overflow: hidden;
|
|
140
|
+
font-size: 14px;
|
|
141
|
+
font-weight: 500;
|
|
142
|
+
line-height: 1.25;
|
|
143
|
+
overflow-wrap: anywhere;
|
|
144
|
+
}
|
|
140
145
|
</style>
|
|
@@ -1,90 +1,95 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import { useTextField, type TextFieldHandle } from "../editor/text-field-context.js";
|
|
6
|
-
import { useHandDrawn } from "../editor/hand-context.js";
|
|
7
|
-
import "./pen.css";
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import { useTextField, type TextFieldHandle } from "../editor/text-field-context.js";
|
|
6
|
+
import { useHandDrawn } from "../editor/hand-context.js";
|
|
7
|
+
import "./pen.css";
|
|
8
8
|
|
|
9
|
-
// The words of a pen text or a shape label: the host's field when it gave one (formatted text,
|
|
10
|
-
// its own bar and undo), else a plain textarea.
|
|
9
|
+
// The words of a pen text or a shape label: the host's field when it gave one (formatted text,
|
|
10
|
+
// its own bar and undo), else a plain textarea.
|
|
11
11
|
|
|
12
|
-
// =========================
|
|
13
|
-
// TYPES
|
|
14
|
-
// =========================
|
|
15
|
-
interface Props {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
12
|
+
// =========================
|
|
13
|
+
// TYPES
|
|
14
|
+
// =========================
|
|
15
|
+
interface Props {
|
|
16
|
+
value: string;
|
|
17
|
+
/** Which pen element it sits in. Sets the size and the box it keeps. */
|
|
18
|
+
variant: "text" | "label";
|
|
19
|
+
onCommit: (next: string, live: boolean) => void;
|
|
20
|
+
ariaLabel: string;
|
|
21
|
+
/** Typing needs the canvas editor; without one the words are shown, not changed. */
|
|
22
|
+
readonly?: boolean;
|
|
23
|
+
selected?: boolean;
|
|
24
|
+
color?: string;
|
|
25
|
+
fontSize?: number;
|
|
26
|
+
fontWeight?: number;
|
|
27
|
+
center?: boolean;
|
|
28
|
+
column?: boolean;
|
|
29
|
+
/** Called when the field closes. */
|
|
30
|
+
onExit?: () => void;
|
|
31
|
+
}
|
|
32
32
|
|
|
33
|
-
// =========================
|
|
34
|
-
// PROPS
|
|
35
|
-
// =========================
|
|
36
|
-
let {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}: Props = $props();
|
|
33
|
+
// =========================
|
|
34
|
+
// PROPS
|
|
35
|
+
// =========================
|
|
36
|
+
let {
|
|
37
|
+
value,
|
|
38
|
+
variant,
|
|
39
|
+
onCommit,
|
|
40
|
+
ariaLabel,
|
|
41
|
+
readonly = false,
|
|
42
|
+
selected = false,
|
|
43
|
+
color,
|
|
44
|
+
fontSize,
|
|
45
|
+
fontWeight,
|
|
46
|
+
center = false,
|
|
47
|
+
column = false,
|
|
48
|
+
onExit,
|
|
49
|
+
}: Props = $props();
|
|
50
50
|
|
|
51
|
-
// =========================
|
|
52
|
-
// STATE
|
|
53
|
-
// =========================
|
|
54
|
-
const Field = useTextField();
|
|
55
|
-
const handDrawn = useHandDrawn();
|
|
56
|
-
let textarea = $state<HTMLTextAreaElement>();
|
|
57
|
-
let field = $state<TextFieldHandle>();
|
|
58
|
-
let editing = $state(false);
|
|
51
|
+
// =========================
|
|
52
|
+
// STATE
|
|
53
|
+
// =========================
|
|
54
|
+
const Field = useTextField();
|
|
55
|
+
const handDrawn = useHandDrawn();
|
|
56
|
+
let textarea = $state<HTMLTextAreaElement>();
|
|
57
|
+
let field = $state<TextFieldHandle>();
|
|
58
|
+
let editing = $state(false);
|
|
59
59
|
|
|
60
|
-
// =========================
|
|
61
|
-
// DERIVED
|
|
62
|
-
// =========================
|
|
63
|
-
let style = $derived(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
// =========================
|
|
61
|
+
// DERIVED
|
|
62
|
+
// =========================
|
|
63
|
+
let style = $derived(
|
|
64
|
+
[
|
|
65
|
+
color && `color: ${color}`,
|
|
66
|
+
fontSize && `font-size: ${fontSize}px`,
|
|
67
|
+
fontWeight && `font-weight: ${fontWeight}`,
|
|
68
|
+
center && "text-align: center",
|
|
69
|
+
]
|
|
70
|
+
.filter(Boolean)
|
|
71
|
+
.join("; "),
|
|
72
|
+
);
|
|
68
73
|
|
|
69
|
-
// =========================
|
|
70
|
-
// FUNCTIONS
|
|
71
|
-
// =========================
|
|
72
|
-
/** Open the field for typing. A host field opens where `point` landed, else at the end. */
|
|
73
|
-
export function edit(point?: { x: number; y: number }) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
74
|
+
// =========================
|
|
75
|
+
// FUNCTIONS
|
|
76
|
+
// =========================
|
|
77
|
+
/** Open the field for typing. A host field opens where `point` landed, else at the end. */
|
|
78
|
+
export function edit(point?: { x: number; y: number }) {
|
|
79
|
+
if (readonly) return;
|
|
80
|
+
if (field) return field.edit(point);
|
|
81
|
+
textarea?.focus();
|
|
82
|
+
}
|
|
78
83
|
|
|
79
|
-
function close() {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
84
|
+
function close() {
|
|
85
|
+
editing = false;
|
|
86
|
+
onExit?.();
|
|
87
|
+
}
|
|
83
88
|
|
|
84
|
-
// A text you aren't typing in drags like any card, so a first press must not focus it.
|
|
85
|
-
function press(event: MouseEvent) {
|
|
86
|
-
|
|
87
|
-
}
|
|
89
|
+
// A text you aren't typing in drags like any card, so a first press must not focus it.
|
|
90
|
+
function press(event: MouseEvent) {
|
|
91
|
+
if (variant === "text" && !editing) event.preventDefault();
|
|
92
|
+
}
|
|
88
93
|
</script>
|
|
89
94
|
|
|
90
95
|
<!-- =========================== -->
|
|
@@ -98,7 +103,9 @@ function press(event: MouseEvent) {
|
|
|
98
103
|
{ariaLabel}
|
|
99
104
|
{readonly}
|
|
100
105
|
{style}
|
|
101
|
-
class="pen-field is-{variant} is-rich {handDrawn() ? 'hand' : ''} {selected
|
|
106
|
+
class="pen-field is-{variant} is-rich {handDrawn() ? 'hand' : ''} {selected
|
|
107
|
+
? 'selected'
|
|
108
|
+
: ''} {column ? 'column' : ''}"
|
|
102
109
|
clickToEdit={variant === "label"}
|
|
103
110
|
onExit={close}
|
|
104
111
|
/>
|
|
@@ -123,6 +130,5 @@ function press(event: MouseEvent) {
|
|
|
123
130
|
// Typing must never reach the canvas shortcuts, where Delete would remove the node.
|
|
124
131
|
event.stopPropagation();
|
|
125
132
|
if (event.key === "Escape") event.currentTarget.blur();
|
|
126
|
-
}}
|
|
127
|
-
></textarea>
|
|
133
|
+
}}></textarea>
|
|
128
134
|
{/if}
|