@tobiasoberpaul/mdk 0.3.0 → 0.4.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/README.md CHANGED
@@ -25,7 +25,7 @@ Your component manages layout, visibility, focus and accessibility. MDK handles
25
25
 
26
26
  For an existing popover or menu, use `createPresenceMotion` to connect its open and close signals. Use `resize: 'transform'` with `createGrowTransition` for local growth on a surface positioned by the host. [Integration guide](https://github.com/TOberpaul/animations/blob/main/docs/LIBRARY.md#animate-an-existing-component)
27
27
 
28
- The library includes Grow, Extract, Morph, Slide and Content transitions. See the [library guide](https://github.com/TOberpaul/animations/blob/main/docs/LIBRARY.md) for the API, CSS tokens and integration patterns.
28
+ The library includes Grow, Extract, Morph, Slide and Fade. See the [library guide](https://github.com/TOberpaul/animations/blob/main/docs/LIBRARY.md) for the API, CSS tokens and integration patterns.
29
29
 
30
30
  Coding assistants can access the MDK reference and integration examples through the public MCP server. See the [MCP setup](https://github.com/TOberpaul/animations/blob/main/docs/AI_INTEGRATION.md#hosted-mcp).
31
31
 
package/dist/behaviors.js CHANGED
@@ -7,13 +7,11 @@ export const motionBehaviors = {
7
7
  };
8
8
  /** Canonical naming shared by declarative integration and consuming components. */
9
9
  export function getMotionKind(content) {
10
- const names = [...Object.keys(motionBehaviors), 'liquid', 'content'];
10
+ const names = [...Object.keys(motionBehaviors), 'content'];
11
11
  const classes = names.filter(name => content.classList.contains(`motion-${name}`));
12
12
  const raw = content.dataset.motion ?? (classes.length === 1 ? classes[0] : undefined);
13
13
  if (raw === 'content')
14
14
  return 'fade';
15
- if (raw === 'liquid')
16
- return content.hasAttribute('data-motion-replace-trigger') ? 'morph' : 'extract';
17
15
  if (!raw || !Object.prototype.hasOwnProperty.call(motionBehaviors, raw))
18
16
  throw new Error('Set data-motion to grow, extract, morph, slide or fade, or use one matching motion-* class.');
19
17
  return raw;
@@ -52,7 +52,7 @@ export function createTransition(options, pattern, tracks, behavior = {}) {
52
52
  }
53
53
  const requestedEasing = token(content, `easing-${pattern}`);
54
54
  const easing = CSS.supports('animation-timing-function', requestedEasing) ? requestedEasing : token(content, 'easing-standard');
55
- const recipe = motionBehaviors[(pattern === 'scale' ? 'grow' : pattern === 'liquid' ? 'extract' : pattern === 'content' ? 'fade' : pattern)];
55
+ const recipe = motionBehaviors[(pattern === 'scale' ? 'grow' : pattern === 'transfer' ? 'extract' : pattern === 'content' ? 'fade' : pattern)];
56
56
  const descriptions = tracks();
57
57
  time *= behavior.durationScale?.() ?? 1;
58
58
  const reveal = options.reveal ? (Array.isArray(options.reveal) ? options.reveal : [options.reveal]) : [];
@@ -152,32 +152,50 @@ function scaleOrigin(content) {
152
152
  const block = horizontal ? ['top', 'bottom'] : writingMode.endsWith('-rl') ? ['right', 'left'] : ['left', 'right'];
153
153
  return origin.replace(/\b(inline|block)-(start|end)\b/g, (_, axis, edge) => (axis === 'inline' ? inline : block)[edge === 'start' ? 0 : 1]);
154
154
  }
155
+ function measureScaleOrigin(content, style, origin, width, height) {
156
+ const probe = content.ownerDocument.createElement('span');
157
+ probe.style.cssText = 'all:initial;position:fixed;visibility:hidden;pointer-events:none;transition:none!important;animation:none!important';
158
+ for (const name of ['font-size', 'font-family', 'line-height']) {
159
+ probe.style.setProperty(name, style.getPropertyValue(name));
160
+ }
161
+ const contentBox = style.transformBox === 'content-box' || style.transformBox === 'fill-box';
162
+ const inset = (side) => contentBox
163
+ ? parseFloat(style.getPropertyValue('padding-' + side)) + parseFloat(style.getPropertyValue('border-' + side + '-width'))
164
+ : 0;
165
+ const left = inset('left'), top = inset('top');
166
+ probe.style.width = `${Math.max(0, width - left - inset('right'))}px`;
167
+ probe.style.height = `${Math.max(0, height - top - inset('bottom'))}px`;
168
+ const read = () => getComputedStyle(probe).transformOrigin.split(' ').map(parseFloat);
169
+ let hostOrigin = style.transformOrigin.split(' ').map(parseFloat);
170
+ const parent = contentBox ? content : content.ownerDocument.body;
171
+ // Resolve keywords and percentages without starting a CSS transition on the host surface.
172
+ parent.appendChild(probe);
173
+ try {
174
+ // Resolved host styles can report percentages in border-box pixels even
175
+ // when transforms use the content box. Inherit onto the sized probe.
176
+ if (contentBox) {
177
+ probe.style.setProperty('transform-origin', 'inherit', 'important');
178
+ hostOrigin = read();
179
+ }
180
+ probe.style.setProperty('transform-origin', origin, 'important');
181
+ const [x, y] = read();
182
+ return { x: x + left, y: y + top, dx: x - hostOrigin[0], dy: y - hostOrigin[1] };
183
+ }
184
+ finally {
185
+ probe.remove();
186
+ }
187
+ }
155
188
  function transformGrowTracks(options) {
156
189
  const { content, axis } = options;
157
190
  const style = getComputedStyle(content);
158
- const hostOrigin = style.transformOrigin.split(' ').map(parseFloat);
159
191
  const opacity = style.opacity;
160
- const property = 'transform-origin';
161
- const inlineOrigin = content.style.getPropertyValue(property);
162
- const priority = content.style.getPropertyPriority(property);
163
192
  const origin = scaleOrigin(content);
164
- if (!CSS.supports(property, origin))
193
+ if (!CSS.supports('transform-origin', origin))
165
194
  throw new Error('Invalid --motion-scale-origin.');
166
- let x, y;
167
- try {
168
- content.style.setProperty(property, origin, 'important');
169
- [x, y] = style.transformOrigin.split(' ').map(parseFloat);
170
- }
171
- finally {
172
- if (inlineOrigin)
173
- content.style.setProperty(property, inlineOrigin, priority);
174
- else
175
- content.style.removeProperty(property);
176
- }
177
195
  const { width, height } = localScale(content, content.getBoundingClientRect());
178
196
  if (!width || !height)
179
197
  throw new Error('Grow content must be measurable before animation.');
180
- const dx = x - hostOrigin[0], dy = y - hostOrigin[1];
198
+ const { x, y, dx, dy } = measureScaleOrigin(content, style, origin, width, height);
181
199
  const end = numberToken(content, 'scale-geometry-end');
182
200
  if (end <= 0 || end > 1)
183
201
  throw new Error('Scale geometry end must satisfy 0 < end <= 1.');
package/dist/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
1
  export { createMorphTransition } from './transitions/morph.js';
2
- export { createLiquidMorphTransition } from './transitions/liquid.js';
3
- export type { LiquidMorphOptions, LiquidMorphTransition } from './transitions/liquid.js';
4
2
  export type { MorphOptions } from './transitions/morph.js';
5
3
  export { createSlideTransition } from './transitions/slide.js';
6
4
  export type { SlideOptions } from './transitions/slide.js';
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export { createMorphTransition } from './transitions/morph.js';
2
- export { createLiquidMorphTransition } from './transitions/liquid.js';
3
2
  export { createSlideTransition } from './transitions/slide.js';
4
3
  export { createScaleTransition } from './transitions/scale.js';
5
4
  export { createContentTransition } from './transitions/content.js';
@@ -58,19 +58,19 @@
58
58
  --motion-scale-origin: center center;
59
59
  --motion-slide-distance: 100%;
60
60
  --motion-slide-peak-offset: .8;
61
- --motion-duration-liquid: var(--motion-duration);
62
- --motion-easing-liquid: var(--motion-easing-standard);
63
- --motion-liquid-geometry-end: .8;
64
- --motion-liquid-reveal-offset: .3;
65
- --motion-liquid-reveal-end: var(--motion-liquid-geometry-end);
66
- --motion-liquid-reveal-blur: var(--motion-reveal-blur);
67
- --motion-liquid-volume-offset: .18;
68
- --motion-liquid-source-hide-start: var(--motion-liquid-reveal-offset);
69
- --motion-liquid-source-hide-end: var(--motion-liquid-reveal-end);
70
- --motion-liquid-source-blur: var(--motion-liquid-reveal-blur);
71
- --motion-liquid-peak-offset: .5;
61
+ --motion-duration-transfer: var(--motion-duration);
62
+ --motion-easing-transfer: var(--motion-easing-standard);
63
+ --motion-transfer-geometry-end: .8;
64
+ --motion-transfer-reveal-offset: .3;
65
+ --motion-transfer-reveal-end: var(--motion-transfer-geometry-end);
66
+ --motion-transfer-reveal-blur: var(--motion-reveal-blur);
67
+ --motion-transfer-volume-offset: .18;
68
+ --motion-transfer-source-hide-start: var(--motion-transfer-reveal-offset);
69
+ --motion-transfer-source-hide-end: var(--motion-transfer-reveal-end);
70
+ --motion-transfer-source-blur: var(--motion-transfer-reveal-blur);
71
+ --motion-transfer-peak-offset: .5;
72
72
  --motion-overshoot-max: .75rem;
73
73
  }
74
74
  @media (prefers-reduced-motion: reduce) {
75
- :root { --motion-duration-morph: 0ms; --motion-duration-slide: 0ms; --motion-duration-scale: 0ms; --motion-duration-backdrop: 0ms; --motion-duration-content: 0ms; --motion-duration-liquid: 0ms; }
75
+ :root { --motion-duration-morph: 0ms; --motion-duration-slide: 0ms; --motion-duration-scale: 0ms; --motion-duration-backdrop: 0ms; --motion-duration-content: 0ms; --motion-duration-transfer: 0ms; }
76
76
  }
@@ -1,5 +1,5 @@
1
- import { type LiquidMorphOptions } from './liquid.js';
1
+ import { type SurfaceTransferOptions } from './surface-transfer.js';
2
2
  import type { Transition } from '../core/lifecycle.js';
3
- export type ExtractOptions = Omit<LiquidMorphOptions, 'replaceTrigger'>;
3
+ export type ExtractOptions = Omit<SurfaceTransferOptions, 'replaceTrigger'>;
4
4
  /** Extract a new surface while retaining the original trigger. */
5
5
  export declare function createExtractTransition(options: ExtractOptions): Transition;
@@ -1,5 +1,5 @@
1
- import { createLiquidMorphTransition } from './liquid.js';
1
+ import { createSurfaceTransfer } from './surface-transfer.js';
2
2
  /** Extract a new surface while retaining the original trigger. */
3
3
  export function createExtractTransition(options) {
4
- return createLiquidMorphTransition({ ...options, replaceTrigger: false });
4
+ return createSurfaceTransfer({ ...options, replaceTrigger: false });
5
5
  }
@@ -1,5 +1,5 @@
1
- import { type LiquidMorphOptions } from './liquid.js';
1
+ import { type SurfaceTransferOptions } from './surface-transfer.js';
2
2
  import type { Transition } from '../core/lifecycle.js';
3
- export type MorphOptions = Omit<LiquidMorphOptions, 'replaceTrigger'>;
3
+ export type MorphOptions = Omit<SurfaceTransferOptions, 'replaceTrigger'>;
4
4
  /** The source becomes the target; the integration manages original-trigger visibility. */
5
5
  export declare function createMorphTransition(options: MorphOptions): Transition;
@@ -1,5 +1,5 @@
1
- import { createLiquidMorphTransition } from './liquid.js';
1
+ import { createSurfaceTransfer } from './surface-transfer.js';
2
2
  /** The source becomes the target; the integration manages original-trigger visibility. */
3
3
  export function createMorphTransition(options) {
4
- return createLiquidMorphTransition({ ...options, replaceTrigger: true });
4
+ return createSurfaceTransfer({ ...options, replaceTrigger: true });
5
5
  }
@@ -1,5 +1,5 @@
1
1
  import type { Options, Transition } from '../core/lifecycle.js';
2
- export interface LiquidMorphOptions extends Options {
2
+ export interface SurfaceTransferOptions extends Options {
3
3
  /** Distinct node: retain the source. Same node as content: become the target.
4
4
  * For the same node, prepare the expanded layout synchronously on opening
5
5
  * and restore its compact layout only on closed. Initialize closed. */
@@ -8,6 +8,5 @@ export interface LiquidMorphOptions extends Options {
8
8
  * trigger. The component hides/shows that trigger in onStateChange. */
9
9
  replaceTrigger?: boolean;
10
10
  }
11
- export type LiquidMorphTransition = Transition;
12
- /** One liquid behavior for separate surfaces and a trigger becoming the target. */
13
- export declare function createLiquidMorphTransition(options: LiquidMorphOptions): LiquidMorphTransition;
11
+ /** Shared surface and foreground animation for Extract and Morph. */
12
+ export declare function createSurfaceTransfer(options: SurfaceTransferOptions): Transition;
@@ -38,12 +38,12 @@ function visibleBackground(element) {
38
38
  const [r, g, b] = context.getImageData(0, 0, 1, 1).data;
39
39
  return `rgb(${r},${g},${b})`;
40
40
  }
41
- /** One liquid behavior for separate surfaces and a trigger becoming the target. */
42
- export function createLiquidMorphTransition(options) {
41
+ /** Shared surface and foreground animation for Extract and Morph. */
42
+ export function createSurfaceTransfer(options) {
43
43
  const sameElement = options.trigger === options.content;
44
44
  const replacesTrigger = sameElement || options.replaceTrigger;
45
45
  if (replacesTrigger && options.initiallyOpen)
46
- throw new Error('A replacing liquid morph must initialize in its closed layout.');
46
+ throw new Error('A replacing transfer morph must initialize in its closed layout.');
47
47
  let previous = options.initiallyOpen ? 'open' : 'closed';
48
48
  let closed;
49
49
  let overlay;
@@ -78,7 +78,7 @@ export function createLiquidMorphTransition(options) {
78
78
  remove();
79
79
  }
80
80
  options.onStateChange?.(state);
81
- } }, 'liquid', () => {
81
+ } }, 'transfer', () => {
82
82
  remove();
83
83
  const { content, trigger } = options;
84
84
  const box = content.getBoundingClientRect(), source = replacesTrigger ? closed.rect : trigger.getBoundingClientRect();
@@ -88,7 +88,7 @@ export function createLiquidMorphTransition(options) {
88
88
  const width = px(style.width) + (style.boxSizing === 'border-box' ? 0 : extraX);
89
89
  const height = px(style.height) + (style.boxSizing === 'border-box' ? 0 : extraY);
90
90
  if (!width || !height || !source.width || !source.height)
91
- throw new Error('Liquid morph elements must be measurable.');
91
+ throw new Error('Surface transfer elements must be measurable.');
92
92
  const scaleX = box.width / width, scaleY = box.height / height;
93
93
  const left = (source.left - box.left) / scaleX, top = (source.top - box.top) / scaleY;
94
94
  const sw = source.width / scaleX, sh = source.height / scaleY;
@@ -102,10 +102,10 @@ export function createLiquidMorphTransition(options) {
102
102
  const borderFrom = replacesTrigger ? closed.border : triggerStyle.borderTopColor, borderTo = style.borderTopColor;
103
103
  const swell = overshootToken(content, 'overshoot-max', sw, sh);
104
104
  const overshoot = overshootToken(content, 'overshoot-max', width, height);
105
- const volume = numberToken(content, 'liquid-volume-offset'), peak = numberToken(content, 'liquid-peak-offset');
106
- const end = numberToken(content, 'liquid-geometry-end');
105
+ const volume = numberToken(content, 'transfer-volume-offset'), peak = numberToken(content, 'transfer-peak-offset');
106
+ const end = numberToken(content, 'transfer-geometry-end');
107
107
  if (!(swell >= 0 && overshoot >= 0 && volume > 0 && volume < peak && peak < end && end < 1))
108
- throw new Error('Invalid liquid geometry tokens.');
108
+ throw new Error('Invalid transfer geometry tokens.');
109
109
  // The initial volume phase swells the trigger symmetrically. Only the target
110
110
  // grows away from its component-owned anchor; preserve their envelope.
111
111
  const anchor = explicitMotionAnchor(content) ?? growthAnchor(source, box);
@@ -140,9 +140,9 @@ export function createLiquidMorphTransition(options) {
140
140
  triggerCopy = replacesTrigger ? closed.copy.cloneNode(true) : copyTrigger(trigger);
141
141
  Object.assign(triggerCopy.style, { position: 'absolute', left: (left - px(style.borderLeftWidth)) + 'px', top: (top - px(style.borderTopWidth)) + 'px', width: sw + 'px', height: sh + 'px', boxSizing: 'border-box', margin: '0', transform: 'none', transition: 'none', animation: 'none', background: 'transparent', borderColor: 'transparent', boxShadow: 'none', pointerEvents: 'none', zIndex: '0' });
142
142
  content.append(triggerCopy);
143
- const revealStart = numberToken(content, 'liquid-reveal-offset'), revealEnd = numberToken(content, 'liquid-reveal-end');
143
+ const revealStart = numberToken(content, 'transfer-reveal-offset'), revealEnd = numberToken(content, 'transfer-reveal-end');
144
144
  if (revealStart < 0 || revealStart >= revealEnd || revealEnd > 1)
145
- throw new Error('Invalid liquid reveal offsets.');
145
+ throw new Error('Invalid transfer reveal offsets.');
146
146
  const clipFrames = [];
147
147
  // Include the exact volume/peak poses, so frame inspection
148
148
  // reach the configured percentage without resampling error.
@@ -186,13 +186,13 @@ export function createLiquidMorphTransition(options) {
186
186
  ];
187
187
  const overlapsTarget = source.left < box.right && source.right > box.left && source.top < box.bottom && source.bottom > box.top;
188
188
  if (replacesTrigger || overlapsTarget) {
189
- const hideStart = numberToken(content, 'liquid-source-hide-start');
190
- const hideEnd = numberToken(content, 'liquid-source-hide-end');
191
- const blur = token(content, 'liquid-source-blur');
189
+ const hideStart = numberToken(content, 'transfer-source-hide-start');
190
+ const hideEnd = numberToken(content, 'transfer-source-hide-end');
191
+ const blur = token(content, 'transfer-source-blur');
192
192
  if (hideStart < 0 || hideStart >= hideEnd || hideEnd > 1)
193
- throw new Error('Liquid source hide offsets must satisfy 0 <= start < end <= 1.');
193
+ throw new Error('Transfer source hide offsets must satisfy 0 <= start < end <= 1.');
194
194
  if (!CSS.supports('filter', `blur(${blur})`))
195
- throw new Error('Liquid source blur must be a valid non-negative CSS length.');
195
+ throw new Error('Transfer source blur must be a valid non-negative CSS length.');
196
196
  const sourceStyle = getComputedStyle(triggerCopy), filter = sourceStyle.filter;
197
197
  const blurred = `${filter === 'none' ? '' : `${filter} `}blur(${blur})`;
198
198
  // Crossfade both contents over the same interval, without moving the
package/docs/LIBRARY.md CHANGED
@@ -134,6 +134,10 @@ Pass `trigger` only to grow from the trigger's edge. Use
134
134
  host transform and leaves layout dimensions and insets alone. The whole surface
135
135
  scales visually, including its border and content. Set `--motion-overshoot-max: 0`
136
136
  to turn off overshoot. This mode works with `createPresenceMotion`.
137
+ MDK resolves the motion origin without changing the surface's own
138
+ `transform-origin`, so host CSS transitions on that property stay independent.
139
+ The anchor follows the surface's `transform-box`, including `content-box`.
140
+ Origin and dimensions are measured at the start of each animation.
137
141
 
138
142
  The default `resize: 'metrics'` still resizes the actual surface. Grow with a
139
143
  `trigger` continues to use trigger-edge geometry. The local transform mode
@@ -147,7 +151,6 @@ supports HTML surfaces without an SVG overlay.
147
151
  | `createScaleTransition` | Deprecated alias for local Grow | Optional `axis`, `backdrop` |
148
152
  | `createExtractTransition` | Extract a new surface while retaining the trigger | `trigger` |
149
153
  | `createMorphTransition` | Transform the trigger into the target surface | `trigger` |
150
- | `createLiquidMorphTransition` | Source volume → encompassing surface → target | `trigger`; optional `replaceTrigger` |
151
154
  | `createSlideTransition` | Bounded translate3d entry or two-pane shift | Optional `side`, `mode`, `outgoing`, `backdrop` |
152
155
  | `createContentTransition` | Fixed slide + blur + fade | Optional `items`, `reveal`, `timing` |
153
156
  | `createMotion` | Selects a factory from markup | See declarative integration below |
@@ -187,16 +190,17 @@ Public factories, declarative markup and example titles use the same meanings:
187
190
 
188
191
  Migration: the earlier `createMorphTransition` name referred to trigger-edge Grow.
189
192
  Use `createGrowTransition` for that old behavior. `createMorphTransition` now
190
- means replacing Morph, consistent with the examples. The lower-level
191
- `createLiquidMorphTransition` remains available with an explicit
192
- `replaceTrigger` flag, and `createScaleTransition` remains an origin-Grow alias.
193
+ means replacing Morph, consistent with the examples. To migrate from the former
194
+ Liquid API or markup, use Extract when the source stays visible and Morph when
195
+ the source becomes the target. Use the `--motion-transfer-*` and
196
+ `--motion-duration-transfer` tokens for the shared animation settings.
193
197
 
194
198
  Extract retains the original trigger. Replacing Morph snapshots its foreground,
195
199
  then crossfades that foreground into target content while one material surface
196
200
  moves between the geometries. The integration hides/inerts the real trigger
197
201
  until closed and restores it afterward. This avoids nested interactive controls.
198
202
 
199
- Liquid animates a temporary HTML surface with CSS dimensions, corners, background and borders. It removes the temporary surface and foreground
203
+ Extract and Morph animate a temporary HTML surface with CSS dimensions, corners, background and borders. They remove the temporary surface and foreground
200
204
  copy at rest. The resting UI is the real HTML component. Trigger swelling is a
201
205
  phase of the click animation; there is no press/hold feature or press/release API.
202
206
 
@@ -207,7 +211,7 @@ the right edge. Both buttons remain visible and the main action is independent.
207
211
 
208
212
  ### Material source and composite inputs
209
213
 
210
- Liquid reads material values from `content`. If a component wrapper is
214
+ Extract and Morph read material values from `content`. If a component wrapper is
211
215
  transparent/borderless but a nested input paints the real material, explicitly
212
216
  prepare a surface with the input's background, border and radius before the
213
217
  motion snapshot. During travel, prevent the inner control from painting a second
@@ -263,12 +267,10 @@ const transition = createMotion({
263
267
  | `data-motion-axis` | Grow axis: `width` or `height` |
264
268
  | `data-motion-side` | Slide entry side |
265
269
  | `data-motion-timing` | Content: `per-item` (default) or `total` |
266
- | `data-motion-replace-trigger` | Presence enables replacing Liquid |
267
270
 
268
271
  An explicit `data-motion` takes precedence over classes. Without it, use exactly
269
272
  one matching class. Declarative `morph` selects the replacing Morph factory directly.
270
- The deprecated `liquid` / `motion-liquid` spelling remains a compatibility path; its
271
- `data-motion-replace-trigger` flag retains its original meaning. Recreate the controller to change behavior after
273
+ Recreate the controller to change behavior after
272
274
  initialization. Change CSS tokens for per-trip visual parameters.
273
275
 
274
276
  ## Content progression and ordering
@@ -362,7 +364,7 @@ can be overridden locally on a surface or globally.
362
364
 
363
365
  | Token | Library default / meaning |
364
366
  | --- | --- |
365
- | `--motion-duration` | `300ms`; aliases for morph, scale, liquid, slide, content, backdrop |
367
+ | `--motion-duration` | `300ms`; aliases for morph, scale, transfer, slide, content, backdrop |
366
368
  | `--motion-easing-standard` | `cubic-bezier(.42, 0, .58, 1)`; symmetric open/close |
367
369
  | `--motion-overshoot-ratio` | `15%` of the surface's shorter side by default. When unset, reads the legacy `--motion-overshoot-min` token. |
368
370
  | `--motion-overshoot-max` | `.75rem` cap shared by trigger and target; morph/scale alias this |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tobiasoberpaul/mdk",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -14,7 +14,7 @@
14
14
  "./motion.css": "./dist/styles/motion.css"
15
15
  },
16
16
  "scripts": {
17
- "build": "tsc && node scripts/copy-css.mjs",
17
+ "build": "node scripts/clean-dist.mjs && tsc && node scripts/copy-css.mjs",
18
18
  "build:examples": "node scripts/build-db-react.mjs && node scripts/build-shadcn.mjs",
19
19
  "build:shadcn": "node scripts/build-shadcn.mjs",
20
20
  "analytics": "node context-starter/analytics/serve.mjs . --codex-history",