fontdue-js 2.15.0 → 2.15.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 2.15.1
2
+
3
+ - Fixes SSR hydration issues
4
+
5
+ ## 2.15.0
6
+
7
+ - Compatibility with React 19
8
+
1
9
  ## 2.14.0
2
10
 
3
11
  - Adds stripe.appearance to the config
@@ -33,13 +33,20 @@ function useSize() {
33
33
  if (!ref.current) return;
34
34
  setSize(ref.current.getBoundingClientRect());
35
35
  }, [ref]);
36
- (0, _resizeObserver.default)(ref, entry => setSize(entry.contentRect));
36
+ (0, _resizeObserver.default)(ref, entry => setSize(entry.contentRect), {
37
+ polyfill: typeof window === 'undefined' ? ServerSideResizeObserverPolyfill : null
38
+ });
37
39
  return {
38
40
  ref,
39
41
  width: size === null || size === void 0 ? void 0 : size.width,
40
42
  height: size === null || size === void 0 ? void 0 : size.height
41
43
  };
42
44
  }
45
+ class ServerSideResizeObserverPolyfill {
46
+ constructor(_callback) {}
47
+ observe(_target, _options) {}
48
+ unobserve(_target) {}
49
+ }
43
50
  function Character(props) {
44
51
  const ref = (0, _react.useRef)(null);
45
52
  const [size, setSize] = (0, _react.useState)(1);
@@ -47,6 +54,8 @@ function Character(props) {
47
54
  if (entry.target.scrollWidth > entry.target.clientWidth) {
48
55
  setSize(size + 1);
49
56
  }
57
+ }, {
58
+ polyfill: typeof window === 'undefined' ? ServerSideResizeObserverPolyfill : null
50
59
  });
51
60
  return /*#__PURE__*/_react.default.createElement("div", _extends({
52
61
  ref: ref
@@ -7,8 +7,8 @@ export interface TypeTesters_props {
7
7
  collectionSlug?: string;
8
8
  defaultMode?: 'group' | 'local';
9
9
  autofit?: boolean;
10
- tags?: string[];
11
- excludeTags?: string[];
10
+ tags?: string[] | null;
11
+ excludeTags?: string[] | null;
12
12
  onFocus?: () => void;
13
13
  onBlur?: () => void;
14
14
  onToolbarOpenClose?: (open: boolean) => void;
@@ -15,8 +15,8 @@ async function TypeTesters(_ref) {
15
15
  let {
16
16
  collectionId,
17
17
  collectionSlug,
18
- tags,
19
- excludeTags,
18
+ tags = null,
19
+ excludeTags = null,
20
20
  ...rest
21
21
  } = _ref;
22
22
  if (collectionId) {
@@ -30,7 +30,11 @@ function createNetworkFetch(options) {
30
30
  body: JSON.stringify({
31
31
  query: request.text,
32
32
  variables
33
- })
33
+ }),
34
+ // @ts-ignore
35
+ next: {
36
+ tags: ['graphql', `operation:${request.name}`]
37
+ }
34
38
  });
35
39
  const json = await resp.json();
36
40
 
@@ -4,4 +4,44 @@ export interface SerializablePreloadedQuery<TQuery extends OperationType> {
4
4
  variables: VariablesOf<TQuery>;
5
5
  response: GraphQLResponse;
6
6
  }
7
- export default function loadSerializableQuery<TQuery extends OperationType>(query: GraphQLTaggedNode, variables: VariablesOf<TQuery>): Promise<SerializablePreloadedQuery<TQuery>>;
7
+ /**
8
+ * RELAY CACHE KEY NORMALIZATION
9
+ *
10
+ * This type transformation is required to fix a cache key inconsistency issue in Relay.
11
+ *
12
+ * THE PROBLEM:
13
+ * Relay's `getOperationVariables()` function always includes ALL argumentDefinitions
14
+ * from the GraphQL operation, even optional ones, setting them to their defaultValue
15
+ * (typically null). This means when Relay generates cache keys, it creates entries like:
16
+ *
17
+ * Cache Key A: { collectionId: "123", tags: null, excludeTags: null, selectable: true }
18
+ * Cache Key B: { collectionId: "123", selectable: true } // when optional vars omitted
19
+ *
20
+ * Even though these represent the same logical query, they produce different cache keys
21
+ * because `JSON.stringify(stableCopy(variables))` serializes them differently.
22
+ *
23
+ * (This is possibly caused by NextJS RSC data serialization and hydration)
24
+ *
25
+ * THE ROOT CAUSE:
26
+ * - GraphQL schema defines: `$tags: [String!], $excludeTags: [String!]` (optional)
27
+ * - TypeScript generates: `tags?: ReadonlyArray<string> | null`
28
+ * - Relay's argumentDefinitions include: `{ name: "tags", defaultValue: null }`
29
+ * - getOperationVariables() always sets: `operationVariables[def.name] = def.defaultValue`
30
+ *
31
+ * THE SOLUTION:
32
+ * RequireAllWithNull<T> transforms optional properties to required properties with
33
+ * explicit null values, forcing callers to be consistent. This ensures server-side
34
+ * preloaded queries and client-side cache lookups use identical variable structures.
35
+ *
36
+ * USAGE:
37
+ * Instead of: { tags, excludeTags } // undefined values
38
+ * Use: { tags: tags ?? null, excludeTags: excludeTags ?? null } // explicit nulls
39
+ *
40
+ * This eliminates cache misses caused by variable structure inconsistencies between
41
+ * server-side rendering and client-side Relay operations.
42
+ */
43
+ type RequireAllWithNull<T> = {
44
+ [K in keyof T]-?: T[K] | null;
45
+ };
46
+ export default function loadSerializableQuery<TQuery extends OperationType>(query: GraphQLTaggedNode, variables: RequireAllWithNull<VariablesOf<TQuery>>): Promise<SerializablePreloadedQuery<TQuery>>;
47
+ export {};
@@ -5,6 +5,43 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = loadSerializableQuery;
7
7
  var _environment = require("./environment");
8
+ /**
9
+ * RELAY CACHE KEY NORMALIZATION
10
+ *
11
+ * This type transformation is required to fix a cache key inconsistency issue in Relay.
12
+ *
13
+ * THE PROBLEM:
14
+ * Relay's `getOperationVariables()` function always includes ALL argumentDefinitions
15
+ * from the GraphQL operation, even optional ones, setting them to their defaultValue
16
+ * (typically null). This means when Relay generates cache keys, it creates entries like:
17
+ *
18
+ * Cache Key A: { collectionId: "123", tags: null, excludeTags: null, selectable: true }
19
+ * Cache Key B: { collectionId: "123", selectable: true } // when optional vars omitted
20
+ *
21
+ * Even though these represent the same logical query, they produce different cache keys
22
+ * because `JSON.stringify(stableCopy(variables))` serializes them differently.
23
+ *
24
+ * (This is possibly caused by NextJS RSC data serialization and hydration)
25
+ *
26
+ * THE ROOT CAUSE:
27
+ * - GraphQL schema defines: `$tags: [String!], $excludeTags: [String!]` (optional)
28
+ * - TypeScript generates: `tags?: ReadonlyArray<string> | null`
29
+ * - Relay's argumentDefinitions include: `{ name: "tags", defaultValue: null }`
30
+ * - getOperationVariables() always sets: `operationVariables[def.name] = def.defaultValue`
31
+ *
32
+ * THE SOLUTION:
33
+ * RequireAllWithNull<T> transforms optional properties to required properties with
34
+ * explicit null values, forcing callers to be consistent. This ensures server-side
35
+ * preloaded queries and client-side cache lookups use identical variable structures.
36
+ *
37
+ * USAGE:
38
+ * Instead of: { tags, excludeTags } // undefined values
39
+ * Use: { tags: tags ?? null, excludeTags: excludeTags ?? null } // explicit nulls
40
+ *
41
+ * This eliminates cache misses caused by variable structure inconsistencies between
42
+ * server-side rendering and client-side Relay operations.
43
+ */
44
+
8
45
  // Call into raw network fetch to get serializable GraphQL query response
9
46
  // This response will be sent to the client to "warm" the QueryResponseCache
10
47
  // to avoid the client fetches.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fontdue-js",
3
- "version": "2.15.0",
3
+ "version": "2.15.1",
4
4
  "scripts": {
5
5
  "build": "npm run relay && run-p build-js build-css build-ts",
6
6
  "build-js": "babel src --out-dir dist --extensions .ts,.tsx,.js,.jsx",
@@ -30,9 +30,9 @@
30
30
  "react-device-detect": "^2.2.3",
31
31
  "react-error-boundary": "^4.1.2",
32
32
  "react-redux": "^9",
33
- "react-relay": "^19.0.0",
33
+ "react-relay": "^20.0.0",
34
34
  "redux": "^5.0.0",
35
- "relay-runtime": "^19.0.0",
35
+ "relay-runtime": "^20.0.0",
36
36
  "store": "^2.0.12",
37
37
  "uuid": "^8.3.2"
38
38
  },
@@ -44,10 +44,11 @@
44
44
  "@babel/preset-typescript": "^7.18.0",
45
45
  "@types/draft-js": "^0.10.44",
46
46
  "@types/fontfaceobserver": "^2.1.0",
47
+ "@types/node": "^24.1.0",
47
48
  "@types/react": "19.0.0",
48
49
  "@types/react-dom": "19.0.0",
49
- "@types/react-relay": "^16.0.0",
50
- "@types/relay-runtime": "^17.0.0",
50
+ "@types/react-relay": "^18.0.0",
51
+ "@types/relay-runtime": "^19.0.0",
51
52
  "@types/uuid": "^8.3.3",
52
53
  "babel-plugin-relay": "^18.0.0",
53
54
  "npm-run-all": "^4.1.5",