@grahlnn/comps 0.1.2 → 0.1.4

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/index.js CHANGED
@@ -2523,6 +2523,7 @@ var MORPH = {
2523
2523
  maxFadeMs: 150,
2524
2524
  ease: "cubic-bezier(0.22, 1, 0.36, 1)",
2525
2525
  geometryEpsilon: 0.5,
2526
+ contentWidthLockEpsilon: 2,
2526
2527
  lineGroupingEpsilon: 1
2527
2528
  };
2528
2529
  var MORPH_SEGMENT_CACHE_LIMIT = 256;
@@ -2930,6 +2931,15 @@ function getDomMeasurementRequestKey(text, renderText, layoutContext, useContent
2930
2931
  }
2931
2932
  return `dom\x00${inlineSizeMode}\x00${text}\x00${renderText}\x00${layoutContext.measurementVersion}\x00${getMorphMeasurementEpoch()}`;
2932
2933
  }
2934
+ function needsMeasurementLayer(measurementBackend, renderText) {
2935
+ if (measurementBackend === "pretext") {
2936
+ return false;
2937
+ }
2938
+ return renderText.length > 0;
2939
+ }
2940
+ function canCacheMeasurementLayerSnapshot(measurementBackend) {
2941
+ return measurementBackend === "dom";
2942
+ }
2933
2943
  function readCachedMorphSnapshot(cache, cacheKey) {
2934
2944
  const cached = cache.get(cacheKey);
2935
2945
  if (cached === undefined) {
@@ -3099,7 +3109,7 @@ function shouldMeasureUsingContentInlineSize(layoutContext, layoutHint) {
3099
3109
  if (layoutHint === null || !isSingleLineSnapshot(layoutHint.snapshot)) {
3100
3110
  return false;
3101
3111
  }
3102
- return nearlyEqual(layoutHint.layoutInlineSize, layoutHint.snapshot.width);
3112
+ return nearlyEqual(layoutHint.layoutInlineSize, layoutHint.snapshot.width, MORPH.contentWidthLockEpsilon);
3103
3113
  }
3104
3114
  function createMorphMeasurementRequest({
3105
3115
  text,
@@ -3117,7 +3127,7 @@ function createMorphMeasurementRequest({
3117
3127
  segments = EMPTY_SEGMENTS;
3118
3128
  }
3119
3129
  let domMeasurementKey = null;
3120
- if (measurementBackend === "dom" && renderText.length > 0) {
3130
+ if (needsMeasurementLayer(measurementBackend, renderText)) {
3121
3131
  domMeasurementKey = getDomMeasurementRequestKey(text, renderText, layoutContext, useContentInlineSize);
3122
3132
  }
3123
3133
  return {
@@ -3189,17 +3199,19 @@ function measureFromNodes({
3189
3199
  pretextSnapshot = measureMorphSnapshotWithPretext(text, measurementLayoutContext);
3190
3200
  }
3191
3201
  let domSnapshot = null;
3192
- if (measurementBackend === "dom") {
3193
- domSnapshot = measureMorphSnapshotFromLayer(text, renderText, segments, layer);
3194
- } else if (measurementBackend !== "pretext") {
3195
- domSnapshot = measureMorphSnapshotWithDomService({
3196
- root,
3197
- layoutContext,
3198
- text,
3199
- renderText,
3200
- segments,
3201
- useContentInlineSize
3202
- });
3202
+ if (measurementBackend !== "pretext") {
3203
+ if (layer !== null) {
3204
+ domSnapshot = measureMorphSnapshotFromLayer(text, renderText, segments, layer);
3205
+ } else {
3206
+ domSnapshot = measureMorphSnapshotWithDomService({
3207
+ root,
3208
+ layoutContext,
3209
+ text,
3210
+ renderText,
3211
+ segments,
3212
+ useContentInlineSize
3213
+ });
3214
+ }
3203
3215
  }
3204
3216
  if (measurementBackend === "probe" && pretextSnapshot !== null && domSnapshot !== null) {
3205
3217
  const trusted = areSnapshotsEquivalentForPretextTrust(pretextSnapshot, domSnapshot);
@@ -3423,10 +3435,18 @@ function resetMorph(session, timeline, setState) {
3423
3435
  setState(EMPTY_STATE);
3424
3436
  }
3425
3437
  function commitStaticMeasurement(session, measurement, setState) {
3438
+ if (!session.animating && session.target === null && session.committed !== null && sameMeasurement(session.committed, measurement)) {
3439
+ return;
3440
+ }
3426
3441
  session.committed = measurement;
3427
3442
  session.target = null;
3428
3443
  session.animating = false;
3429
- setState(createStaticState(measurement));
3444
+ setState((current) => {
3445
+ if (current.stage === "idle" && current.plan === null && current.measurement !== null && sameMeasurement(current.measurement, measurement)) {
3446
+ return current;
3447
+ }
3448
+ return createStaticState(measurement);
3449
+ });
3430
3450
  }
3431
3451
  function scheduleMorphTimeline({
3432
3452
  session,
@@ -3810,7 +3830,7 @@ function useMorphTransition(text, className, bootstrapText = null) {
3810
3830
  const measurementBackend = measurementRequest?.measurementBackend ?? null;
3811
3831
  const segments = measurementRequest?.segments ?? EMPTY_SEGMENTS;
3812
3832
  const domMeasurementKey = measurementRequest?.domMeasurementKey ?? null;
3813
- const shouldRenderBootstrapSourceMeasurementLayer = bootstrapMeasurementRequest?.measurementBackend === "dom" && bootstrapMeasurementRequest.renderText.length > 0;
3833
+ const shouldRenderBootstrapSourceMeasurementLayer = bootstrapMeasurementRequest?.domMeasurementKey !== null;
3814
3834
  useLayoutEffect(() => {
3815
3835
  if (ref.current === null || layoutContext === null) {
3816
3836
  completedDomMeasurementKeyRef.current = null;
@@ -3834,7 +3854,7 @@ function useMorphTransition(text, className, bootstrapText = null) {
3834
3854
  }
3835
3855
  if (pendingBootstrapText !== null && pendingBootstrapText !== text && bootstrapMeasurementRequest !== null && measurementRequest !== null) {
3836
3856
  let bootstrapDomSnapshot = null;
3837
- if (bootstrapMeasurementRequest.domMeasurementKey !== null) {
3857
+ if (bootstrapMeasurementRequest.domMeasurementKey !== null && canCacheMeasurementLayerSnapshot(bootstrapMeasurementRequest.measurementBackend)) {
3838
3858
  bootstrapDomSnapshot = readCachedMorphSnapshot(domMeasurementSnapshotCacheRef.current, bootstrapMeasurementRequest.domMeasurementKey);
3839
3859
  }
3840
3860
  if (bootstrapMeasurementRequest.domMeasurementKey !== null && bootstrapDomSnapshot === null && bootstrapMeasurementLayerRef.current === null) {
@@ -3851,7 +3871,7 @@ function useMorphTransition(text, className, bootstrapText = null) {
3851
3871
  renderText: bootstrapMeasurementRequest.renderText,
3852
3872
  segments: bootstrapMeasurementRequest.segments
3853
3873
  });
3854
- if (bootstrapMeasurementRequest.domMeasurementKey !== null && bootstrapDomSnapshot === null) {
3874
+ if (bootstrapMeasurementRequest.domMeasurementKey !== null && bootstrapDomSnapshot === null && canCacheMeasurementLayerSnapshot(bootstrapMeasurementRequest.measurementBackend)) {
3855
3875
  rememberCachedMorphSnapshot(domMeasurementSnapshotCacheRef.current, bootstrapMeasurementRequest.domMeasurementKey, bootstrapMeasurement.snapshot);
3856
3876
  }
3857
3877
  completedDomMeasurementKeyRef.current = null;
@@ -3863,7 +3883,10 @@ function useMorphTransition(text, className, bootstrapText = null) {
3863
3883
  return;
3864
3884
  }
3865
3885
  if (domMeasurementKey !== null) {
3866
- const cachedSnapshot = readCachedMorphSnapshot(domMeasurementSnapshotCacheRef.current, domMeasurementKey);
3886
+ let cachedSnapshot = null;
3887
+ if (canCacheMeasurementLayerSnapshot(measurementBackend)) {
3888
+ cachedSnapshot = readCachedMorphSnapshot(domMeasurementSnapshotCacheRef.current, domMeasurementKey);
3889
+ }
3867
3890
  if (cachedSnapshot !== null) {
3868
3891
  completedDomMeasurementKeyRef.current = domMeasurementKey;
3869
3892
  if (domMeasurementRequestKey !== null) {
@@ -3906,7 +3929,9 @@ function useMorphTransition(text, className, bootstrapText = null) {
3906
3929
  setState
3907
3930
  });
3908
3931
  if (nextMeasurement !== null) {
3909
- rememberCachedMorphSnapshot(domMeasurementSnapshotCacheRef.current, domMeasurementKey, nextMeasurement.snapshot);
3932
+ if (canCacheMeasurementLayerSnapshot(measurementBackend)) {
3933
+ rememberCachedMorphSnapshot(domMeasurementSnapshotCacheRef.current, domMeasurementKey, nextMeasurement.snapshot);
3934
+ }
3910
3935
  }
3911
3936
  completedDomMeasurementKeyRef.current = domMeasurementKey;
3912
3937
  if (domMeasurementRequestKey !== null) {
@@ -4017,7 +4042,7 @@ function ActiveTorph({
4017
4042
  } = useMorphTransition(text, className, bootstrapText);
4018
4043
  const plan = state.plan;
4019
4044
  const shouldRenderOverlay = state.stage !== "idle" && plan !== null;
4020
- const shouldRenderMeasurementLayer = measurementBackend === "dom" && domMeasurementRequestKey !== null;
4045
+ const shouldRenderMeasurementLayer = domMeasurementRequestKey !== null;
4021
4046
  const flowText = resolveVisibleFlowText(pendingBootstrapText, committedMeasurement, state.measurement, text);
4022
4047
  let bootstrapMeasurementLayer = null;
4023
4048
  if (shouldRenderBootstrapSourceMeasurementLayer && bootstrapMeasurementRequest !== null) {
@@ -4101,6 +4126,7 @@ export {
4101
4126
  resolveFlowText,
4102
4127
  resolveActivationBootstrapText,
4103
4128
  pairMorphCharacters,
4129
+ needsMeasurementLayer,
4104
4130
  measureMorphSnapshotFromLayer,
4105
4131
  getRootStyle,
4106
4132
  getRootDisplay,
@@ -1,4 +1,5 @@
1
1
  import { type CSSProperties } from "react";
2
+ import { type PretextMorphMeasurementBackend } from "../utils/text-layout/pretextMorph";
2
3
  export type SupportedWhiteSpace = "normal" | "nowrap" | "pre-wrap";
3
4
  export type MorphCharacterLayout = {
4
5
  glyph: string;
@@ -76,6 +77,7 @@ type GlyphExit = {
76
77
  from: MorphCharacterLayout;
77
78
  };
78
79
  type GlyphPairing = GlyphMove | GlyphEnter | GlyphExit;
80
+ export declare function needsMeasurementLayer(measurementBackend: PretextMorphMeasurementBackend, renderText: string): boolean;
79
81
  export declare function measureMorphSnapshotFromLayer(text: string, renderText: string, segments: readonly MorphSegment[], layer: HTMLElement | null): MorphSnapshot;
80
82
  export declare function pairMorphCharacters(previous: MorphCharacterLayout[], next: MorphCharacterLayout[]): GlyphPairing[];
81
83
  export declare function resolveMorphFrameBounds(previous: MorphSnapshot, next: MorphSnapshot): {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grahlnn/comps",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "React components from grahlnn/comps.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",