@zyncat/ui 0.8.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/LICENSE +21 -0
- package/README.md +133 -0
- package/dist/alert.css +132 -0
- package/dist/alert.d.ts +46 -0
- package/dist/alert.js +80 -0
- package/dist/alert.js.map +1 -0
- package/dist/avatar-group.d.ts +24 -0
- package/dist/avatar-group.js +23 -0
- package/dist/avatar-group.js.map +1 -0
- package/dist/avatar.css +200 -0
- package/dist/avatar.d.ts +35 -0
- package/dist/avatar.js +67 -0
- package/dist/avatar.js.map +1 -0
- package/dist/badge.css +182 -0
- package/dist/badge.d.ts +34 -0
- package/dist/badge.js +4 -0
- package/dist/badge.js.map +1 -0
- package/dist/button.css +269 -0
- package/dist/button.d.ts +44 -0
- package/dist/button.js +4 -0
- package/dist/button.js.map +1 -0
- package/dist/checkbox.css +177 -0
- package/dist/checkbox.d.ts +35 -0
- package/dist/checkbox.js +5 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chunk-2ERBBFZS.js +12 -0
- package/dist/chunk-2ERBBFZS.js.map +1 -0
- package/dist/chunk-2HORSLXJ.js +191 -0
- package/dist/chunk-2HORSLXJ.js.map +1 -0
- package/dist/chunk-36WVAQKL.js +40 -0
- package/dist/chunk-36WVAQKL.js.map +1 -0
- package/dist/chunk-3SBCBYB7.js +575 -0
- package/dist/chunk-3SBCBYB7.js.map +1 -0
- package/dist/chunk-4R2GQO43.js +125 -0
- package/dist/chunk-4R2GQO43.js.map +1 -0
- package/dist/chunk-64UU4LGU.js +258 -0
- package/dist/chunk-64UU4LGU.js.map +1 -0
- package/dist/chunk-7SZCJ7WI.js +35 -0
- package/dist/chunk-7SZCJ7WI.js.map +1 -0
- package/dist/chunk-BIDVNLJO.js +38 -0
- package/dist/chunk-BIDVNLJO.js.map +1 -0
- package/dist/chunk-CONSWNIV.js +17 -0
- package/dist/chunk-CONSWNIV.js.map +1 -0
- package/dist/chunk-EQ32F2QJ.js +75 -0
- package/dist/chunk-EQ32F2QJ.js.map +1 -0
- package/dist/chunk-GY7JOPUQ.js +111 -0
- package/dist/chunk-GY7JOPUQ.js.map +1 -0
- package/dist/chunk-I4XQ4PV2.js +30 -0
- package/dist/chunk-I4XQ4PV2.js.map +1 -0
- package/dist/chunk-JSKXZMLH.js +67 -0
- package/dist/chunk-JSKXZMLH.js.map +1 -0
- package/dist/chunk-L3Q3VDIW.js +295 -0
- package/dist/chunk-L3Q3VDIW.js.map +1 -0
- package/dist/chunk-LDC3RIYA.js +62 -0
- package/dist/chunk-LDC3RIYA.js.map +1 -0
- package/dist/chunk-MKIQFK7S.js +43 -0
- package/dist/chunk-MKIQFK7S.js.map +1 -0
- package/dist/chunk-MMRIQNEN.js +20 -0
- package/dist/chunk-MMRIQNEN.js.map +1 -0
- package/dist/chunk-MXOPCFWR.js +59 -0
- package/dist/chunk-MXOPCFWR.js.map +1 -0
- package/dist/chunk-NEF5XAHG.js +17 -0
- package/dist/chunk-NEF5XAHG.js.map +1 -0
- package/dist/chunk-NNXJCLTV.js +22 -0
- package/dist/chunk-NNXJCLTV.js.map +1 -0
- package/dist/chunk-O4N2OBTR.js +94 -0
- package/dist/chunk-O4N2OBTR.js.map +1 -0
- package/dist/chunk-PMECHR3A.js +38 -0
- package/dist/chunk-PMECHR3A.js.map +1 -0
- package/dist/chunk-QDK66S4G.js +44 -0
- package/dist/chunk-QDK66S4G.js.map +1 -0
- package/dist/chunk-QGNC7LH5.js +8 -0
- package/dist/chunk-QGNC7LH5.js.map +1 -0
- package/dist/chunk-QMSJZCK3.js +398 -0
- package/dist/chunk-QMSJZCK3.js.map +1 -0
- package/dist/chunk-S5ZTZANS.js +57 -0
- package/dist/chunk-S5ZTZANS.js.map +1 -0
- package/dist/chunk-S7B34VGN.js +14 -0
- package/dist/chunk-S7B34VGN.js.map +1 -0
- package/dist/chunk-TCUCYFT7.js +25 -0
- package/dist/chunk-TCUCYFT7.js.map +1 -0
- package/dist/chunk-TYHR4VNM.js +193 -0
- package/dist/chunk-TYHR4VNM.js.map +1 -0
- package/dist/chunk-U5QQZC3U.js +56 -0
- package/dist/chunk-U5QQZC3U.js.map +1 -0
- package/dist/chunk-UE63OOVG.js +13 -0
- package/dist/chunk-UE63OOVG.js.map +1 -0
- package/dist/chunk-VTJTGVZZ.js +22 -0
- package/dist/chunk-VTJTGVZZ.js.map +1 -0
- package/dist/chunk-W3SHPKSB.js +49 -0
- package/dist/chunk-W3SHPKSB.js.map +1 -0
- package/dist/chunk-XZAEIQDR.js +188 -0
- package/dist/chunk-XZAEIQDR.js.map +1 -0
- package/dist/chunk-YGGCQNNU.js +92 -0
- package/dist/chunk-YGGCQNNU.js.map +1 -0
- package/dist/collapse.css +88 -0
- package/dist/collapse.d.ts +46 -0
- package/dist/collapse.js +5 -0
- package/dist/collapse.js.map +1 -0
- package/dist/count-badge.d.ts +13 -0
- package/dist/count-badge.js +13 -0
- package/dist/count-badge.js.map +1 -0
- package/dist/date-field.d.ts +25 -0
- package/dist/date-field.js +87 -0
- package/dist/date-field.js.map +1 -0
- package/dist/date-picker.css +595 -0
- package/dist/date-range-field.d.ts +33 -0
- package/dist/date-range-field.js +404 -0
- package/dist/date-range-field.js.map +1 -0
- package/dist/datetime-field.d.ts +29 -0
- package/dist/datetime-field.js +155 -0
- package/dist/datetime-field.js.map +1 -0
- package/dist/dialog.css +180 -0
- package/dist/dialog.d.ts +42 -0
- package/dist/dialog.js +128 -0
- package/dist/dialog.js.map +1 -0
- package/dist/dom-props-C0jrllBw.d.ts +5 -0
- package/dist/field-chrome-CMPOQSLs.d.ts +28 -0
- package/dist/field-shell-Cuda-feL.d.ts +24 -0
- package/dist/glide.d.ts +15 -0
- package/dist/glide.js +5 -0
- package/dist/glide.js.map +1 -0
- package/dist/icon.css +33 -0
- package/dist/input.css +333 -0
- package/dist/mcp.js +359 -0
- package/dist/motion-devtools.css +265 -0
- package/dist/motion-devtools.d.ts +51 -0
- package/dist/motion-devtools.js +354 -0
- package/dist/motion-devtools.js.map +1 -0
- package/dist/motion-scale-Canq4stZ.d.ts +18 -0
- package/dist/motion-tokens.d.ts +28 -0
- package/dist/motion-tokens.js +3 -0
- package/dist/motion-tokens.js.map +1 -0
- package/dist/multi-select.d.ts +44 -0
- package/dist/multi-select.js +109 -0
- package/dist/multi-select.js.map +1 -0
- package/dist/number-field.d.ts +36 -0
- package/dist/number-field.js +112 -0
- package/dist/number-field.js.map +1 -0
- package/dist/odometer.css +62 -0
- package/dist/otp-field.d.ts +31 -0
- package/dist/otp-field.js +98 -0
- package/dist/otp-field.js.map +1 -0
- package/dist/overlay.css +23 -0
- package/dist/pagination.css +43 -0
- package/dist/pagination.d.ts +29 -0
- package/dist/pagination.js +107 -0
- package/dist/pagination.js.map +1 -0
- package/dist/popover.css +69 -0
- package/dist/popover.d.ts +35 -0
- package/dist/popover.js +15 -0
- package/dist/popover.js.map +1 -0
- package/dist/radio-group.css +300 -0
- package/dist/radio-group.d.ts +52 -0
- package/dist/radio-group.js +115 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/select.css +416 -0
- package/dist/select.d.ts +49 -0
- package/dist/select.js +99 -0
- package/dist/select.js.map +1 -0
- package/dist/sheet.css +26 -0
- package/dist/sheet.d.ts +31 -0
- package/dist/sheet.js +14 -0
- package/dist/sheet.js.map +1 -0
- package/dist/status-badge.d.ts +19 -0
- package/dist/status-badge.js +72 -0
- package/dist/status-badge.js.map +1 -0
- package/dist/table.css +348 -0
- package/dist/table.d.ts +75 -0
- package/dist/table.js +262 -0
- package/dist/table.js.map +1 -0
- package/dist/tabs.css +208 -0
- package/dist/tabs.d.ts +71 -0
- package/dist/tabs.js +181 -0
- package/dist/tabs.js.map +1 -0
- package/dist/tag.css +248 -0
- package/dist/tag.d.ts +52 -0
- package/dist/tag.js +72 -0
- package/dist/tag.js.map +1 -0
- package/dist/text-field.d.ts +28 -0
- package/dist/text-field.js +69 -0
- package/dist/text-field.js.map +1 -0
- package/dist/textarea.css +219 -0
- package/dist/textarea.d.ts +38 -0
- package/dist/textarea.js +144 -0
- package/dist/textarea.js.map +1 -0
- package/dist/time-field.d.ts +28 -0
- package/dist/time-field.js +66 -0
- package/dist/time-field.js.map +1 -0
- package/dist/timing-7JA_zQHP.d.ts +27 -0
- package/dist/toast-store.d.ts +86 -0
- package/dist/toast-store.js +3 -0
- package/dist/toast-store.js.map +1 -0
- package/dist/toast.css +257 -0
- package/dist/toast.d.ts +12 -0
- package/dist/toast.js +310 -0
- package/dist/toast.js.map +1 -0
- package/dist/toggle-tag.d.ts +34 -0
- package/dist/toggle-tag.js +57 -0
- package/dist/toggle-tag.js.map +1 -0
- package/dist/toggle.css +152 -0
- package/dist/toggle.d.ts +31 -0
- package/dist/toggle.js +75 -0
- package/dist/toggle.js.map +1 -0
- package/dist/tooltip.css +86 -0
- package/dist/tooltip.d.ts +30 -0
- package/dist/tooltip.js +268 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/types-SGMShK7R.d.ts +22 -0
- package/llms.txt +196 -0
- package/next.d.mts +7 -0
- package/next.mjs +59 -0
- package/package.json +257 -0
- package/src/components/composites/alert/Alert.tsx +141 -0
- package/src/components/composites/alert/alert.css +132 -0
- package/src/components/composites/date-picker/DateField.tsx +80 -0
- package/src/components/composites/date-picker/DateRangeField.tsx +110 -0
- package/src/components/composites/date-picker/DateTimeField.tsx +162 -0
- package/src/components/composites/date-picker/TimeField.tsx +78 -0
- package/src/components/composites/date-picker/calendar-panel.tsx +216 -0
- package/src/components/composites/date-picker/date-picker.css +595 -0
- package/src/components/composites/date-picker/date-utils.ts +56 -0
- package/src/components/composites/date-picker/field-shell.tsx +85 -0
- package/src/components/composites/date-picker/range-panel.tsx +363 -0
- package/src/components/composites/date-picker/time-core.tsx +290 -0
- package/src/components/composites/date-picker/use-day-focus.ts +35 -0
- package/src/components/composites/dialog/Dialog.tsx +198 -0
- package/src/components/composites/dialog/dialog.css +180 -0
- package/src/components/composites/pagination/Pagination.tsx +131 -0
- package/src/components/composites/pagination/pagination.css +43 -0
- package/src/components/composites/popover/Popover.tsx +141 -0
- package/src/components/composites/popover/popover.css +69 -0
- package/src/components/composites/select/MultiSelect.tsx +133 -0
- package/src/components/composites/select/Select.tsx +122 -0
- package/src/components/composites/select/core/index.ts +4 -0
- package/src/components/composites/select/core/menu.tsx +100 -0
- package/src/components/composites/select/core/panel.tsx +154 -0
- package/src/components/composites/select/core/trigger.tsx +74 -0
- package/src/components/composites/select/core/types.ts +39 -0
- package/src/components/composites/select/core/use-listbox.ts +182 -0
- package/src/components/composites/select/select.css +416 -0
- package/src/components/composites/sheet/Sheet.tsx +135 -0
- package/src/components/composites/sheet/sheet.css +26 -0
- package/src/components/composites/sheet/use-sheet-drag.ts +126 -0
- package/src/components/composites/table/Table.tsx +377 -0
- package/src/components/composites/table/table.css +348 -0
- package/src/components/composites/tabs/Tabs.tsx +278 -0
- package/src/components/composites/tabs/tabs.css +208 -0
- package/src/components/composites/toast/Toast.tsx +380 -0
- package/src/components/composites/toast/toast-store.ts +295 -0
- package/src/components/composites/toast/toast.css +257 -0
- package/src/components/composites/tooltip/Tooltip.tsx +110 -0
- package/src/components/composites/tooltip/tooltip-host.tsx +184 -0
- package/src/components/composites/tooltip/tooltip-store.ts +81 -0
- package/src/components/composites/tooltip/tooltip.css +86 -0
- package/src/components/dev/MotionDevtools.tsx +200 -0
- package/src/components/dev/motion-devtools.css +265 -0
- package/src/components/dev/slowmo-engine.ts +230 -0
- package/src/components/internal/glass/glass.css +100 -0
- package/src/components/internal/glass/glint.ts +9 -0
- package/src/components/internal/hooks/use-controllable.ts +21 -0
- package/src/components/internal/hooks/use-scroll-edges.ts +46 -0
- package/src/components/internal/icon/Icon.tsx +66 -0
- package/src/components/internal/icon/IconSlot.tsx +10 -0
- package/src/components/internal/icon/icon.css +33 -0
- package/src/components/internal/overlay/focus.ts +68 -0
- package/src/components/internal/overlay/layer.tsx +149 -0
- package/src/components/internal/overlay/modal.tsx +141 -0
- package/src/components/internal/overlay/overlay.css +23 -0
- package/src/components/internal/overlay/position.ts +103 -0
- package/src/components/internal/utils/cx.ts +3 -0
- package/src/components/internal/utils/token-px.ts +8 -0
- package/src/components/primitives/avatar/Avatar.tsx +120 -0
- package/src/components/primitives/avatar/AvatarGroup.tsx +56 -0
- package/src/components/primitives/avatar/avatar.css +200 -0
- package/src/components/primitives/badge/Badge.tsx +75 -0
- package/src/components/primitives/badge/CountBadge.tsx +20 -0
- package/src/components/primitives/badge/StatusBadge.tsx +111 -0
- package/src/components/primitives/badge/badge.css +182 -0
- package/src/components/primitives/badge/odometer.css +62 -0
- package/src/components/primitives/badge/odometer.tsx +36 -0
- package/src/components/primitives/button/Button.tsx +102 -0
- package/src/components/primitives/button/button.css +269 -0
- package/src/components/primitives/checkbox/Checkbox.tsx +76 -0
- package/src/components/primitives/checkbox/check-glyph.tsx +28 -0
- package/src/components/primitives/checkbox/checkbox.css +177 -0
- package/src/components/primitives/collapse/Collapse.tsx +86 -0
- package/src/components/primitives/collapse/collapse.css +88 -0
- package/src/components/primitives/collapse/collapse.typecheck.tsx +29 -0
- package/src/components/primitives/input/NumberField.tsx +139 -0
- package/src/components/primitives/input/OtpField.tsx +134 -0
- package/src/components/primitives/input/TextField.tsx +110 -0
- package/src/components/primitives/input/field-chrome.tsx +83 -0
- package/src/components/primitives/input/input.css +333 -0
- package/src/components/primitives/radio-group/RadioGroup.tsx +183 -0
- package/src/components/primitives/radio-group/radio-group.css +300 -0
- package/src/components/primitives/tag/Tag.tsx +143 -0
- package/src/components/primitives/tag/ToggleTag.tsx +97 -0
- package/src/components/primitives/tag/tag.css +248 -0
- package/src/components/primitives/textarea/Textarea.tsx +190 -0
- package/src/components/primitives/textarea/textarea.css +219 -0
- package/src/components/primitives/toggle/Toggle.tsx +105 -0
- package/src/components/primitives/toggle/toggle.css +152 -0
- package/src/css.d.ts +1 -0
- package/src/dom-props.ts +1 -0
- package/src/engine/animate.ts +141 -0
- package/src/engine/drag.ts +53 -0
- package/src/engine/ease.ts +155 -0
- package/src/engine/flip.ts +59 -0
- package/src/engine/index.ts +13 -0
- package/src/mcp/server.ts +420 -0
- package/src/motion/element.tsx +53 -0
- package/src/motion/flip.tsx +87 -0
- package/src/motion/glide.tsx +47 -0
- package/src/motion/motion-timing.ts +33 -0
- package/src/motion/presence-context.ts +18 -0
- package/src/motion/presence.tsx +91 -0
- package/src/motion/timing.ts +49 -0
- package/src/motion/use-motion.ts +64 -0
- package/src/styles.css +26 -0
- package/src/tokens/avatar.css +20 -0
- package/src/tokens/color.css +58 -0
- package/src/tokens/elevation.css +22 -0
- package/src/tokens/fonts.css +3 -0
- package/src/tokens/glass.css +20 -0
- package/src/tokens/icons.css +7 -0
- package/src/tokens/layers.css +6 -0
- package/src/tokens/motion-scale.ts +17 -0
- package/src/tokens/motion-tokens.ts +92 -0
- package/src/tokens/motion.css +49 -0
- package/src/tokens/radius.css +11 -0
- package/src/tokens/semantic.css +65 -0
- package/src/tokens/spacing.css +26 -0
- package/src/tokens/typography.css +52 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/* MotionDevtools - a floating dev overlay, styled on-brand with the design system's own
|
|
2
|
+
surface tokens so the <Button>/<Checkbox>/<Collapse> it dogfoods render natively.
|
|
3
|
+
|
|
4
|
+
Collapsed it's a small pill (gauge + current factor); opening morphs it into the full panel.
|
|
5
|
+
The width eases (CSS transition) in step with the <Collapse>-driven body height, so it grows
|
|
6
|
+
as one piece and never teleports. Everything that would change size on open lives INSIDE the
|
|
7
|
+
Collapse, so nothing clips while the pill is still narrow.
|
|
8
|
+
|
|
9
|
+
The one non-negotiable trick: it RESETS --duration-* to their canonical values on its own
|
|
10
|
+
root. The engine scales those tokens globally to slow the app; without this local reset the
|
|
11
|
+
panel's own controls - and this very expand/collapse - would slow down with everything else.
|
|
12
|
+
A motion debugger must stay crisp while the app runs in slow-mo. Token fallbacks keep it
|
|
13
|
+
legible if dropped in without the base layer. */
|
|
14
|
+
|
|
15
|
+
.mdt {
|
|
16
|
+
/* immune to the global slow-mo the engine applies to --duration-* */
|
|
17
|
+
--duration-fast: 140ms;
|
|
18
|
+
--duration-base: 200ms;
|
|
19
|
+
--duration-slow: 300ms;
|
|
20
|
+
--duration-slower: 450ms;
|
|
21
|
+
--duration-slowest: 900ms;
|
|
22
|
+
--duration-spin: 600ms;
|
|
23
|
+
--duration-pulse: 1600ms;
|
|
24
|
+
|
|
25
|
+
--mdt-offset: 16px;
|
|
26
|
+
--mdt-surface: color-mix(in oklab, var(--bg-surface, #fff) 88%, transparent);
|
|
27
|
+
|
|
28
|
+
position: fixed;
|
|
29
|
+
z-index: 2147483000; /* above every app layer, including tooltips */
|
|
30
|
+
display: flex;
|
|
31
|
+
color: var(--text-body, oklch(0.35 0.01 264));
|
|
32
|
+
font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
|
|
33
|
+
-webkit-font-smoothing: antialiased;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.mdt--top-left {
|
|
37
|
+
top: var(--mdt-offset);
|
|
38
|
+
left: var(--mdt-offset);
|
|
39
|
+
}
|
|
40
|
+
.mdt--top-right {
|
|
41
|
+
top: var(--mdt-offset);
|
|
42
|
+
right: var(--mdt-offset);
|
|
43
|
+
}
|
|
44
|
+
.mdt--bottom-left {
|
|
45
|
+
bottom: var(--mdt-offset);
|
|
46
|
+
left: var(--mdt-offset);
|
|
47
|
+
}
|
|
48
|
+
.mdt--bottom-right {
|
|
49
|
+
bottom: var(--mdt-offset);
|
|
50
|
+
right: var(--mdt-offset);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* ---------- card (pill when collapsed, panel when open) ---------- */
|
|
54
|
+
|
|
55
|
+
.mdt__panel {
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
/* Compact pill when collapsed; eases to the full panel width in step with the <Collapse>
|
|
58
|
+
body height below, so the whole thing morphs open and never teleports. */
|
|
59
|
+
width: 128px;
|
|
60
|
+
padding: 5px;
|
|
61
|
+
border: 1px solid var(--border-subtle, oklch(0.92 0.004 264));
|
|
62
|
+
border-radius: var(--radius-xl, 0.75rem);
|
|
63
|
+
background: var(--mdt-surface);
|
|
64
|
+
backdrop-filter: blur(16px) saturate(1.6);
|
|
65
|
+
-webkit-backdrop-filter: blur(16px) saturate(1.6);
|
|
66
|
+
box-shadow: var(--shadow-lg, 0 12px 28px oklch(0 0 0 / 0.1));
|
|
67
|
+
animation: mdt-in var(--duration-base) var(--ease-entrance, ease);
|
|
68
|
+
transition:
|
|
69
|
+
width var(--duration-slow) var(--ease-entrance, ease),
|
|
70
|
+
box-shadow var(--duration-slow) var(--ease-entrance, ease);
|
|
71
|
+
}
|
|
72
|
+
.mdt__panel.is-open {
|
|
73
|
+
width: 232px;
|
|
74
|
+
box-shadow: var(--shadow-xl, 0 24px 48px oklch(0 0 0 / 0.16));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@keyframes mdt-in {
|
|
78
|
+
from {
|
|
79
|
+
opacity: 0;
|
|
80
|
+
transform: translateY(6px) scale(0.985);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* ---------- pill / header (the toggle) ---------- */
|
|
85
|
+
|
|
86
|
+
.mdt__head {
|
|
87
|
+
appearance: none;
|
|
88
|
+
width: 100%;
|
|
89
|
+
display: flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
gap: 0.5rem;
|
|
92
|
+
padding: 0.3125rem 0.4375rem;
|
|
93
|
+
border: 0;
|
|
94
|
+
border-radius: var(--radius-md, 0.375rem);
|
|
95
|
+
background: transparent;
|
|
96
|
+
color: inherit;
|
|
97
|
+
font: inherit;
|
|
98
|
+
text-align: left;
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
transition: background var(--duration-fast) var(--ease-standard, ease);
|
|
101
|
+
}
|
|
102
|
+
.mdt__head:hover {
|
|
103
|
+
background: var(--neutral-wash, oklch(0.5 0.01 264 / 0.07));
|
|
104
|
+
}
|
|
105
|
+
.mdt__head:focus-visible {
|
|
106
|
+
outline: none;
|
|
107
|
+
box-shadow: var(--ring-accent, 0 0 0 3px oklch(0.7 0.12 185 / 0.35));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.mdt__glyph {
|
|
111
|
+
color: var(--text-subtle, oklch(0.6 0.01 264));
|
|
112
|
+
flex: none;
|
|
113
|
+
display: block;
|
|
114
|
+
}
|
|
115
|
+
.mdt--active .mdt__glyph {
|
|
116
|
+
color: var(--accent, oklch(0.62 0.12 185));
|
|
117
|
+
}
|
|
118
|
+
.mdt--paused .mdt__glyph {
|
|
119
|
+
color: var(--warning, oklch(0.72 0.13 75));
|
|
120
|
+
}
|
|
121
|
+
.mdt__spacer {
|
|
122
|
+
flex: 1;
|
|
123
|
+
}
|
|
124
|
+
.mdt__badge {
|
|
125
|
+
font-size: 0.75rem;
|
|
126
|
+
font-weight: 650;
|
|
127
|
+
font-variant-numeric: tabular-nums;
|
|
128
|
+
line-height: 1;
|
|
129
|
+
padding: 0.1875rem 0.4375rem;
|
|
130
|
+
border-radius: var(--radius-full, 999px);
|
|
131
|
+
color: var(--text-muted, oklch(0.55 0.01 264));
|
|
132
|
+
background: var(--neutral-wash, oklch(0.5 0.01 264 / 0.08));
|
|
133
|
+
white-space: nowrap;
|
|
134
|
+
}
|
|
135
|
+
.mdt--active .mdt__badge {
|
|
136
|
+
color: var(--text-on-accent, #fff);
|
|
137
|
+
background: var(--accent, oklch(0.62 0.12 185));
|
|
138
|
+
}
|
|
139
|
+
.mdt--paused .mdt__badge {
|
|
140
|
+
color: var(--text-on-accent, #fff);
|
|
141
|
+
background: var(--warning, oklch(0.72 0.13 75));
|
|
142
|
+
}
|
|
143
|
+
.mdt__chevron {
|
|
144
|
+
color: var(--text-subtle, oklch(0.6 0.01 264));
|
|
145
|
+
flex: none;
|
|
146
|
+
transition: transform var(--duration-base) var(--ease-standard, ease);
|
|
147
|
+
}
|
|
148
|
+
.mdt__chevron--open {
|
|
149
|
+
transform: rotate(180deg);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* ---------- body (inside <Collapse>) ---------- */
|
|
153
|
+
|
|
154
|
+
.mdt__body {
|
|
155
|
+
box-sizing: border-box;
|
|
156
|
+
/* Hold a stable layout width so controls don't reflow as the card animates open; the
|
|
157
|
+
collapsed pill is narrower, so this overflows and is clipped by <Collapse>'s overflow. */
|
|
158
|
+
width: 100%;
|
|
159
|
+
min-width: 208px;
|
|
160
|
+
display: flex;
|
|
161
|
+
flex-direction: column;
|
|
162
|
+
gap: 0.8125rem;
|
|
163
|
+
padding: 0.625rem 0.375rem 0.375rem;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.mdt__title {
|
|
167
|
+
font-size: 0.6875rem;
|
|
168
|
+
font-weight: 650;
|
|
169
|
+
letter-spacing: 0.06em;
|
|
170
|
+
text-transform: uppercase;
|
|
171
|
+
color: var(--text-subtle, oklch(0.6 0.01 264));
|
|
172
|
+
}
|
|
173
|
+
.mdt__readout {
|
|
174
|
+
display: flex;
|
|
175
|
+
align-items: baseline;
|
|
176
|
+
gap: 0.375rem;
|
|
177
|
+
margin-top: -0.375rem;
|
|
178
|
+
}
|
|
179
|
+
.mdt__value {
|
|
180
|
+
font-size: 1.5rem;
|
|
181
|
+
font-weight: 700;
|
|
182
|
+
font-variant-numeric: tabular-nums;
|
|
183
|
+
line-height: 1;
|
|
184
|
+
color: var(--text-strong, oklch(0.25 0.01 264));
|
|
185
|
+
}
|
|
186
|
+
.mdt__unit {
|
|
187
|
+
font-size: 0.75rem;
|
|
188
|
+
color: var(--text-muted, oklch(0.55 0.01 264));
|
|
189
|
+
font-weight: 500;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.mdt__slider {
|
|
193
|
+
-webkit-appearance: none;
|
|
194
|
+
appearance: none;
|
|
195
|
+
width: 100%;
|
|
196
|
+
height: 4px;
|
|
197
|
+
border-radius: 999px;
|
|
198
|
+
background: linear-gradient(
|
|
199
|
+
to right,
|
|
200
|
+
var(--accent, oklch(0.62 0.12 185)) 0%,
|
|
201
|
+
var(--accent, oklch(0.62 0.12 185)) var(--mdt-fill, 0%),
|
|
202
|
+
var(--bg-muted, oklch(0.93 0.004 264)) var(--mdt-fill, 0%)
|
|
203
|
+
);
|
|
204
|
+
cursor: pointer;
|
|
205
|
+
margin: 0;
|
|
206
|
+
}
|
|
207
|
+
.mdt__slider::-webkit-slider-thumb {
|
|
208
|
+
-webkit-appearance: none;
|
|
209
|
+
appearance: none;
|
|
210
|
+
width: 16px;
|
|
211
|
+
height: 16px;
|
|
212
|
+
border-radius: 50%;
|
|
213
|
+
background: var(--bg-surface, #fff);
|
|
214
|
+
border: 2px solid var(--accent, oklch(0.62 0.12 185));
|
|
215
|
+
box-shadow: var(--shadow-sm, 0 1px 2px oklch(0 0 0 / 0.15));
|
|
216
|
+
}
|
|
217
|
+
.mdt__slider::-moz-range-thumb {
|
|
218
|
+
width: 16px;
|
|
219
|
+
height: 16px;
|
|
220
|
+
border-radius: 50%;
|
|
221
|
+
background: var(--bg-surface, #fff);
|
|
222
|
+
border: 2px solid var(--accent, oklch(0.62 0.12 185));
|
|
223
|
+
box-shadow: var(--shadow-sm, 0 1px 2px oklch(0 0 0 / 0.15));
|
|
224
|
+
}
|
|
225
|
+
.mdt__slider:focus-visible {
|
|
226
|
+
outline: none;
|
|
227
|
+
}
|
|
228
|
+
.mdt__slider:focus-visible::-webkit-slider-thumb {
|
|
229
|
+
box-shadow: var(--ring-accent, 0 0 0 3px oklch(0.7 0.12 185 / 0.35));
|
|
230
|
+
}
|
|
231
|
+
.mdt__slider:focus-visible::-moz-range-thumb {
|
|
232
|
+
box-shadow: var(--ring-accent, 0 0 0 3px oklch(0.7 0.12 185 / 0.35));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* preset chip grid + action row - children are DS <Button>s */
|
|
236
|
+
.mdt__chips {
|
|
237
|
+
display: grid;
|
|
238
|
+
grid-template-columns: repeat(5, 1fr);
|
|
239
|
+
gap: 0.25rem;
|
|
240
|
+
}
|
|
241
|
+
.mdt__chips .btn {
|
|
242
|
+
padding-inline: 0;
|
|
243
|
+
min-width: 0;
|
|
244
|
+
}
|
|
245
|
+
.mdt__row {
|
|
246
|
+
display: flex;
|
|
247
|
+
gap: 0.375rem;
|
|
248
|
+
}
|
|
249
|
+
.mdt__row .btn {
|
|
250
|
+
flex: 1;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.mdt__opt {
|
|
254
|
+
border-top: 1px solid var(--border-subtle, oklch(0.92 0.004 264));
|
|
255
|
+
padding-top: 0.75rem;
|
|
256
|
+
display: flex;
|
|
257
|
+
flex-direction: column;
|
|
258
|
+
gap: 0.5rem;
|
|
259
|
+
}
|
|
260
|
+
.mdt__hint {
|
|
261
|
+
font-size: 0.6875rem;
|
|
262
|
+
line-height: 1.45;
|
|
263
|
+
color: var(--text-subtle, oklch(0.6 0.01 264));
|
|
264
|
+
margin: 0;
|
|
265
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
interface SlowmoState {
|
|
4
|
+
/** 1 = real time. >1 = that many times slower (4 = quarter speed). */
|
|
5
|
+
factor: number;
|
|
6
|
+
/** Freeze motion in place - useful for inspecting a transition mid-flight. */
|
|
7
|
+
paused: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface SlowmoOptions {
|
|
10
|
+
/** Also scale setTimeout/setInterval so duration-coupled JS cleanups don't truncate
|
|
11
|
+
* slowed CSS. Turn off if stretched app timers get in your way. @default true */
|
|
12
|
+
scaleTimers: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Imperative control surface - drive slow-mo from a console, a hotkey, or the panel.
|
|
15
|
+
* Safe to call during SSR (no-ops the DOM work, still tracks state for hydration). */
|
|
16
|
+
declare const motionSlowmo: {
|
|
17
|
+
/** Current state (a copy). */
|
|
18
|
+
get(): SlowmoState;
|
|
19
|
+
/** Merge a partial state. factor is clamped to [1, 64]. */
|
|
20
|
+
set(patch: Partial<SlowmoState>): void;
|
|
21
|
+
/** Tune engine behaviour (e.g. stop scaling timers). Applies immediately if active. */
|
|
22
|
+
configure(patch: Partial<SlowmoOptions>): void;
|
|
23
|
+
/** Convenience: back to real time and unpaused. */
|
|
24
|
+
reset(): void;
|
|
25
|
+
/** Subscribe to state changes; returns an unsubscribe fn. */
|
|
26
|
+
subscribe(cb: (s: SlowmoState) => void): () => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type MotionDevtoolsPlacement = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
30
|
+
interface MotionDevtoolsProps {
|
|
31
|
+
/** Which corner of the viewport to pin to. @default 'bottom-right' */
|
|
32
|
+
placement?: MotionDevtoolsPlacement;
|
|
33
|
+
/** Distance from the viewport edges, in px. @default 16 */
|
|
34
|
+
offset?: number;
|
|
35
|
+
/** Quick-select slow-down factors (1 = real time). @default [1, 2, 4, 8, 16] */
|
|
36
|
+
presets?: number[];
|
|
37
|
+
/** Upper bound of the fine slider. @default 16 */
|
|
38
|
+
maxFactor?: number;
|
|
39
|
+
/** Slow-down factor to start at. @default 1 */
|
|
40
|
+
defaultFactor?: number;
|
|
41
|
+
/** Scale setTimeout/setInterval too, so duration-coupled JS cleanups don't truncate
|
|
42
|
+
* slowed CSS. Exposed as a live toggle in the panel. @default true */
|
|
43
|
+
scaleTimers?: boolean;
|
|
44
|
+
/** Remember the chosen factor across reloads (localStorage). @default true */
|
|
45
|
+
persist?: boolean;
|
|
46
|
+
/** Start with the full panel open rather than collapsed to its header. @default false */
|
|
47
|
+
defaultOpen?: boolean;
|
|
48
|
+
}
|
|
49
|
+
declare function MotionDevtools({ placement, offset, presets, maxFactor, defaultFactor, scaleTimers, persist, defaultOpen, }: MotionDevtoolsProps): react.ReactPortal;
|
|
50
|
+
|
|
51
|
+
export { MotionDevtools, type MotionDevtoolsPlacement, type MotionDevtoolsProps, type SlowmoState, MotionDevtools as default, motionSlowmo };
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
'use client';import { clock } from './chunk-L3Q3VDIW.js';
|
|
2
|
+
import { Button } from './chunk-U5QQZC3U.js';
|
|
3
|
+
import { Checkbox } from './chunk-QDK66S4G.js';
|
|
4
|
+
import './chunk-NNXJCLTV.js';
|
|
5
|
+
import { Collapse } from './chunk-7SZCJ7WI.js';
|
|
6
|
+
import './chunk-VTJTGVZZ.js';
|
|
7
|
+
import { cx } from './chunk-QGNC7LH5.js';
|
|
8
|
+
import './motion-devtools.css';
|
|
9
|
+
import { useState, useEffect } from 'react';
|
|
10
|
+
import { createPortal } from 'react-dom';
|
|
11
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
12
|
+
|
|
13
|
+
// src/components/dev/slowmo-engine.ts
|
|
14
|
+
var CANONICAL = {
|
|
15
|
+
"--duration-fast": 140,
|
|
16
|
+
"--duration-base": 200,
|
|
17
|
+
"--duration-slow": 300,
|
|
18
|
+
"--duration-slower": 450,
|
|
19
|
+
"--duration-slowest": 900,
|
|
20
|
+
"--duration-spin": 600,
|
|
21
|
+
"--duration-pulse": 1600
|
|
22
|
+
};
|
|
23
|
+
var DURATION_TOKENS = Object.keys(CANONICAL);
|
|
24
|
+
var COLLAPSED_MS = 4;
|
|
25
|
+
var FROZEN_MS = 6e5;
|
|
26
|
+
var MAX_TIMER_DELAY = 2 ** 30;
|
|
27
|
+
var clamp = (min, max, v) => v < min ? min : v > max ? max : v;
|
|
28
|
+
var hasDOM = typeof document !== "undefined" && typeof window !== "undefined";
|
|
29
|
+
var state = { factor: 1, paused: false };
|
|
30
|
+
var options = { scaleTimers: true };
|
|
31
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
32
|
+
var active = false;
|
|
33
|
+
var baseMs = {};
|
|
34
|
+
var origSetTimeout = null;
|
|
35
|
+
var origSetInterval = null;
|
|
36
|
+
var origAnimate = null;
|
|
37
|
+
var trackedRates = /* @__PURE__ */ new Map();
|
|
38
|
+
function readBaseMs(token) {
|
|
39
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue(token).trim();
|
|
40
|
+
const n = raw.endsWith("ms") ? parseFloat(raw) : raw.endsWith("s") ? parseFloat(raw) * 1e3 : parseFloat(raw);
|
|
41
|
+
if (isNaN(n) || n <= COLLAPSED_MS) return CANONICAL[token];
|
|
42
|
+
return n;
|
|
43
|
+
}
|
|
44
|
+
function applyCssTokens() {
|
|
45
|
+
const root = document.documentElement.style;
|
|
46
|
+
for (const token of DURATION_TOKENS) {
|
|
47
|
+
const ms = state.paused ? FROZEN_MS : baseMs[token] * state.factor;
|
|
48
|
+
root.setProperty(token, `${ms}ms`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function clearCssTokens() {
|
|
52
|
+
const root = document.documentElement.style;
|
|
53
|
+
for (const token of DURATION_TOKENS) root.removeProperty(token);
|
|
54
|
+
}
|
|
55
|
+
function scaleDelay(delay) {
|
|
56
|
+
if (typeof delay !== "number" || !isFinite(delay)) return delay;
|
|
57
|
+
return Math.min(delay * state.factor, MAX_TIMER_DELAY);
|
|
58
|
+
}
|
|
59
|
+
function patchTimers() {
|
|
60
|
+
if (origSetTimeout) return;
|
|
61
|
+
origSetTimeout = window.setTimeout;
|
|
62
|
+
origSetInterval = window.setInterval;
|
|
63
|
+
const nativeTimeout = origSetTimeout.bind(window);
|
|
64
|
+
const nativeInterval = origSetInterval.bind(window);
|
|
65
|
+
window.setTimeout = ((h, t, ...a) => nativeTimeout(h, scaleDelay(t), ...a));
|
|
66
|
+
window.setInterval = ((h, t, ...a) => nativeInterval(h, scaleDelay(t), ...a));
|
|
67
|
+
}
|
|
68
|
+
function restoreTimers() {
|
|
69
|
+
if (origSetTimeout) window.setTimeout = origSetTimeout;
|
|
70
|
+
if (origSetInterval) window.setInterval = origSetInterval;
|
|
71
|
+
origSetTimeout = origSetInterval = null;
|
|
72
|
+
}
|
|
73
|
+
function liveRate() {
|
|
74
|
+
return state.paused ? 0 : 1 / state.factor;
|
|
75
|
+
}
|
|
76
|
+
function track(anim, original) {
|
|
77
|
+
if (trackedRates.has(anim)) return;
|
|
78
|
+
trackedRates.set(anim, original);
|
|
79
|
+
const forget = () => trackedRates.delete(anim);
|
|
80
|
+
anim.finished.then(forget).catch(forget);
|
|
81
|
+
}
|
|
82
|
+
function patchAnimate() {
|
|
83
|
+
if (origAnimate) return;
|
|
84
|
+
origAnimate = Element.prototype.animate;
|
|
85
|
+
const original = origAnimate;
|
|
86
|
+
Element.prototype.animate = function(...args) {
|
|
87
|
+
const anim = original.apply(this, args);
|
|
88
|
+
try {
|
|
89
|
+
track(anim, anim.playbackRate);
|
|
90
|
+
anim.playbackRate = liveRate();
|
|
91
|
+
} catch {
|
|
92
|
+
}
|
|
93
|
+
return anim;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function restoreAnimate() {
|
|
97
|
+
if (origAnimate) Element.prototype.animate = origAnimate;
|
|
98
|
+
origAnimate = null;
|
|
99
|
+
}
|
|
100
|
+
function sweepExisting() {
|
|
101
|
+
const rate = liveRate();
|
|
102
|
+
for (const anim of document.getAnimations()) {
|
|
103
|
+
try {
|
|
104
|
+
track(anim, anim.playbackRate);
|
|
105
|
+
anim.playbackRate = rate;
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function applyTrackedRates() {
|
|
111
|
+
const rate = liveRate();
|
|
112
|
+
for (const anim of trackedRates.keys()) {
|
|
113
|
+
try {
|
|
114
|
+
anim.playbackRate = rate;
|
|
115
|
+
} catch {
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function restoreTrackedRates() {
|
|
120
|
+
for (const [anim, original] of trackedRates) {
|
|
121
|
+
try {
|
|
122
|
+
anim.playbackRate = original;
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
trackedRates.clear();
|
|
127
|
+
}
|
|
128
|
+
function applyEngineClock() {
|
|
129
|
+
clock.scale = state.paused ? Infinity : state.factor;
|
|
130
|
+
}
|
|
131
|
+
function install() {
|
|
132
|
+
active = true;
|
|
133
|
+
baseMs = {};
|
|
134
|
+
for (const token of DURATION_TOKENS) baseMs[token] = readBaseMs(token);
|
|
135
|
+
applyCssTokens();
|
|
136
|
+
applyEngineClock();
|
|
137
|
+
if (options.scaleTimers) patchTimers();
|
|
138
|
+
patchAnimate();
|
|
139
|
+
sweepExisting();
|
|
140
|
+
}
|
|
141
|
+
function reconfigure() {
|
|
142
|
+
applyCssTokens();
|
|
143
|
+
applyEngineClock();
|
|
144
|
+
applyTrackedRates();
|
|
145
|
+
}
|
|
146
|
+
function uninstall() {
|
|
147
|
+
active = false;
|
|
148
|
+
clearCssTokens();
|
|
149
|
+
clock.scale = 1;
|
|
150
|
+
restoreTimers();
|
|
151
|
+
restoreAnimate();
|
|
152
|
+
restoreTrackedRates();
|
|
153
|
+
}
|
|
154
|
+
function notify() {
|
|
155
|
+
const snapshot = { ...state };
|
|
156
|
+
for (const cb of listeners) cb(snapshot);
|
|
157
|
+
}
|
|
158
|
+
function shouldBeActive(factor, paused) {
|
|
159
|
+
return factor > 1 || paused;
|
|
160
|
+
}
|
|
161
|
+
var motionSlowmo = {
|
|
162
|
+
/** Current state (a copy). */
|
|
163
|
+
get() {
|
|
164
|
+
return { ...state };
|
|
165
|
+
},
|
|
166
|
+
/** Merge a partial state. factor is clamped to [1, 64]. */
|
|
167
|
+
set(patch) {
|
|
168
|
+
if (typeof patch.factor === "number") state.factor = clamp(1, 64, patch.factor);
|
|
169
|
+
if (typeof patch.paused === "boolean") state.paused = patch.paused;
|
|
170
|
+
if (hasDOM) {
|
|
171
|
+
const wantActive = shouldBeActive(state.factor, state.paused);
|
|
172
|
+
if (!active && wantActive) install();
|
|
173
|
+
else if (active && !wantActive) uninstall();
|
|
174
|
+
else if (active) reconfigure();
|
|
175
|
+
}
|
|
176
|
+
notify();
|
|
177
|
+
},
|
|
178
|
+
/** Tune engine behaviour (e.g. stop scaling timers). Applies immediately if active. */
|
|
179
|
+
configure(patch) {
|
|
180
|
+
if (typeof patch.scaleTimers === "boolean" && patch.scaleTimers !== options.scaleTimers) {
|
|
181
|
+
options.scaleTimers = patch.scaleTimers;
|
|
182
|
+
if (active) options.scaleTimers ? patchTimers() : restoreTimers();
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
/** Convenience: back to real time and unpaused. */
|
|
186
|
+
reset() {
|
|
187
|
+
this.set({ factor: 1, paused: false });
|
|
188
|
+
},
|
|
189
|
+
/** Subscribe to state changes; returns an unsubscribe fn. */
|
|
190
|
+
subscribe(cb) {
|
|
191
|
+
listeners.add(cb);
|
|
192
|
+
return () => listeners.delete(cb);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
var STORAGE_KEY = "zyncat-ui:motion-devtools";
|
|
196
|
+
var fmt = (n) => Number.isInteger(n) ? String(n) : n.toFixed(1);
|
|
197
|
+
function GaugeGlyph() {
|
|
198
|
+
return /* @__PURE__ */ jsxs("svg", { className: "mdt__glyph", width: "15", height: "15", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
|
|
199
|
+
/* @__PURE__ */ jsx(
|
|
200
|
+
"path",
|
|
201
|
+
{
|
|
202
|
+
d: "M12 4a8 8 0 0 1 8 8 8 8 0 0 1-.6 3",
|
|
203
|
+
fill: "none",
|
|
204
|
+
stroke: "currentColor",
|
|
205
|
+
strokeWidth: "2",
|
|
206
|
+
strokeLinecap: "round"
|
|
207
|
+
}
|
|
208
|
+
),
|
|
209
|
+
/* @__PURE__ */ jsx(
|
|
210
|
+
"path",
|
|
211
|
+
{
|
|
212
|
+
d: "M12 4a8 8 0 0 0-8 8 8 8 0 0 0 .6 3",
|
|
213
|
+
fill: "none",
|
|
214
|
+
stroke: "currentColor",
|
|
215
|
+
strokeWidth: "2",
|
|
216
|
+
strokeLinecap: "round",
|
|
217
|
+
opacity: "0.35"
|
|
218
|
+
}
|
|
219
|
+
),
|
|
220
|
+
/* @__PURE__ */ jsx("path", { d: "M12 12l4-2.5", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
221
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1.6", fill: "currentColor" })
|
|
222
|
+
] });
|
|
223
|
+
}
|
|
224
|
+
function MotionDevtools({
|
|
225
|
+
placement = "bottom-right",
|
|
226
|
+
offset = 16,
|
|
227
|
+
presets = [1, 2, 4, 8, 16],
|
|
228
|
+
maxFactor = 16,
|
|
229
|
+
defaultFactor = 1,
|
|
230
|
+
scaleTimers = true,
|
|
231
|
+
persist = true,
|
|
232
|
+
defaultOpen = false
|
|
233
|
+
}) {
|
|
234
|
+
const [mounted, setMounted] = useState(false);
|
|
235
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
236
|
+
const [snap, setSnap] = useState(() => motionSlowmo.get());
|
|
237
|
+
const [timers, setTimers] = useState(scaleTimers);
|
|
238
|
+
useEffect(() => motionSlowmo.subscribe(setSnap), []);
|
|
239
|
+
useEffect(() => {
|
|
240
|
+
setMounted(true);
|
|
241
|
+
let initial = { factor: defaultFactor, paused: false };
|
|
242
|
+
if (persist) {
|
|
243
|
+
try {
|
|
244
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
245
|
+
if (raw) initial = { ...initial, ...JSON.parse(raw) };
|
|
246
|
+
} catch {
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
motionSlowmo.set(initial);
|
|
250
|
+
if ((initial.factor ?? 1) > 1 || initial.paused) setOpen(true);
|
|
251
|
+
}, []);
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
motionSlowmo.configure({ scaleTimers: timers });
|
|
254
|
+
}, [timers]);
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
if (!persist) return;
|
|
257
|
+
try {
|
|
258
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify({ factor: snap.factor, paused: snap.paused }));
|
|
259
|
+
} catch {
|
|
260
|
+
}
|
|
261
|
+
}, [snap.factor, snap.paused, persist]);
|
|
262
|
+
if (!mounted) return null;
|
|
263
|
+
const active2 = shouldBeActive(snap.factor, snap.paused);
|
|
264
|
+
const rootClass = cx("mdt", `mdt--${placement}`, active2 && "mdt--active", snap.paused && "mdt--paused");
|
|
265
|
+
const setFactor = (factor) => motionSlowmo.set({ factor, paused: false });
|
|
266
|
+
const fill = `${(Math.min(snap.factor, maxFactor) - 1) / Math.max(1, maxFactor - 1) * 100}%`;
|
|
267
|
+
const pillBadge = snap.factor === 1 ? "1\xD7" : `${fmt(snap.factor)}\xD7`;
|
|
268
|
+
return createPortal(
|
|
269
|
+
/* @__PURE__ */ jsx("div", { className: rootClass, style: { "--mdt-offset": `${offset}px` }, children: /* @__PURE__ */ jsxs("div", { className: "mdt__panel" + (open ? " is-open" : ""), role: "group", "aria-label": "Motion devtools", children: [
|
|
270
|
+
/* @__PURE__ */ jsxs(
|
|
271
|
+
"button",
|
|
272
|
+
{
|
|
273
|
+
className: "mdt__head",
|
|
274
|
+
onClick: () => setOpen((o) => !o),
|
|
275
|
+
"aria-expanded": open,
|
|
276
|
+
title: "Motion devtools",
|
|
277
|
+
"aria-label": open ? "Collapse motion devtools" : "Expand motion devtools",
|
|
278
|
+
children: [
|
|
279
|
+
/* @__PURE__ */ jsx(GaugeGlyph, {}),
|
|
280
|
+
/* @__PURE__ */ jsx("span", { className: "mdt__spacer" }),
|
|
281
|
+
/* @__PURE__ */ jsx("span", { className: "mdt__badge", children: pillBadge }),
|
|
282
|
+
/* @__PURE__ */ jsx(
|
|
283
|
+
"svg",
|
|
284
|
+
{
|
|
285
|
+
className: "mdt__chevron" + (open ? " mdt__chevron--open" : ""),
|
|
286
|
+
width: "12",
|
|
287
|
+
height: "12",
|
|
288
|
+
viewBox: "0 0 12 12",
|
|
289
|
+
"aria-hidden": "true",
|
|
290
|
+
children: /* @__PURE__ */ jsx("path", { d: "M2.5 4.5 6 8l3.5-3.5", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" })
|
|
291
|
+
}
|
|
292
|
+
)
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
),
|
|
296
|
+
/* @__PURE__ */ jsx(Collapse, { open, fade: true, children: /* @__PURE__ */ jsxs("div", { className: "mdt__body", children: [
|
|
297
|
+
/* @__PURE__ */ jsx("span", { className: "mdt__title", children: "Motion" }),
|
|
298
|
+
/* @__PURE__ */ jsxs("div", { className: "mdt__readout", children: [
|
|
299
|
+
/* @__PURE__ */ jsx("span", { className: "mdt__value", children: snap.paused ? "Paused" : snap.factor === 1 ? "Normal" : `${fmt(snap.factor)}\xD7` }),
|
|
300
|
+
/* @__PURE__ */ jsx("span", { className: "mdt__unit", children: snap.paused ? "frozen" : snap.factor === 1 ? "real-time" : "slower" })
|
|
301
|
+
] }),
|
|
302
|
+
/* @__PURE__ */ jsx(
|
|
303
|
+
"input",
|
|
304
|
+
{
|
|
305
|
+
className: "mdt__slider",
|
|
306
|
+
type: "range",
|
|
307
|
+
min: 1,
|
|
308
|
+
max: maxFactor,
|
|
309
|
+
step: 0.5,
|
|
310
|
+
value: Math.min(snap.factor, maxFactor),
|
|
311
|
+
onChange: (e) => setFactor(Number(e.target.value)),
|
|
312
|
+
style: { "--mdt-fill": fill },
|
|
313
|
+
"aria-label": "Slow-down factor"
|
|
314
|
+
}
|
|
315
|
+
),
|
|
316
|
+
/* @__PURE__ */ jsx("div", { className: "mdt__chips", children: presets.map((p) => /* @__PURE__ */ jsxs(
|
|
317
|
+
Button,
|
|
318
|
+
{
|
|
319
|
+
size: "sm",
|
|
320
|
+
variant: !snap.paused && snap.factor === p ? "primary" : "secondary",
|
|
321
|
+
onClick: () => setFactor(p),
|
|
322
|
+
children: [
|
|
323
|
+
p,
|
|
324
|
+
"\xD7"
|
|
325
|
+
]
|
|
326
|
+
},
|
|
327
|
+
p
|
|
328
|
+
)) }),
|
|
329
|
+
/* @__PURE__ */ jsxs("div", { className: "mdt__row", children: [
|
|
330
|
+
/* @__PURE__ */ jsx(
|
|
331
|
+
Button,
|
|
332
|
+
{
|
|
333
|
+
size: "sm",
|
|
334
|
+
variant: snap.paused ? "primary" : "secondary",
|
|
335
|
+
onClick: () => motionSlowmo.set({ paused: !snap.paused }),
|
|
336
|
+
children: snap.paused ? "Resume" : "Freeze"
|
|
337
|
+
}
|
|
338
|
+
),
|
|
339
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", disabled: !active2, onClick: () => motionSlowmo.reset(), children: "Reset" })
|
|
340
|
+
] }),
|
|
341
|
+
/* @__PURE__ */ jsxs("div", { className: "mdt__opt", children: [
|
|
342
|
+
/* @__PURE__ */ jsx(Checkbox, { size: "sm", checked: timers, onChange: (e) => setTimers(e.target.checked), label: "Scale timers" }),
|
|
343
|
+
/* @__PURE__ */ jsx("p", { className: "mdt__hint", children: "Slows CSS, Motion & WAAPI together. Timer scaling keeps duration-based cleanups from cutting animations short." })
|
|
344
|
+
] })
|
|
345
|
+
] }) })
|
|
346
|
+
] }) }),
|
|
347
|
+
document.body
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
var MotionDevtools_default = MotionDevtools;
|
|
351
|
+
|
|
352
|
+
export { MotionDevtools, MotionDevtools_default as default, motionSlowmo };
|
|
353
|
+
//# sourceMappingURL=motion-devtools.js.map
|
|
354
|
+
//# sourceMappingURL=motion-devtools.js.map
|