@contentful/experiences-sdk-react 1.5.0 → 1.5.1-beta.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
@@ -1,11 +1,18 @@
1
1
  # @contentful/experiences-sdk-react
2
+ ### Purpose
3
+ - To bundle up and expose features from other packages to be used by the end user. This is the package that users will install and import into their own React projects.
4
+ - Note that this is a React-specific package. Therefore, unlike the core package, React specific compatibilities are implemented here and support for other frontend frameworks would result in a new package being created under a separate namespace.
2
5
 
3
- This package provides the core SDK for Contentful Studio Experiences. It offers a set of tools and services that enable developers to build, manage, and enhance experiences.
6
+ ### Concepts
7
+ - **Experience object**: Generalized typed definition of what an experience is. Contains information about the component tree, unbound values, and data source that are converted from the content entry so that the experiences packages can use the transformed object, handle manipulations to the tree, validate its values, and update the experience object back to the content entry as users trigger and save their changes.
8
+ - **ExperienceRoot**: Main entry point component that users will use in their React project which takes in a experience object as a prop. The experience object can be fetched in a multitude of ways. One common way for Vite React projects for example would be to use the `useFetchBySlug/useFetchById` hooks. However, for SSR they would use the `fetchBySlug/fetchById` functions instead. Additionally, users can create their own experience object using custom transformations they provide for themselves and pass their transformed object as a prop to the `ExperienceRoot` provided that the object complies with the experience type.
9
+ - **SSR**: Making the SDK compatible with SSR is provided in the SDK package itself. However, there are discussion on moving the logic into the core package in the future.
10
+ - **Breakpoints**: Defines how we separate desktop, tablet, and mobile breakpoints for each viewport.
11
+ - **Preview vs Live vs Editor mode**: Editor mode is what is seen in the Contentful web app for experiences with the Component sidebar, Visual editor, and the Design sidebar where users are allowed to drag and drop components, edit the styles, and publish their changes. Live mode is the ability to view a user's experience with published changes. Preview mode is the ability to see a user's experience with unpublished changes.
12
+ - **PreviewDeliveryRoot vs VisualEditorRoot**: In the `ExperienceRoot.tsx` file, notice there is logic to either render the `<VisualEditorRoot>` vs the `<PreviewDeliveryRoot>` depending on whether or not the user is in editor mode. Note for both compoments, they have their own way of parsing through the entire component tree and rendering the components to the UI. This is because the Visual editor has to add wrapping divs for drag and drop while the Preview delivery can just print the components to the UI as is. Additionally, the name PreviewDelivery converges the Live and Preview mode concepts into just one idea. In reality, PreviewDeliveryRoot works more as the Live mode concept. There are plans to iterate and to build a third mode for Preview and rename `<PreviewDeliveryRoot>` to just `<DeliveryRoot>` or `<LiveRoot>`.
13
+ - **Preview vs Delivery API**: Each experience object will draw their source of truth from a content entry which is either fetched via Contentful's Delivery or Preview API. The user will define which API is used when setting up experiences. This is not to be confused with "Preview" or "Delivery/Live" mode with respect to experiences as they are separate entities.
14
+ - **Component Registry**: Takes in the component definitions and registers them into the UI where the `enrichComponentDefinition` function will apply styles that are defined by the component themselves as default styles. This will ensure that the user dragging a built-in or structure component will display the default styles defined by Contentful.
4
15
 
5
- ## Installation
6
-
7
- Please follow the guide to [Set up Experiences SDK](https://www.contentful.com/developers/docs/experiences/set-up-experiences-sdk/).
8
-
9
- ## Documentation
10
-
11
- Please refer to our [Documentation](https://www.contentful.com/developers/docs/experiences/) to learn more about it.
16
+ ### Relevant Contentful documentation links
17
+ - [Component definition schema](https://www.contentful.com/developers/docs/experiences/component-definition-schema/)
18
+ - [Data structures](https://www.contentful.com/developers/docs/experiences/data-structures/)
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as _contentful_experiences_core from '@contentful/experiences-core';
3
3
  import { EntityStore, VisualEditorMode } from '@contentful/experiences-core';
4
- export { VisualEditorMode, createExperience, defineDesignTokens, fetchById, fetchBySlug } from '@contentful/experiences-core';
4
+ export { VisualEditorMode, createExperience, defineBreakpoints, defineDesignTokens, fetchById, fetchBySlug } from '@contentful/experiences-core';
5
5
  import { Experience, ComponentRegistration, ComponentRegistrationOptions } from '@contentful/experiences-core/types';
6
6
  export { ComponentDefinition, ExternalSDKMode } from '@contentful/experiences-core/types';
7
7
  import { ContentfulClientApi } from 'contentful';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
- import { containerDefinition, sectionDefinition, columnsDefinition, singleColumnDefinition, dividerDefinition, builtInStyles, optionalBuiltInStyles, sendMessage, designTokensRegistry, buildCfStyles, isEmptyStructureWithRelativeHeight, buildStyleTag, checkIsAssemblyNode, resolveHyperlinkPattern, transformBoundContentValue, mediaQueryMatcher, getFallbackBreakpointIndex, getActiveBreakpointIndex, getValueForBreakpoint, doesMismatchMessageSchema, tryParseMessage, fetchById, fetchBySlug, validateExperienceBuilderConfig, VisualEditorMode, toCSSAttribute } from '@contentful/experiences-core';
3
- export { VisualEditorMode, createExperience, defineDesignTokens, fetchById, fetchBySlug } from '@contentful/experiences-core';
2
+ import { containerDefinition, sectionDefinition, columnsDefinition, singleColumnDefinition, dividerDefinition, builtInStyles, optionalBuiltInStyles, sendMessage, breakpointsRegistry, designTokensRegistry, buildCfStyles, isEmptyStructureWithRelativeHeight, buildStyleTag, checkIsAssemblyNode, resolveHyperlinkPattern, transformBoundContentValue, mediaQueryMatcher, getFallbackBreakpointIndex, getActiveBreakpointIndex, getValueForBreakpoint, doesMismatchMessageSchema, tryParseMessage, fetchById, fetchBySlug, runBreakpointsValidation, validateExperienceBuilderConfig, VisualEditorMode, toCSSAttribute } from '@contentful/experiences-core';
3
+ export { VisualEditorMode, createExperience, defineBreakpoints, defineDesignTokens, fetchById, fetchBySlug } from '@contentful/experiences-core';
4
4
  import React, { useState, useLayoutEffect, useMemo, useEffect, useCallback, useRef, Suspense } from 'react';
5
5
  import { omit } from 'lodash-es';
6
6
  import { INTERNAL_EVENTS, CONTENTFUL_COMPONENTS, OUTGOING_EVENTS, ASSEMBLY_DEFAULT_CATEGORY, EMPTY_CONTAINER_HEIGHT, HYPERLINK_DEFAULT_PATTERN, CF_STYLE_ATTRIBUTES, INCOMING_EVENTS, VISUAL_EDITOR_EVENTS } from '@contentful/experiences-core/constants';
@@ -10,7 +10,7 @@ import { ContentfulContainer, Columns, SingleColumn } from '@contentful/experien
10
10
  import styleInject from 'style-inject';
11
11
  import md5 from 'md5';
12
12
 
13
- const SDK_VERSION = '1.5.0-beta.0';
13
+ const SDK_VERSION = '1.5.0';
14
14
 
15
15
  var util;
16
16
  (function (util) {
@@ -4132,6 +4132,7 @@ const BreakpointSchema = z
4132
4132
  query: z.string().regex(/^\*$|^<[0-9*]+px$/),
4133
4133
  previewSize: z.string(),
4134
4134
  displayName: z.string(),
4135
+ displayIconUrl: z.string().optional(),
4135
4136
  })
4136
4137
  .strict();
4137
4138
  const UnboundValuesSchema = z.record(uuidKeySchema, z.object({
@@ -4177,10 +4178,21 @@ const UsedComponentsSchema = z.array(z.object({
4177
4178
  }),
4178
4179
  }));
4179
4180
  const breakpointsRefinement = (value, ctx) => {
4180
- if (!value.length || value[0].id !== 'desktop' || value[0].query !== '*') {
4181
+ if (!value.length || value[0].query !== '*') {
4181
4182
  ctx.addIssue({
4182
4183
  code: z.ZodIssueCode.custom,
4183
- message: `The first breakpoint should include the following attributes: { "id": "desktop", "query": "*" }`,
4184
+ message: `The first breakpoint should include the following attributes: { "query": "*" }`,
4185
+ });
4186
+ }
4187
+ const hasDuplicateIds = value.some((currentBreakpoint, currentBreakpointIndex) => {
4188
+ // check if the current breakpoint id is found in the rest of the array
4189
+ const breakpointIndex = value.findIndex((breakpoint) => breakpoint.id === currentBreakpoint.id);
4190
+ return breakpointIndex !== currentBreakpointIndex;
4191
+ });
4192
+ if (hasDuplicateIds) {
4193
+ ctx.addIssue({
4194
+ code: z.ZodIssueCode.custom,
4195
+ message: `Breakpoint IDs must be unique`,
4184
4196
  });
4185
4197
  }
4186
4198
  // Extract the queries boundary by removing the special characters around it
@@ -4591,6 +4603,9 @@ const sendConnectedEventWithRegisteredComponents = () => {
4591
4603
  sdkVersion: SDK_VERSION,
4592
4604
  definitions: registeredDefinitions,
4593
4605
  });
4606
+ sendMessage(OUTGOING_EVENTS.RegisteredBreakpoints, {
4607
+ breakpoints: breakpointsRegistry,
4608
+ });
4594
4609
  sendMessage(OUTGOING_EVENTS.DesignTokens, {
4595
4610
  designTokens: designTokensRegistry,
4596
4611
  resolvedCssVariables: resolveCssVariables(designTokensRegistry),
@@ -5068,6 +5083,7 @@ const useInitializeVisualEditor = (params) => {
5068
5083
  useEffect(() => {
5069
5084
  if (!hasConnectEventBeenSent.current) {
5070
5085
  runRegisteredComponentValidations();
5086
+ runBreakpointsValidation();
5071
5087
  // sending CONNECT but with the registered components now
5072
5088
  sendConnectedEventWithRegisteredComponents();
5073
5089
  hasConnectEventBeenSent.current = true;
@@ -5094,6 +5110,7 @@ const useInitializeVisualEditor = (params) => {
5094
5110
  detail: {
5095
5111
  componentRegistry,
5096
5112
  designTokens: designTokensRegistry,
5113
+ breakpoints: breakpointsRegistry,
5097
5114
  locale,
5098
5115
  entities: initialEntities ?? [],
5099
5116
  },