@elementor/editor-styles-repository 0.8.4 → 0.8.5
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +6 -0
- package/dist/index.d.mts +9 -7
- package/dist/index.d.ts +9 -7
- package/dist/index.js +42 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/hooks/{use-create-actions-by-provider.ts → use-get-styles-repository-create-action.ts} +9 -2
- package/src/index.ts +1 -1
- package/src/utils/__tests__/validate-style-label.test.ts +92 -9
- package/src/utils/validate-style-label.ts +45 -9
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @elementor/editor-styles-repository@0.8.
|
|
2
|
+
> @elementor/editor-styles-repository@0.8.5 build
|
|
3
3
|
> tsup --config=../../tsup.build.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[32mESM[39m [1mdist/index.mjs [22m[
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[
|
|
15
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
17
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m8.13 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m15.65 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 94ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m10.08 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m16.50 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 102ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m3.
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 9115ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m3.35 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.35 KB[39m
|
package/CHANGELOG.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -41,15 +41,17 @@ declare function useProviders(): StylesProvider[];
|
|
|
41
41
|
|
|
42
42
|
type CreateAction = Required<StylesProvider['actions']>['create'];
|
|
43
43
|
type CreateTuple = [StylesProvider, CreateAction];
|
|
44
|
-
declare function
|
|
44
|
+
declare function useGetStylesRepositoryCreateAction(): CreateTuple | null;
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
type ValidationEvent = 'inputChange' | 'create' | 'rename';
|
|
47
|
+
type ValidationResult = {
|
|
48
|
+
isValid: true;
|
|
49
|
+
errorMessage: null;
|
|
49
50
|
} | {
|
|
50
|
-
isValid:
|
|
51
|
-
|
|
51
|
+
isValid: false;
|
|
52
|
+
errorMessage: string;
|
|
52
53
|
};
|
|
54
|
+
declare function validateStyleLabel(label: string, event: ValidationEvent | 'rename'): ValidationResult;
|
|
53
55
|
|
|
54
56
|
type CreateStylesProviderOptions = {
|
|
55
57
|
key: string | (() => string);
|
|
@@ -80,4 +82,4 @@ declare const ELEMENTS_STYLES_RESERVED_LABEL = "local";
|
|
|
80
82
|
|
|
81
83
|
declare function init(): void;
|
|
82
84
|
|
|
83
|
-
export { type CreateStylesProviderOptions, ELEMENTS_BASE_STYLES_PROVIDER_KEY, ELEMENTS_STYLES_PROVIDER_KEY_PREFIX, ELEMENTS_STYLES_RESERVED_LABEL, type Meta, type StylesProvider, type UpdateActionPayload, type UpdatePropsActionPayload, createStylesProvider, init, isElementsStylesProvider, stylesRepository,
|
|
85
|
+
export { type CreateStylesProviderOptions, ELEMENTS_BASE_STYLES_PROVIDER_KEY, ELEMENTS_STYLES_PROVIDER_KEY_PREFIX, ELEMENTS_STYLES_RESERVED_LABEL, type Meta, type StylesProvider, type UpdateActionPayload, type UpdatePropsActionPayload, createStylesProvider, init, isElementsStylesProvider, stylesRepository, useGetStylesRepositoryCreateAction, useProviders, validateStyleLabel };
|
package/dist/index.d.ts
CHANGED
|
@@ -41,15 +41,17 @@ declare function useProviders(): StylesProvider[];
|
|
|
41
41
|
|
|
42
42
|
type CreateAction = Required<StylesProvider['actions']>['create'];
|
|
43
43
|
type CreateTuple = [StylesProvider, CreateAction];
|
|
44
|
-
declare function
|
|
44
|
+
declare function useGetStylesRepositoryCreateAction(): CreateTuple | null;
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
type ValidationEvent = 'inputChange' | 'create' | 'rename';
|
|
47
|
+
type ValidationResult = {
|
|
48
|
+
isValid: true;
|
|
49
|
+
errorMessage: null;
|
|
49
50
|
} | {
|
|
50
|
-
isValid:
|
|
51
|
-
|
|
51
|
+
isValid: false;
|
|
52
|
+
errorMessage: string;
|
|
52
53
|
};
|
|
54
|
+
declare function validateStyleLabel(label: string, event: ValidationEvent | 'rename'): ValidationResult;
|
|
53
55
|
|
|
54
56
|
type CreateStylesProviderOptions = {
|
|
55
57
|
key: string | (() => string);
|
|
@@ -80,4 +82,4 @@ declare const ELEMENTS_STYLES_RESERVED_LABEL = "local";
|
|
|
80
82
|
|
|
81
83
|
declare function init(): void;
|
|
82
84
|
|
|
83
|
-
export { type CreateStylesProviderOptions, ELEMENTS_BASE_STYLES_PROVIDER_KEY, ELEMENTS_STYLES_PROVIDER_KEY_PREFIX, ELEMENTS_STYLES_RESERVED_LABEL, type Meta, type StylesProvider, type UpdateActionPayload, type UpdatePropsActionPayload, createStylesProvider, init, isElementsStylesProvider, stylesRepository,
|
|
85
|
+
export { type CreateStylesProviderOptions, ELEMENTS_BASE_STYLES_PROVIDER_KEY, ELEMENTS_STYLES_PROVIDER_KEY_PREFIX, ELEMENTS_STYLES_RESERVED_LABEL, type Meta, type StylesProvider, type UpdateActionPayload, type UpdatePropsActionPayload, createStylesProvider, init, isElementsStylesProvider, stylesRepository, useGetStylesRepositoryCreateAction, useProviders, validateStyleLabel };
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
init: () => init,
|
|
28
28
|
isElementsStylesProvider: () => isElementsStylesProvider,
|
|
29
29
|
stylesRepository: () => stylesRepository,
|
|
30
|
-
|
|
30
|
+
useGetStylesRepositoryCreateAction: () => useGetStylesRepositoryCreateAction,
|
|
31
31
|
useProviders: () => useProviders,
|
|
32
32
|
validateStyleLabel: () => validateStyleLabel
|
|
33
33
|
});
|
|
@@ -76,16 +76,22 @@ function useProviders() {
|
|
|
76
76
|
return stylesRepository.getProviders();
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
// src/hooks/use-
|
|
79
|
+
// src/hooks/use-get-styles-repository-create-action.ts
|
|
80
80
|
var import_react2 = require("react");
|
|
81
|
-
function
|
|
81
|
+
function useGetStylesRepositoryCreateAction() {
|
|
82
82
|
return (0, import_react2.useMemo)(() => {
|
|
83
|
-
|
|
83
|
+
const createActions = stylesRepository.getProviders().map((provider) => {
|
|
84
84
|
if (!provider.actions.create) {
|
|
85
85
|
return null;
|
|
86
86
|
}
|
|
87
87
|
return [provider, provider.actions.create];
|
|
88
88
|
}).filter((item) => !!item);
|
|
89
|
+
if (createActions.length === 1) {
|
|
90
|
+
return createActions[0];
|
|
91
|
+
} else if (createActions.length === 0) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
throw new Error("Multiple providers with create action found in styles repository.");
|
|
89
95
|
}, []);
|
|
90
96
|
}
|
|
91
97
|
|
|
@@ -186,25 +192,49 @@ function isValidElementsMeta(meta) {
|
|
|
186
192
|
}
|
|
187
193
|
|
|
188
194
|
// src/utils/validate-style-label.ts
|
|
189
|
-
var
|
|
190
|
-
var
|
|
191
|
-
|
|
195
|
+
var NO_START_DIGIT_REGEX = /^(|[^0-9].*)$/;
|
|
196
|
+
var NO_SPACES_REGEX = /^\S*$/;
|
|
197
|
+
var NO_SPECIAL_CHARS_REGEX = /^(|[a-zA-Z0-9_-]+)$/;
|
|
198
|
+
var NO_DOUBLE_HYPHEN_START_REGEX = /^(?!--).*/;
|
|
199
|
+
var NO_HYPHEN_DIGIT_START_REGEX = /^(?!-[0-9])/;
|
|
200
|
+
var NO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX = /^(?!.*(--|__)).*/;
|
|
201
|
+
var NO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX = /^(?![-_]).*(?<![-_])$/;
|
|
202
|
+
var RESERVED_CLASS_NAMES = ["container"];
|
|
203
|
+
var schema = import_schema.z.string().max(50, (0, import_i18n.__)("Class name is too long. Please keep it under 50 characters.", "elementor")).regex(NO_START_DIGIT_REGEX, (0, import_i18n.__)("Class names must start with a letter.", "elementor")).regex(NO_SPACES_REGEX, (0, import_i18n.__)("Class names can\u2019t contain spaces.", "elementor")).regex(
|
|
204
|
+
NO_SPECIAL_CHARS_REGEX,
|
|
205
|
+
(0, import_i18n.__)("Class names can only use letters, numbers, dashes (-), and underscores (_).", "elementor")
|
|
206
|
+
).regex(NO_DOUBLE_HYPHEN_START_REGEX, (0, import_i18n.__)("Double hyphens are reserved for custom properties.", "elementor")).regex(
|
|
207
|
+
NO_HYPHEN_DIGIT_START_REGEX,
|
|
208
|
+
(0, import_i18n.__)("Class names can\u2019t start with a hyphen followed by a number.", "elementor")
|
|
209
|
+
).regex(
|
|
210
|
+
NO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX,
|
|
211
|
+
(0, import_i18n.__)("Avoid using multiple dashes or underscores in a row.", "elementor")
|
|
212
|
+
).regex(
|
|
213
|
+
NO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX,
|
|
214
|
+
(0, import_i18n.__)("Class names can\u2019t start or end with a dash or underscore.", "elementor")
|
|
215
|
+
).refine((value) => !RESERVED_CLASS_NAMES.includes(value), {
|
|
216
|
+
message: (0, import_i18n.__)("This name is reserved and can\u2019t be used. Try something more specific.", "elementor")
|
|
217
|
+
});
|
|
218
|
+
function validateStyleLabel(label, event) {
|
|
192
219
|
const existingLabels = /* @__PURE__ */ new Set([
|
|
193
220
|
ELEMENTS_STYLES_RESERVED_LABEL,
|
|
194
221
|
...stylesRepository.all().map((styleDef) => styleDef.label.toLowerCase())
|
|
195
222
|
]);
|
|
196
|
-
const
|
|
197
|
-
|
|
223
|
+
const fullValidationEvent = ["create", "rename"].includes(event);
|
|
224
|
+
const result = schema.refine((value) => !(fullValidationEvent && value.length < 2), {
|
|
225
|
+
message: (0, import_i18n.__)("Class name is too short. Use at least 2 characters.", "elementor")
|
|
226
|
+
}).refine((value) => !(fullValidationEvent && existingLabels.has(value)), {
|
|
227
|
+
message: (0, import_i18n.__)("This class name already exists. Please choose a unique name.", "elementor")
|
|
198
228
|
}).safeParse(label.toLowerCase());
|
|
199
229
|
if (result.success) {
|
|
200
230
|
return {
|
|
201
231
|
isValid: true,
|
|
202
|
-
|
|
232
|
+
errorMessage: null
|
|
203
233
|
};
|
|
204
234
|
}
|
|
205
235
|
return {
|
|
206
236
|
isValid: false,
|
|
207
|
-
|
|
237
|
+
errorMessage: result.error.format()._errors[0]
|
|
208
238
|
};
|
|
209
239
|
}
|
|
210
240
|
|
|
@@ -245,7 +275,7 @@ function init() {
|
|
|
245
275
|
init,
|
|
246
276
|
isElementsStylesProvider,
|
|
247
277
|
stylesRepository,
|
|
248
|
-
|
|
278
|
+
useGetStylesRepositoryCreateAction,
|
|
249
279
|
useProviders,
|
|
250
280
|
validateStyleLabel
|
|
251
281
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils/create-styles-repository.ts","../src/styles-repository.ts","../src/hooks/use-providers.ts","../src/hooks/use-create-actions-by-provider.ts","../src/utils/validate-style-label.ts","../src/providers/document-elements-styles-provider.ts","../src/errors.ts","../src/utils/create-styles-provider.ts","../src/utils/is-elements-styles-provider.ts","../src/providers/element-base-styles-provider.ts","../src/init.ts"],"sourcesContent":["export * from './types';\n\nexport { stylesRepository } from './styles-repository';\nexport { useProviders } from './hooks/use-providers';\nexport { useCreateActionsByProvider } from './hooks/use-create-actions-by-provider';\nexport { validateStyleLabel } from './utils/validate-style-label';\nexport { createStylesProvider, type CreateStylesProviderOptions } from './utils/create-styles-provider';\nexport { isElementsStylesProvider } from './utils/is-elements-styles-provider';\n\nexport { ELEMENTS_BASE_STYLES_PROVIDER_KEY } from './providers/element-base-styles-provider';\nexport {\n\tELEMENTS_STYLES_PROVIDER_KEY_PREFIX,\n\tELEMENTS_STYLES_RESERVED_LABEL,\n} from './providers/document-elements-styles-provider';\n\nexport { init } from './init';\n","import { type Meta, type StylesProvider } from '../types';\n\nexport const createStylesRepository = () => {\n\tconst providers: StylesProvider[] = [];\n\n\tconst getProviders = () => {\n\t\treturn providers.slice( 0 ).sort( ( a, b ) => ( a.priority > b.priority ? -1 : 1 ) );\n\t};\n\n\tconst register = ( provider: StylesProvider ) => {\n\t\tproviders.push( provider );\n\t};\n\n\tconst all = ( meta: Meta = {} ) => {\n\t\treturn getProviders().flatMap( ( provider ) => provider.actions.all( meta ) );\n\t};\n\n\tconst subscribe = ( cb: () => void ) => {\n\t\tconst unsubscribes = providers.map( ( provider ) => {\n\t\t\treturn provider.subscribe( cb );\n\t\t} );\n\n\t\treturn () => {\n\t\t\tunsubscribes.forEach( ( unsubscribe ) => unsubscribe() );\n\t\t};\n\t};\n\n\tconst getProviderByKey = ( key: string ) => {\n\t\treturn providers.find( ( provider ) => provider.getKey() === key );\n\t};\n\n\treturn {\n\t\tall,\n\t\tregister,\n\t\tsubscribe,\n\t\tgetProviders,\n\t\tgetProviderByKey,\n\t};\n};\n","import { createStylesRepository } from './utils/create-styles-repository';\n\nexport const stylesRepository = createStylesRepository();\n","import { useEffect, useReducer } from 'react';\n\nimport { stylesRepository } from '../styles-repository';\n\nexport function useProviders() {\n\tconst [ , rerender ] = useReducer( ( prev ) => ! prev, false );\n\n\tuseEffect( () => stylesRepository.subscribe( rerender ), [] );\n\n\treturn stylesRepository.getProviders();\n}\n","import { useMemo } from 'react';\n\nimport { stylesRepository } from '../styles-repository';\nimport { type StylesProvider } from '../types';\n\ntype CreateAction = Required< StylesProvider[ 'actions' ] >[ 'create' ];\ntype CreateTuple = [ StylesProvider, CreateAction ];\n\nexport function useCreateActionsByProvider() {\n\treturn useMemo( () => {\n\t\treturn stylesRepository\n\t\t\t.getProviders()\n\t\t\t.map< CreateTuple | null >( ( provider ) => {\n\t\t\t\tif ( ! provider.actions.create ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn [ provider, provider.actions.create ];\n\t\t\t} )\n\t\t\t.filter( ( item ) => !! item );\n\t}, [] );\n}\n","import { z } from '@elementor/schema';\nimport { __ } from '@wordpress/i18n';\n\nimport { ELEMENTS_STYLES_RESERVED_LABEL } from '../providers/document-elements-styles-provider';\nimport { stylesRepository } from '../styles-repository';\n\nconst VALID_LABEL_REGEX = /^[a-zA-Z0-9_-]+$/;\n\nconst schema = z\n\t.string()\n\t.min( 1, __( 'Cannot be empty', 'elementor' ) )\n\t.max( 50, __( 'Cannot be longer than 50 characters', 'elementor' ) )\n\t.regex( VALID_LABEL_REGEX, __( 'Invalid format', 'elementor' ) );\n\nexport function validateStyleLabel( label: string ) {\n\tconst existingLabels = new Set( [\n\t\tELEMENTS_STYLES_RESERVED_LABEL,\n\t\t...stylesRepository.all().map( ( styleDef ) => styleDef.label.toLowerCase() ),\n\t] );\n\n\tconst result = schema\n\t\t.refine( ( value ) => ! existingLabels.has( value ), {\n\t\t\tmessage: __( 'Name exists', 'elementor' ),\n\t\t} )\n\t\t.safeParse( label.toLowerCase() );\n\n\tif ( result.success ) {\n\t\treturn {\n\t\t\tisValid: true,\n\t\t\terror: null,\n\t\t};\n\t}\n\n\treturn {\n\t\tisValid: false,\n\t\terror: result.error.format()._errors[ 0 ],\n\t};\n}\n","import {\n\tgetCurrentDocumentId,\n\tgetElements,\n\tgetElementStyles,\n\tstyleRerenderEvents,\n\tupdateElementStyle,\n} from '@elementor/editor-elements';\nimport { __privateListenTo as listenTo } from '@elementor/editor-v1-adapters';\n\nimport { ActiveDocumentMustExistError, InvalidElementsStyleProviderMetaError } from '../errors';\nimport { createStylesProvider } from '../utils/create-styles-provider';\n\nexport const ELEMENTS_STYLES_PROVIDER_KEY_PREFIX = 'document-elements-';\nexport const ELEMENTS_STYLES_RESERVED_LABEL = 'local';\n\ntype ElementsMeta = {\n\telementId: string;\n};\n\nexport const documentElementsStylesProvider = createStylesProvider( {\n\tkey: () => {\n\t\tconst documentId = getCurrentDocumentId();\n\n\t\tif ( ! documentId ) {\n\t\t\tthrow new ActiveDocumentMustExistError();\n\t\t}\n\n\t\treturn `${ ELEMENTS_STYLES_PROVIDER_KEY_PREFIX }${ documentId }`;\n\t},\n\tpriority: 50,\n\tsubscribe: ( cb ) => listenTo( styleRerenderEvents, cb ),\n\tactions: {\n\t\tall: ( meta = {} ) => {\n\t\t\tlet elements = getElements();\n\n\t\t\tif ( isValidElementsMeta( meta ) ) {\n\t\t\t\telements = elements.filter( ( element ) => element.id === meta.elementId );\n\t\t\t}\n\n\t\t\treturn elements.flatMap( ( element ) => Object.values( element.model.get( 'styles' ) ?? {} ) );\n\t\t},\n\n\t\tget: ( id, meta = {} ) => {\n\t\t\tif ( ! isValidElementsMeta( meta ) ) {\n\t\t\t\tthrow new InvalidElementsStyleProviderMetaError( { context: { meta } } );\n\t\t\t}\n\n\t\t\tconst styles = getElementStyles( meta.elementId ) ?? {};\n\n\t\t\treturn styles[ id ] ?? null;\n\t\t},\n\n\t\tupdateProps: ( args, meta = {} ) => {\n\t\t\tif ( ! isValidElementsMeta( meta ) ) {\n\t\t\t\tthrow new InvalidElementsStyleProviderMetaError( { context: { meta } } );\n\t\t\t}\n\n\t\t\tupdateElementStyle( {\n\t\t\t\telementId: meta.elementId,\n\t\t\t\tstyleId: args.id,\n\t\t\t\tmeta: args.meta,\n\t\t\t\tprops: args.props,\n\t\t\t} );\n\t\t},\n\t},\n} );\n\nfunction isValidElementsMeta( meta: Record< string, unknown > ): meta is ElementsMeta {\n\treturn 'elementId' in meta && typeof meta.elementId === 'string' && !! meta.elementId;\n}\n","import { createError } from '@elementor/utils';\n\nexport const InvalidElementsStyleProviderMetaError = createError< { meta: Record< string, unknown > } >( {\n\tcode: 'invalid_elements_style_provider_meta',\n\tmessage: 'Invalid elements style provider meta.',\n} );\n\nexport const ActiveDocumentMustExistError = createError( {\n\tcode: 'active_document_must_exist',\n\tmessage: 'Active document must exist.',\n} );\n","import { type StylesProvider } from '../types';\n\nexport type CreateStylesProviderOptions = {\n\tkey: string | ( () => string );\n\tpriority?: number;\n\tlimit?: number;\n\tsubscribe?: ( callback: () => void ) => () => void;\n\tlabels?: {\n\t\tsingular: string;\n\t\tplural: string;\n\t};\n\tactions: {\n\t\tall: StylesProvider[ 'actions' ][ 'all' ];\n\t\tget: StylesProvider[ 'actions' ][ 'get' ];\n\t\tcreate?: StylesProvider[ 'actions' ][ 'create' ];\n\t\tdelete?: StylesProvider[ 'actions' ][ 'delete' ];\n\t\tupdate?: StylesProvider[ 'actions' ][ 'update' ];\n\t\tupdateProps?: StylesProvider[ 'actions' ][ 'updateProps' ];\n\t};\n};\n\nconst DEFAULT_LIMIT = 10000;\nconst DEFAULT_PRIORITY = 10;\n\nexport function createStylesProvider( {\n\tkey,\n\tpriority = DEFAULT_PRIORITY,\n\tlimit = DEFAULT_LIMIT,\n\tsubscribe = () => () => {},\n\tlabels,\n\tactions,\n}: CreateStylesProviderOptions ): StylesProvider {\n\treturn {\n\t\tgetKey: typeof key === 'string' ? () => key : key,\n\t\tpriority,\n\t\tlimit,\n\t\tsubscribe,\n\t\tlabels: {\n\t\t\tsingular: labels?.singular ?? null,\n\t\t\tplural: labels?.plural ?? null,\n\t\t},\n\t\tactions: {\n\t\t\tall: actions.all,\n\t\t\tget: actions.get,\n\t\t\tcreate: actions.create,\n\t\t\tdelete: actions.delete,\n\t\t\tupdate: actions.update,\n\t\t\tupdateProps: actions.updateProps,\n\t\t},\n\t};\n}\n","import { ELEMENTS_STYLES_PROVIDER_KEY_PREFIX } from '../providers/document-elements-styles-provider';\n\nexport function isElementsStylesProvider( key: string ) {\n\treturn new RegExp( `^${ ELEMENTS_STYLES_PROVIDER_KEY_PREFIX }\\\\d+$` ).test( key );\n}\n","import { getWidgetsCache } from '@elementor/editor-elements';\n\nimport { createStylesProvider } from '../utils/create-styles-provider';\n\nexport const ELEMENTS_BASE_STYLES_PROVIDER_KEY = 'element-base-styles';\n\nexport const elementBaseStylesProvider = createStylesProvider( {\n\tkey: ELEMENTS_BASE_STYLES_PROVIDER_KEY,\n\tactions: {\n\t\tall() {\n\t\t\tconst widgetsCache = getWidgetsCache();\n\n\t\t\treturn Object.values( widgetsCache ?? {} ).flatMap( ( widget ) =>\n\t\t\t\tObject.values( widget.base_styles ?? {} )\n\t\t\t);\n\t\t},\n\n\t\tget( id ) {\n\t\t\treturn this.all().find( ( style ) => style.id === id ) ?? null;\n\t\t},\n\t},\n} );\n","import { documentElementsStylesProvider } from './providers/document-elements-styles-provider';\nimport { elementBaseStylesProvider } from './providers/element-base-styles-provider';\nimport { stylesRepository } from './styles-repository';\n\nexport function init() {\n\tstylesRepository.register( documentElementsStylesProvider );\n\tstylesRepository.register( elementBaseStylesProvider );\n}\n"],"mappings":"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","names":["import_react","listenTo","import_editor_elements"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/create-styles-repository.ts","../src/styles-repository.ts","../src/hooks/use-providers.ts","../src/hooks/use-get-styles-repository-create-action.ts","../src/utils/validate-style-label.ts","../src/providers/document-elements-styles-provider.ts","../src/errors.ts","../src/utils/create-styles-provider.ts","../src/utils/is-elements-styles-provider.ts","../src/providers/element-base-styles-provider.ts","../src/init.ts"],"sourcesContent":["export * from './types';\n\nexport { stylesRepository } from './styles-repository';\nexport { useProviders } from './hooks/use-providers';\nexport { useGetStylesRepositoryCreateAction } from './hooks/use-get-styles-repository-create-action';\nexport { validateStyleLabel } from './utils/validate-style-label';\nexport { createStylesProvider, type CreateStylesProviderOptions } from './utils/create-styles-provider';\nexport { isElementsStylesProvider } from './utils/is-elements-styles-provider';\n\nexport { ELEMENTS_BASE_STYLES_PROVIDER_KEY } from './providers/element-base-styles-provider';\nexport {\n\tELEMENTS_STYLES_PROVIDER_KEY_PREFIX,\n\tELEMENTS_STYLES_RESERVED_LABEL,\n} from './providers/document-elements-styles-provider';\n\nexport { init } from './init';\n","import { type Meta, type StylesProvider } from '../types';\n\nexport const createStylesRepository = () => {\n\tconst providers: StylesProvider[] = [];\n\n\tconst getProviders = () => {\n\t\treturn providers.slice( 0 ).sort( ( a, b ) => ( a.priority > b.priority ? -1 : 1 ) );\n\t};\n\n\tconst register = ( provider: StylesProvider ) => {\n\t\tproviders.push( provider );\n\t};\n\n\tconst all = ( meta: Meta = {} ) => {\n\t\treturn getProviders().flatMap( ( provider ) => provider.actions.all( meta ) );\n\t};\n\n\tconst subscribe = ( cb: () => void ) => {\n\t\tconst unsubscribes = providers.map( ( provider ) => {\n\t\t\treturn provider.subscribe( cb );\n\t\t} );\n\n\t\treturn () => {\n\t\t\tunsubscribes.forEach( ( unsubscribe ) => unsubscribe() );\n\t\t};\n\t};\n\n\tconst getProviderByKey = ( key: string ) => {\n\t\treturn providers.find( ( provider ) => provider.getKey() === key );\n\t};\n\n\treturn {\n\t\tall,\n\t\tregister,\n\t\tsubscribe,\n\t\tgetProviders,\n\t\tgetProviderByKey,\n\t};\n};\n","import { createStylesRepository } from './utils/create-styles-repository';\n\nexport const stylesRepository = createStylesRepository();\n","import { useEffect, useReducer } from 'react';\n\nimport { stylesRepository } from '../styles-repository';\n\nexport function useProviders() {\n\tconst [ , rerender ] = useReducer( ( prev ) => ! prev, false );\n\n\tuseEffect( () => stylesRepository.subscribe( rerender ), [] );\n\n\treturn stylesRepository.getProviders();\n}\n","import { useMemo } from 'react';\n\nimport { stylesRepository } from '../styles-repository';\nimport { type StylesProvider } from '../types';\n\ntype CreateAction = Required< StylesProvider[ 'actions' ] >[ 'create' ];\ntype CreateTuple = [ StylesProvider, CreateAction ];\n\nexport function useGetStylesRepositoryCreateAction() {\n\treturn useMemo( () => {\n\t\tconst createActions = stylesRepository\n\t\t\t.getProviders()\n\t\t\t.map< CreateTuple | null >( ( provider ) => {\n\t\t\t\tif ( ! provider.actions.create ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn [ provider, provider.actions.create ];\n\t\t\t} )\n\t\t\t.filter( ( item ) => !! item );\n\n\t\tif ( createActions.length === 1 ) {\n\t\t\treturn createActions[ 0 ];\n\t\t} else if ( createActions.length === 0 ) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow new Error( 'Multiple providers with create action found in styles repository.' );\n\t}, [] );\n}\n","import { z } from '@elementor/schema';\nimport { __ } from '@wordpress/i18n';\n\nimport { ELEMENTS_STYLES_RESERVED_LABEL } from '../providers/document-elements-styles-provider';\nimport { stylesRepository } from '../styles-repository';\n\nconst NO_START_DIGIT_REGEX = /^(|[^0-9].*)$/;\nconst NO_SPACES_REGEX = /^\\S*$/;\nconst NO_SPECIAL_CHARS_REGEX = /^(|[a-zA-Z0-9_-]+)$/;\nconst NO_DOUBLE_HYPHEN_START_REGEX = /^(?!--).*/;\nconst NO_HYPHEN_DIGIT_START_REGEX = /^(?!-[0-9])/;\nconst NO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX = /^(?!.*(--|__)).*/;\nconst NO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX = /^(?![-_]).*(?<![-_])$/;\n\nconst RESERVED_CLASS_NAMES = [ 'container' ];\n\nconst schema = z\n\t.string()\n\t.max( 50, __( 'Class name is too long. Please keep it under 50 characters.', 'elementor' ) )\n\t.regex( NO_START_DIGIT_REGEX, __( 'Class names must start with a letter.', 'elementor' ) )\n\t.regex( NO_SPACES_REGEX, __( 'Class names can’t contain spaces.', 'elementor' ) )\n\t.regex(\n\t\tNO_SPECIAL_CHARS_REGEX,\n\t\t__( 'Class names can only use letters, numbers, dashes (-), and underscores (_).', 'elementor' )\n\t)\n\t.regex( NO_DOUBLE_HYPHEN_START_REGEX, __( 'Double hyphens are reserved for custom properties.', 'elementor' ) )\n\t.regex(\n\t\tNO_HYPHEN_DIGIT_START_REGEX,\n\t\t__( 'Class names can’t start with a hyphen followed by a number.', 'elementor' )\n\t)\n\t.regex(\n\t\tNO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX,\n\t\t__( 'Avoid using multiple dashes or underscores in a row.', 'elementor' )\n\t)\n\t.regex(\n\t\tNO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX,\n\t\t__( 'Class names can’t start or end with a dash or underscore.', 'elementor' )\n\t)\n\t.refine( ( value ) => ! RESERVED_CLASS_NAMES.includes( value ), {\n\t\tmessage: __( 'This name is reserved and can’t be used. Try something more specific.', 'elementor' ),\n\t} );\n\ntype ValidationEvent = 'inputChange' | 'create' | 'rename';\ntype ValidationResult = { isValid: true; errorMessage: null } | { isValid: false; errorMessage: string };\n\nexport function validateStyleLabel( label: string, event: ValidationEvent | 'rename' ): ValidationResult {\n\tconst existingLabels = new Set( [\n\t\tELEMENTS_STYLES_RESERVED_LABEL,\n\t\t...stylesRepository.all().map( ( styleDef ) => styleDef.label.toLowerCase() ),\n\t] );\n\n\tconst fullValidationEvent = [ 'create', 'rename' ].includes( event );\n\n\tconst result = schema\n\t\t.refine( ( value ) => ! ( fullValidationEvent && value.length < 2 ), {\n\t\t\tmessage: __( 'Class name is too short. Use at least 2 characters.', 'elementor' ),\n\t\t} )\n\t\t.refine( ( value ) => ! ( fullValidationEvent && existingLabels.has( value ) ), {\n\t\t\tmessage: __( 'This class name already exists. Please choose a unique name.', 'elementor' ),\n\t\t} )\n\t\t.safeParse( label.toLowerCase() );\n\n\tif ( result.success ) {\n\t\treturn {\n\t\t\tisValid: true,\n\t\t\terrorMessage: null,\n\t\t};\n\t}\n\n\treturn {\n\t\tisValid: false,\n\t\terrorMessage: result.error.format()._errors[ 0 ],\n\t};\n}\n","import {\n\tgetCurrentDocumentId,\n\tgetElements,\n\tgetElementStyles,\n\tstyleRerenderEvents,\n\tupdateElementStyle,\n} from '@elementor/editor-elements';\nimport { __privateListenTo as listenTo } from '@elementor/editor-v1-adapters';\n\nimport { ActiveDocumentMustExistError, InvalidElementsStyleProviderMetaError } from '../errors';\nimport { createStylesProvider } from '../utils/create-styles-provider';\n\nexport const ELEMENTS_STYLES_PROVIDER_KEY_PREFIX = 'document-elements-';\nexport const ELEMENTS_STYLES_RESERVED_LABEL = 'local';\n\ntype ElementsMeta = {\n\telementId: string;\n};\n\nexport const documentElementsStylesProvider = createStylesProvider( {\n\tkey: () => {\n\t\tconst documentId = getCurrentDocumentId();\n\n\t\tif ( ! documentId ) {\n\t\t\tthrow new ActiveDocumentMustExistError();\n\t\t}\n\n\t\treturn `${ ELEMENTS_STYLES_PROVIDER_KEY_PREFIX }${ documentId }`;\n\t},\n\tpriority: 50,\n\tsubscribe: ( cb ) => listenTo( styleRerenderEvents, cb ),\n\tactions: {\n\t\tall: ( meta = {} ) => {\n\t\t\tlet elements = getElements();\n\n\t\t\tif ( isValidElementsMeta( meta ) ) {\n\t\t\t\telements = elements.filter( ( element ) => element.id === meta.elementId );\n\t\t\t}\n\n\t\t\treturn elements.flatMap( ( element ) => Object.values( element.model.get( 'styles' ) ?? {} ) );\n\t\t},\n\n\t\tget: ( id, meta = {} ) => {\n\t\t\tif ( ! isValidElementsMeta( meta ) ) {\n\t\t\t\tthrow new InvalidElementsStyleProviderMetaError( { context: { meta } } );\n\t\t\t}\n\n\t\t\tconst styles = getElementStyles( meta.elementId ) ?? {};\n\n\t\t\treturn styles[ id ] ?? null;\n\t\t},\n\n\t\tupdateProps: ( args, meta = {} ) => {\n\t\t\tif ( ! isValidElementsMeta( meta ) ) {\n\t\t\t\tthrow new InvalidElementsStyleProviderMetaError( { context: { meta } } );\n\t\t\t}\n\n\t\t\tupdateElementStyle( {\n\t\t\t\telementId: meta.elementId,\n\t\t\t\tstyleId: args.id,\n\t\t\t\tmeta: args.meta,\n\t\t\t\tprops: args.props,\n\t\t\t} );\n\t\t},\n\t},\n} );\n\nfunction isValidElementsMeta( meta: Record< string, unknown > ): meta is ElementsMeta {\n\treturn 'elementId' in meta && typeof meta.elementId === 'string' && !! meta.elementId;\n}\n","import { createError } from '@elementor/utils';\n\nexport const InvalidElementsStyleProviderMetaError = createError< { meta: Record< string, unknown > } >( {\n\tcode: 'invalid_elements_style_provider_meta',\n\tmessage: 'Invalid elements style provider meta.',\n} );\n\nexport const ActiveDocumentMustExistError = createError( {\n\tcode: 'active_document_must_exist',\n\tmessage: 'Active document must exist.',\n} );\n","import { type StylesProvider } from '../types';\n\nexport type CreateStylesProviderOptions = {\n\tkey: string | ( () => string );\n\tpriority?: number;\n\tlimit?: number;\n\tsubscribe?: ( callback: () => void ) => () => void;\n\tlabels?: {\n\t\tsingular: string;\n\t\tplural: string;\n\t};\n\tactions: {\n\t\tall: StylesProvider[ 'actions' ][ 'all' ];\n\t\tget: StylesProvider[ 'actions' ][ 'get' ];\n\t\tcreate?: StylesProvider[ 'actions' ][ 'create' ];\n\t\tdelete?: StylesProvider[ 'actions' ][ 'delete' ];\n\t\tupdate?: StylesProvider[ 'actions' ][ 'update' ];\n\t\tupdateProps?: StylesProvider[ 'actions' ][ 'updateProps' ];\n\t};\n};\n\nconst DEFAULT_LIMIT = 10000;\nconst DEFAULT_PRIORITY = 10;\n\nexport function createStylesProvider( {\n\tkey,\n\tpriority = DEFAULT_PRIORITY,\n\tlimit = DEFAULT_LIMIT,\n\tsubscribe = () => () => {},\n\tlabels,\n\tactions,\n}: CreateStylesProviderOptions ): StylesProvider {\n\treturn {\n\t\tgetKey: typeof key === 'string' ? () => key : key,\n\t\tpriority,\n\t\tlimit,\n\t\tsubscribe,\n\t\tlabels: {\n\t\t\tsingular: labels?.singular ?? null,\n\t\t\tplural: labels?.plural ?? null,\n\t\t},\n\t\tactions: {\n\t\t\tall: actions.all,\n\t\t\tget: actions.get,\n\t\t\tcreate: actions.create,\n\t\t\tdelete: actions.delete,\n\t\t\tupdate: actions.update,\n\t\t\tupdateProps: actions.updateProps,\n\t\t},\n\t};\n}\n","import { ELEMENTS_STYLES_PROVIDER_KEY_PREFIX } from '../providers/document-elements-styles-provider';\n\nexport function isElementsStylesProvider( key: string ) {\n\treturn new RegExp( `^${ ELEMENTS_STYLES_PROVIDER_KEY_PREFIX }\\\\d+$` ).test( key );\n}\n","import { getWidgetsCache } from '@elementor/editor-elements';\n\nimport { createStylesProvider } from '../utils/create-styles-provider';\n\nexport const ELEMENTS_BASE_STYLES_PROVIDER_KEY = 'element-base-styles';\n\nexport const elementBaseStylesProvider = createStylesProvider( {\n\tkey: ELEMENTS_BASE_STYLES_PROVIDER_KEY,\n\tactions: {\n\t\tall() {\n\t\t\tconst widgetsCache = getWidgetsCache();\n\n\t\t\treturn Object.values( widgetsCache ?? {} ).flatMap( ( widget ) =>\n\t\t\t\tObject.values( widget.base_styles ?? {} )\n\t\t\t);\n\t\t},\n\n\t\tget( id ) {\n\t\t\treturn this.all().find( ( style ) => style.id === id ) ?? null;\n\t\t},\n\t},\n} );\n","import { documentElementsStylesProvider } from './providers/document-elements-styles-provider';\nimport { elementBaseStylesProvider } from './providers/element-base-styles-provider';\nimport { stylesRepository } from './styles-repository';\n\nexport function init() {\n\tstylesRepository.register( documentElementsStylesProvider );\n\tstylesRepository.register( elementBaseStylesProvider );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,yBAAyB,MAAM;AAC3C,QAAM,YAA8B,CAAC;AAErC,QAAM,eAAe,MAAM;AAC1B,WAAO,UAAU,MAAO,CAAE,EAAE,KAAM,CAAE,GAAG,MAAS,EAAE,WAAW,EAAE,WAAW,KAAK,CAAI;AAAA,EACpF;AAEA,QAAM,WAAW,CAAE,aAA8B;AAChD,cAAU,KAAM,QAAS;AAAA,EAC1B;AAEA,QAAM,MAAM,CAAE,OAAa,CAAC,MAAO;AAClC,WAAO,aAAa,EAAE,QAAS,CAAE,aAAc,SAAS,QAAQ,IAAK,IAAK,CAAE;AAAA,EAC7E;AAEA,QAAM,YAAY,CAAE,OAAoB;AACvC,UAAM,eAAe,UAAU,IAAK,CAAE,aAAc;AACnD,aAAO,SAAS,UAAW,EAAG;AAAA,IAC/B,CAAE;AAEF,WAAO,MAAM;AACZ,mBAAa,QAAS,CAAE,gBAAiB,YAAY,CAAE;AAAA,IACxD;AAAA,EACD;AAEA,QAAM,mBAAmB,CAAE,QAAiB;AAC3C,WAAO,UAAU,KAAM,CAAE,aAAc,SAAS,OAAO,MAAM,GAAI;AAAA,EAClE;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;;;ACpCO,IAAM,mBAAmB,uBAAuB;;;ACFvD,mBAAsC;AAI/B,SAAS,eAAe;AAC9B,QAAM,CAAE,EAAE,QAAS,QAAI,yBAAY,CAAE,SAAU,CAAE,MAAM,KAAM;AAE7D,8BAAW,MAAM,iBAAiB,UAAW,QAAS,GAAG,CAAC,CAAE;AAE5D,SAAO,iBAAiB,aAAa;AACtC;;;ACVA,IAAAA,gBAAwB;AAQjB,SAAS,qCAAqC;AACpD,aAAO,uBAAS,MAAM;AACrB,UAAM,gBAAgB,iBACpB,aAAa,EACb,IAA2B,CAAE,aAAc;AAC3C,UAAK,CAAE,SAAS,QAAQ,QAAS;AAChC,eAAO;AAAA,MACR;AAEA,aAAO,CAAE,UAAU,SAAS,QAAQ,MAAO;AAAA,IAC5C,CAAE,EACD,OAAQ,CAAE,SAAU,CAAC,CAAE,IAAK;AAE9B,QAAK,cAAc,WAAW,GAAI;AACjC,aAAO,cAAe,CAAE;AAAA,IACzB,WAAY,cAAc,WAAW,GAAI;AACxC,aAAO;AAAA,IACR;AACA,UAAM,IAAI,MAAO,mEAAoE;AAAA,EACtF,GAAG,CAAC,CAAE;AACP;;;AC5BA,oBAAkB;AAClB,kBAAmB;;;ACDnB,6BAMO;AACP,gCAA8C;;;ACP9C,mBAA4B;AAErB,IAAM,4CAAwC,0BAAoD;AAAA,EACxG,MAAM;AAAA,EACN,SAAS;AACV,CAAE;AAEK,IAAM,mCAA+B,0BAAa;AAAA,EACxD,MAAM;AAAA,EACN,SAAS;AACV,CAAE;;;ACWF,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAElB,SAAS,qBAAsB;AAAA,EACrC;AAAA,EACA,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,YAAY,MAAM,MAAM;AAAA,EAAC;AAAA,EACzB;AAAA,EACA;AACD,GAAiD;AAChD,SAAO;AAAA,IACN,QAAQ,OAAO,QAAQ,WAAW,MAAM,MAAM;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,MACP,UAAU,QAAQ,YAAY;AAAA,MAC9B,QAAQ,QAAQ,UAAU;AAAA,IAC3B;AAAA,IACA,SAAS;AAAA,MACR,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,MACb,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA,MAChB,aAAa,QAAQ;AAAA,IACtB;AAAA,EACD;AACD;;;AFtCO,IAAM,sCAAsC;AAC5C,IAAM,iCAAiC;AAMvC,IAAM,iCAAiC,qBAAsB;AAAA,EACnE,KAAK,MAAM;AACV,UAAM,iBAAa,6CAAqB;AAExC,QAAK,CAAE,YAAa;AACnB,YAAM,IAAI,6BAA6B;AAAA,IACxC;AAEA,WAAO,GAAI,mCAAoC,GAAI,UAAW;AAAA,EAC/D;AAAA,EACA,UAAU;AAAA,EACV,WAAW,CAAE,WAAQ,0BAAAC,mBAAU,4CAAqB,EAAG;AAAA,EACvD,SAAS;AAAA,IACR,KAAK,CAAE,OAAO,CAAC,MAAO;AACrB,UAAI,eAAW,oCAAY;AAE3B,UAAK,oBAAqB,IAAK,GAAI;AAClC,mBAAW,SAAS,OAAQ,CAAE,YAAa,QAAQ,OAAO,KAAK,SAAU;AAAA,MAC1E;AAEA,aAAO,SAAS,QAAS,CAAE,YAAa,OAAO,OAAQ,QAAQ,MAAM,IAAK,QAAS,KAAK,CAAC,CAAE,CAAE;AAAA,IAC9F;AAAA,IAEA,KAAK,CAAE,IAAI,OAAO,CAAC,MAAO;AACzB,UAAK,CAAE,oBAAqB,IAAK,GAAI;AACpC,cAAM,IAAI,sCAAuC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAE;AAAA,MACxE;AAEA,YAAM,aAAS,yCAAkB,KAAK,SAAU,KAAK,CAAC;AAEtD,aAAO,OAAQ,EAAG,KAAK;AAAA,IACxB;AAAA,IAEA,aAAa,CAAE,MAAM,OAAO,CAAC,MAAO;AACnC,UAAK,CAAE,oBAAqB,IAAK,GAAI;AACpC,cAAM,IAAI,sCAAuC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAE;AAAA,MACxE;AAEA,qDAAoB;AAAA,QACnB,WAAW,KAAK;AAAA,QAChB,SAAS,KAAK;AAAA,QACd,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,MACb,CAAE;AAAA,IACH;AAAA,EACD;AACD,CAAE;AAEF,SAAS,oBAAqB,MAAwD;AACrF,SAAO,eAAe,QAAQ,OAAO,KAAK,cAAc,YAAY,CAAC,CAAE,KAAK;AAC7E;;;AD/DA,IAAM,uBAAuB;AAC7B,IAAM,kBAAkB;AACxB,IAAM,yBAAyB;AAC/B,IAAM,+BAA+B;AACrC,IAAM,8BAA8B;AACpC,IAAM,8CAA8C;AACpD,IAAM,4CAA4C;AAElD,IAAM,uBAAuB,CAAE,WAAY;AAE3C,IAAM,SAAS,gBACb,OAAO,EACP,IAAK,QAAI,gBAAI,+DAA+D,WAAY,CAAE,EAC1F,MAAO,0BAAsB,gBAAI,yCAAyC,WAAY,CAAE,EACxF,MAAO,qBAAiB,gBAAI,0CAAqC,WAAY,CAAE,EAC/E;AAAA,EACA;AAAA,MACA,gBAAI,+EAA+E,WAAY;AAChG,EACC,MAAO,kCAA8B,gBAAI,sDAAsD,WAAY,CAAE,EAC7G;AAAA,EACA;AAAA,MACA,gBAAI,oEAA+D,WAAY;AAChF,EACC;AAAA,EACA;AAAA,MACA,gBAAI,wDAAwD,WAAY;AACzE,EACC;AAAA,EACA;AAAA,MACA,gBAAI,kEAA6D,WAAY;AAC9E,EACC,OAAQ,CAAE,UAAW,CAAE,qBAAqB,SAAU,KAAM,GAAG;AAAA,EAC/D,aAAS,gBAAI,8EAAyE,WAAY;AACnG,CAAE;AAKI,SAAS,mBAAoB,OAAe,OAAsD;AACxG,QAAM,iBAAiB,oBAAI,IAAK;AAAA,IAC/B;AAAA,IACA,GAAG,iBAAiB,IAAI,EAAE,IAAK,CAAE,aAAc,SAAS,MAAM,YAAY,CAAE;AAAA,EAC7E,CAAE;AAEF,QAAM,sBAAsB,CAAE,UAAU,QAAS,EAAE,SAAU,KAAM;AAEnE,QAAM,SAAS,OACb,OAAQ,CAAE,UAAW,EAAI,uBAAuB,MAAM,SAAS,IAAK;AAAA,IACpE,aAAS,gBAAI,uDAAuD,WAAY;AAAA,EACjF,CAAE,EACD,OAAQ,CAAE,UAAW,EAAI,uBAAuB,eAAe,IAAK,KAAM,IAAK;AAAA,IAC/E,aAAS,gBAAI,gEAAgE,WAAY;AAAA,EAC1F,CAAE,EACD,UAAW,MAAM,YAAY,CAAE;AAEjC,MAAK,OAAO,SAAU;AACrB,WAAO;AAAA,MACN,SAAS;AAAA,MACT,cAAc;AAAA,IACf;AAAA,EACD;AAEA,SAAO;AAAA,IACN,SAAS;AAAA,IACT,cAAc,OAAO,MAAM,OAAO,EAAE,QAAS,CAAE;AAAA,EAChD;AACD;;;AIvEO,SAAS,yBAA0B,KAAc;AACvD,SAAO,IAAI,OAAQ,IAAK,mCAAoC,OAAQ,EAAE,KAAM,GAAI;AACjF;;;ACJA,IAAAC,0BAAgC;AAIzB,IAAM,oCAAoC;AAE1C,IAAM,4BAA4B,qBAAsB;AAAA,EAC9D,KAAK;AAAA,EACL,SAAS;AAAA,IACR,MAAM;AACL,YAAM,mBAAe,yCAAgB;AAErC,aAAO,OAAO,OAAQ,gBAAgB,CAAC,CAAE,EAAE;AAAA,QAAS,CAAE,WACrD,OAAO,OAAQ,OAAO,eAAe,CAAC,CAAE;AAAA,MACzC;AAAA,IACD;AAAA,IAEA,IAAK,IAAK;AACT,aAAO,KAAK,IAAI,EAAE,KAAM,CAAE,UAAW,MAAM,OAAO,EAAG,KAAK;AAAA,IAC3D;AAAA,EACD;AACD,CAAE;;;ACjBK,SAAS,OAAO;AACtB,mBAAiB,SAAU,8BAA+B;AAC1D,mBAAiB,SAAU,yBAA0B;AACtD;","names":["import_react","listenTo","import_editor_elements"]}
|
package/dist/index.mjs
CHANGED
|
@@ -41,16 +41,22 @@ function useProviders() {
|
|
|
41
41
|
return stylesRepository.getProviders();
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
// src/hooks/use-
|
|
44
|
+
// src/hooks/use-get-styles-repository-create-action.ts
|
|
45
45
|
import { useMemo } from "react";
|
|
46
|
-
function
|
|
46
|
+
function useGetStylesRepositoryCreateAction() {
|
|
47
47
|
return useMemo(() => {
|
|
48
|
-
|
|
48
|
+
const createActions = stylesRepository.getProviders().map((provider) => {
|
|
49
49
|
if (!provider.actions.create) {
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
52
|
return [provider, provider.actions.create];
|
|
53
53
|
}).filter((item) => !!item);
|
|
54
|
+
if (createActions.length === 1) {
|
|
55
|
+
return createActions[0];
|
|
56
|
+
} else if (createActions.length === 0) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
throw new Error("Multiple providers with create action found in styles repository.");
|
|
54
60
|
}, []);
|
|
55
61
|
}
|
|
56
62
|
|
|
@@ -157,25 +163,49 @@ function isValidElementsMeta(meta) {
|
|
|
157
163
|
}
|
|
158
164
|
|
|
159
165
|
// src/utils/validate-style-label.ts
|
|
160
|
-
var
|
|
161
|
-
var
|
|
162
|
-
|
|
166
|
+
var NO_START_DIGIT_REGEX = /^(|[^0-9].*)$/;
|
|
167
|
+
var NO_SPACES_REGEX = /^\S*$/;
|
|
168
|
+
var NO_SPECIAL_CHARS_REGEX = /^(|[a-zA-Z0-9_-]+)$/;
|
|
169
|
+
var NO_DOUBLE_HYPHEN_START_REGEX = /^(?!--).*/;
|
|
170
|
+
var NO_HYPHEN_DIGIT_START_REGEX = /^(?!-[0-9])/;
|
|
171
|
+
var NO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX = /^(?!.*(--|__)).*/;
|
|
172
|
+
var NO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX = /^(?![-_]).*(?<![-_])$/;
|
|
173
|
+
var RESERVED_CLASS_NAMES = ["container"];
|
|
174
|
+
var schema = z.string().max(50, __("Class name is too long. Please keep it under 50 characters.", "elementor")).regex(NO_START_DIGIT_REGEX, __("Class names must start with a letter.", "elementor")).regex(NO_SPACES_REGEX, __("Class names can\u2019t contain spaces.", "elementor")).regex(
|
|
175
|
+
NO_SPECIAL_CHARS_REGEX,
|
|
176
|
+
__("Class names can only use letters, numbers, dashes (-), and underscores (_).", "elementor")
|
|
177
|
+
).regex(NO_DOUBLE_HYPHEN_START_REGEX, __("Double hyphens are reserved for custom properties.", "elementor")).regex(
|
|
178
|
+
NO_HYPHEN_DIGIT_START_REGEX,
|
|
179
|
+
__("Class names can\u2019t start with a hyphen followed by a number.", "elementor")
|
|
180
|
+
).regex(
|
|
181
|
+
NO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX,
|
|
182
|
+
__("Avoid using multiple dashes or underscores in a row.", "elementor")
|
|
183
|
+
).regex(
|
|
184
|
+
NO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX,
|
|
185
|
+
__("Class names can\u2019t start or end with a dash or underscore.", "elementor")
|
|
186
|
+
).refine((value) => !RESERVED_CLASS_NAMES.includes(value), {
|
|
187
|
+
message: __("This name is reserved and can\u2019t be used. Try something more specific.", "elementor")
|
|
188
|
+
});
|
|
189
|
+
function validateStyleLabel(label, event) {
|
|
163
190
|
const existingLabels = /* @__PURE__ */ new Set([
|
|
164
191
|
ELEMENTS_STYLES_RESERVED_LABEL,
|
|
165
192
|
...stylesRepository.all().map((styleDef) => styleDef.label.toLowerCase())
|
|
166
193
|
]);
|
|
167
|
-
const
|
|
168
|
-
|
|
194
|
+
const fullValidationEvent = ["create", "rename"].includes(event);
|
|
195
|
+
const result = schema.refine((value) => !(fullValidationEvent && value.length < 2), {
|
|
196
|
+
message: __("Class name is too short. Use at least 2 characters.", "elementor")
|
|
197
|
+
}).refine((value) => !(fullValidationEvent && existingLabels.has(value)), {
|
|
198
|
+
message: __("This class name already exists. Please choose a unique name.", "elementor")
|
|
169
199
|
}).safeParse(label.toLowerCase());
|
|
170
200
|
if (result.success) {
|
|
171
201
|
return {
|
|
172
202
|
isValid: true,
|
|
173
|
-
|
|
203
|
+
errorMessage: null
|
|
174
204
|
};
|
|
175
205
|
}
|
|
176
206
|
return {
|
|
177
207
|
isValid: false,
|
|
178
|
-
|
|
208
|
+
errorMessage: result.error.format()._errors[0]
|
|
179
209
|
};
|
|
180
210
|
}
|
|
181
211
|
|
|
@@ -215,7 +245,7 @@ export {
|
|
|
215
245
|
init,
|
|
216
246
|
isElementsStylesProvider,
|
|
217
247
|
stylesRepository,
|
|
218
|
-
|
|
248
|
+
useGetStylesRepositoryCreateAction,
|
|
219
249
|
useProviders,
|
|
220
250
|
validateStyleLabel
|
|
221
251
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/create-styles-repository.ts","../src/styles-repository.ts","../src/hooks/use-providers.ts","../src/hooks/use-create-actions-by-provider.ts","../src/utils/validate-style-label.ts","../src/providers/document-elements-styles-provider.ts","../src/errors.ts","../src/utils/create-styles-provider.ts","../src/utils/is-elements-styles-provider.ts","../src/providers/element-base-styles-provider.ts","../src/init.ts"],"sourcesContent":["import { type Meta, type StylesProvider } from '../types';\n\nexport const createStylesRepository = () => {\n\tconst providers: StylesProvider[] = [];\n\n\tconst getProviders = () => {\n\t\treturn providers.slice( 0 ).sort( ( a, b ) => ( a.priority > b.priority ? -1 : 1 ) );\n\t};\n\n\tconst register = ( provider: StylesProvider ) => {\n\t\tproviders.push( provider );\n\t};\n\n\tconst all = ( meta: Meta = {} ) => {\n\t\treturn getProviders().flatMap( ( provider ) => provider.actions.all( meta ) );\n\t};\n\n\tconst subscribe = ( cb: () => void ) => {\n\t\tconst unsubscribes = providers.map( ( provider ) => {\n\t\t\treturn provider.subscribe( cb );\n\t\t} );\n\n\t\treturn () => {\n\t\t\tunsubscribes.forEach( ( unsubscribe ) => unsubscribe() );\n\t\t};\n\t};\n\n\tconst getProviderByKey = ( key: string ) => {\n\t\treturn providers.find( ( provider ) => provider.getKey() === key );\n\t};\n\n\treturn {\n\t\tall,\n\t\tregister,\n\t\tsubscribe,\n\t\tgetProviders,\n\t\tgetProviderByKey,\n\t};\n};\n","import { createStylesRepository } from './utils/create-styles-repository';\n\nexport const stylesRepository = createStylesRepository();\n","import { useEffect, useReducer } from 'react';\n\nimport { stylesRepository } from '../styles-repository';\n\nexport function useProviders() {\n\tconst [ , rerender ] = useReducer( ( prev ) => ! prev, false );\n\n\tuseEffect( () => stylesRepository.subscribe( rerender ), [] );\n\n\treturn stylesRepository.getProviders();\n}\n","import { useMemo } from 'react';\n\nimport { stylesRepository } from '../styles-repository';\nimport { type StylesProvider } from '../types';\n\ntype CreateAction = Required< StylesProvider[ 'actions' ] >[ 'create' ];\ntype CreateTuple = [ StylesProvider, CreateAction ];\n\nexport function useCreateActionsByProvider() {\n\treturn useMemo( () => {\n\t\treturn stylesRepository\n\t\t\t.getProviders()\n\t\t\t.map< CreateTuple | null >( ( provider ) => {\n\t\t\t\tif ( ! provider.actions.create ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn [ provider, provider.actions.create ];\n\t\t\t} )\n\t\t\t.filter( ( item ) => !! item );\n\t}, [] );\n}\n","import { z } from '@elementor/schema';\nimport { __ } from '@wordpress/i18n';\n\nimport { ELEMENTS_STYLES_RESERVED_LABEL } from '../providers/document-elements-styles-provider';\nimport { stylesRepository } from '../styles-repository';\n\nconst VALID_LABEL_REGEX = /^[a-zA-Z0-9_-]+$/;\n\nconst schema = z\n\t.string()\n\t.min( 1, __( 'Cannot be empty', 'elementor' ) )\n\t.max( 50, __( 'Cannot be longer than 50 characters', 'elementor' ) )\n\t.regex( VALID_LABEL_REGEX, __( 'Invalid format', 'elementor' ) );\n\nexport function validateStyleLabel( label: string ) {\n\tconst existingLabels = new Set( [\n\t\tELEMENTS_STYLES_RESERVED_LABEL,\n\t\t...stylesRepository.all().map( ( styleDef ) => styleDef.label.toLowerCase() ),\n\t] );\n\n\tconst result = schema\n\t\t.refine( ( value ) => ! existingLabels.has( value ), {\n\t\t\tmessage: __( 'Name exists', 'elementor' ),\n\t\t} )\n\t\t.safeParse( label.toLowerCase() );\n\n\tif ( result.success ) {\n\t\treturn {\n\t\t\tisValid: true,\n\t\t\terror: null,\n\t\t};\n\t}\n\n\treturn {\n\t\tisValid: false,\n\t\terror: result.error.format()._errors[ 0 ],\n\t};\n}\n","import {\n\tgetCurrentDocumentId,\n\tgetElements,\n\tgetElementStyles,\n\tstyleRerenderEvents,\n\tupdateElementStyle,\n} from '@elementor/editor-elements';\nimport { __privateListenTo as listenTo } from '@elementor/editor-v1-adapters';\n\nimport { ActiveDocumentMustExistError, InvalidElementsStyleProviderMetaError } from '../errors';\nimport { createStylesProvider } from '../utils/create-styles-provider';\n\nexport const ELEMENTS_STYLES_PROVIDER_KEY_PREFIX = 'document-elements-';\nexport const ELEMENTS_STYLES_RESERVED_LABEL = 'local';\n\ntype ElementsMeta = {\n\telementId: string;\n};\n\nexport const documentElementsStylesProvider = createStylesProvider( {\n\tkey: () => {\n\t\tconst documentId = getCurrentDocumentId();\n\n\t\tif ( ! documentId ) {\n\t\t\tthrow new ActiveDocumentMustExistError();\n\t\t}\n\n\t\treturn `${ ELEMENTS_STYLES_PROVIDER_KEY_PREFIX }${ documentId }`;\n\t},\n\tpriority: 50,\n\tsubscribe: ( cb ) => listenTo( styleRerenderEvents, cb ),\n\tactions: {\n\t\tall: ( meta = {} ) => {\n\t\t\tlet elements = getElements();\n\n\t\t\tif ( isValidElementsMeta( meta ) ) {\n\t\t\t\telements = elements.filter( ( element ) => element.id === meta.elementId );\n\t\t\t}\n\n\t\t\treturn elements.flatMap( ( element ) => Object.values( element.model.get( 'styles' ) ?? {} ) );\n\t\t},\n\n\t\tget: ( id, meta = {} ) => {\n\t\t\tif ( ! isValidElementsMeta( meta ) ) {\n\t\t\t\tthrow new InvalidElementsStyleProviderMetaError( { context: { meta } } );\n\t\t\t}\n\n\t\t\tconst styles = getElementStyles( meta.elementId ) ?? {};\n\n\t\t\treturn styles[ id ] ?? null;\n\t\t},\n\n\t\tupdateProps: ( args, meta = {} ) => {\n\t\t\tif ( ! isValidElementsMeta( meta ) ) {\n\t\t\t\tthrow new InvalidElementsStyleProviderMetaError( { context: { meta } } );\n\t\t\t}\n\n\t\t\tupdateElementStyle( {\n\t\t\t\telementId: meta.elementId,\n\t\t\t\tstyleId: args.id,\n\t\t\t\tmeta: args.meta,\n\t\t\t\tprops: args.props,\n\t\t\t} );\n\t\t},\n\t},\n} );\n\nfunction isValidElementsMeta( meta: Record< string, unknown > ): meta is ElementsMeta {\n\treturn 'elementId' in meta && typeof meta.elementId === 'string' && !! meta.elementId;\n}\n","import { createError } from '@elementor/utils';\n\nexport const InvalidElementsStyleProviderMetaError = createError< { meta: Record< string, unknown > } >( {\n\tcode: 'invalid_elements_style_provider_meta',\n\tmessage: 'Invalid elements style provider meta.',\n} );\n\nexport const ActiveDocumentMustExistError = createError( {\n\tcode: 'active_document_must_exist',\n\tmessage: 'Active document must exist.',\n} );\n","import { type StylesProvider } from '../types';\n\nexport type CreateStylesProviderOptions = {\n\tkey: string | ( () => string );\n\tpriority?: number;\n\tlimit?: number;\n\tsubscribe?: ( callback: () => void ) => () => void;\n\tlabels?: {\n\t\tsingular: string;\n\t\tplural: string;\n\t};\n\tactions: {\n\t\tall: StylesProvider[ 'actions' ][ 'all' ];\n\t\tget: StylesProvider[ 'actions' ][ 'get' ];\n\t\tcreate?: StylesProvider[ 'actions' ][ 'create' ];\n\t\tdelete?: StylesProvider[ 'actions' ][ 'delete' ];\n\t\tupdate?: StylesProvider[ 'actions' ][ 'update' ];\n\t\tupdateProps?: StylesProvider[ 'actions' ][ 'updateProps' ];\n\t};\n};\n\nconst DEFAULT_LIMIT = 10000;\nconst DEFAULT_PRIORITY = 10;\n\nexport function createStylesProvider( {\n\tkey,\n\tpriority = DEFAULT_PRIORITY,\n\tlimit = DEFAULT_LIMIT,\n\tsubscribe = () => () => {},\n\tlabels,\n\tactions,\n}: CreateStylesProviderOptions ): StylesProvider {\n\treturn {\n\t\tgetKey: typeof key === 'string' ? () => key : key,\n\t\tpriority,\n\t\tlimit,\n\t\tsubscribe,\n\t\tlabels: {\n\t\t\tsingular: labels?.singular ?? null,\n\t\t\tplural: labels?.plural ?? null,\n\t\t},\n\t\tactions: {\n\t\t\tall: actions.all,\n\t\t\tget: actions.get,\n\t\t\tcreate: actions.create,\n\t\t\tdelete: actions.delete,\n\t\t\tupdate: actions.update,\n\t\t\tupdateProps: actions.updateProps,\n\t\t},\n\t};\n}\n","import { ELEMENTS_STYLES_PROVIDER_KEY_PREFIX } from '../providers/document-elements-styles-provider';\n\nexport function isElementsStylesProvider( key: string ) {\n\treturn new RegExp( `^${ ELEMENTS_STYLES_PROVIDER_KEY_PREFIX }\\\\d+$` ).test( key );\n}\n","import { getWidgetsCache } from '@elementor/editor-elements';\n\nimport { createStylesProvider } from '../utils/create-styles-provider';\n\nexport const ELEMENTS_BASE_STYLES_PROVIDER_KEY = 'element-base-styles';\n\nexport const elementBaseStylesProvider = createStylesProvider( {\n\tkey: ELEMENTS_BASE_STYLES_PROVIDER_KEY,\n\tactions: {\n\t\tall() {\n\t\t\tconst widgetsCache = getWidgetsCache();\n\n\t\t\treturn Object.values( widgetsCache ?? {} ).flatMap( ( widget ) =>\n\t\t\t\tObject.values( widget.base_styles ?? {} )\n\t\t\t);\n\t\t},\n\n\t\tget( id ) {\n\t\t\treturn this.all().find( ( style ) => style.id === id ) ?? null;\n\t\t},\n\t},\n} );\n","import { documentElementsStylesProvider } from './providers/document-elements-styles-provider';\nimport { elementBaseStylesProvider } from './providers/element-base-styles-provider';\nimport { stylesRepository } from './styles-repository';\n\nexport function init() {\n\tstylesRepository.register( documentElementsStylesProvider );\n\tstylesRepository.register( elementBaseStylesProvider );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/create-styles-repository.ts","../src/styles-repository.ts","../src/hooks/use-providers.ts","../src/hooks/use-get-styles-repository-create-action.ts","../src/utils/validate-style-label.ts","../src/providers/document-elements-styles-provider.ts","../src/errors.ts","../src/utils/create-styles-provider.ts","../src/utils/is-elements-styles-provider.ts","../src/providers/element-base-styles-provider.ts","../src/init.ts"],"sourcesContent":["import { type Meta, type StylesProvider } from '../types';\n\nexport const createStylesRepository = () => {\n\tconst providers: StylesProvider[] = [];\n\n\tconst getProviders = () => {\n\t\treturn providers.slice( 0 ).sort( ( a, b ) => ( a.priority > b.priority ? -1 : 1 ) );\n\t};\n\n\tconst register = ( provider: StylesProvider ) => {\n\t\tproviders.push( provider );\n\t};\n\n\tconst all = ( meta: Meta = {} ) => {\n\t\treturn getProviders().flatMap( ( provider ) => provider.actions.all( meta ) );\n\t};\n\n\tconst subscribe = ( cb: () => void ) => {\n\t\tconst unsubscribes = providers.map( ( provider ) => {\n\t\t\treturn provider.subscribe( cb );\n\t\t} );\n\n\t\treturn () => {\n\t\t\tunsubscribes.forEach( ( unsubscribe ) => unsubscribe() );\n\t\t};\n\t};\n\n\tconst getProviderByKey = ( key: string ) => {\n\t\treturn providers.find( ( provider ) => provider.getKey() === key );\n\t};\n\n\treturn {\n\t\tall,\n\t\tregister,\n\t\tsubscribe,\n\t\tgetProviders,\n\t\tgetProviderByKey,\n\t};\n};\n","import { createStylesRepository } from './utils/create-styles-repository';\n\nexport const stylesRepository = createStylesRepository();\n","import { useEffect, useReducer } from 'react';\n\nimport { stylesRepository } from '../styles-repository';\n\nexport function useProviders() {\n\tconst [ , rerender ] = useReducer( ( prev ) => ! prev, false );\n\n\tuseEffect( () => stylesRepository.subscribe( rerender ), [] );\n\n\treturn stylesRepository.getProviders();\n}\n","import { useMemo } from 'react';\n\nimport { stylesRepository } from '../styles-repository';\nimport { type StylesProvider } from '../types';\n\ntype CreateAction = Required< StylesProvider[ 'actions' ] >[ 'create' ];\ntype CreateTuple = [ StylesProvider, CreateAction ];\n\nexport function useGetStylesRepositoryCreateAction() {\n\treturn useMemo( () => {\n\t\tconst createActions = stylesRepository\n\t\t\t.getProviders()\n\t\t\t.map< CreateTuple | null >( ( provider ) => {\n\t\t\t\tif ( ! provider.actions.create ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn [ provider, provider.actions.create ];\n\t\t\t} )\n\t\t\t.filter( ( item ) => !! item );\n\n\t\tif ( createActions.length === 1 ) {\n\t\t\treturn createActions[ 0 ];\n\t\t} else if ( createActions.length === 0 ) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow new Error( 'Multiple providers with create action found in styles repository.' );\n\t}, [] );\n}\n","import { z } from '@elementor/schema';\nimport { __ } from '@wordpress/i18n';\n\nimport { ELEMENTS_STYLES_RESERVED_LABEL } from '../providers/document-elements-styles-provider';\nimport { stylesRepository } from '../styles-repository';\n\nconst NO_START_DIGIT_REGEX = /^(|[^0-9].*)$/;\nconst NO_SPACES_REGEX = /^\\S*$/;\nconst NO_SPECIAL_CHARS_REGEX = /^(|[a-zA-Z0-9_-]+)$/;\nconst NO_DOUBLE_HYPHEN_START_REGEX = /^(?!--).*/;\nconst NO_HYPHEN_DIGIT_START_REGEX = /^(?!-[0-9])/;\nconst NO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX = /^(?!.*(--|__)).*/;\nconst NO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX = /^(?![-_]).*(?<![-_])$/;\n\nconst RESERVED_CLASS_NAMES = [ 'container' ];\n\nconst schema = z\n\t.string()\n\t.max( 50, __( 'Class name is too long. Please keep it under 50 characters.', 'elementor' ) )\n\t.regex( NO_START_DIGIT_REGEX, __( 'Class names must start with a letter.', 'elementor' ) )\n\t.regex( NO_SPACES_REGEX, __( 'Class names can’t contain spaces.', 'elementor' ) )\n\t.regex(\n\t\tNO_SPECIAL_CHARS_REGEX,\n\t\t__( 'Class names can only use letters, numbers, dashes (-), and underscores (_).', 'elementor' )\n\t)\n\t.regex( NO_DOUBLE_HYPHEN_START_REGEX, __( 'Double hyphens are reserved for custom properties.', 'elementor' ) )\n\t.regex(\n\t\tNO_HYPHEN_DIGIT_START_REGEX,\n\t\t__( 'Class names can’t start with a hyphen followed by a number.', 'elementor' )\n\t)\n\t.regex(\n\t\tNO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX,\n\t\t__( 'Avoid using multiple dashes or underscores in a row.', 'elementor' )\n\t)\n\t.regex(\n\t\tNO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX,\n\t\t__( 'Class names can’t start or end with a dash or underscore.', 'elementor' )\n\t)\n\t.refine( ( value ) => ! RESERVED_CLASS_NAMES.includes( value ), {\n\t\tmessage: __( 'This name is reserved and can’t be used. Try something more specific.', 'elementor' ),\n\t} );\n\ntype ValidationEvent = 'inputChange' | 'create' | 'rename';\ntype ValidationResult = { isValid: true; errorMessage: null } | { isValid: false; errorMessage: string };\n\nexport function validateStyleLabel( label: string, event: ValidationEvent | 'rename' ): ValidationResult {\n\tconst existingLabels = new Set( [\n\t\tELEMENTS_STYLES_RESERVED_LABEL,\n\t\t...stylesRepository.all().map( ( styleDef ) => styleDef.label.toLowerCase() ),\n\t] );\n\n\tconst fullValidationEvent = [ 'create', 'rename' ].includes( event );\n\n\tconst result = schema\n\t\t.refine( ( value ) => ! ( fullValidationEvent && value.length < 2 ), {\n\t\t\tmessage: __( 'Class name is too short. Use at least 2 characters.', 'elementor' ),\n\t\t} )\n\t\t.refine( ( value ) => ! ( fullValidationEvent && existingLabels.has( value ) ), {\n\t\t\tmessage: __( 'This class name already exists. Please choose a unique name.', 'elementor' ),\n\t\t} )\n\t\t.safeParse( label.toLowerCase() );\n\n\tif ( result.success ) {\n\t\treturn {\n\t\t\tisValid: true,\n\t\t\terrorMessage: null,\n\t\t};\n\t}\n\n\treturn {\n\t\tisValid: false,\n\t\terrorMessage: result.error.format()._errors[ 0 ],\n\t};\n}\n","import {\n\tgetCurrentDocumentId,\n\tgetElements,\n\tgetElementStyles,\n\tstyleRerenderEvents,\n\tupdateElementStyle,\n} from '@elementor/editor-elements';\nimport { __privateListenTo as listenTo } from '@elementor/editor-v1-adapters';\n\nimport { ActiveDocumentMustExistError, InvalidElementsStyleProviderMetaError } from '../errors';\nimport { createStylesProvider } from '../utils/create-styles-provider';\n\nexport const ELEMENTS_STYLES_PROVIDER_KEY_PREFIX = 'document-elements-';\nexport const ELEMENTS_STYLES_RESERVED_LABEL = 'local';\n\ntype ElementsMeta = {\n\telementId: string;\n};\n\nexport const documentElementsStylesProvider = createStylesProvider( {\n\tkey: () => {\n\t\tconst documentId = getCurrentDocumentId();\n\n\t\tif ( ! documentId ) {\n\t\t\tthrow new ActiveDocumentMustExistError();\n\t\t}\n\n\t\treturn `${ ELEMENTS_STYLES_PROVIDER_KEY_PREFIX }${ documentId }`;\n\t},\n\tpriority: 50,\n\tsubscribe: ( cb ) => listenTo( styleRerenderEvents, cb ),\n\tactions: {\n\t\tall: ( meta = {} ) => {\n\t\t\tlet elements = getElements();\n\n\t\t\tif ( isValidElementsMeta( meta ) ) {\n\t\t\t\telements = elements.filter( ( element ) => element.id === meta.elementId );\n\t\t\t}\n\n\t\t\treturn elements.flatMap( ( element ) => Object.values( element.model.get( 'styles' ) ?? {} ) );\n\t\t},\n\n\t\tget: ( id, meta = {} ) => {\n\t\t\tif ( ! isValidElementsMeta( meta ) ) {\n\t\t\t\tthrow new InvalidElementsStyleProviderMetaError( { context: { meta } } );\n\t\t\t}\n\n\t\t\tconst styles = getElementStyles( meta.elementId ) ?? {};\n\n\t\t\treturn styles[ id ] ?? null;\n\t\t},\n\n\t\tupdateProps: ( args, meta = {} ) => {\n\t\t\tif ( ! isValidElementsMeta( meta ) ) {\n\t\t\t\tthrow new InvalidElementsStyleProviderMetaError( { context: { meta } } );\n\t\t\t}\n\n\t\t\tupdateElementStyle( {\n\t\t\t\telementId: meta.elementId,\n\t\t\t\tstyleId: args.id,\n\t\t\t\tmeta: args.meta,\n\t\t\t\tprops: args.props,\n\t\t\t} );\n\t\t},\n\t},\n} );\n\nfunction isValidElementsMeta( meta: Record< string, unknown > ): meta is ElementsMeta {\n\treturn 'elementId' in meta && typeof meta.elementId === 'string' && !! meta.elementId;\n}\n","import { createError } from '@elementor/utils';\n\nexport const InvalidElementsStyleProviderMetaError = createError< { meta: Record< string, unknown > } >( {\n\tcode: 'invalid_elements_style_provider_meta',\n\tmessage: 'Invalid elements style provider meta.',\n} );\n\nexport const ActiveDocumentMustExistError = createError( {\n\tcode: 'active_document_must_exist',\n\tmessage: 'Active document must exist.',\n} );\n","import { type StylesProvider } from '../types';\n\nexport type CreateStylesProviderOptions = {\n\tkey: string | ( () => string );\n\tpriority?: number;\n\tlimit?: number;\n\tsubscribe?: ( callback: () => void ) => () => void;\n\tlabels?: {\n\t\tsingular: string;\n\t\tplural: string;\n\t};\n\tactions: {\n\t\tall: StylesProvider[ 'actions' ][ 'all' ];\n\t\tget: StylesProvider[ 'actions' ][ 'get' ];\n\t\tcreate?: StylesProvider[ 'actions' ][ 'create' ];\n\t\tdelete?: StylesProvider[ 'actions' ][ 'delete' ];\n\t\tupdate?: StylesProvider[ 'actions' ][ 'update' ];\n\t\tupdateProps?: StylesProvider[ 'actions' ][ 'updateProps' ];\n\t};\n};\n\nconst DEFAULT_LIMIT = 10000;\nconst DEFAULT_PRIORITY = 10;\n\nexport function createStylesProvider( {\n\tkey,\n\tpriority = DEFAULT_PRIORITY,\n\tlimit = DEFAULT_LIMIT,\n\tsubscribe = () => () => {},\n\tlabels,\n\tactions,\n}: CreateStylesProviderOptions ): StylesProvider {\n\treturn {\n\t\tgetKey: typeof key === 'string' ? () => key : key,\n\t\tpriority,\n\t\tlimit,\n\t\tsubscribe,\n\t\tlabels: {\n\t\t\tsingular: labels?.singular ?? null,\n\t\t\tplural: labels?.plural ?? null,\n\t\t},\n\t\tactions: {\n\t\t\tall: actions.all,\n\t\t\tget: actions.get,\n\t\t\tcreate: actions.create,\n\t\t\tdelete: actions.delete,\n\t\t\tupdate: actions.update,\n\t\t\tupdateProps: actions.updateProps,\n\t\t},\n\t};\n}\n","import { ELEMENTS_STYLES_PROVIDER_KEY_PREFIX } from '../providers/document-elements-styles-provider';\n\nexport function isElementsStylesProvider( key: string ) {\n\treturn new RegExp( `^${ ELEMENTS_STYLES_PROVIDER_KEY_PREFIX }\\\\d+$` ).test( key );\n}\n","import { getWidgetsCache } from '@elementor/editor-elements';\n\nimport { createStylesProvider } from '../utils/create-styles-provider';\n\nexport const ELEMENTS_BASE_STYLES_PROVIDER_KEY = 'element-base-styles';\n\nexport const elementBaseStylesProvider = createStylesProvider( {\n\tkey: ELEMENTS_BASE_STYLES_PROVIDER_KEY,\n\tactions: {\n\t\tall() {\n\t\t\tconst widgetsCache = getWidgetsCache();\n\n\t\t\treturn Object.values( widgetsCache ?? {} ).flatMap( ( widget ) =>\n\t\t\t\tObject.values( widget.base_styles ?? {} )\n\t\t\t);\n\t\t},\n\n\t\tget( id ) {\n\t\t\treturn this.all().find( ( style ) => style.id === id ) ?? null;\n\t\t},\n\t},\n} );\n","import { documentElementsStylesProvider } from './providers/document-elements-styles-provider';\nimport { elementBaseStylesProvider } from './providers/element-base-styles-provider';\nimport { stylesRepository } from './styles-repository';\n\nexport function init() {\n\tstylesRepository.register( documentElementsStylesProvider );\n\tstylesRepository.register( elementBaseStylesProvider );\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
package/src/hooks/{use-create-actions-by-provider.ts → use-get-styles-repository-create-action.ts}
RENAMED
|
@@ -6,9 +6,9 @@ import { type StylesProvider } from '../types';
|
|
|
6
6
|
type CreateAction = Required< StylesProvider[ 'actions' ] >[ 'create' ];
|
|
7
7
|
type CreateTuple = [ StylesProvider, CreateAction ];
|
|
8
8
|
|
|
9
|
-
export function
|
|
9
|
+
export function useGetStylesRepositoryCreateAction() {
|
|
10
10
|
return useMemo( () => {
|
|
11
|
-
|
|
11
|
+
const createActions = stylesRepository
|
|
12
12
|
.getProviders()
|
|
13
13
|
.map< CreateTuple | null >( ( provider ) => {
|
|
14
14
|
if ( ! provider.actions.create ) {
|
|
@@ -18,5 +18,12 @@ export function useCreateActionsByProvider() {
|
|
|
18
18
|
return [ provider, provider.actions.create ];
|
|
19
19
|
} )
|
|
20
20
|
.filter( ( item ) => !! item );
|
|
21
|
+
|
|
22
|
+
if ( createActions.length === 1 ) {
|
|
23
|
+
return createActions[ 0 ];
|
|
24
|
+
} else if ( createActions.length === 0 ) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
throw new Error( 'Multiple providers with create action found in styles repository.' );
|
|
21
28
|
}, [] );
|
|
22
29
|
}
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from './types';
|
|
|
2
2
|
|
|
3
3
|
export { stylesRepository } from './styles-repository';
|
|
4
4
|
export { useProviders } from './hooks/use-providers';
|
|
5
|
-
export {
|
|
5
|
+
export { useGetStylesRepositoryCreateAction } from './hooks/use-get-styles-repository-create-action';
|
|
6
6
|
export { validateStyleLabel } from './utils/validate-style-label';
|
|
7
7
|
export { createStylesProvider, type CreateStylesProviderOptions } from './utils/create-styles-provider';
|
|
8
8
|
export { isElementsStylesProvider } from './utils/is-elements-styles-provider';
|
|
@@ -13,25 +13,108 @@ describe( 'validateStyleLabel', () => {
|
|
|
13
13
|
|
|
14
14
|
it( 'should pass validation if label is valid', () => {
|
|
15
15
|
// Act.
|
|
16
|
-
const result = validateStyleLabel( 'valid-label' );
|
|
16
|
+
const result = validateStyleLabel( 'valid-label', 'create' );
|
|
17
17
|
|
|
18
18
|
// Assert.
|
|
19
19
|
expect( result.isValid ).toBe( true );
|
|
20
|
-
expect( result.
|
|
20
|
+
expect( result.errorMessage ).toBeNull();
|
|
21
21
|
} );
|
|
22
22
|
|
|
23
23
|
it.each( [
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
{
|
|
25
|
+
reason: 'label is too long',
|
|
26
|
+
label: 'super-long-class-label-with-more-than-50-characters',
|
|
27
|
+
message: 'Class name is too long. Please keep it under 50 characters.',
|
|
28
|
+
},
|
|
29
|
+
{ reason: 'label starts with a number', label: '1invalid', message: 'Class names must start with a letter.' },
|
|
30
|
+
{
|
|
31
|
+
reason: 'label contains spaces',
|
|
32
|
+
label: 'invalid label',
|
|
33
|
+
message: 'Class names can’t contain spaces.',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
reason: 'label contains special characters',
|
|
37
|
+
label: 'invalid@label',
|
|
38
|
+
message: 'Class names can only use letters, numbers, dashes (-), and underscores (_).',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
reason: 'label starts with double hyphens',
|
|
42
|
+
label: '--invalid',
|
|
43
|
+
message: 'Double hyphens are reserved for custom properties.',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
reason: 'label starts with a hyphen followed by a number',
|
|
47
|
+
label: '-1invalid',
|
|
48
|
+
message: 'Class names can’t start with a hyphen followed by a number.',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
reason: 'label contains consecutive dashes',
|
|
52
|
+
label: 'invalid--label',
|
|
53
|
+
message: 'Avoid using multiple dashes or underscores in a row.',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
reason: 'label contains consecutive underscores',
|
|
57
|
+
label: 'invalid__label',
|
|
58
|
+
message: 'Avoid using multiple dashes or underscores in a row.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
reason: 'label starts with a dash',
|
|
62
|
+
label: '-invalid',
|
|
63
|
+
message: 'Class names can’t start or end with a dash or underscore.',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
reason: 'label ends with a dash',
|
|
67
|
+
label: 'invalid-',
|
|
68
|
+
message: 'Class names can’t start or end with a dash or underscore.',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
reason: 'label starts with an underscore',
|
|
72
|
+
label: '_invalid',
|
|
73
|
+
message: 'Class names can’t start or end with a dash or underscore.',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
reason: 'label ends with an underscore',
|
|
77
|
+
label: 'invalid_',
|
|
78
|
+
message: 'Class names can’t start or end with a dash or underscore.',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
reason: 'label is a reserved name',
|
|
82
|
+
label: 'container',
|
|
83
|
+
message: 'This name is reserved and can’t be used. Try something more specific.',
|
|
84
|
+
},
|
|
29
85
|
] )( 'should fail validation if $reason', ( { label, message } ) => {
|
|
30
86
|
// Act.
|
|
31
|
-
const result = validateStyleLabel( label );
|
|
87
|
+
const result = validateStyleLabel( label, 'inputChange' );
|
|
32
88
|
|
|
33
89
|
// Assert.
|
|
34
90
|
expect( result.isValid ).toBe( false );
|
|
35
|
-
expect( result.
|
|
91
|
+
expect( result.errorMessage ).toBe( message );
|
|
92
|
+
} );
|
|
93
|
+
|
|
94
|
+
it.each( [
|
|
95
|
+
{ label: '', event: 'create', labelDescription: 'empty' },
|
|
96
|
+
{ label: '', event: 'rename', labelDescription: 'empty' },
|
|
97
|
+
|
|
98
|
+
{ label: 'a', event: 'create', labelDescription: 'single-character' },
|
|
99
|
+
{ label: 'a', event: 'rename', labelDescription: 'single-character' },
|
|
100
|
+
] )( 'should fail validation for a "$labelDescription" label when event is "$event"', ( { label, event } ) => {
|
|
101
|
+
// Act.
|
|
102
|
+
const result = validateStyleLabel( label, event as 'create' | 'rename' );
|
|
103
|
+
|
|
104
|
+
// Assert.
|
|
105
|
+
expect( result.isValid ).toBe( false );
|
|
106
|
+
expect( result.errorMessage ).toBe( 'Class name is too short. Use at least 2 characters.' );
|
|
107
|
+
} );
|
|
108
|
+
|
|
109
|
+
it.each( [
|
|
110
|
+
{ label: '', labelDescription: 'empty' },
|
|
111
|
+
{ label: 'a', labelDescription: 'single-character' },
|
|
112
|
+
] )( 'should fail validation for a "$labelDescription" label when event is "inputChange"', ( { label } ) => {
|
|
113
|
+
// Act.
|
|
114
|
+
const result = validateStyleLabel( label, 'inputChange' );
|
|
115
|
+
|
|
116
|
+
// Assert.
|
|
117
|
+
expect( result.isValid ).toBe( true );
|
|
118
|
+
expect( result.errorMessage ).toBeNull();
|
|
36
119
|
} );
|
|
37
120
|
} );
|
|
@@ -4,35 +4,71 @@ import { __ } from '@wordpress/i18n';
|
|
|
4
4
|
import { ELEMENTS_STYLES_RESERVED_LABEL } from '../providers/document-elements-styles-provider';
|
|
5
5
|
import { stylesRepository } from '../styles-repository';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const NO_START_DIGIT_REGEX = /^(|[^0-9].*)$/;
|
|
8
|
+
const NO_SPACES_REGEX = /^\S*$/;
|
|
9
|
+
const NO_SPECIAL_CHARS_REGEX = /^(|[a-zA-Z0-9_-]+)$/;
|
|
10
|
+
const NO_DOUBLE_HYPHEN_START_REGEX = /^(?!--).*/;
|
|
11
|
+
const NO_HYPHEN_DIGIT_START_REGEX = /^(?!-[0-9])/;
|
|
12
|
+
const NO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX = /^(?!.*(--|__)).*/;
|
|
13
|
+
const NO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX = /^(?![-_]).*(?<![-_])$/;
|
|
14
|
+
|
|
15
|
+
const RESERVED_CLASS_NAMES = [ 'container' ];
|
|
8
16
|
|
|
9
17
|
const schema = z
|
|
10
18
|
.string()
|
|
11
|
-
.
|
|
12
|
-
.
|
|
13
|
-
.regex(
|
|
19
|
+
.max( 50, __( 'Class name is too long. Please keep it under 50 characters.', 'elementor' ) )
|
|
20
|
+
.regex( NO_START_DIGIT_REGEX, __( 'Class names must start with a letter.', 'elementor' ) )
|
|
21
|
+
.regex( NO_SPACES_REGEX, __( 'Class names can’t contain spaces.', 'elementor' ) )
|
|
22
|
+
.regex(
|
|
23
|
+
NO_SPECIAL_CHARS_REGEX,
|
|
24
|
+
__( 'Class names can only use letters, numbers, dashes (-), and underscores (_).', 'elementor' )
|
|
25
|
+
)
|
|
26
|
+
.regex( NO_DOUBLE_HYPHEN_START_REGEX, __( 'Double hyphens are reserved for custom properties.', 'elementor' ) )
|
|
27
|
+
.regex(
|
|
28
|
+
NO_HYPHEN_DIGIT_START_REGEX,
|
|
29
|
+
__( 'Class names can’t start with a hyphen followed by a number.', 'elementor' )
|
|
30
|
+
)
|
|
31
|
+
.regex(
|
|
32
|
+
NO_CONSECUTIVE_HYPHENS_OR_UNDERSCORES_REGEX,
|
|
33
|
+
__( 'Avoid using multiple dashes or underscores in a row.', 'elementor' )
|
|
34
|
+
)
|
|
35
|
+
.regex(
|
|
36
|
+
NO_LEADING_TRAILING_DASH_UNDERSCORE_REGEX,
|
|
37
|
+
__( 'Class names can’t start or end with a dash or underscore.', 'elementor' )
|
|
38
|
+
)
|
|
39
|
+
.refine( ( value ) => ! RESERVED_CLASS_NAMES.includes( value ), {
|
|
40
|
+
message: __( 'This name is reserved and can’t be used. Try something more specific.', 'elementor' ),
|
|
41
|
+
} );
|
|
42
|
+
|
|
43
|
+
type ValidationEvent = 'inputChange' | 'create' | 'rename';
|
|
44
|
+
type ValidationResult = { isValid: true; errorMessage: null } | { isValid: false; errorMessage: string };
|
|
14
45
|
|
|
15
|
-
export function validateStyleLabel( label: string ) {
|
|
46
|
+
export function validateStyleLabel( label: string, event: ValidationEvent | 'rename' ): ValidationResult {
|
|
16
47
|
const existingLabels = new Set( [
|
|
17
48
|
ELEMENTS_STYLES_RESERVED_LABEL,
|
|
18
49
|
...stylesRepository.all().map( ( styleDef ) => styleDef.label.toLowerCase() ),
|
|
19
50
|
] );
|
|
20
51
|
|
|
52
|
+
const fullValidationEvent = [ 'create', 'rename' ].includes( event );
|
|
53
|
+
|
|
21
54
|
const result = schema
|
|
22
|
-
.refine( ( value ) => !
|
|
23
|
-
message: __( '
|
|
55
|
+
.refine( ( value ) => ! ( fullValidationEvent && value.length < 2 ), {
|
|
56
|
+
message: __( 'Class name is too short. Use at least 2 characters.', 'elementor' ),
|
|
57
|
+
} )
|
|
58
|
+
.refine( ( value ) => ! ( fullValidationEvent && existingLabels.has( value ) ), {
|
|
59
|
+
message: __( 'This class name already exists. Please choose a unique name.', 'elementor' ),
|
|
24
60
|
} )
|
|
25
61
|
.safeParse( label.toLowerCase() );
|
|
26
62
|
|
|
27
63
|
if ( result.success ) {
|
|
28
64
|
return {
|
|
29
65
|
isValid: true,
|
|
30
|
-
|
|
66
|
+
errorMessage: null,
|
|
31
67
|
};
|
|
32
68
|
}
|
|
33
69
|
|
|
34
70
|
return {
|
|
35
71
|
isValid: false,
|
|
36
|
-
|
|
72
|
+
errorMessage: result.error.format()._errors[ 0 ],
|
|
37
73
|
};
|
|
38
74
|
}
|