react-datocms 8.0.0-0 → 8.0.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.
Files changed (80) hide show
  1. package/README.md +35 -15
  2. package/dist/cjs/ContentLink/index.js +104 -0
  3. package/dist/cjs/ContentLink/index.js.map +1 -0
  4. package/dist/cjs/Image/index.js +3 -3
  5. package/dist/cjs/Image/index.js.map +1 -1
  6. package/dist/cjs/Image/utils.js +3 -3
  7. package/dist/cjs/Image/utils.js.map +1 -1
  8. package/dist/cjs/SRCImage/index.js +3 -4
  9. package/dist/cjs/SRCImage/index.js.map +1 -1
  10. package/dist/cjs/SRCImage/utils.js +4 -4
  11. package/dist/cjs/SRCImage/utils.js.map +1 -1
  12. package/dist/cjs/Seo/nextUtils.js +1 -2
  13. package/dist/cjs/Seo/nextUtils.js.map +1 -1
  14. package/dist/cjs/Seo/remixUtils.js +2 -3
  15. package/dist/cjs/Seo/remixUtils.js.map +1 -1
  16. package/dist/cjs/Seo/renderMetaTags.js +1 -2
  17. package/dist/cjs/Seo/renderMetaTags.js.map +1 -1
  18. package/dist/cjs/Seo/renderMetaTagsToString.js +1 -2
  19. package/dist/cjs/Seo/renderMetaTagsToString.js.map +1 -1
  20. package/dist/cjs/StructuredText/index.js +34 -11
  21. package/dist/cjs/StructuredText/index.js.map +1 -1
  22. package/dist/cjs/VideoPlayer/index.js +45 -14
  23. package/dist/cjs/VideoPlayer/index.js.map +1 -1
  24. package/dist/cjs/index.js +2 -0
  25. package/dist/cjs/index.js.map +1 -1
  26. package/dist/cjs/useContentLink/index.js +111 -0
  27. package/dist/cjs/useContentLink/index.js.map +1 -0
  28. package/dist/cjs/useQuerySubscription/index.js +1 -2
  29. package/dist/cjs/useQuerySubscription/index.js.map +1 -1
  30. package/dist/cjs/useSiteSearch/index.js +3 -10
  31. package/dist/cjs/useSiteSearch/index.js.map +1 -1
  32. package/dist/esm/ContentLink/index.js +101 -0
  33. package/dist/esm/ContentLink/index.js.map +1 -0
  34. package/dist/esm/Image/index.js +3 -3
  35. package/dist/esm/Image/index.js.map +1 -1
  36. package/dist/esm/SRCImage/index.js +2 -2
  37. package/dist/esm/SRCImage/index.js.map +1 -1
  38. package/dist/esm/StructuredText/index.js +22 -4
  39. package/dist/esm/StructuredText/index.js.map +1 -1
  40. package/dist/esm/VideoPlayer/index.js +30 -9
  41. package/dist/esm/VideoPlayer/index.js.map +1 -1
  42. package/dist/esm/index.js +2 -0
  43. package/dist/esm/index.js.map +1 -1
  44. package/dist/esm/useContentLink/index.js +105 -0
  45. package/dist/esm/useContentLink/index.js.map +1 -0
  46. package/dist/esm/useSiteSearch/index.js +2 -8
  47. package/dist/esm/useSiteSearch/index.js.map +1 -1
  48. package/dist/types/ContentLink/index.d.ts +88 -0
  49. package/dist/types/Image/index.d.ts +8 -1
  50. package/dist/types/Image/utils.d.ts +0 -1
  51. package/dist/types/SRCImage/index.d.ts +10 -3
  52. package/dist/types/SRCImage/utils.d.ts +1 -2
  53. package/dist/types/Seo/renderMetaTags.d.ts +0 -1
  54. package/dist/types/StructuredText/index.d.ts +20 -9
  55. package/dist/types/VideoPlayer/index.d.ts +6 -6
  56. package/dist/types/index.d.ts +2 -0
  57. package/dist/types/useContentLink/index.d.ts +91 -0
  58. package/dist/types/useSiteSearch/index.d.ts +3 -1
  59. package/dist/types/useVideoPlayer/index.d.ts +2 -2
  60. package/package.json +32 -17
  61. package/src/ContentLink/index.tsx +134 -0
  62. package/src/Image/__tests__/__snapshots__/index.test.tsx.snap +20 -0
  63. package/src/Image/index.tsx +11 -1
  64. package/src/SRCImage/__tests__/__snapshots__/index.test.tsx.snap +7 -0
  65. package/src/SRCImage/index.tsx +11 -2
  66. package/src/SRCImage/utils.tsx +1 -1
  67. package/src/StructuredText/__tests__/__snapshots__/index.test.tsx.snap +17 -0
  68. package/src/StructuredText/__tests__/index.test.tsx +27 -1
  69. package/src/StructuredText/index.tsx +80 -15
  70. package/src/VideoPlayer/index.tsx +43 -17
  71. package/src/index.ts +3 -0
  72. package/src/useContentLink/index.ts +187 -0
  73. package/src/useSiteSearch/index.tsx +6 -5
  74. package/src/useVideoPlayer/index.ts +2 -2
  75. package/dist/cjs/VideoPlayer/lazy.js +0 -35
  76. package/dist/cjs/VideoPlayer/lazy.js.map +0 -1
  77. package/dist/esm/VideoPlayer/lazy.js +0 -9
  78. package/dist/esm/VideoPlayer/lazy.js.map +0 -1
  79. package/dist/types/VideoPlayer/lazy.d.ts +0 -6
  80. package/src/VideoPlayer/lazy.tsx +0 -26
@@ -8,6 +8,8 @@ import {
8
8
  renderNodeRule,
9
9
  } from 'datocms-structured-text-generic-html-renderer';
10
10
  import {
11
+ type CdaStructuredTextRecord,
12
+ type CdaStructuredTextValue,
11
13
  type Node,
12
14
  RenderError,
13
15
  type RenderResult,
@@ -15,8 +17,10 @@ import {
15
17
  type Document as StructuredTextDocument,
16
18
  type StructuredText as StructuredTextGraphQlResponse,
17
19
  type Record as StructuredTextGraphQlResponseRecord,
20
+ type TypesafeCdaStructuredTextValue,
18
21
  type TypesafeStructuredText as TypesafeStructuredTextGraphQlResponse,
19
22
  isBlock,
23
+ isInlineBlock,
20
24
  isInlineItem,
21
25
  isItemLink,
22
26
  isStructuredText,
@@ -25,14 +29,11 @@ import React, { type ReactElement, cloneElement, isValidElement } from 'react';
25
29
 
26
30
  export { renderNodeRule, renderMarkRule, RenderError };
27
31
 
28
- // deprecated
29
- export { renderNodeRule as renderRule };
30
-
31
32
  export type {
32
- StructuredTextGraphQlResponse,
33
- TypesafeStructuredTextGraphQlResponse,
34
33
  StructuredTextDocument,
35
- StructuredTextGraphQlResponseRecord,
34
+ CdaStructuredTextValue,
35
+ TypesafeCdaStructuredTextValue,
36
+ CdaStructuredTextRecord,
36
37
  };
37
38
 
38
39
  type AdapterReturn = ReactElement | string | null;
@@ -80,12 +81,16 @@ export type RenderBlockContext<R extends StructuredTextGraphQlResponseRecord> =
80
81
  };
81
82
 
82
83
  export type StructuredTextPropTypes<
83
- R1 extends StructuredTextGraphQlResponseRecord,
84
- R2 extends StructuredTextGraphQlResponseRecord = R1,
84
+ BlockRecord extends
85
+ StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
86
+ LinkRecord extends
87
+ StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
88
+ InlineBlockRecord extends
89
+ StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
85
90
  > = {
86
91
  /** The actual field value you get from DatoCMS **/
87
92
  data:
88
- | StructuredTextGraphQlResponse<R1, R2>
93
+ | StructuredTextGraphQlResponse<BlockRecord, LinkRecord, InlineBlockRecord>
89
94
  | StructuredTextDocument
90
95
  | Node
91
96
  | null
@@ -96,14 +101,20 @@ export type StructuredTextPropTypes<
96
101
  customMarkRules?: RenderMarkRule<H, T, F>[];
97
102
  /** Fuction that converts an 'inlineItem' node into React **/
98
103
  renderInlineRecord?: (
99
- context: RenderInlineRecordContext<R2>,
104
+ context: RenderInlineRecordContext<LinkRecord>,
100
105
  ) => ReactElement | null;
101
106
  /** Fuction that converts an 'itemLink' node into React **/
102
107
  renderLinkToRecord?: (
103
- context: RenderRecordLinkContext<R2>,
108
+ context: RenderRecordLinkContext<LinkRecord>,
104
109
  ) => ReactElement | null;
105
110
  /** Fuction that converts a 'block' node into React **/
106
- renderBlock?: (context: RenderBlockContext<R1>) => ReactElement | null;
111
+ renderBlock?: (
112
+ context: RenderBlockContext<BlockRecord>,
113
+ ) => ReactElement | null;
114
+ /** Fuction that converts an 'inlineBlock' node into React **/
115
+ renderInlineBlock?: (
116
+ context: RenderBlockContext<InlineBlockRecord>,
117
+ ) => ReactElement | null;
107
118
  /** Function that converts 'link' and 'itemLink' `meta` into HTML props */
108
119
  metaTransformer?: TransformMetaFn;
109
120
  /** Fuction that converts a simple string text into React **/
@@ -117,13 +128,18 @@ export type StructuredTextPropTypes<
117
128
  };
118
129
 
119
130
  export function StructuredText<
120
- R1 extends StructuredTextGraphQlResponseRecord,
121
- R2 extends StructuredTextGraphQlResponseRecord = R1,
131
+ BlockRecord extends
132
+ StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
133
+ LinkRecord extends
134
+ StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
135
+ InlineBlockRecord extends
136
+ StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
122
137
  >({
123
138
  data,
124
139
  renderInlineRecord,
125
140
  renderLinkToRecord,
126
141
  renderBlock,
142
+ renderInlineBlock,
127
143
  renderText,
128
144
  renderNode,
129
145
  renderFragment,
@@ -131,7 +147,11 @@ export function StructuredText<
131
147
  customRules,
132
148
  customNodeRules,
133
149
  metaTransformer,
134
- }: StructuredTextPropTypes<R1, R2>): ReactElement | null {
150
+ }: StructuredTextPropTypes<
151
+ BlockRecord,
152
+ LinkRecord,
153
+ InlineBlockRecord
154
+ >): ReactElement | null {
135
155
  const result = render(data, {
136
156
  adapter: {
137
157
  renderText: renderText || defaultAdapter.renderText,
@@ -234,6 +254,35 @@ export function StructuredText<
234
254
 
235
255
  return appendKeyToValidElement(renderBlock({ record: item }), key);
236
256
  }),
257
+ renderNodeRule(isInlineBlock, ({ node, key }) => {
258
+ if (!renderInlineBlock) {
259
+ throw new RenderError(
260
+ `The Structured Text document contains an 'inlineBlock' node, but no 'renderInlineBlock' prop is specified!`,
261
+ node,
262
+ );
263
+ }
264
+
265
+ if (!(isStructuredText(data) && data.inlineBlocks)) {
266
+ throw new RenderError(
267
+ `The document contains an 'inlineBlock' node, but the passed data prop is not a Structured Text GraphQL response, or data.inlineBlocks is not present!`,
268
+ node,
269
+ );
270
+ }
271
+
272
+ const item = data.inlineBlocks.find((item) => item.id === node.item);
273
+
274
+ if (!item) {
275
+ throw new RenderError(
276
+ `The Structured Text document contains an 'inlineBlock' node, but cannot find a record with ID ${node.item} inside data.inlineBlocks!`,
277
+ node,
278
+ );
279
+ }
280
+
281
+ return appendKeyToValidElement(
282
+ renderInlineBlock({ record: item }),
283
+ key,
284
+ );
285
+ }),
237
286
  ...(customNodeRules || customRules || []),
238
287
  ],
239
288
  });
@@ -244,3 +293,19 @@ export function StructuredText<
244
293
 
245
294
  return result || null;
246
295
  }
296
+
297
+ // ============================================================================
298
+ // DEPRECATED EXPORTS - kept for backward compatibility
299
+ // ============================================================================
300
+
301
+ /**
302
+ * @deprecated Use renderNodeRule instead
303
+ */
304
+ export { renderNodeRule as renderRule };
305
+
306
+ /** @deprecated Use CdaStructuredTextValue */
307
+ export type { StructuredTextGraphQlResponse };
308
+ /** @deprecated Use TypesafeCdaStructuredTextValue */
309
+ export type { TypesafeStructuredTextGraphQlResponse };
310
+ /** @deprecated Use CdaStructuredTextRecord */
311
+ export type { StructuredTextGraphQlResponseRecord };
@@ -1,4 +1,4 @@
1
- "use client";
1
+ 'use client';
2
2
 
3
3
  // This file defines a React component that easily displays a video player using
4
4
  // data stored on DatoCMS and retrieved via DatoCMS GraphQL API. The component
@@ -8,24 +8,26 @@
8
8
  //
9
9
  // [1]: https://www.mux.com/player
10
10
 
11
- import React, { forwardRef } from "react";
11
+ import React, { forwardRef } from 'react';
12
12
 
13
13
  // We use and extend Typescript types defined in the MUX player.
14
14
 
15
- import type MuxPlayerElement from "@mux/mux-player";
16
- import type { MuxPlayerProps } from "@mux/mux-player-react";
15
+ import type MuxPlayerElement from '@mux/mux-player';
16
+ import type { MuxPlayerProps } from '@mux/mux-player-react';
17
17
 
18
18
  // React MUX player is made available in two flavours: eager and lazy loaded. We
19
- // choose to use the eager loading version as the default approch, but
20
- // we also provide a lazy loading version..
19
+ // choose to use the lazy version to avoid loading the web component uselessly.
20
+ // MUX player lazy version loads internally the eager version using
21
+ // `React.lazy()`.
21
22
 
22
- import MuxPlayer from "@mux/mux-player-react";
23
+ import MuxPlayer from '@mux/mux-player-react/lazy';
23
24
 
24
25
  // The core of this component is the `useVideoPlayer` hook: it takes
25
26
  // data from DatoCMS GraphQL API and returns props as expected by the
26
27
  // `<MuxPlayer />` component.
27
28
 
28
- import { useVideoPlayer } from "../useVideoPlayer/index.js";
29
+ import { decodeStega } from '@datocms/content-link';
30
+ import { useVideoPlayer } from '../useVideoPlayer/index.js';
29
31
 
30
32
  type Maybe<T> = T | null;
31
33
  type Possibly<T> = Maybe<T> | undefined;
@@ -36,6 +38,8 @@ type Possibly<T> = Maybe<T> | undefined;
36
38
  export type Video = {
37
39
  /** Title attribute (`title`) for the video */
38
40
  title?: Possibly<string>;
41
+ /** Alt attribute used for content link integration (passed as data-datocms-content-link-source) */
42
+ alt?: Possibly<string>;
39
43
  /** The height of the video */
40
44
  height?: Possibly<number>;
41
45
  /** The width of the video */
@@ -62,18 +66,17 @@ export type VideoPlayerProps = MuxPlayerProps & {
62
66
  data?: Video;
63
67
  };
64
68
 
65
- type VideoPlayerType = React.ForwardRefExoticComponent<
66
- VideoPlayerProps & React.RefAttributes<MuxPlayerElement>
67
- >;
68
-
69
- export const VideoPlayer: VideoPlayerType = forwardRef<
69
+ export const VideoPlayer: (
70
+ props: VideoPlayerProps,
71
+ ) => ReturnType<typeof MuxPlayer> = forwardRef<
70
72
  MuxPlayerElement,
71
73
  VideoPlayerProps
72
- >((props: VideoPlayerProps, ref) => {
74
+ >((props, ref) => {
73
75
  const {
74
76
  data = {},
75
77
  disableCookies = true,
76
- preload = "metadata",
78
+ disableTracking = true,
79
+ preload = 'metadata',
77
80
  style: styleFromProps,
78
81
  ...rest
79
82
  } = props;
@@ -92,6 +95,29 @@ export const VideoPlayer: VideoPlayerType = forwardRef<
92
95
  ...styleFromProps,
93
96
  };
94
97
 
98
+ // Extract alt for DatoCMS Content Link integration
99
+ // See: https://github.com/datocms/content-link
100
+ const { alt } = data;
101
+
102
+ // Only include data-datocms-content-link-source if alt contains stega encoding
103
+ const contentLinkSource = alt && decodeStega(alt) ? alt : undefined;
104
+
105
+ // Note: Custom data-* attributes can be passed to the underlying <mux-player> web component
106
+ // in two ways:
107
+ //
108
+ // 1. Kebab-case (passes through as-is):
109
+ // <VideoPlayer data-player-id="my-player" />
110
+ //
111
+ // 2. CamelCase (auto-converts to kebab-case):
112
+ // <VideoPlayer dataPlayerId="my-player" />
113
+ //
114
+ // Both result in: <mux-player data-player-id="my-player">
115
+ //
116
+ // The MuxPlayer React component transforms camelCase props to kebab-case to match
117
+ // web component attribute conventions. Any props not explicitly handled by VideoPlayer
118
+ // are spread via {...rest} and forwarded to MuxPlayer, which then applies them to
119
+ // the underlying <mux-player> element.
120
+
95
121
  return (
96
122
  <MuxPlayer
97
123
  ref={ref}
@@ -99,12 +125,12 @@ export const VideoPlayer: VideoPlayerType = forwardRef<
99
125
  preload={preload}
100
126
  title={title}
101
127
  disableCookies={disableCookies}
128
+ disableTracking={disableTracking}
102
129
  playbackId={playbackId}
103
130
  style={style}
104
131
  placeholder={placeholder}
132
+ data-datocms-content-link-source={contentLinkSource}
105
133
  {...rest}
106
134
  />
107
135
  );
108
136
  });
109
-
110
- export default VideoPlayer;
package/src/index.ts CHANGED
@@ -7,3 +7,6 @@ export * from './VideoPlayer/index.js';
7
7
  export * from './useQuerySubscription/index.js';
8
8
  export * from './useSiteSearch/index.js';
9
9
  export * from './useVideoPlayer/index.js';
10
+
11
+ export * from './ContentLink/index.js';
12
+ export * from './useContentLink/index.js';
@@ -0,0 +1,187 @@
1
+ 'use client';
2
+
3
+ import { type Controller, createController } from '@datocms/content-link';
4
+ import { useCallback, useEffect, useRef } from 'react';
5
+
6
+ // Re-export types and utilities from @datocms/content-link for convenience
7
+ export { decodeStega, stripStega } from '@datocms/content-link';
8
+ export type { Controller } from '@datocms/content-link';
9
+
10
+ export type UseContentLinkOptions = {
11
+ /**
12
+ * Whether the controller is enabled, or an options object.
13
+ * - Pass `true` (default): Enables the controller with stega encoding preserved (allows controller recreation)
14
+ * - Pass `false`: Disables the controller completely
15
+ * - Pass `{ stripStega: true }`: Enables the controller and strips stega encoding after stamping
16
+ *
17
+ * When stripStega is false (default): Stega encoding remains in the DOM, allowing controllers
18
+ * to be disposed and recreated on the same page. The invisible characters don't affect display
19
+ * but preserve the source of truth.
20
+ *
21
+ * When stripStega is true: Stega encoding is permanently removed from text nodes, providing
22
+ * clean textContent for programmatic access. However, recreating a controller on the same page
23
+ * won't detect elements since the encoding is lost.
24
+ */
25
+ enabled?: boolean | { stripStega: boolean };
26
+ /** Callback when Web Previews plugin requests navigation */
27
+ onNavigateTo?: (path: string) => void;
28
+ /** Ref to limit scanning to this root instead of document */
29
+ root?: React.RefObject<HTMLElement>;
30
+ };
31
+
32
+ export interface ClickToEditOptions {
33
+ /**
34
+ * Whether to automatically scroll to the nearest editable element if none
35
+ * is currently visible in the viewport when click-to-edit mode is enabled.
36
+ *
37
+ * @default false
38
+ */
39
+ scrollToNearestTarget?: boolean;
40
+
41
+ /**
42
+ * Only enable click-to-edit on devices that support hover (i.e., non-touch devices).
43
+ * Uses `window.matchMedia('(hover: hover)')` to detect hover capability.
44
+ *
45
+ * This is useful to avoid showing overlays on touch devices where they may
46
+ * interfere with normal scrolling and tapping behavior.
47
+ *
48
+ * When set to `true` on a touch-only device, click-to-edit will not be
49
+ * automatically enabled, but users can still toggle it manually using
50
+ * the Alt/Option key.
51
+ *
52
+ * @default false
53
+ */
54
+ hoverOnly?: boolean;
55
+ }
56
+
57
+ export type UseContentLinkResult = {
58
+ /** The controller instance, or null if disabled */
59
+ controller: Controller | null;
60
+ /** Enable click-to-edit overlays */
61
+ enableClickToEdit: (options?: ClickToEditOptions) => void;
62
+ /** Disable click-to-edit overlays */
63
+ disableClickToEdit: () => void;
64
+ /** Check if click-to-edit is enabled */
65
+ isClickToEditEnabled: () => boolean;
66
+ /** Highlight all editable elements */
67
+ flashAll: (scrollToNearestTarget?: boolean) => void;
68
+ /** Notify Web Previews plugin of current path */
69
+ setCurrentPath: (path: string) => void;
70
+ };
71
+
72
+ /**
73
+ * Hook to control the ContentLink controller for Visual Editing.
74
+ *
75
+ * This hook provides low-level access to the @datocms/content-link controller,
76
+ * allowing you to programmatically control click-to-edit overlays and
77
+ * communicate with the DatoCMS Web Previews plugin.
78
+ *
79
+ * @param options - Configuration options for the controller
80
+ * @returns An object containing the controller instance and its methods
81
+ *
82
+ * @example
83
+ * ```tsx
84
+ * import { useContentLink } from 'react-datocms';
85
+ *
86
+ * function MyComponent() {
87
+ * const { enableClickToEdit, flashAll } = useContentLink({
88
+ * onNavigateTo: (path) => router.push(path),
89
+ * });
90
+ *
91
+ * return (
92
+ * <button onClick={() => enableClickToEdit({ scrollToNearestTarget: true })}>
93
+ * Enable Editing
94
+ * </button>
95
+ * );
96
+ * }
97
+ * ```
98
+ */
99
+ export function useContentLink(
100
+ options: UseContentLinkOptions = {},
101
+ ): UseContentLinkResult {
102
+ const { enabled = true, onNavigateTo, root } = options;
103
+
104
+ const controllerRef = useRef<Controller | null>(null);
105
+ // Store the callback in a ref to avoid recreating the controller when it changes
106
+ const onNavigateToRef = useRef(onNavigateTo);
107
+
108
+ // Keep the callback ref up to date
109
+ useEffect(() => {
110
+ onNavigateToRef.current = onNavigateTo;
111
+ }, [onNavigateTo]);
112
+
113
+ // Create/dispose controller based on enabled flag and root only
114
+ // The onNavigateTo callback is accessed via ref, so changes don't trigger recreation
115
+ useEffect(() => {
116
+ // Check if controller is disabled
117
+ const isEnabled =
118
+ enabled === true || (typeof enabled === 'object' && enabled !== null);
119
+
120
+ if (!isEnabled) {
121
+ if (controllerRef.current) {
122
+ controllerRef.current.dispose();
123
+ controllerRef.current = null;
124
+ }
125
+ return;
126
+ }
127
+
128
+ // Extract stripStega option if enabled is an object
129
+ const stripStega = typeof enabled === 'object' ? enabled.stripStega : false;
130
+
131
+ const controller = createController({
132
+ onNavigateTo: (path: string) => onNavigateToRef.current?.(path),
133
+ root: root?.current || undefined,
134
+ stripStega,
135
+ });
136
+
137
+ controllerRef.current = controller;
138
+
139
+ return () => {
140
+ controller.dispose();
141
+ controllerRef.current = null;
142
+ };
143
+ }, [enabled, root]);
144
+
145
+ // Stable method references that call through to the controller
146
+ const enableClickToEdit = useCallback((opts?: ClickToEditOptions) => {
147
+ // If hoverOnly is true, check if the device supports hover
148
+ if (
149
+ opts?.hoverOnly &&
150
+ (typeof window === 'undefined' ||
151
+ !window.matchMedia('(hover: hover)').matches)
152
+ ) {
153
+ return;
154
+ }
155
+
156
+ controllerRef.current?.enableClickToEdit(
157
+ opts?.scrollToNearestTarget
158
+ ? { scrollToNearestTarget: opts.scrollToNearestTarget }
159
+ : undefined,
160
+ );
161
+ }, []);
162
+
163
+ const disableClickToEdit = useCallback(() => {
164
+ controllerRef.current?.disableClickToEdit();
165
+ }, []);
166
+
167
+ const isClickToEditEnabled = useCallback(() => {
168
+ return controllerRef.current?.isClickToEditEnabled() ?? false;
169
+ }, []);
170
+
171
+ const flashAll = useCallback((scrollToNearestTarget?: boolean) => {
172
+ controllerRef.current?.flashAll(scrollToNearestTarget);
173
+ }, []);
174
+
175
+ const setCurrentPath = useCallback((path: string) => {
176
+ controllerRef.current?.setCurrentPath(path);
177
+ }, []);
178
+
179
+ return {
180
+ controller: controllerRef.current,
181
+ enableClickToEdit,
182
+ disableClickToEdit,
183
+ isClickToEditEnabled,
184
+ flashAll,
185
+ setCurrentPath,
186
+ };
187
+ }
@@ -15,6 +15,7 @@ type SearchResultInstancesHrefSchema = {
15
15
  fuzzy?: boolean;
16
16
  query: string;
17
17
  build_trigger_id?: string;
18
+ search_index_id?: string;
18
19
  locale?: string;
19
20
  [k: string]: unknown;
20
21
  };
@@ -62,7 +63,8 @@ type Highlighter = (
62
63
 
63
64
  export type UseSiteSearchConfig<Client extends GenericClient> = {
64
65
  client: Client;
65
- buildTriggerId: string;
66
+ buildTriggerId?: string;
67
+ searchIndexId?: string;
66
68
  fuzzySearch?: boolean;
67
69
  resultsPerPage?: number;
68
70
  highlightMatch?: Highlighter;
@@ -161,6 +163,8 @@ export function useSiteSearch<Client extends GenericClient>(
161
163
  query: state.query,
162
164
  locale: state.locale,
163
165
  build_trigger_id: config.buildTriggerId,
166
+ search_index_id: config.searchIndexId,
167
+ ...(config.fuzzySearch === true ? { fuzzy: true } : {}),
164
168
  },
165
169
  page: {
166
170
  limit: resultsPerPage,
@@ -168,10 +172,6 @@ export function useSiteSearch<Client extends GenericClient>(
168
172
  },
169
173
  };
170
174
 
171
- if (config.fuzzySearch) {
172
- request.fuzzy = 'true';
173
- }
174
-
175
175
  const response = await config.client.searchResults.rawList(request);
176
176
 
177
177
  if (!isCancelled) {
@@ -199,6 +199,7 @@ export function useSiteSearch<Client extends GenericClient>(
199
199
  resultsPerPage,
200
200
  state,
201
201
  config.buildTriggerId,
202
+ config.searchIndexId,
202
203
  config.fuzzySearch,
203
204
  config.client.config.apiToken,
204
205
  ]);
@@ -1,6 +1,6 @@
1
- import type { MuxPlayerProps } from '@mux/mux-player-react/.';
1
+ import type { MuxPlayerProps } from '@mux/mux-player-react';
2
2
 
3
- import type { Video } from '../VideoPlayer';
3
+ import type { Video } from '../VideoPlayer/index.js';
4
4
 
5
5
  type Maybe<T> = T | null;
6
6
  type Possibly<T> = Maybe<T> | undefined;
@@ -1,35 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.VideoPlayer = void 0;
27
- const react_1 = __importStar(require("react"));
28
- const LazyLoadedVideoPlayer = react_1.default.lazy(() => Promise.resolve().then(() => __importStar(require("./index.js"))));
29
- exports.VideoPlayer = (0, react_1.forwardRef)((props, ref) => {
30
- const { className, style } = props;
31
- return (react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", { className: className, style: style }) },
32
- react_1.default.createElement(LazyLoadedVideoPlayer, Object.assign({}, props, { ref: ref }))));
33
- });
34
- exports.default = exports.VideoPlayer;
35
- //# sourceMappingURL=lazy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../../src/VideoPlayer/lazy.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAoD;AAMpD,MAAM,qBAAqB,GAAG,eAAK,CAAC,IAAI,CAAC,GAAG,EAAE,mDAAQ,YAAY,GAAC,CAAC,CAAC;AAMxD,QAAA,WAAW,GAAoB,IAAA,kBAAU,EAGpD,CAAC,KAAuB,EAAE,GAAG,EAAE,EAAE;IACjC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAEnC,OAAO,CACL,8BAAC,gBAAQ,IAAC,QAAQ,EAAE,uCAAK,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAI;QAC7D,8BAAC,qBAAqB,oBAAK,KAAK,IAAE,GAAG,EAAE,GAAG,IAAI,CACrC,CACZ,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,kBAAe,mBAAW,CAAC"}
@@ -1,9 +0,0 @@
1
- import React, { Suspense, forwardRef } from "react";
2
- const LazyLoadedVideoPlayer = React.lazy(() => import("./index.js"));
3
- export const VideoPlayer = forwardRef((props, ref) => {
4
- const { className, style } = props;
5
- return (React.createElement(Suspense, { fallback: React.createElement("div", { className: className, style: style }) },
6
- React.createElement(LazyLoadedVideoPlayer, Object.assign({}, props, { ref: ref }))));
7
- });
8
- export default VideoPlayer;
9
- //# sourceMappingURL=lazy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../../src/VideoPlayer/lazy.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAMpD,MAAM,qBAAqB,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;AAMrE,MAAM,CAAC,MAAM,WAAW,GAAoB,UAAU,CAGpD,CAAC,KAAuB,EAAE,GAAG,EAAE,EAAE;IACjC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAEnC,OAAO,CACL,oBAAC,QAAQ,IAAC,QAAQ,EAAE,6BAAK,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAI;QAC7D,oBAAC,qBAAqB,oBAAK,KAAK,IAAE,GAAG,EAAE,GAAG,IAAI,CACrC,CACZ,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,eAAe,WAAW,CAAC"}
@@ -1,6 +0,0 @@
1
- import React from "react";
2
- import type MuxPlayerElement from "@mux/mux-player";
3
- import type { VideoPlayerProps } from "./index";
4
- type VideoPlayerType = React.ForwardRefExoticComponent<VideoPlayerProps & React.RefAttributes<MuxPlayerElement>>;
5
- export declare const VideoPlayer: VideoPlayerType;
6
- export default VideoPlayer;
@@ -1,26 +0,0 @@
1
- import React, { Suspense, forwardRef } from "react";
2
- import type MuxPlayerElement from "@mux/mux-player";
3
- import type MuxPlayer from "@mux/mux-player-react/.";
4
-
5
- import type { VideoPlayerProps } from "./index";
6
-
7
- const LazyLoadedVideoPlayer = React.lazy(() => import("./index.js"));
8
-
9
- type VideoPlayerType = React.ForwardRefExoticComponent<
10
- VideoPlayerProps & React.RefAttributes<MuxPlayerElement>
11
- >;
12
-
13
- export const VideoPlayer: VideoPlayerType = forwardRef<
14
- MuxPlayerElement,
15
- VideoPlayerProps
16
- >((props: VideoPlayerProps, ref) => {
17
- const { className, style } = props;
18
-
19
- return (
20
- <Suspense fallback={<div className={className} style={style} />}>
21
- <LazyLoadedVideoPlayer {...props} ref={ref} />
22
- </Suspense>
23
- );
24
- });
25
-
26
- export default VideoPlayer;