@ceebee/ui 1.1.1 → 1.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/client.d.ts +21 -1
- package/dist/client.js +156 -6
- package/dist/styles.css +135 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -309,4 +309,24 @@ declare const StickerGroup: typeof StickerGroupRoot & {
|
|
|
309
309
|
Skeleton: typeof StickerGroupSkeleton;
|
|
310
310
|
};
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
interface PanZoomCanvasSkeletonProps {
|
|
313
|
+
label?: string;
|
|
314
|
+
}
|
|
315
|
+
declare function PanZoomCanvasSkeleton({ label }: PanZoomCanvasSkeletonProps): react.JSX.Element;
|
|
316
|
+
|
|
317
|
+
interface PanZoomCanvasProps {
|
|
318
|
+
label: string;
|
|
319
|
+
children: ReactNode;
|
|
320
|
+
hint?: string;
|
|
321
|
+
zoomInLabel?: string;
|
|
322
|
+
zoomOutLabel?: string;
|
|
323
|
+
resetLabel?: string;
|
|
324
|
+
zoomStatusLabel?: string;
|
|
325
|
+
motion?: boolean;
|
|
326
|
+
}
|
|
327
|
+
declare function PanZoomCanvasRoot({ label, children, hint, zoomInLabel, zoomOutLabel, resetLabel, zoomStatusLabel, motion: motionEnabled, }: PanZoomCanvasProps): react.JSX.Element;
|
|
328
|
+
declare const PanZoomCanvas: typeof PanZoomCanvasRoot & {
|
|
329
|
+
Skeleton: typeof PanZoomCanvasSkeleton;
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
export { Checklist, type ChecklistProps, type ChecklistTask, type Command, CommandPalette, type CommandPaletteProps, DEFAULT_LABELS, type DurationToken, type Labels, LabelsProvider, type LabelsProviderProps, type MotionHelpers, MotionProvider, type MotionProviderProps, type MotionSettings, type NavItem, type NavSection, type PaletteCommand, PanZoomCanvas, type PanZoomCanvasProps, type PanZoomCanvasSkeletonProps, type RankedCommand, Reveal, type RevealProps, Sidebar, type SidebarProps, type SpringPreset, Stagger, type StaggerProps, StickerGroup, type StickerGroupProps, type StickerGroupSkeletonProps, type StickerItem, ThemeBridge, type ThemeBridgeProps, type ThemeChoice, ThemeProvider, type ToastOptions, type ToastPosition, ToastProvider, type ToastProviderProps, TopBar, type TopBarProps, filterCommands, groupCommands, rankCommand, useLabels, useMotionSettings, useTheme, useToast };
|
package/dist/client.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { theme, ConfigProvider, Progress } from 'antd';
|
|
2
|
+
import { Button, theme, ConfigProvider, Progress } from 'antd';
|
|
3
3
|
export * from 'antd';
|
|
4
|
-
import { createContext, useContext, useMemo,
|
|
4
|
+
import { createContext, useState, useRef, useContext, useMemo, useCallback, useEffect, Children } from 'react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
export { default as enUSLocale } from 'antd/locale/en_US.js';
|
|
7
7
|
export { default as enUSDatePickerLocale } from 'antd/lib/date-picker/locale/en_US.js';
|
|
8
8
|
export { default as idIDLocale } from 'antd/locale/id_ID.js';
|
|
9
9
|
export { default as zhCNLocale } from 'antd/locale/zh_CN.js';
|
|
10
10
|
import { Dialog } from '@base-ui/react/dialog';
|
|
11
|
-
import { X, Search, Check, ChevronRight, PanelLeftOpen, PanelLeftClose, Info, XCircle, AlertTriangle, CheckCircle2 } from 'lucide-react';
|
|
11
|
+
import { X, Minus, Plus, RotateCcw, Search, Check, ChevronRight, PanelLeftOpen, PanelLeftClose, Info, XCircle, AlertTriangle, CheckCircle2 } from 'lucide-react';
|
|
12
12
|
import { Toast } from '@base-ui/react/toast';
|
|
13
13
|
import { Popover } from '@base-ui/react/popover';
|
|
14
14
|
import { AnimatePresence, motion } from 'motion/react';
|
|
@@ -80,6 +80,11 @@ function readCeebeeThemeToken(root) {
|
|
|
80
80
|
colorText: color("--cb-fg"),
|
|
81
81
|
colorTextSecondary: color("--cb-fg-muted"),
|
|
82
82
|
colorTextTertiary: color("--cb-fg-subtle"),
|
|
83
|
+
/* Ant derives its placeholder colour from its own algorithm rather than from any token this
|
|
84
|
+
bridge already sends, and lands on a 25%-alpha grey that fails WCAG AA text contrast in both
|
|
85
|
+
modes. Placeholder text is text, so it takes the subtle foreground like every other quiet
|
|
86
|
+
label. */
|
|
87
|
+
colorTextPlaceholder: color("--cb-fg-subtle"),
|
|
83
88
|
colorTextLightSolid: color("--cb-fg-on-brand"),
|
|
84
89
|
colorBgBase: color("--cb-bg"),
|
|
85
90
|
colorBgContainer: color("--cb-surface"),
|
|
@@ -572,14 +577,14 @@ var OFFSETS = {
|
|
|
572
577
|
function Reveal({
|
|
573
578
|
children,
|
|
574
579
|
from = "below",
|
|
575
|
-
distance = 12,
|
|
580
|
+
distance: distance2 = 12,
|
|
576
581
|
delay = 0,
|
|
577
582
|
spring = "soft",
|
|
578
583
|
onView = false,
|
|
579
584
|
className
|
|
580
585
|
}) {
|
|
581
586
|
const { enabled, spring: transition } = useMotionSettings();
|
|
582
|
-
const offset = enabled ? OFFSETS[from](
|
|
587
|
+
const offset = enabled ? OFFSETS[from](distance2) : {};
|
|
583
588
|
const hidden = { opacity: 0, ...offset };
|
|
584
589
|
const shown = { opacity: 1, x: 0, y: 0 };
|
|
585
590
|
return /* @__PURE__ */ jsx(
|
|
@@ -670,5 +675,150 @@ function StickerGroupRoot({
|
|
|
670
675
|
}) }) });
|
|
671
676
|
}
|
|
672
677
|
var StickerGroup = Object.assign(StickerGroupRoot, { Skeleton: StickerGroupSkeleton });
|
|
678
|
+
function PanZoomCanvasSkeleton({ label = "Loading canvas" }) {
|
|
679
|
+
return /* @__PURE__ */ jsxs("div", { className: "cb-pan-zoom-canvas cb-pan-zoom-canvas--skeleton", role: "status", "aria-label": label, children: [
|
|
680
|
+
/* @__PURE__ */ jsx("span", { className: "cb-pan-zoom-canvas__skeleton-controls", "aria-hidden": "true" }),
|
|
681
|
+
/* @__PURE__ */ jsx("span", { className: "cb-pan-zoom-canvas__skeleton-node cb-pan-zoom-canvas__skeleton-node--start", "aria-hidden": "true" }),
|
|
682
|
+
/* @__PURE__ */ jsx("span", { className: "cb-pan-zoom-canvas__skeleton-line", "aria-hidden": "true" }),
|
|
683
|
+
/* @__PURE__ */ jsx("span", { className: "cb-pan-zoom-canvas__skeleton-node cb-pan-zoom-canvas__skeleton-node--end", "aria-hidden": "true" })
|
|
684
|
+
] });
|
|
685
|
+
}
|
|
686
|
+
var MIN_SCALE = 0.5;
|
|
687
|
+
var MAX_SCALE = 2;
|
|
688
|
+
var SCALE_STEP = 0.25;
|
|
689
|
+
function clampScale(value) {
|
|
690
|
+
return Math.min(MAX_SCALE, Math.max(MIN_SCALE, value));
|
|
691
|
+
}
|
|
692
|
+
function distance([first, second]) {
|
|
693
|
+
return Math.hypot(second.x - first.x, second.y - first.y);
|
|
694
|
+
}
|
|
695
|
+
function PanZoomCanvasRoot({
|
|
696
|
+
label,
|
|
697
|
+
children,
|
|
698
|
+
hint,
|
|
699
|
+
zoomInLabel = "Zoom in",
|
|
700
|
+
zoomOutLabel = "Zoom out",
|
|
701
|
+
resetLabel = "Reset canvas",
|
|
702
|
+
zoomStatusLabel = "Canvas zoom",
|
|
703
|
+
motion: motionEnabled = true
|
|
704
|
+
}) {
|
|
705
|
+
const motionSettings = useMotionSettings();
|
|
706
|
+
const [pan, setPan] = useState({ x: 0, y: 0 });
|
|
707
|
+
const [scale, setScale] = useState(1);
|
|
708
|
+
const pointers = useRef(/* @__PURE__ */ new Map());
|
|
709
|
+
const dragOrigin = useRef(null);
|
|
710
|
+
const pinchOrigin = useRef(null);
|
|
711
|
+
const stepRef = useRef(null);
|
|
712
|
+
const shouldAnimate = motionEnabled && motionSettings.enabled;
|
|
713
|
+
function reset() {
|
|
714
|
+
setPan({ x: 0, y: 0 });
|
|
715
|
+
setScale(1);
|
|
716
|
+
}
|
|
717
|
+
function zoom(delta) {
|
|
718
|
+
setScale((current) => clampScale(current + delta));
|
|
719
|
+
}
|
|
720
|
+
function onKeyDown(event) {
|
|
721
|
+
const movement = {
|
|
722
|
+
ArrowLeft: { x: -1, y: 0 },
|
|
723
|
+
ArrowRight: { x: 1, y: 0 },
|
|
724
|
+
ArrowUp: { x: 0, y: -1 },
|
|
725
|
+
ArrowDown: { x: 0, y: 1 }
|
|
726
|
+
};
|
|
727
|
+
if (movement[event.key]) {
|
|
728
|
+
event.preventDefault();
|
|
729
|
+
setPan((current) => ({ x: current.x + movement[event.key].x, y: current.y + movement[event.key].y }));
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
if (event.key === "+" || event.key === "=") {
|
|
733
|
+
event.preventDefault();
|
|
734
|
+
zoom(SCALE_STEP);
|
|
735
|
+
}
|
|
736
|
+
if (event.key === "-") {
|
|
737
|
+
event.preventDefault();
|
|
738
|
+
zoom(-SCALE_STEP);
|
|
739
|
+
}
|
|
740
|
+
if (event.key === "0" || event.key === "Home") {
|
|
741
|
+
event.preventDefault();
|
|
742
|
+
reset();
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
function onPointerDown(event) {
|
|
746
|
+
if (event.target.closest("a, button, input, select, textarea")) return;
|
|
747
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
748
|
+
pointers.current.set(event.pointerId, { x: event.clientX, y: event.clientY });
|
|
749
|
+
const points = [...pointers.current.values()];
|
|
750
|
+
if (points.length === 1) dragOrigin.current = { point: points[0], pan };
|
|
751
|
+
if (points.length === 2) pinchOrigin.current = { distance: distance(points), scale };
|
|
752
|
+
}
|
|
753
|
+
function onPointerMove(event) {
|
|
754
|
+
if (!pointers.current.has(event.pointerId)) return;
|
|
755
|
+
pointers.current.set(event.pointerId, { x: event.clientX, y: event.clientY });
|
|
756
|
+
const points = [...pointers.current.values()];
|
|
757
|
+
if (points.length === 2 && pinchOrigin.current) {
|
|
758
|
+
const nextDistance = distance(points);
|
|
759
|
+
setScale(clampScale(pinchOrigin.current.scale * (nextDistance / pinchOrigin.current.distance)));
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
if (points.length === 1 && dragOrigin.current) {
|
|
763
|
+
const step = stepRef.current?.getBoundingClientRect().width || 1;
|
|
764
|
+
setPan({
|
|
765
|
+
x: dragOrigin.current.pan.x + (points[0].x - dragOrigin.current.point.x) / step,
|
|
766
|
+
y: dragOrigin.current.pan.y + (points[0].y - dragOrigin.current.point.y) / step
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
function releasePointer(event) {
|
|
771
|
+
pointers.current.delete(event.pointerId);
|
|
772
|
+
pinchOrigin.current = null;
|
|
773
|
+
const remaining = [...pointers.current.values()];
|
|
774
|
+
dragOrigin.current = remaining.length === 1 ? { point: remaining[0], pan } : null;
|
|
775
|
+
}
|
|
776
|
+
function onWheel(event) {
|
|
777
|
+
if (!event.ctrlKey && !event.metaKey) return;
|
|
778
|
+
event.preventDefault();
|
|
779
|
+
zoom(event.deltaY < 0 ? SCALE_STEP : -SCALE_STEP);
|
|
780
|
+
}
|
|
781
|
+
const transformStyle = {
|
|
782
|
+
"--cb-pan-zoom-x": pan.x,
|
|
783
|
+
"--cb-pan-zoom-y": pan.y,
|
|
784
|
+
"--cb-pan-zoom-scale": scale
|
|
785
|
+
};
|
|
786
|
+
return /* @__PURE__ */ jsxs("section", { className: "cb-pan-zoom-canvas", "data-motion": String(shouldAnimate), children: [
|
|
787
|
+
/* @__PURE__ */ jsxs("div", { className: "cb-pan-zoom-canvas__toolbar", children: [
|
|
788
|
+
hint ? /* @__PURE__ */ jsx("p", { className: "cb-pan-zoom-canvas__hint", children: hint }) : /* @__PURE__ */ jsx("span", {}),
|
|
789
|
+
/* @__PURE__ */ jsxs("div", { className: "cb-pan-zoom-canvas__controls", children: [
|
|
790
|
+
/* @__PURE__ */ jsx(Button, { type: "text", size: "small", icon: /* @__PURE__ */ jsx(Minus, { "aria-hidden": "true" }), "aria-label": zoomOutLabel, onClick: () => zoom(-SCALE_STEP), disabled: scale <= MIN_SCALE }),
|
|
791
|
+
/* @__PURE__ */ jsxs("output", { className: "cb-pan-zoom-canvas__zoom", "aria-label": zoomStatusLabel, children: [
|
|
792
|
+
Math.round(scale * 100),
|
|
793
|
+
"%"
|
|
794
|
+
] }),
|
|
795
|
+
/* @__PURE__ */ jsx(Button, { type: "text", size: "small", icon: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" }), "aria-label": zoomInLabel, onClick: () => zoom(SCALE_STEP), disabled: scale >= MAX_SCALE }),
|
|
796
|
+
/* @__PURE__ */ jsx(Button, { type: "text", size: "small", icon: /* @__PURE__ */ jsx(RotateCcw, { "aria-hidden": "true" }), "aria-label": resetLabel, onClick: reset })
|
|
797
|
+
] })
|
|
798
|
+
] }),
|
|
799
|
+
/* @__PURE__ */ jsxs(
|
|
800
|
+
"div",
|
|
801
|
+
{
|
|
802
|
+
className: "cb-pan-zoom-canvas__viewport",
|
|
803
|
+
role: "region",
|
|
804
|
+
"aria-label": label,
|
|
805
|
+
tabIndex: 0,
|
|
806
|
+
"data-pan-x": pan.x,
|
|
807
|
+
"data-pan-y": pan.y,
|
|
808
|
+
onKeyDown,
|
|
809
|
+
onPointerDown,
|
|
810
|
+
onPointerMove,
|
|
811
|
+
onPointerUp: releasePointer,
|
|
812
|
+
onPointerCancel: releasePointer,
|
|
813
|
+
onWheel,
|
|
814
|
+
children: [
|
|
815
|
+
/* @__PURE__ */ jsx("span", { ref: stepRef, className: "cb-pan-zoom-canvas__step", "aria-hidden": "true" }),
|
|
816
|
+
/* @__PURE__ */ jsx("div", { className: "cb-pan-zoom-canvas__content", style: transformStyle, children })
|
|
817
|
+
]
|
|
818
|
+
}
|
|
819
|
+
)
|
|
820
|
+
] });
|
|
821
|
+
}
|
|
822
|
+
var PanZoomCanvas = Object.assign(PanZoomCanvasRoot, { Skeleton: PanZoomCanvasSkeleton });
|
|
673
823
|
|
|
674
|
-
export { Checklist, CommandPalette, DEFAULT_LABELS, LabelsProvider, MotionProvider, Reveal, Sidebar, Stagger, StickerGroup, ThemeBridge, ThemeProvider, ToastProvider, TopBar, filterCommands, groupCommands, rankCommand, useLabels, useMotionSettings, useTheme, useToast };
|
|
824
|
+
export { Checklist, CommandPalette, DEFAULT_LABELS, LabelsProvider, MotionProvider, PanZoomCanvas, Reveal, Sidebar, Stagger, StickerGroup, ThemeBridge, ThemeProvider, ToastProvider, TopBar, filterCommands, groupCommands, rankCommand, useLabels, useMotionSettings, useTheme, useToast };
|
package/dist/styles.css
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
--cb-control-height-sm: 2rem;
|
|
42
42
|
--cb-control-height-md: 2.5rem;
|
|
43
43
|
--cb-control-height-lg: 3rem;
|
|
44
|
+
--cb-canvas-block-size: 32rem;
|
|
44
45
|
|
|
45
46
|
--cb-sticker-enter-y: var(--cb-space-3);
|
|
46
47
|
--cb-sticker-exit-x: var(--cb-space-6);
|
|
@@ -102,6 +103,10 @@
|
|
|
102
103
|
--cb-fg-muted: oklch(0.45 0.02 280);
|
|
103
104
|
--cb-fg-subtle: oklch(0.53 0.018 280);
|
|
104
105
|
--cb-fg-on-brand: oklch(0.99 0 0);
|
|
106
|
+
/* Brand-coloured text on a surface. The brand ramp step that carries body text at WCAG AA is
|
|
107
|
+
not the same step in both modes, so link colour is a token rather than a ramp reference a
|
|
108
|
+
product has to pick per theme. */
|
|
109
|
+
--cb-fg-link: var(--cb-brand-600);
|
|
105
110
|
/* A boundary has to be visible to be a boundary: border-strong carries the 3:1 WCAG asks of a
|
|
106
111
|
control's edge, and border the quieter separation between panels. */
|
|
107
112
|
|
|
@@ -178,6 +183,7 @@
|
|
|
178
183
|
|
|
179
184
|
--cb-brand-500: oklch(0.72 0.19 var(--cb-hue-brand));
|
|
180
185
|
--cb-brand-600: oklch(0.64 0.2 var(--cb-hue-brand));
|
|
186
|
+
--cb-fg-link: var(--cb-brand-500);
|
|
181
187
|
|
|
182
188
|
--cb-shadow-sm: 0 1px 2px oklch(0 0 0 / 0.4);
|
|
183
189
|
--cb-shadow-md: 0 6px 20px oklch(0 0 0 / 0.45);
|
|
@@ -228,6 +234,7 @@
|
|
|
228
234
|
|
|
229
235
|
--cb-brand-500: oklch(0.72 0.19 var(--cb-hue-brand));
|
|
230
236
|
--cb-brand-600: oklch(0.64 0.2 var(--cb-hue-brand));
|
|
237
|
+
--cb-fg-link: var(--cb-brand-500);
|
|
231
238
|
|
|
232
239
|
--cb-shadow-sm: 0 1px 2px oklch(0 0 0 / 0.4);
|
|
233
240
|
--cb-shadow-md: 0 6px 20px oklch(0 0 0 / 0.45);
|
|
@@ -918,6 +925,134 @@ html, body { background: var(--cb-bg); color: var(--cb-fg); }
|
|
|
918
925
|
object-fit: cover;
|
|
919
926
|
}
|
|
920
927
|
|
|
928
|
+
/* data/pan-zoom-canvas/pan-zoom-canvas.css */
|
|
929
|
+
.cb-pan-zoom-canvas {
|
|
930
|
+
background: var(--cb-surface);
|
|
931
|
+
border: var(--cb-border-width) solid var(--cb-border);
|
|
932
|
+
border-radius: var(--cb-radius-lg);
|
|
933
|
+
color: var(--cb-fg);
|
|
934
|
+
min-inline-size: 0;
|
|
935
|
+
overflow: hidden;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
.cb-pan-zoom-canvas__toolbar {
|
|
939
|
+
align-items: center;
|
|
940
|
+
background: var(--cb-bg-subtle);
|
|
941
|
+
border-block-end: var(--cb-border-width) solid var(--cb-border);
|
|
942
|
+
display: flex;
|
|
943
|
+
gap: var(--cb-space-3);
|
|
944
|
+
justify-content: space-between;
|
|
945
|
+
min-block-size: var(--cb-control-height-lg);
|
|
946
|
+
padding: var(--cb-space-2) var(--cb-space-3);
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
.cb-pan-zoom-canvas__hint {
|
|
950
|
+
color: var(--cb-fg-muted);
|
|
951
|
+
font-size: var(--cb-text-xs);
|
|
952
|
+
margin: 0;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
.cb-pan-zoom-canvas__controls {
|
|
956
|
+
align-items: center;
|
|
957
|
+
display: flex;
|
|
958
|
+
gap: var(--cb-space-1);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
.cb-pan-zoom-canvas__controls svg {
|
|
962
|
+
block-size: var(--cb-text-md);
|
|
963
|
+
inline-size: var(--cb-text-md);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
.cb-pan-zoom-canvas__zoom {
|
|
967
|
+
color: var(--cb-fg-muted);
|
|
968
|
+
font-size: var(--cb-text-xs);
|
|
969
|
+
font-variant-numeric: tabular-nums;
|
|
970
|
+
min-inline-size: var(--cb-control-height-md);
|
|
971
|
+
text-align: center;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.cb-pan-zoom-canvas__viewport {
|
|
975
|
+
block-size: var(--cb-canvas-block-size);
|
|
976
|
+
cursor: grab;
|
|
977
|
+
overflow: hidden;
|
|
978
|
+
position: relative;
|
|
979
|
+
touch-action: none;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.cb-pan-zoom-canvas__viewport:active { cursor: grabbing; }
|
|
983
|
+
|
|
984
|
+
.cb-pan-zoom-canvas__viewport:focus-visible {
|
|
985
|
+
outline: var(--cb-focus-width) solid var(--cb-focus);
|
|
986
|
+
outline-offset: var(--cb-focus-offset-inset);
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
.cb-pan-zoom-canvas__step {
|
|
990
|
+
inline-size: var(--cb-space-5);
|
|
991
|
+
pointer-events: none;
|
|
992
|
+
position: absolute;
|
|
993
|
+
visibility: hidden;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
.cb-pan-zoom-canvas__content {
|
|
997
|
+
min-block-size: 100%;
|
|
998
|
+
min-inline-size: 100%;
|
|
999
|
+
transform: translate(
|
|
1000
|
+
calc(var(--cb-space-5) * var(--cb-pan-zoom-x)),
|
|
1001
|
+
calc(var(--cb-space-5) * var(--cb-pan-zoom-y))
|
|
1002
|
+
) scale(var(--cb-pan-zoom-scale));
|
|
1003
|
+
transform-origin: center;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.cb-pan-zoom-canvas[data-motion="true"] .cb-pan-zoom-canvas__content {
|
|
1007
|
+
transition: transform var(--cb-duration-base) var(--cb-ease-standard);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
.cb-pan-zoom-canvas--skeleton {
|
|
1011
|
+
block-size: var(--cb-canvas-block-size);
|
|
1012
|
+
position: relative;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
.cb-pan-zoom-canvas__skeleton-controls,
|
|
1016
|
+
.cb-pan-zoom-canvas__skeleton-node,
|
|
1017
|
+
.cb-pan-zoom-canvas__skeleton-line {
|
|
1018
|
+
background: var(--cb-bg-subtle);
|
|
1019
|
+
display: block;
|
|
1020
|
+
position: absolute;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
.cb-pan-zoom-canvas__skeleton-controls {
|
|
1024
|
+
block-size: var(--cb-control-height-sm);
|
|
1025
|
+
border-radius: var(--cb-radius-sm);
|
|
1026
|
+
inline-size: calc(var(--cb-space-8) * 2);
|
|
1027
|
+
inset-block-start: var(--cb-space-3);
|
|
1028
|
+
inset-inline-end: var(--cb-space-3);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
.cb-pan-zoom-canvas__skeleton-node {
|
|
1032
|
+
block-size: var(--cb-control-height-lg);
|
|
1033
|
+
border-radius: var(--cb-radius-md);
|
|
1034
|
+
inline-size: calc(var(--cb-space-8) * 2);
|
|
1035
|
+
inset-block-start: 50%;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
.cb-pan-zoom-canvas__skeleton-node--start { inset-inline-start: var(--cb-space-6); }
|
|
1039
|
+
.cb-pan-zoom-canvas__skeleton-node--end { inset-inline-end: var(--cb-space-6); }
|
|
1040
|
+
|
|
1041
|
+
.cb-pan-zoom-canvas__skeleton-line {
|
|
1042
|
+
block-size: var(--cb-border-width);
|
|
1043
|
+
inset-block-start: calc(50% + var(--cb-space-3));
|
|
1044
|
+
inset-inline: calc(var(--cb-space-8) * 3);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1048
|
+
.cb-pan-zoom-canvas__content { transition: none; }
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
@media (forced-colors: active) {
|
|
1052
|
+
.cb-pan-zoom-canvas,
|
|
1053
|
+
.cb-pan-zoom-canvas__toolbar { border-color: CanvasText; }
|
|
1054
|
+
}
|
|
1055
|
+
|
|
921
1056
|
/* data/sticker-group/sticker-group.css */
|
|
922
1057
|
.cb-sticker-group {
|
|
923
1058
|
display: flex;
|