@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,112 +1,123 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
-
import type { PenColor } from "../pen/types.js";
|
|
2
|
+
import type { PenColor } from "../pen/types.js";
|
|
3
3
|
|
|
4
|
-
export interface StyleLabels {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
4
|
+
export interface StyleLabels {
|
|
5
|
+
panel: string;
|
|
6
|
+
fill: string;
|
|
7
|
+
stroke: string;
|
|
8
|
+
/** The stroke row's name when the selection has no outline, only ink, like text. */
|
|
9
|
+
colour: string;
|
|
10
|
+
none: string;
|
|
11
|
+
width: string;
|
|
12
|
+
/** Thin, regular, thick. */
|
|
13
|
+
widths: readonly [string, string, string];
|
|
14
|
+
font: string;
|
|
15
|
+
regular: string;
|
|
16
|
+
bold: string;
|
|
17
|
+
colors: Record<PenColor, string>;
|
|
18
|
+
}
|
|
19
19
|
</script>
|
|
20
20
|
|
|
21
21
|
<script lang="ts">
|
|
22
|
-
// =========================
|
|
23
|
-
// IMPORTS
|
|
24
|
-
// =========================
|
|
25
|
-
import { Panel, useStore } from "@xyflow/svelte";
|
|
26
|
-
import type { CanvasOp } from "../ops/ops.js";
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} from "../editor/style.js";
|
|
36
|
-
import { PEN_COLORS } from "../pen/types.js";
|
|
37
|
-
import "../pen/pen.css";
|
|
38
|
-
import { placeBeside, type Box } from "./place-panel.js";
|
|
39
|
-
import "./canvas-ui.css";
|
|
22
|
+
// =========================
|
|
23
|
+
// IMPORTS
|
|
24
|
+
// =========================
|
|
25
|
+
import { Panel, useStore } from "@xyflow/svelte";
|
|
26
|
+
import type { CanvasOp } from "../ops/ops.js";
|
|
27
|
+
import {
|
|
28
|
+
FONT_SIZES,
|
|
29
|
+
styleOps,
|
|
30
|
+
summarizeStyle,
|
|
31
|
+
type FontWeight,
|
|
32
|
+
type StyleNode,
|
|
33
|
+
type StyleValues,
|
|
34
|
+
type WidthLevel,
|
|
35
|
+
} from "../editor/style.js";
|
|
36
|
+
import { PEN_COLORS } from "../pen/types.js";
|
|
37
|
+
import "../pen/pen.css";
|
|
38
|
+
import { placeBeside, type Box } from "./place-panel.js";
|
|
39
|
+
import "./canvas-ui.css";
|
|
40
40
|
|
|
41
|
-
// =========================
|
|
42
|
-
// TYPES
|
|
43
|
-
// =========================
|
|
44
|
-
interface Props {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
41
|
+
// =========================
|
|
42
|
+
// TYPES
|
|
43
|
+
// =========================
|
|
44
|
+
interface Props {
|
|
45
|
+
/** The selected cards. The panel hides when none of them takes a style. */
|
|
46
|
+
nodes: readonly StyleNode[];
|
|
47
|
+
/** The node type of a frame or group, whose fill and outline the panel sets. */
|
|
48
|
+
frameType?: string;
|
|
49
|
+
labels: StyleLabels;
|
|
50
|
+
/** One call per change, so each is one undo step. */
|
|
51
|
+
commit: (ops: CanvasOp[]) => void;
|
|
52
|
+
}
|
|
53
53
|
|
|
54
|
-
// =========================
|
|
55
|
-
// PROPS
|
|
56
|
-
// =========================
|
|
57
|
-
let { nodes, frameType = "group", labels, commit }: Props = $props();
|
|
54
|
+
// =========================
|
|
55
|
+
// PROPS
|
|
56
|
+
// =========================
|
|
57
|
+
let { nodes, frameType = "group", labels, commit }: Props = $props();
|
|
58
58
|
|
|
59
|
-
// =========================
|
|
60
|
-
// STATE
|
|
61
|
-
// =========================
|
|
62
|
-
const store = useStore();
|
|
63
|
-
let barWidth = $state(0);
|
|
64
|
-
let barHeight = $state(0);
|
|
59
|
+
// =========================
|
|
60
|
+
// STATE
|
|
61
|
+
// =========================
|
|
62
|
+
const store = useStore();
|
|
63
|
+
let barWidth = $state(0);
|
|
64
|
+
let barHeight = $state(0);
|
|
65
65
|
|
|
66
|
-
// =========================
|
|
67
|
-
// DERIVED
|
|
68
|
-
// =========================
|
|
69
|
-
const WEIGHTS: readonly FontWeight[] = ["regular", "bold"];
|
|
70
|
-
const LEVELS: readonly WidthLevel[] = [0, 1, 2];
|
|
66
|
+
// =========================
|
|
67
|
+
// DERIVED
|
|
68
|
+
// =========================
|
|
69
|
+
const WEIGHTS: readonly FontWeight[] = ["regular", "bold"];
|
|
70
|
+
const LEVELS: readonly WidthLevel[] = [0, 1, 2];
|
|
71
71
|
|
|
72
|
-
let summary = $derived(summarizeStyle(nodes, frameType));
|
|
73
|
-
let strokeLabel = $derived(
|
|
72
|
+
let summary = $derived(summarizeStyle(nodes, frameType));
|
|
73
|
+
let strokeLabel = $derived(
|
|
74
|
+
summary?.controls.has("fill") || summary?.controls.has("width") ? labels.stroke : labels.colour,
|
|
75
|
+
);
|
|
74
76
|
|
|
75
|
-
// The selection in screen pixels, read from the live viewport so the panel follows a pan, a zoom and a drag.
|
|
76
|
-
let selection = $derived.by<Box | null>(() => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
77
|
+
// The selection in screen pixels, read from the live viewport so the panel follows a pan, a zoom and a drag.
|
|
78
|
+
let selection = $derived.by<Box | null>(() => {
|
|
79
|
+
const { x, y, zoom } = store.viewport;
|
|
80
|
+
let box: Box | null = null;
|
|
81
|
+
for (const node of nodes) {
|
|
82
|
+
const internal = store.nodeLookup.get(node.id);
|
|
83
|
+
if (!internal) continue;
|
|
84
|
+
const at = internal.internals.positionAbsolute;
|
|
85
|
+
const width = internal.measured.width ?? internal.width ?? 0;
|
|
86
|
+
const height = internal.measured.height ?? internal.height ?? 0;
|
|
87
|
+
const left = at.x * zoom + x;
|
|
88
|
+
const top = at.y * zoom + y;
|
|
89
|
+
const right = left + width * zoom;
|
|
90
|
+
const bottom = top + height * zoom;
|
|
91
|
+
box = box
|
|
92
|
+
? {
|
|
93
|
+
left: Math.min(box.left, left),
|
|
94
|
+
top: Math.min(box.top, top),
|
|
95
|
+
right: Math.max(box.right, right),
|
|
96
|
+
bottom: Math.max(box.bottom, bottom),
|
|
97
|
+
}
|
|
98
|
+
: { left, top, right, bottom };
|
|
99
|
+
}
|
|
100
|
+
return box;
|
|
101
|
+
});
|
|
95
102
|
|
|
96
|
-
// Beside the selection on the side with room, never over its grips. Null leaves the panel docked at the right edge.
|
|
97
|
-
let placed = $derived(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
// Beside the selection on the side with room, never over its grips. Null leaves the panel docked at the right edge.
|
|
104
|
+
let placed = $derived(
|
|
105
|
+
selection && barWidth > 0
|
|
106
|
+
? placeBeside(
|
|
107
|
+
selection,
|
|
108
|
+
{ width: barWidth, height: barHeight },
|
|
109
|
+
{ width: store.width, height: store.height },
|
|
110
|
+
)
|
|
111
|
+
: null,
|
|
112
|
+
);
|
|
102
113
|
|
|
103
|
-
// =========================
|
|
104
|
-
// FUNCTIONS
|
|
105
|
-
// =========================
|
|
106
|
-
function change(next: Partial<StyleValues>) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
114
|
+
// =========================
|
|
115
|
+
// FUNCTIONS
|
|
116
|
+
// =========================
|
|
117
|
+
function change(next: Partial<StyleValues>) {
|
|
118
|
+
const ops = styleOps(nodes, next, frameType);
|
|
119
|
+
if (ops.length > 0) commit(ops);
|
|
120
|
+
}
|
|
110
121
|
</script>
|
|
111
122
|
|
|
112
123
|
<!-- =========================== -->
|
|
@@ -116,13 +127,19 @@ function change(next: Partial<StyleValues>) {
|
|
|
116
127
|
<Panel
|
|
117
128
|
position="center-right"
|
|
118
129
|
class="cv-dock cv-style-dock {placed ? 'is-placed' : ''}"
|
|
119
|
-
style={placed
|
|
130
|
+
style={placed
|
|
131
|
+
? `--cv-style-x:${Math.round(placed.x)}px;--cv-style-y:${Math.round(placed.y)}px`
|
|
132
|
+
: undefined}
|
|
120
133
|
data-side={placed?.side}
|
|
121
134
|
>
|
|
122
135
|
<div
|
|
123
136
|
bind:offsetWidth={barWidth}
|
|
124
137
|
bind:offsetHeight={barHeight}
|
|
125
|
-
class="cv-bar cv-side cv-style t-enter"
|
|
138
|
+
class="cv-bar cv-side cv-style t-enter"
|
|
139
|
+
role="toolbar"
|
|
140
|
+
aria-label={labels.panel}
|
|
141
|
+
data-testid="style-panel"
|
|
142
|
+
>
|
|
126
143
|
{#if summary.controls.has("fill")}
|
|
127
144
|
<div class="cv-section" role="group" aria-label={labels.fill} data-testid="style-fill">
|
|
128
145
|
<span class="cv-label" aria-hidden="true">{labels.fill}</span>
|
|
@@ -199,8 +216,8 @@ function change(next: Partial<StyleValues>) {
|
|
|
199
216
|
class="cv-btn cv-figure"
|
|
200
217
|
aria-pressed={summary.values.fontSize === size}
|
|
201
218
|
aria-label="{labels.font}: {size}"
|
|
202
|
-
onclick={() => change({ fontSize: size })}
|
|
203
|
-
>
|
|
219
|
+
onclick={() => change({ fontSize: size })}>{size}</button
|
|
220
|
+
>
|
|
204
221
|
{/each}
|
|
205
222
|
{#each WEIGHTS as weight (weight)}
|
|
206
223
|
<button
|
|
@@ -210,8 +227,8 @@ function change(next: Partial<StyleValues>) {
|
|
|
210
227
|
aria-pressed={summary.values.fontWeight === weight}
|
|
211
228
|
aria-label={weight === "bold" ? labels.bold : labels.regular}
|
|
212
229
|
data-tip={weight === "bold" ? labels.bold : labels.regular}
|
|
213
|
-
onclick={() => change({ fontWeight: weight })}
|
|
214
|
-
>
|
|
230
|
+
onclick={() => change({ fontWeight: weight })}>Aa</button
|
|
231
|
+
>
|
|
215
232
|
{/each}
|
|
216
233
|
</div>
|
|
217
234
|
</div>
|
|
@@ -1,148 +1,156 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// =========================
|
|
3
|
-
// IMPORTS
|
|
4
|
-
// =========================
|
|
5
|
-
import { useStore } from "@xyflow/svelte";
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import { useStore } from "@xyflow/svelte";
|
|
6
6
|
|
|
7
|
-
// =========================
|
|
8
|
-
// TYPES
|
|
9
|
-
// =========================
|
|
10
|
-
interface Props {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
7
|
+
// =========================
|
|
8
|
+
// TYPES
|
|
9
|
+
// =========================
|
|
10
|
+
interface Props {
|
|
11
|
+
/** Flow units between dots at the finest level, the same as the snap grid. */
|
|
12
|
+
gap?: number;
|
|
13
|
+
/** Dot diameter in flow units at the finest level, so it grows and shrinks with zoom. */
|
|
14
|
+
size?: number;
|
|
15
|
+
/** Any CSS colour; the theme's pattern colour when unset. */
|
|
16
|
+
color?: string;
|
|
17
|
+
}
|
|
18
18
|
|
|
19
|
-
// =========================
|
|
20
|
-
// CONSTANTS
|
|
21
|
-
// =========================
|
|
22
|
-
// Five levels, each twice as wide. A level fades out between these screen spacings,
|
|
23
|
-
// so a zoomed-out board keeps an even texture instead of a grey haze.
|
|
24
|
-
const LEVELS = 5;
|
|
25
|
-
const FADE_START = 6;
|
|
26
|
-
const FADE_END = 12;
|
|
27
|
-
// Screen-pixel bounds: a dot never vanishes zoomed out or turns into a blob zoomed in.
|
|
28
|
-
const MIN_RADIUS = 0.5;
|
|
29
|
-
const MAX_RADIUS = 2;
|
|
19
|
+
// =========================
|
|
20
|
+
// CONSTANTS
|
|
21
|
+
// =========================
|
|
22
|
+
// Five levels, each twice as wide. A level fades out between these screen spacings,
|
|
23
|
+
// so a zoomed-out board keeps an even texture instead of a grey haze.
|
|
24
|
+
const LEVELS = 5;
|
|
25
|
+
const FADE_START = 6;
|
|
26
|
+
const FADE_END = 12;
|
|
27
|
+
// Screen-pixel bounds: a dot never vanishes zoomed out or turns into a blob zoomed in.
|
|
28
|
+
const MIN_RADIUS = 0.5;
|
|
29
|
+
const MAX_RADIUS = 2;
|
|
30
30
|
|
|
31
|
-
// =========================
|
|
32
|
-
// PROPS
|
|
33
|
-
// =========================
|
|
34
|
-
let {
|
|
31
|
+
// =========================
|
|
32
|
+
// PROPS
|
|
33
|
+
// =========================
|
|
34
|
+
let {
|
|
35
|
+
gap = 20,
|
|
36
|
+
size = 2,
|
|
37
|
+
color = "var(--xy-background-pattern-color, var(--xy-background-pattern-color-default))",
|
|
38
|
+
}: Props = $props();
|
|
35
39
|
|
|
36
|
-
// =========================
|
|
37
|
-
// STATE
|
|
38
|
-
// =========================
|
|
39
|
-
const store = useStore();
|
|
40
|
-
let canvas = $state<HTMLCanvasElement | null>(null);
|
|
41
|
-
let width = $state(0);
|
|
42
|
-
let height = $state(0);
|
|
43
|
-
let ratio = $state(1);
|
|
44
|
-
let theme = $state(0);
|
|
40
|
+
// =========================
|
|
41
|
+
// STATE
|
|
42
|
+
// =========================
|
|
43
|
+
const store = useStore();
|
|
44
|
+
let canvas = $state<HTMLCanvasElement | null>(null);
|
|
45
|
+
let width = $state(0);
|
|
46
|
+
let height = $state(0);
|
|
47
|
+
let ratio = $state(1);
|
|
48
|
+
let theme = $state(0);
|
|
45
49
|
|
|
46
|
-
// =========================
|
|
47
|
-
// FUNCTIONS
|
|
48
|
-
// =========================
|
|
49
|
-
function smoothstep(from: number, to: number, value: number) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
50
|
+
// =========================
|
|
51
|
+
// FUNCTIONS
|
|
52
|
+
// =========================
|
|
53
|
+
function smoothstep(from: number, to: number, value: number) {
|
|
54
|
+
const t = Math.min(1, Math.max(0, (value - from) / (to - from)));
|
|
55
|
+
return t * t * (3 - 2 * t);
|
|
56
|
+
}
|
|
53
57
|
|
|
54
|
-
// Pan redraws every frame, so a tile is built once per size and colour.
|
|
55
|
-
// eslint-disable-next-line svelte/prefer-svelte-reactivity -- render cache written inside the draw effect, never rendered
|
|
56
|
-
const tiles = new Map<string, HTMLCanvasElement>();
|
|
58
|
+
// Pan redraws every frame, so a tile is built once per size and colour.
|
|
59
|
+
// eslint-disable-next-line svelte/prefer-svelte-reactivity -- render cache written inside the draw effect, never rendered
|
|
60
|
+
const tiles = new Map<string, HTMLCanvasElement>();
|
|
57
61
|
|
|
58
|
-
function dotTile(step: number, radius: number, fill: string) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
62
|
+
function dotTile(step: number, radius: number, fill: string) {
|
|
63
|
+
const key = `${step}:${radius.toFixed(2)}:${fill}`;
|
|
64
|
+
const hit = tiles.get(key);
|
|
65
|
+
if (hit) return hit;
|
|
66
|
+
if (tiles.size > 64) tiles.clear();
|
|
67
|
+
const tile = document.createElement("canvas");
|
|
68
|
+
tiles.set(key, tile);
|
|
69
|
+
tile.width = step;
|
|
70
|
+
tile.height = step;
|
|
71
|
+
const context = tile.getContext("2d");
|
|
72
|
+
if (!context) return tile;
|
|
73
|
+
context.fillStyle = fill;
|
|
74
|
+
context.beginPath();
|
|
75
|
+
context.arc(step / 2, step / 2, radius, 0, Math.PI * 2);
|
|
76
|
+
context.fill();
|
|
77
|
+
return tile;
|
|
78
|
+
}
|
|
75
79
|
|
|
76
|
-
// fallow-ignore-next-line complexity
|
|
77
|
-
function draw(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
// fallow-ignore-next-line complexity
|
|
81
|
+
function draw(
|
|
82
|
+
element: HTMLCanvasElement,
|
|
83
|
+
view: { x: number; y: number; zoom: number },
|
|
84
|
+
fill: string,
|
|
85
|
+
) {
|
|
86
|
+
const context = element.getContext("2d");
|
|
87
|
+
if (!context) return;
|
|
88
|
+
context.setTransform(1, 0, 0, 1, 0, 0);
|
|
89
|
+
context.clearRect(0, 0, element.width, element.height);
|
|
82
90
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
91
|
+
for (let level = 0; level < LEVELS; level++) {
|
|
92
|
+
const spacing = gap * 2 ** level * view.zoom;
|
|
93
|
+
// A coarser level draws bigger dots, so zooming out reads as moving away.
|
|
94
|
+
const screenRadius = (size / 2) * 2 ** level * view.zoom;
|
|
95
|
+
const radius = Math.min(MAX_RADIUS, Math.max(MIN_RADIUS, screenRadius)) * ratio;
|
|
96
|
+
const last = level === LEVELS - 1;
|
|
97
|
+
const alpha = last ? 1 : smoothstep(FADE_START, FADE_END, spacing);
|
|
98
|
+
if (alpha <= 0.01) continue;
|
|
99
|
+
const step = spacing * ratio;
|
|
100
|
+
const tileSize = Math.max(2, Math.round(step));
|
|
101
|
+
const scale = step / tileSize;
|
|
102
|
+
const pattern = context.createPattern(dotTile(tileSize, radius / scale, fill), "repeat");
|
|
103
|
+
if (!pattern) return;
|
|
104
|
+
pattern.setTransform(
|
|
105
|
+
new DOMMatrix([scale, 0, 0, scale, view.x * ratio - step / 2, view.y * ratio - step / 2]),
|
|
106
|
+
);
|
|
107
|
+
context.globalAlpha = alpha;
|
|
108
|
+
context.fillStyle = pattern;
|
|
109
|
+
context.fillRect(0, 0, element.width, element.height);
|
|
110
|
+
if (alpha >= 0.999) break;
|
|
111
|
+
}
|
|
112
|
+
context.globalAlpha = 1;
|
|
103
113
|
}
|
|
104
|
-
context.globalAlpha = 1;
|
|
105
|
-
}
|
|
106
114
|
|
|
107
|
-
// =========================
|
|
108
|
-
// EFFECTS
|
|
109
|
-
// =========================
|
|
110
|
-
$effect(() => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
// =========================
|
|
116
|
+
// EFFECTS
|
|
117
|
+
// =========================
|
|
118
|
+
$effect(() => {
|
|
119
|
+
if (!canvas) return;
|
|
120
|
+
const element = canvas;
|
|
121
|
+
const observer = new ResizeObserver(() => {
|
|
122
|
+
width = element.clientWidth;
|
|
123
|
+
height = element.clientHeight;
|
|
124
|
+
ratio = window.devicePixelRatio || 1;
|
|
125
|
+
});
|
|
126
|
+
observer.observe(element);
|
|
127
|
+
return () => observer.disconnect();
|
|
117
128
|
});
|
|
118
|
-
observer.observe(element);
|
|
119
|
-
return () => observer.disconnect();
|
|
120
|
-
});
|
|
121
129
|
|
|
122
|
-
// The dot colour is a theme token, so a theme switch redraws.
|
|
123
|
-
$effect(() => {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
});
|
|
130
|
+
// The dot colour is a theme token, so a theme switch redraws.
|
|
131
|
+
$effect(() => {
|
|
132
|
+
const root = document.documentElement;
|
|
133
|
+
const observer = new MutationObserver(() => (theme += 1));
|
|
134
|
+
observer.observe(root, { attributes: true, attributeFilter: ["class"] });
|
|
135
|
+
return () => observer.disconnect();
|
|
136
|
+
});
|
|
129
137
|
|
|
130
|
-
// Read once per theme: a computed style read mid-pan restyles the whole page every frame.
|
|
131
|
-
let fill = $derived.by(() => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
});
|
|
138
|
+
// Read once per theme: a computed style read mid-pan restyles the whole page every frame.
|
|
139
|
+
let fill = $derived.by(() => {
|
|
140
|
+
void theme;
|
|
141
|
+
void color;
|
|
142
|
+
return canvas ? getComputedStyle(canvas).color : "";
|
|
143
|
+
});
|
|
136
144
|
|
|
137
|
-
// fallow-ignore-next-line complexity
|
|
138
|
-
$effect(() => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
});
|
|
145
|
+
// fallow-ignore-next-line complexity
|
|
146
|
+
$effect(() => {
|
|
147
|
+
if (!canvas || !width || !height) return;
|
|
148
|
+
const pixelWidth = Math.round(width * ratio);
|
|
149
|
+
const pixelHeight = Math.round(height * ratio);
|
|
150
|
+
if (canvas.width !== pixelWidth) canvas.width = pixelWidth;
|
|
151
|
+
if (canvas.height !== pixelHeight) canvas.height = pixelHeight;
|
|
152
|
+
draw(canvas, store.viewport, fill);
|
|
153
|
+
});
|
|
146
154
|
</script>
|
|
147
155
|
|
|
148
156
|
<!-- =========================== -->
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
`?type=style&lang.css` virtual module that Tailwind v4's Vite plugin mis-parses
|
|
4
|
-
when this package is consumed as source from node_modules (tailwindlabs/
|
|
5
|
-
tailwindcss#20000). Selectors are namespaced under `.hr-area-chart`. */
|
|
1
|
+
/* A plain stylesheet, not a `<style>` block, because Tailwind v4's Vite plugin mis-parses that
|
|
2
|
+
virtual module when this package is consumed from node_modules (tailwindcss#20000). */
|
|
6
3
|
|
|
7
4
|
.hr-area-chart {
|
|
8
5
|
width: 100%;
|
package/src/charts/bar-chart.css
CHANGED
|
@@ -24,9 +24,8 @@
|
|
|
24
24
|
width: 100%;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/*
|
|
28
|
-
|
|
29
|
-
parent must be a flex column that gives this a determinate height. */
|
|
27
|
+
/* height="fill" grows the chart to its parent's height, so the parent must be a
|
|
28
|
+
flex column with a determinate height. */
|
|
30
29
|
.hr-bar-chart.hr-bar-fill {
|
|
31
30
|
flex: 1 1 auto;
|
|
32
31
|
min-height: 0;
|
package/src/charts/charts.css
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
themes for free.
|
|
5
|
-
|
|
6
|
-
WHY: layerchart's built-in `default` tooltip paints itself with
|
|
7
|
-
`light-dark(var(--color-surface-100, white), var(--color-surface-300, black))`
|
|
8
|
-
and a `backdrop-filter` blur. Apps that don't define `--color-surface-*` (and
|
|
9
|
-
don't set `color-scheme`) fall back to a translucent white card, which is
|
|
10
|
-
unreadable on a dark page. These rules repaint it with `--popover` /
|
|
11
|
-
`--border` / `--muted-foreground`, which already flip per theme. The selectors
|
|
12
|
-
stay unlayered so they beat layerchart's `@layer component` defaults
|
|
13
|
-
regardless of specificity. */
|
|
1
|
+
/* Layerchart's tooltip falls back to translucent white on a dark page without
|
|
2
|
+
`--color-surface-*`, so these unlayered rules repaint it with `--popover`,
|
|
3
|
+
beating its `@layer component` defaults. */
|
|
14
4
|
|
|
15
5
|
.lc-tooltip-container[data-variant="default"] {
|
|
16
6
|
color: var(--popover-foreground, var(--foreground));
|
|
@@ -109,10 +99,8 @@
|
|
|
109
99
|
--chart-card-shadow: 0 1px 2px 0 oklch(0 0 0 / 0.04), 0 1px 3px 0 oklch(0 0 0 / 0.06);
|
|
110
100
|
}
|
|
111
101
|
|
|
112
|
-
/*
|
|
113
|
-
|
|
114
|
-
here, scoped to the chart roots, so the look is defined once. `:where()` keeps
|
|
115
|
-
specificity at 0 so a component can still override locally if it must. */
|
|
102
|
+
/* Axis labels, grid rules and hover highlights for every chart, defined once.
|
|
103
|
+
`:where()` keeps specificity at 0 so a component can still override them. */
|
|
116
104
|
:where(
|
|
117
105
|
.hr-area-chart,
|
|
118
106
|
.hr-bar-chart,
|