@m3cms/react
Advanced tools
Comparing version
import { JSONSchema7 } from 'json-schema'; | ||
import React, { ReactNode, PropsWithChildren } from 'react'; | ||
import React, { FunctionComponent, PropsWithChildren, RefObject } from 'react'; | ||
import * as _m3cms_common from '@m3cms/common'; | ||
import { UiSchema, LoadSliceWidgetsData, LoadObject, Locale, TapElementData } from '@m3cms/common'; | ||
import * as zustand from 'zustand'; | ||
import { LoadObject } from '@m3cms/common'; | ||
import { M3CmsConfig as M3CmsConfig$1 } from '@m3cms/api'; | ||
declare type CmsComponentProps = { | ||
tag: string; | ||
content?: unknown; | ||
schema: JSONSchema7; | ||
defaultContent?: {}; | ||
/** | ||
* Extends the React Functional Component to add the CMS properties. | ||
* This properties are used to transform a component in a componente integrated with the CMS of M3. | ||
*/ | ||
interface CmsFunctionalComponent<TProps = {}> extends FunctionComponent<TProps> { | ||
/** | ||
* @required | ||
* The schema of the component. It will be used to generate the form in the CMS with the | ||
* current component props to edit the component. | ||
* This schema is a JSON Schema 7. A JSON Schema is a standard to describe a JSON object. | ||
* You can read more about JSON Schema in https://json-schema.org/ | ||
* | ||
* @example | ||
* ```ts | ||
* Component.schema = { | ||
* "title": "Button", | ||
* "type": "object", | ||
* "properties": { | ||
* "text": { | ||
* "type": "string", | ||
* "title": "Text" | ||
* }, | ||
* "color": { | ||
* "type": "string", | ||
* "title": "Color" | ||
* "enum": ["primary", "secondary"] | ||
* } | ||
* } | ||
*``` | ||
*/ | ||
schema?: JSONSchema7; | ||
/** | ||
* @required | ||
* The default content of the component. | ||
* Like if you have a component with a prop text, you can set the default value of the text prop | ||
* | ||
* @exemple | ||
* ```ts | ||
* Component.defaultContent = { | ||
* text: "Hello World" | ||
* } | ||
* ``` | ||
*/ | ||
defaultContent?: Partial<TProps>; | ||
/** | ||
* This is the uiSchema of the component. It is component utilities in the CSM | ||
* | ||
* @see [uiSchemas available](https://todo.com.br) | ||
* | ||
* @example | ||
* ```ts | ||
* Component.uiSchema = { | ||
* "title": { | ||
* "ui:widget": "ColorPickerWidget", | ||
* }, | ||
* } | ||
*/ | ||
uiSchema?: Partial<Record<keyof TProps, UiSchema>>; | ||
/** | ||
* The path of the component. It is used to generate the path of the component in the CMS | ||
* in the side menu. | ||
* | ||
* @exemple | ||
* ```ts | ||
* Component.path = "HeroSection" | ||
* Component.path = "HeroSection/Card" | ||
* ``` | ||
*/ | ||
path?: string; | ||
uiSchema?: unknown; | ||
Component: React.FC<any>; | ||
/** | ||
* If this component it will be too slice Component. | ||
* A slice component is a component that will be used in the Editable | ||
* Area Component. These types of components can be addable, removable, | ||
* dynamically moved by the customer. | ||
* | ||
* @see | ||
* | ||
* @exemple | ||
* ```ts | ||
* Component.id = "AnyComponentId" | ||
* Component.sliceWidget = { | ||
* AnyComponentId: { | ||
* name: "Magic Component", | ||
* icon: "<img src="https://cdn-icons-png.flaticon.com/512/867/867891.png" />" | ||
* } | ||
* } | ||
* ``` | ||
*/ | ||
sliceWidget?: LoadSliceWidgetsData; | ||
/** | ||
* @required | ||
* id of the component. This id is used to identify the component in the CMS. | ||
* Use a unique id for each component. Don't confuse this with the tag property. | ||
* | ||
* @example | ||
* Component.id = "Hero" | ||
* Component.id = "ProductShelf" | ||
*/ | ||
id?: string; | ||
/** | ||
* @deprecated | ||
* Be careful maybe you are confusing this with the defaultContent property. This property is not used in the CMS. and it not recommended to use it. | ||
* use the defaultContent property may causa rendering issues. | ||
* | ||
* @see [twitter of React Develop](https://twitter.com/dan_abramov/status/1133878326358171650) | ||
* @see [stackOverflow discursion](https://stackoverflow.com/questions/47774695/react-functional-component-default-props-vs-default-parameters) | ||
* @see [github discursion](https://github.com/reactjs/rfcs/pull/107) | ||
*/ | ||
defaultProps?: never; | ||
} | ||
/** | ||
* | ||
*/ | ||
type CmsComponentData<T = any> = { | ||
/** | ||
* This is the tag of the component. It is id of the component in the CMS. For each tag there is a component | ||
*/ | ||
tag?: string; | ||
/** | ||
* The component itself | ||
*/ | ||
component: CmsFunctionalComponent<T>; | ||
}; | ||
declare function CmsComponent$1({ tag, schema, defaultContent, path, uiSchema, Component, }: CmsComponentProps): JSX.Element; | ||
declare function CmsPageProvider({ children }: { | ||
children: ReactNode; | ||
}): JSX.Element; | ||
type CmsComponentProps = { | ||
/** | ||
* Which tag will be used for the component. | ||
* This tag will be used to identify the component in the CMS. | ||
*/ | ||
tag: string; | ||
/** | ||
* this property will be used to receive data from the CMS api that | ||
* fill in the component's props. | ||
*/ | ||
content?: Record<string, unknown>; | ||
component: CmsFunctionalComponent<any>; | ||
/** | ||
* If for some reason you have some component property that will always be | ||
* static at the code level. You can pass these properties through here. | ||
* | ||
* Currently only the editable area component arrives and use this. In general | ||
* try to let all your component properties come straight from the CMS | ||
*/ | ||
nonMutableProps?: Record<string, unknown>; | ||
}; | ||
declare function CmsComponent$1({ tag, component: Component, content, nonMutableProps }: CmsComponentProps): JSX.Element; | ||
type CmsComponentsProps = { | ||
components: CmsComponentData[]; | ||
data: Record<string, Record<string, unknown>>; | ||
}; | ||
declare function CmsComponents({ components, data }: CmsComponentsProps): (JSX.Element | null)[]; | ||
declare function CmsPageProvider({ children }: PropsWithChildren): JSX.Element; | ||
declare const CmsGlobalContext: React.Context<{}>; | ||
@@ -32,3 +174,3 @@ declare function CmsGlobalProvider({ children }: PropsWithChildren): JSX.Element; | ||
} | ||
interface BearState { | ||
interface CmsState { | ||
components: CmsComponent[]; | ||
@@ -45,7 +187,9 @@ addComponent: (cmsComponent: CmsComponent) => void; | ||
setPickingState: (isPickingState: boolean) => void; | ||
draggingData: undefined | string; | ||
setDraggingData: (draggingData: undefined | string) => void; | ||
} | ||
declare const useCmsContextV2: zustand.UseBoundStore<Omit<zustand.StoreApi<BearState>, "setState"> & { | ||
declare const useCmsContext: zustand.UseBoundStore<Omit<zustand.StoreApi<CmsState>, "setState"> & { | ||
setState<A extends string | { | ||
type: unknown; | ||
}>(partial: BearState | Partial<BearState> | ((state: BearState) => BearState | Partial<BearState>), replace?: boolean | undefined, action?: A | undefined): void; | ||
}>(partial: CmsState | Partial<CmsState> | ((state: CmsState) => CmsState | Partial<CmsState>), replace?: boolean | undefined, action?: A | undefined): void; | ||
}>; | ||
@@ -58,3 +202,3 @@ | ||
declare type ProjectStoreProps = { | ||
type ProjectStoreProps = { | ||
language: string | undefined; | ||
@@ -69,14 +213,65 @@ projectName: string | undefined; | ||
declare type Widget = "TextWidget"; | ||
declare type UiSchema = { | ||
"ui:widget": Widget; | ||
type EditableAreaProps = { | ||
enabledWidgets: string[]; | ||
children: Array<{ | ||
/** | ||
* id do componente React | ||
*/ | ||
widget: string; | ||
/** | ||
* Qual tag será usada para o componente. Geralmente essas tags vao ser | ||
* automaticamente geradas pelo CMS | ||
*/ | ||
tag: string; | ||
}>; | ||
apiConfig: M3CmsConfig$1; | ||
allCmsComponents: CmsFunctionalComponent<any>[]; | ||
}; | ||
declare type CmsComponentData = { | ||
tag: string; | ||
component: (prop: Record<string, unknown>) => JSX.Element; | ||
schema: JSONSchema7; | ||
defaultContent: Record<string, unknown>; | ||
uiSchema?: Record<string, UiSchema>; | ||
declare const EditableArea: CmsFunctionalComponent<EditableAreaProps>; | ||
declare function getSliceWidgetData(allComponents: CmsFunctionalComponent<any>[]): (_m3cms_common.LoadSliceWidgetsData | undefined)[]; | ||
type EditableAreaProdProps = Pick<EditableAreaProps, "allCmsComponents" | "children"> & { | ||
data: Record<string, Record<string, unknown>>; | ||
}; | ||
declare function EditableAreaProd({ children, data, allCmsComponents }: EditableAreaProdProps): JSX.Element; | ||
export { BearState, CmsComponent$1 as CmsComponent, CmsComponentData, CmsComponentProps, CmsGlobalContext, CmsGlobalProvider, CmsPageProvider, ProjectStoreProps, UiSchema, Widget, useCmsContextV2, useOuvirMensageira, useProject }; | ||
type CmsComponentSwitch = CmsComponentProps & { | ||
/** | ||
* This property is used to pass the editable area component to the component. | ||
* Help to render the EditableArea optimized for production. | ||
*/ | ||
editableArea?: EditableAreaProdProps; | ||
/** | ||
* Whether it is a cms page or not. | ||
**/ | ||
isCmsPage: boolean; | ||
}; | ||
declare function CmsComponentSwitch({ editableArea, isCmsPage, ...props }: CmsComponentSwitch): JSX.Element; | ||
declare function CmsComponentProd({ component: Component, content, nonMutableProps }: CmsComponentProps): JSX.Element; | ||
type M3CmsConfig<TSchema extends { | ||
properties: unknown; | ||
}, T extends HTMLElement> = { | ||
tag: LoadObject['tag']; | ||
defaultContent?: LoadObject['defaultContent']; | ||
path?: LoadObject['path']; | ||
schema: LoadObject['schema']; | ||
uiSchema?: LoadObject['uiSchema']; | ||
ref: RefObject<T>; | ||
content?: Partial<Record<keyof TSchema["properties"], string>>; | ||
locale?: Locale; | ||
}; | ||
declare function handleSendMessageRemove(tag: string): void; | ||
declare function handleSendMessageTap(data: TapElementData): void; | ||
declare function handleSendMessageHover(tag: string): void; | ||
declare function handleSendMessageMouseMove({ clientX, clientY }: MouseEvent): void; | ||
declare function handleAddSlide(index: number): void; | ||
declare function handleSliceWidgets(data: LoadSliceWidgetsData): void; | ||
declare function handleSendMessageLoadPage(): void; | ||
declare function handleSendMessageLoadElement<TSchema extends { | ||
properties: unknown; | ||
}, TRef extends HTMLElement>(data: Omit<Required<M3CmsConfig<TSchema, TRef>>, 'ref' | 'locale'>): void; | ||
export { CmsComponent$1 as CmsComponent, CmsComponentData, CmsComponentProd, CmsComponentProps, CmsComponentSwitch, CmsComponents, CmsComponentsProps, CmsFunctionalComponent, CmsGlobalContext, CmsGlobalProvider, CmsPageProvider, CmsState, EditableArea, EditableAreaProd, EditableAreaProdProps, EditableAreaProps, M3CmsConfig, ProjectStoreProps, getSliceWidgetData, handleAddSlide, handleSendMessageHover, handleSendMessageLoadElement, handleSendMessageLoadPage, handleSendMessageMouseMove, handleSendMessageRemove, handleSendMessageTap, handleSliceWidgets, useCmsContext, useOuvirMensageira, useProject }; |
@@ -0,1 +1,2 @@ | ||
"use strict"; | ||
var __create = Object.create; | ||
@@ -24,49 +25,87 @@ var __defProp = Object.defineProperty; | ||
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); | ||
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); | ||
var __objRest = (source, exclude) => { | ||
var target = {}; | ||
for (var prop in source) | ||
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) | ||
target[prop] = source[prop]; | ||
if (source != null && __getOwnPropSymbols) | ||
for (var prop of __getOwnPropSymbols(source)) { | ||
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) | ||
target[prop] = source[prop]; | ||
} | ||
return target; | ||
}; | ||
var __export = (target, all) => { | ||
__markAsModule(target); | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __reExport = (target, module2, desc) => { | ||
if (module2 && typeof module2 === "object" || typeof module2 === "function") { | ||
for (let key of __getOwnPropNames(module2)) | ||
if (!__hasOwnProp.call(target, key) && key !== "default") | ||
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return target; | ||
return to; | ||
}; | ||
var __toModule = (module2) => { | ||
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); | ||
}; | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
// If the importer is in node compatibility mode or this is not an ESM | ||
// file that has been converted to a CommonJS file using a Babel- | ||
// compatible transform (i.e. "__esModule" has not been set), then set | ||
// "default" to the CommonJS "module.exports" for node compatibility. | ||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
mod | ||
)); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/index.tsx | ||
__export(exports, { | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
CmsComponent: () => CmsComponent, | ||
CmsComponentProd: () => CmsComponentProd, | ||
CmsComponentSwitch: () => CmsComponentSwitch, | ||
CmsComponents: () => CmsComponents, | ||
CmsGlobalContext: () => CmsGlobalContext, | ||
CmsGlobalProvider: () => CmsGlobalProvider, | ||
CmsPageProvider: () => CmsPageProvider, | ||
useCmsContextV2: () => useCmsContextV2, | ||
EditableArea: () => EditableArea_schema_default, | ||
EditableAreaProd: () => EditableAreaProd, | ||
getSliceWidgetData: () => getSliceWidgetData, | ||
handleAddSlide: () => handleAddSlide, | ||
handleSendMessageHover: () => handleSendMessageHover, | ||
handleSendMessageLoadElement: () => handleSendMessageLoadElement, | ||
handleSendMessageLoadPage: () => handleSendMessageLoadPage, | ||
handleSendMessageMouseMove: () => handleSendMessageMouseMove, | ||
handleSendMessageRemove: () => handleSendMessageRemove, | ||
handleSendMessageTap: () => handleSendMessageTap, | ||
handleSliceWidgets: () => handleSliceWidgets, | ||
useCmsContext: () => useCmsContext, | ||
useOuvirMensageira: () => useOuvirMensageira, | ||
useProject: () => useProject | ||
}); | ||
module.exports = __toCommonJS(src_exports); | ||
// src/components/cmsComponent.tsx | ||
var import_react = __toModule(require("react")); | ||
var import_react = require("react"); | ||
// src/utils/handles.ts | ||
var import_common = __toModule(require("@m3cms/common")); | ||
function handleRemove(tag) { | ||
var import_common = require("@m3cms/common"); | ||
function handleSendMessageRemove(tag) { | ||
(0, import_common.sendMessage)(import_common.AppEvent.REMOVE_ELEMENT, tag); | ||
} | ||
function handleTap(data) { | ||
function handleSendMessageTap(data) { | ||
(0, import_common.sendMessage)(import_common.AppEvent.TAP_ELEMENT, data); | ||
} | ||
function handleHover(tag) { | ||
function handleSendMessageHover(tag) { | ||
(0, import_common.sendMessage)(import_common.AppEvent.HOVER_ELEMENT, tag); | ||
} | ||
function handleMouseMove({ clientX, clientY }) { | ||
function handleSendMessageMouseMove({ clientX, clientY }) { | ||
(0, import_common.sendMessage)(import_common.AppEvent.MOUSE_MOVE, { x: clientX, y: clientY }); | ||
} | ||
function handleLoadPage() { | ||
function handleAddSlide(index) { | ||
(0, import_common.sendMessage)(import_common.AppEvent.ADD_SLICE, index); | ||
} | ||
function handleSliceWidgets(data) { | ||
(0, import_common.sendMessage)(import_common.AppEvent.LOAD_SLICE_WIDGETS, data); | ||
} | ||
function handleSendMessageLoadPage() { | ||
(0, import_common.sendMessage)(import_common.AppEvent.LOAD_PAGE, { | ||
@@ -79,3 +118,3 @@ metadata: [ | ||
} | ||
function handleLoadElement(data) { | ||
function handleSendMessageLoadElement(data) { | ||
(0, import_common.sendMessage)(import_common.AppEvent.LOAD_ELEMENT, { | ||
@@ -91,76 +130,101 @@ tag: data.tag, | ||
// src/hooks/useCmsContextV2.ts | ||
var import_zustand = __toModule(require("zustand")); | ||
var import_middleware = __toModule(require("zustand/middleware")); | ||
"use client"; | ||
var useCmsContextV2 = (0, import_zustand.create)((0, import_middleware.devtools)((set, get) => ({ | ||
isPickingState: false, | ||
setPickingState: (isPickingState) => set({ isPickingState }), | ||
components: [], | ||
selectedElement: void 0, | ||
setElementSelected: (tag) => set({ selectedElement: tag }), | ||
locale: void 0, | ||
setLocale: (locale) => set({ locale }), | ||
contents: {}, | ||
setContents: (tag, contents) => set({ | ||
contents: __spreadProps(__spreadValues({}, get().contents), { | ||
[tag]: contents | ||
}) | ||
}), | ||
removeComponent: (tag) => set((state) => { | ||
const components = state.components.filter((component) => component.tag !== tag); | ||
handleRemove(tag); | ||
return { components }; | ||
}), | ||
addComponent(cmsComponent) { | ||
set((state) => { | ||
const hasComponent = state.components.find((component) => component.tag === cmsComponent.tag); | ||
if (hasComponent) | ||
return state; | ||
handleLoadElement({ | ||
tag: cmsComponent.tag, | ||
schema: cmsComponent.schema, | ||
defaultContent: cmsComponent.defaultContent, | ||
uiSchema: cmsComponent.uiSchema, | ||
content: {}, | ||
path: cmsComponent.path || cmsComponent.tag | ||
}); | ||
return __spreadProps(__spreadValues({}, state), { | ||
components: [...state.components, cmsComponent] | ||
}); | ||
}); | ||
} | ||
}), { name: "useZustandStore", trace: true })); | ||
// src/hooks/useCmsContext.ts | ||
var import_zustand = require("zustand"); | ||
var import_middleware = require("zustand/middleware"); | ||
var useCmsContext = (0, import_zustand.create)( | ||
(0, import_middleware.devtools)( | ||
(set, get) => ({ | ||
draggingData: void 0, | ||
setDraggingData: (draggingData) => set({ draggingData }), | ||
isPickingState: false, | ||
setPickingState: (isPickingState) => set({ isPickingState }), | ||
components: [], | ||
selectedElement: void 0, | ||
setElementSelected: (tag) => { | ||
const cmsComponent = get().components.find((component) => component.tag === tag); | ||
if (cmsComponent) { | ||
handleSendMessageLoadElement({ | ||
tag: cmsComponent.tag, | ||
schema: cmsComponent.schema, | ||
defaultContent: cmsComponent.defaultContent, | ||
uiSchema: cmsComponent.uiSchema, | ||
// @ts-ignore | ||
content: cmsComponent.defaultContent, | ||
path: cmsComponent.path || cmsComponent.tag | ||
}); | ||
} | ||
return set({ selectedElement: tag }); | ||
}, | ||
locale: void 0, | ||
setLocale: (locale) => set({ locale }), | ||
contents: {}, | ||
setContents: (tag, contents) => set({ | ||
contents: __spreadProps(__spreadValues({}, get().contents), { | ||
[tag]: contents | ||
}) | ||
}), | ||
removeComponent: (tag) => set((state) => { | ||
const components = state.components.filter((component) => component.tag !== tag); | ||
handleSendMessageRemove(tag); | ||
return { components }; | ||
}), | ||
addComponent(cmsComponent) { | ||
set((state) => { | ||
const hasComponent = state.components.find((component) => component.tag === cmsComponent.tag); | ||
if (hasComponent) | ||
return state; | ||
handleSendMessageLoadElement({ | ||
tag: cmsComponent.tag, | ||
schema: cmsComponent.schema, | ||
defaultContent: cmsComponent.defaultContent, | ||
uiSchema: cmsComponent.uiSchema, | ||
content: {}, | ||
path: cmsComponent.path || cmsComponent.tag | ||
}); | ||
return __spreadProps(__spreadValues({}, state), { | ||
components: [...state.components, cmsComponent] | ||
}); | ||
}); | ||
} | ||
}), | ||
{ name: "useCmsContext", trace: true } | ||
) | ||
); | ||
// src/components/cmsComponent.tsx | ||
var import_usehooks_ts = __toModule(require("usehooks-ts")); | ||
var import_react2 = __toModule(require("react")); | ||
"use client"; | ||
var import_usehooks_ts = require("usehooks-ts"); | ||
var import_react2 = __toESM(require("react")); | ||
function CmsComponent({ | ||
tag, | ||
schema, | ||
defaultContent = {}, | ||
path = tag, | ||
uiSchema = {}, | ||
Component | ||
component: Component, | ||
content = {}, | ||
nonMutableProps = {} | ||
}) { | ||
const { schema: schema2, defaultContent: defaultContent2, path, uiSchema: uiSchema2 } = Component; | ||
const ref = (0, import_react.useRef)(null); | ||
const isHover = (0, import_usehooks_ts.useHover)(ref); | ||
const { addComponent, selectedElement, content, isPickingState } = useCmsContextV2((state) => ({ | ||
const { addComponent, selectedElement, cmsContent, isPickingState, removeComponent } = useCmsContext((state) => ({ | ||
addComponent: state.addComponent, | ||
selectedElement: state.selectedElement, | ||
content: state.contents[tag] || {}, | ||
isPickingState: state.isPickingState | ||
cmsContent: state.contents[tag] || {}, | ||
isPickingState: state.isPickingState, | ||
removeComponent: state.removeComponent | ||
})); | ||
if (isHover) | ||
handleHover(tag); | ||
handleSendMessageHover(tag); | ||
if (!schema2) { | ||
throw new Error(`Component ${tag} must have a schema to be used in the CMS`); | ||
} | ||
(0, import_react.useEffect)(() => { | ||
addComponent({ | ||
schema, | ||
schema: schema2, | ||
tag, | ||
content, | ||
defaultContent, | ||
content: cmsContent, | ||
defaultContent: defaultContent2, | ||
path, | ||
uiSchema | ||
uiSchema: uiSchema2 | ||
}); | ||
return () => { | ||
removeComponent(tag); | ||
}; | ||
}, [addComponent]); | ||
@@ -170,21 +234,71 @@ const isSelected = selectedElement === tag; | ||
if (isSelected) { | ||
props = content; | ||
props = __spreadValues(__spreadValues({}, cmsContent), nonMutableProps); | ||
} else { | ||
props = __spreadValues(__spreadValues({}, defaultContent), content); | ||
props = __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, defaultContent2), content), cmsContent), nonMutableProps); | ||
} | ||
return /* @__PURE__ */ import_react2.default.createElement("div", { | ||
ref, | ||
"aria-selected": isHover && isPickingState || isSelected, | ||
draggable: true, | ||
"aria-label": `componente ${tag}`, | ||
className: "csmComponent", | ||
onClick: () => handleTap({ tag, content }) | ||
}, /* @__PURE__ */ import_react2.default.createElement(Component, __spreadValues({}, props))); | ||
const onKeyDown = ({ key }) => { | ||
const validKeys = ["Enter", " "]; | ||
if (validKeys.includes(key)) { | ||
onClick(); | ||
} | ||
}; | ||
const onClick = (e) => { | ||
isPickingState && handleSendMessageTap({ tag, content }); | ||
handleSendMessageLoadElement({ | ||
schema: schema2, | ||
tag, | ||
content: cmsContent, | ||
defaultContent: defaultContent2, | ||
path: path != null ? path : tag, | ||
uiSchema: uiSchema2 | ||
}); | ||
if (e) { | ||
e.stopPropagation(); | ||
} | ||
}; | ||
return /* @__PURE__ */ import_react2.default.createElement( | ||
"div", | ||
__spreadValues({ | ||
ref, | ||
className: "csmComponent", | ||
onClick, | ||
onKeyDown | ||
}, getAccessibleProperties()), | ||
/* @__PURE__ */ import_react2.default.createElement(Component, __spreadValues({}, props)) | ||
); | ||
function getAccessibleProperties() { | ||
return { | ||
role: "button", | ||
tabIndex: isPickingState ? 0 : -1, | ||
"aria-selected": isHover && isPickingState || isSelected, | ||
draggable: true, | ||
"aria-label": `componente ${tag}`, | ||
"aria-disabled": !isPickingState, | ||
title: isPickingState ? `Clique para editar o componente ${tag}` : void 0 | ||
}; | ||
} | ||
} | ||
// src/components/cmsComponents.tsx | ||
var import_react3 = __toESM(require("react")); | ||
function CmsComponents({ components = [], data }) { | ||
return components.map(({ component, tag }) => { | ||
if (!tag) | ||
return null; | ||
return /* @__PURE__ */ import_react3.default.createElement( | ||
CmsComponent, | ||
{ | ||
key: tag, | ||
component, | ||
tag, | ||
content: data == null ? void 0 : data[tag] | ||
} | ||
); | ||
}); | ||
} | ||
// src/hooks/useOuvirMensageira.ts | ||
var import_common2 = __toModule(require("@m3cms/common")); | ||
"use client"; | ||
var import_common2 = require("@m3cms/common"); | ||
function useOuvirMensageira() { | ||
const { setContents, setElementSelected, setLocale, components } = useCmsContextV2((state) => ({ | ||
const { setContents, setElementSelected, setLocale, components, setDraggingData } = useCmsContext((state) => ({ | ||
setContents: state.setContents, | ||
@@ -194,5 +308,6 @@ setElementSelected: state.setElementSelected, | ||
components: state.components, | ||
setPickingState: state.setPickingState | ||
setPickingState: state.setPickingState, | ||
setDraggingData: state.setDraggingData | ||
})); | ||
const setPickingState = useCmsContextV2((state) => state.setPickingState); | ||
const setPickingState = useCmsContext((state) => state.setPickingState); | ||
function handleLoadPageWidgetsHandler() { | ||
@@ -233,2 +348,7 @@ const contentReduce = components.reduce((acc, component) => { | ||
break; | ||
case import_common2.CmsEventType.CHANGE_DRAGGING_STATE: | ||
if (typeof parsedData.data === "string" || parsedData.data === void 0) { | ||
setDraggingData(parsedData.data); | ||
} | ||
break; | ||
default: | ||
@@ -247,23 +367,26 @@ } | ||
// src/components/CmsPageProvider.tsx | ||
var import_usehooks_ts2 = __toModule(require("usehooks-ts")); | ||
var import_react3 = __toModule(require("react")); | ||
var import_common3 = __toModule(require("@m3cms/common")); | ||
"use client"; | ||
var CmsContext = (0, import_react3.createContext)({}); | ||
var import_usehooks_ts2 = require("usehooks-ts"); | ||
var import_react4 = __toESM(require("react")); | ||
var import_common3 = require("@m3cms/common"); | ||
function CmsPageProvider({ children }) { | ||
const { setTrue: setWidgetsAreLoaded, value: widgetsAlreadyLoaded } = (0, import_usehooks_ts2.useBoolean)(false); | ||
const { handleMessage, handleLoadPageWidgetsHandler } = useOuvirMensageira(); | ||
const locale = useCmsContextV2((state) => state.locale); | ||
const sendMessage3 = useCmsContextV2((state) => state.setLocale); | ||
const locale = useCmsContext((state) => state.locale); | ||
const sendMessage3 = useCmsContext((state) => state.setLocale); | ||
const components = useCmsContext((state) => state.components); | ||
(0, import_usehooks_ts2.useEventListener)("message", handleMessage); | ||
(0, import_usehooks_ts2.useEventListener)("mousemove", handleMouseMove); | ||
(0, import_usehooks_ts2.useEventListener)("mousemove", handleSendMessageMouseMove); | ||
requestLocale(); | ||
(0, import_react3.useEffect)(() => { | ||
(0, import_react4.useEffect)(() => { | ||
if (widgetsAlreadyLoaded) | ||
return; | ||
if (components.length === 0) | ||
return; | ||
handleLoadPageWidgetsHandler(); | ||
handleLoadPage(); | ||
handleSendMessageLoadPage(); | ||
setWidgetsAreLoaded(); | ||
return () => { | ||
}; | ||
}, [handleLoadPageWidgetsHandler]); | ||
return /* @__PURE__ */ import_react3.default.createElement(CmsContext.Provider, { | ||
value: {} | ||
}, children); | ||
}, [components]); | ||
return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, children); | ||
function requestLocale() { | ||
@@ -277,15 +400,11 @@ if (locale === void 0) { | ||
// src/components/CmsGlobalProvider.tsx | ||
var import_react4 = __toModule(require("react")); | ||
"use client"; | ||
var CmsGlobalContext = (0, import_react4.createContext)({}); | ||
var import_react5 = __toESM(require("react")); | ||
var CmsGlobalContext = (0, import_react5.createContext)({}); | ||
function CmsGlobalProvider({ children }) { | ||
const { handleMessage, handleLoadPageWidgetsHandler } = useOuvirMensageira(); | ||
return /* @__PURE__ */ import_react4.default.createElement(CmsGlobalContext.Provider, { | ||
value: {} | ||
}, children); | ||
return /* @__PURE__ */ import_react5.default.createElement(CmsGlobalContext.Provider, { value: {} }, children); | ||
} | ||
// src/hooks/useProject.ts | ||
var import_zustand2 = __toModule(require("zustand")); | ||
"use client"; | ||
var import_zustand2 = require("zustand"); | ||
var useProject = (0, import_zustand2.create)((set) => ({ | ||
@@ -299,11 +418,265 @@ language: void 0, | ||
})); | ||
// src/components/cmsComponentSwitch.tsx | ||
var import_react8 = __toESM(require("react")); | ||
// src/components/cmsComponentProd.tsx | ||
var import_react6 = __toESM(require("react")); | ||
function CmsComponentProd({ | ||
component: Component, | ||
content = {}, | ||
nonMutableProps = {} | ||
}) { | ||
const props = __spreadValues(__spreadValues(__spreadValues({}, Component.defaultContent), content), nonMutableProps); | ||
return /* @__PURE__ */ import_react6.default.createElement(Component, __spreadValues({}, props)); | ||
} | ||
// src/components/EditableArea/EditableAreaProd.tsx | ||
var import_react7 = __toESM(require("react")); | ||
function EditableAreaProd({ children = [], data = {}, allCmsComponents }) { | ||
console.log("marlon passos"); | ||
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, children.map(({ widget, tag }) => { | ||
const Component = allCmsComponents.find((a) => a.id === widget); | ||
if (!Component) | ||
return null; | ||
const { defaultContent: defaultContent2 } = Component; | ||
return /* @__PURE__ */ import_react7.default.createElement( | ||
Component, | ||
__spreadValues(__spreadValues({ | ||
key: tag | ||
}, defaultContent2), data == null ? void 0 : data[tag]) | ||
); | ||
})); | ||
} | ||
// src/components/cmsComponentSwitch.tsx | ||
function CmsComponentSwitch(_a) { | ||
var _b = _a, { editableArea, isCmsPage } = _b, props = __objRest(_b, ["editableArea", "isCmsPage"]); | ||
return isCmsPage ? /* @__PURE__ */ import_react8.default.createElement(CmsComponent, __spreadValues({}, props)) : editableArea ? /* @__PURE__ */ import_react8.default.createElement( | ||
EditableAreaProd, | ||
{ | ||
allCmsComponents: editableArea.allCmsComponents, | ||
children: editableArea.children, | ||
data: editableArea.data | ||
} | ||
) : /* @__PURE__ */ import_react8.default.createElement(CmsComponentProd, __spreadValues({}, props)); | ||
} | ||
// src/components/EditableArea/EditableArea.tsx | ||
var import_react10 = __toESM(require("react")); | ||
var import_api = require("@m3cms/api"); | ||
// src/components/EditableArea/Separator.tsx | ||
var import_react9 = __toESM(require("react")); | ||
var import_usehooks_ts3 = require("usehooks-ts"); | ||
function useMouseNear(nearSpace = 40) { | ||
const ref = (0, import_react9.useRef)(null); | ||
const [isMouseNear, setIsMouseNear] = (0, import_react9.useState)(false); | ||
const handleMouseMove = (0, import_react9.useCallback)((event) => { | ||
if (!ref.current) | ||
return; | ||
const separatorRect = ref.current.getBoundingClientRect(); | ||
const distance = Math.abs(event.clientY - separatorRect.y); | ||
setIsMouseNear(distance <= nearSpace); | ||
}, [ref.current]); | ||
(0, import_usehooks_ts3.useEventListener)("mousemove", handleMouseMove); | ||
return { | ||
ref, | ||
isMouseNear | ||
}; | ||
} | ||
function Separator({ index, handleIndex, isDragging }) { | ||
const { isMouseNear, ref } = useMouseNear(); | ||
if (!isDragging) | ||
return null; | ||
return /* @__PURE__ */ import_react9.default.createElement( | ||
"div", | ||
{ | ||
className: "separator", | ||
"aria-hidden": !isMouseNear, | ||
tabIndex: isDragging ? 0 : -1, | ||
"aria-label": `click to add a new component at position ${index}`, | ||
ref, | ||
onClick: handleClick, | ||
onKeyDown: handleKeyDown | ||
} | ||
); | ||
function handleKeyDown({ key }) { | ||
const validKeys = ["Enter", " "]; | ||
if (validKeys.includes(key)) { | ||
handleIndex(index); | ||
} | ||
} | ||
function handleClick() { | ||
isDragging && isMouseNear && handleIndex(index); | ||
} | ||
} | ||
// src/components/EditableArea/EditableArea.tsx | ||
var EditableArea = ({ | ||
children = [], | ||
allCmsComponents = [], | ||
apiConfig | ||
}) => { | ||
const [components, setComponents] = (0, import_react10.useState)([]); | ||
const tags = components.filter((a) => a.tag !== void 0).map((a) => a.tag); | ||
const { data } = (0, import_api.useCmsData)(tags, apiConfig); | ||
const draggingData = useCmsContext((a) => a.draggingData); | ||
const isDragging = Boolean(draggingData); | ||
(0, import_react10.useEffect)(() => { | ||
if (children.length === 0) | ||
return; | ||
const cc = children.reduce((acc, { widget, tag }) => { | ||
const component = allCmsComponents.find((a) => a.id === widget); | ||
if (!component || !component.schema) | ||
return acc; | ||
component.path = `home-slice/${tag}`; | ||
const componentData = { | ||
component, | ||
tag | ||
}; | ||
return [...acc, componentData]; | ||
}, []); | ||
setComponents(cc); | ||
}, [children]); | ||
(0, import_react10.useEffect)(() => { | ||
getSliceWidgetData(allCmsComponents).forEach((sliceWidget) => { | ||
if (!sliceWidget) | ||
return; | ||
handleSliceWidgets(sliceWidget); | ||
}); | ||
}, [data]); | ||
let index = 0; | ||
return /* @__PURE__ */ import_react10.default.createElement( | ||
"div", | ||
{ | ||
className: "c" | ||
}, | ||
/* @__PURE__ */ import_react10.default.createElement(Separator, { index: getAndUpdateIndex(), handleIndex: handleAddSlide, isDragging }), | ||
components.map(({ component, tag }, i) => { | ||
if (!tag) | ||
return null; | ||
return /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement( | ||
CmsComponent, | ||
{ | ||
key: tag, | ||
component, | ||
tag, | ||
content: data == null ? void 0 : data[tag] | ||
} | ||
), isComponentBeforeLast(i) && /* @__PURE__ */ import_react10.default.createElement( | ||
Separator, | ||
{ | ||
index: getAndUpdateIndex(), | ||
handleIndex: handleAddSlide, | ||
isDragging | ||
} | ||
)); | ||
}), | ||
/* @__PURE__ */ import_react10.default.createElement(Separator, { index: getAndUpdateIndex(), handleIndex: handleAddSlide, isDragging }) | ||
); | ||
function getAndUpdateIndex() { | ||
return index++; | ||
} | ||
function isComponentBeforeLast(i) { | ||
return i < components.length - 1; | ||
} | ||
}; | ||
var EditableArea_default = EditableArea; | ||
function getSliceWidgetData(allComponents) { | ||
return allComponents.reduce((acc, value) => { | ||
if ("sliceWidget" in value && value.sliceWidget) { | ||
acc.push(value.sliceWidget); | ||
} | ||
return acc; | ||
}, []); | ||
} | ||
// src/components/EditableArea/EditableArea.schema.ts | ||
var id = "home-slice"; | ||
var defaultContent = { | ||
enabledWidgets: [ | ||
"@mobnine.image", | ||
"@mobnine.shelf", | ||
"@mobnine.shelf_tabs", | ||
"@mobnine.banners", | ||
"@mobnine.info_card", | ||
"@mobnine.text", | ||
"@mobnine.separator", | ||
"@mobnine.empty", | ||
"FsHero", | ||
"FsProductShelf" | ||
], | ||
children: [ | ||
{ | ||
"widget": "FsHero", | ||
"tag": "FsHero" | ||
}, | ||
{ | ||
"widget": "@mobnine.shelf_tabs", | ||
"tag": "home.shelf-tabs" | ||
}, | ||
{ | ||
"widget": "@mobnine.info_card", | ||
"tag": "home.infocard" | ||
}, | ||
{ | ||
"widget": "@mobnine.shelf", | ||
"tag": "home.shelf" | ||
} | ||
] | ||
}; | ||
var schema = { | ||
"title": "\xC1rea edit\xE1vel", | ||
"type": "object", | ||
"properties": { | ||
"children": { | ||
"type": "array", | ||
"items": { | ||
"type": "object", | ||
"properties": { | ||
"widget": { | ||
"type": "string" | ||
}, | ||
"tag": { | ||
"type": "string" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
var uiSchema = { | ||
"children": { | ||
"ui:widget": "SliceWidget" | ||
} | ||
}; | ||
EditableArea_default.id = id; | ||
EditableArea_default.schema = schema; | ||
EditableArea_default.defaultContent = defaultContent; | ||
EditableArea_default.uiSchema = uiSchema; | ||
var EditableArea_schema_default = EditableArea_default; | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
CmsComponent, | ||
CmsComponentProd, | ||
CmsComponentSwitch, | ||
CmsComponents, | ||
CmsGlobalContext, | ||
CmsGlobalProvider, | ||
CmsPageProvider, | ||
useCmsContextV2, | ||
EditableArea, | ||
EditableAreaProd, | ||
getSliceWidgetData, | ||
handleAddSlide, | ||
handleSendMessageHover, | ||
handleSendMessageLoadElement, | ||
handleSendMessageLoadPage, | ||
handleSendMessageMouseMove, | ||
handleSendMessageRemove, | ||
handleSendMessageTap, | ||
handleSliceWidgets, | ||
useCmsContext, | ||
useOuvirMensageira, | ||
useProject | ||
}); |
{ | ||
"name": "@m3cms/react", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"main": "./dist/index.js", | ||
@@ -12,28 +12,58 @@ "module": "./dist/index.mjs", | ||
], | ||
"scripts": { | ||
"build": "tsup src/index.tsx --format esm,cjs --dts --external react", | ||
"dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react", | ||
"lint": "eslint \"src/**/*.ts*\"", | ||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" | ||
}, | ||
"dependencies": { | ||
"json-schema": "^0.4.0", | ||
"zustand": "^4.3.8", | ||
"usehooks-ts": "^2.9.1", | ||
"@m3cms/common": "workspace:*" | ||
"zustand": "^4.3.9", | ||
"@m3cms/common": "0.1.0", | ||
"@m3cms/api": "0.1.0" | ||
}, | ||
"devDependencies": { | ||
"@testing-library/jest-dom": "^5.17.0", | ||
"@testing-library/react": "^14.0.0", | ||
"@testing-library/user-event": "^14.4.3", | ||
"@types/json-schema": "^7.0.12", | ||
"@m3cms/tsconfig": "workspace:*", | ||
"@types/react": "^18.0.9", | ||
"@types/react-dom": "^18.0.4", | ||
"eslint": "^8.15.0", | ||
"eslint-config-m3cms": "workspace:*", | ||
"react": "^18.2.0", | ||
"tsup": "^5.10.1", | ||
"typescript": "^4.5.3" | ||
"@types/react": "^18.2.17", | ||
"@types/react-dom": "^18.2.7", | ||
"@vitejs/plugin-react": "^4.0.3", | ||
"@vitest/coverage-v8": "^0.33.0", | ||
"eslint": "^8.46.0", | ||
"jsdom": "^22.1.0", | ||
"react-dom": "^18.2.0", | ||
"tsup": "^7.1.0", | ||
"typescript": "^5.1.6", | ||
"vitest": "^0.33.0", | ||
"@m3cms/tsconfig": "0.0.1", | ||
"eslint-config-m3cms": "0.0.1" | ||
}, | ||
"peerDependencies": { | ||
"react": "^18.2.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"keywords": [ | ||
"m3", | ||
"cms", | ||
"react" | ||
], | ||
"author": "M3, a Cadastra Company", | ||
"contributors": [ | ||
{ | ||
"name": "Marlon Passos", | ||
"email": "marlon.passos@m3ecommerce.com" | ||
} | ||
], | ||
"description": "M3 CMS API", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://bitbucket.org/m3ecommerce/m3_cms_web_adapter/src/master/" | ||
}, | ||
"homepage": "https://bitbucket.org/m3ecommerce/m3_cms_web_adapter/src/master/README.md", | ||
"scripts": { | ||
"build": "tsup src/index.ts --format esm,cjs --dts --external react", | ||
"dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react", | ||
"lint": "eslint \"src/**/*.ts*\"", | ||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", | ||
"test": "vitest run" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
87783
287.08%7
75%2223
258.55%1
-50%0
-100%6
50%16
77.78%1
Infinity%+ Added
+ Added
+ Added
Updated
Updated