@elementor/editor-global-classes 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,60 @@
1
1
  # @elementor/editor-global-classes
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c042725: Create `@elementor/editor-ui` package.
8
+ - 2b3f888: Show list of global classes in manager panel.
9
+ - 4fbe12c: Update `@elementor/icons` version.
10
+ - 19b0381: Change styles repository API
11
+ - 68efdb1: Show long classes with ellipsis and tooltip.
12
+
13
+ ### Patch Changes
14
+
15
+ - 6c4d4a7: refactored CSS class menu and fix it's keyboard navigation
16
+ - b34f498: Fix global class styles not updating
17
+ - 1a9c943: Subscribe only to the global classes slice
18
+ - Updated dependencies [65d6ac7]
19
+ - Updated dependencies [d61b1bc]
20
+ - Updated dependencies [c042725]
21
+ - Updated dependencies [2b3f888]
22
+ - Updated dependencies [6c4d4a7]
23
+ - Updated dependencies [4fbe12c]
24
+ - Updated dependencies [b34f498]
25
+ - Updated dependencies [19b0381]
26
+ - Updated dependencies [68efdb1]
27
+ - Updated dependencies [1a9c943]
28
+ - @elementor/editor-editing-panel@1.10.0
29
+ - @elementor/editor-styles-repository@0.6.0
30
+ - @elementor/editor-ui@0.1.0
31
+ - @elementor/editor-panels@0.10.5
32
+ - @elementor/editor@0.17.5
33
+ - @elementor/editor-styles@0.5.4
34
+ - @elementor/store@0.9.0
35
+
36
+ ## 0.3.0
37
+
38
+ ### Minor Changes
39
+
40
+ - 005d737: Register new css class manager panel.
41
+
42
+ ### Patch Changes
43
+
44
+ - Updated dependencies [b8b2053]
45
+ - Updated dependencies [e3c4a37]
46
+ - Updated dependencies [f691712]
47
+ - Updated dependencies [cfbd198]
48
+ - Updated dependencies [a13a209]
49
+ - Updated dependencies [99fccc1]
50
+ - Updated dependencies [c9de3e2]
51
+ - Updated dependencies [005d737]
52
+ - Updated dependencies [7b499aa]
53
+ - @elementor/editor-styles-repository@0.5.0
54
+ - @elementor/editor-editing-panel@1.9.0
55
+ - @elementor/editor-panels@0.10.4
56
+ - @elementor/editor@0.17.4
57
+
3
58
  ## 0.2.1
4
59
 
5
60
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,31 +1,65 @@
1
1
  "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
2
24
 
3
25
  // src/init.ts
4
26
  var import_editor = require("@elementor/editor");
27
+ var import_editor_editing_panel = require("@elementor/editor-editing-panel");
28
+ var import_editor_panels2 = require("@elementor/editor-panels");
5
29
  var import_editor_styles_repository = require("@elementor/editor-styles-repository");
6
- var import_store6 = require("@elementor/store");
30
+ var import_store7 = require("@elementor/store");
7
31
 
8
- // src/components/logic-hooks.tsx
9
- var import_react = require("react");
10
- var import_store2 = require("@elementor/store");
32
+ // src/components/class-manager/class-manager-button.tsx
33
+ var React3 = __toESM(require("react"));
34
+ var import_icons2 = require("@elementor/icons");
35
+ var import_ui3 = require("@elementor/ui");
36
+ var import_i18n2 = require("@wordpress/i18n");
11
37
 
12
- // src/api.ts
13
- var import_http = require("@elementor/http");
14
- var RESOURCE_URL = "/global-classes";
15
- var apiClient = {
16
- all: async () => {
17
- return (0, import_http.httpService)().get(RESOURCE_URL);
18
- },
19
- post: async (data) => {
20
- return (0, import_http.httpService)().post(RESOURCE_URL, data);
21
- },
22
- put: async (id, data) => {
23
- return (0, import_http.httpService)().put(`${RESOURCE_URL}/${id}`, data);
24
- }
25
- };
38
+ // src/components/class-manager/class-manager-panel.tsx
39
+ var React2 = __toESM(require("react"));
40
+ var import_editor_panels = require("@elementor/editor-panels");
41
+ var import_icons = require("@elementor/icons");
42
+ var import_ui2 = require("@elementor/ui");
43
+ var import_i18n = require("@wordpress/i18n");
44
+
45
+ // src/components/class-manager/global-classes-list.tsx
46
+ var React = __toESM(require("react"));
47
+ var import_editor_ui = require("@elementor/editor-ui");
48
+ var import_ui = require("@elementor/ui");
26
49
 
27
50
  // src/store.ts
51
+ var import_editor_props = require("@elementor/editor-props");
52
+ var import_editor_styles = require("@elementor/editor-styles");
28
53
  var import_store = require("@elementor/store");
54
+
55
+ // src/errors.ts
56
+ var import_utils = require("@elementor/utils");
57
+ var GlobalClassNotFoundError = (0, import_utils.createError)({
58
+ code: "global_class_not_found",
59
+ message: "Global class not found."
60
+ });
61
+
62
+ // src/store.ts
29
63
  var initialState = {
30
64
  items: {},
31
65
  order: []
@@ -46,6 +80,20 @@ var slice = (0, import_store.__createSlice)({
46
80
  update(state, { payload }) {
47
81
  state.items[payload.style.id] = payload.style;
48
82
  state.order = payload.order;
83
+ },
84
+ updateProps(state, {
85
+ payload
86
+ }) {
87
+ const style = state.items[payload.id];
88
+ if (!style) {
89
+ throw new GlobalClassNotFoundError({ context: { styleId: payload.id } });
90
+ }
91
+ const variant = (0, import_editor_styles.getVariantByMeta)(style, payload.meta);
92
+ if (variant) {
93
+ variant.props = (0, import_editor_props.mergeProps)(variant.props, payload.props);
94
+ } else {
95
+ style.variants.push({ meta: payload.meta, props: payload.props });
96
+ }
49
97
  }
50
98
  }
51
99
  });
@@ -56,11 +104,62 @@ var selectOrderedGlobalClasses = (0, import_store.__createSelector)(
56
104
  selectOrder,
57
105
  (items, order) => order.map((id) => items[id])
58
106
  );
59
- var selectClass = (state, id) => state[SLICE_NAME].items[id];
107
+ var selectClass = (state, id) => state[SLICE_NAME].items[id] ?? null;
108
+ var useOrderedGlobalClasses = () => {
109
+ const items = (0, import_store.__useSelector)(selectOrderedGlobalClasses);
110
+ return items;
111
+ };
112
+
113
+ // src/components/class-manager/global-classes-list.tsx
114
+ var GlobalClassesList = () => {
115
+ const cssClasses = useOrderedGlobalClasses();
116
+ return /* @__PURE__ */ React.createElement(import_ui.Stack, null, /* @__PURE__ */ React.createElement(import_ui.List, { role: "list" }, cssClasses?.map(({ id, label }) => {
117
+ return /* @__PURE__ */ React.createElement(import_ui.Stack, { key: id, direction: "row", alignItems: "center", gap: 1, role: "listitem" }, /* @__PURE__ */ React.createElement(import_ui.ListItemButton, { sx: { borderRadius: 1 } }, /* @__PURE__ */ React.createElement(import_editor_ui.EllipsisWithTooltip, { title: label, as: import_ui.Typography, variant: "caption" })));
118
+ })));
119
+ };
120
+
121
+ // src/components/class-manager/class-manager-panel.tsx
122
+ var { panel, usePanelActions, usePanelStatus } = (0, import_editor_panels.__createPanel)({
123
+ id: "class-manager-panel",
124
+ component: ClassManagerPanel
125
+ });
126
+ function ClassManagerPanel() {
127
+ return /* @__PURE__ */ React2.createElement(import_ui2.ErrorBoundary, { fallback: /* @__PURE__ */ React2.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React2.createElement(import_editor_panels.Panel, null, /* @__PURE__ */ React2.createElement(import_editor_panels.PanelHeader, null, /* @__PURE__ */ React2.createElement(import_ui2.Stack, { p: 1, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React2.createElement(import_editor_panels.PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React2.createElement(import_icons.ColorSwatchIcon, { fontSize: "inherit", sx: { transform: "rotate(90deg)" } }), (0, import_i18n.__)("CSS Class manager")), /* @__PURE__ */ React2.createElement(CloseButton, { sx: { marginLeft: "auto" } }))), /* @__PURE__ */ React2.createElement(import_editor_panels.PanelBody, { px: 2 }, /* @__PURE__ */ React2.createElement(GlobalClassesList, null))));
128
+ }
129
+ var CloseButton = (props) => {
130
+ const { close } = usePanelActions();
131
+ return /* @__PURE__ */ React2.createElement(import_ui2.IconButton, { size: "small", color: "secondary", onClick: close, ...props }, /* @__PURE__ */ React2.createElement(import_icons.XIcon, { fontSize: "small" }));
132
+ };
133
+ var ErrorBoundaryFallback = () => /* @__PURE__ */ React2.createElement(import_ui2.Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React2.createElement(import_ui2.Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React2.createElement("strong", null, (0, import_i18n.__)("Something went wrong", "elementor"))));
134
+
135
+ // src/components/class-manager/class-manager-button.tsx
136
+ var ClassManagerButton = () => {
137
+ const { open } = usePanelActions();
138
+ return /* @__PURE__ */ React3.createElement(import_ui3.Tooltip, { title: (0, import_i18n2.__)("Class manager"), placement: "top" }, /* @__PURE__ */ React3.createElement(import_ui3.IconButton, { onClick: open }, /* @__PURE__ */ React3.createElement(import_icons2.ColorSwatchIcon, { fontSize: "tiny" })));
139
+ };
140
+
141
+ // src/components/logic-hooks.tsx
142
+ var import_react = require("react");
143
+ var import_store3 = require("@elementor/store");
144
+
145
+ // src/api.ts
146
+ var import_http = require("@elementor/http");
147
+ var RESOURCE_URL = "/global-classes";
148
+ var apiClient = {
149
+ all: async () => {
150
+ return (0, import_http.httpService)().get(RESOURCE_URL);
151
+ },
152
+ post: async (data) => {
153
+ return (0, import_http.httpService)().post(RESOURCE_URL, data);
154
+ },
155
+ put: async (id, data) => {
156
+ return (0, import_http.httpService)().put(`${RESOURCE_URL}/${id}`, data);
157
+ }
158
+ };
60
159
 
61
160
  // src/components/logic-hooks.tsx
62
161
  function LogicHooks() {
63
- const dispatch2 = (0, import_store2.__useDispatch)();
162
+ const dispatch2 = (0, import_store3.__useDispatch)();
64
163
  (0, import_react.useEffect)(() => {
65
164
  apiClient.all().then((res) => {
66
165
  const { data, meta } = res.data;
@@ -71,17 +170,18 @@ function LogicHooks() {
71
170
  }
72
171
 
73
172
  // src/global-classes-styles-provider.ts
74
- var import_store4 = require("@elementor/store");
75
- var import_i18n = require("@wordpress/i18n");
173
+ var import_store5 = require("@elementor/store");
174
+ var import_i18n3 = require("@wordpress/i18n");
76
175
  var globalClassesStylesProvider = {
77
176
  key: "global-classes",
78
177
  priority: 30,
79
178
  actions: {
80
- get: () => selectOrderedGlobalClasses((0, import_store4.__getState)()),
179
+ get: () => selectOrderedGlobalClasses((0, import_store5.__getState)()),
180
+ getById: (id) => selectClass((0, import_store5.__getState)(), id),
81
181
  create: async (style) => {
82
182
  const res = await apiClient.post(style);
83
183
  const { data, meta } = res.data;
84
- (0, import_store4.__dispatch)(
184
+ (0, import_store5.__dispatch)(
85
185
  slice.actions.add({
86
186
  style: data,
87
187
  order: meta.order
@@ -90,34 +190,48 @@ var globalClassesStylesProvider = {
90
190
  return data;
91
191
  },
92
192
  update: async (payload) => {
93
- const style = selectClass((0, import_store4.__getState)(), payload.id);
193
+ const style = selectClass((0, import_store5.__getState)(), payload.id);
94
194
  const mergedData = { ...style, ...payload };
95
195
  const res = await apiClient.put(payload.id, mergedData);
96
196
  const { data, meta } = res.data;
97
- (0, import_store4.__dispatch)(
197
+ (0, import_store5.__dispatch)(
98
198
  slice.actions.update({
99
199
  style: data,
100
200
  order: meta.order
101
201
  })
102
202
  );
103
203
  return data;
204
+ },
205
+ updateProps: (args) => {
206
+ (0, import_store5.__dispatch)(
207
+ slice.actions.updateProps({
208
+ id: args.id,
209
+ meta: args.meta,
210
+ props: args.props
211
+ })
212
+ );
104
213
  }
105
214
  },
106
- subscribe: (cb) => (0, import_store4.__subscribe)(cb),
215
+ subscribe: (cb) => (0, import_store5.__subscribeWithSelector)((state) => state.globalClasses, cb),
107
216
  labels: {
108
- singular: (0, import_i18n.__)("Global CSS Class", "elementor"),
109
- plural: (0, import_i18n.__)("Global CSS Classes", "elementor")
217
+ singular: (0, import_i18n3.__)("Global CSS Class", "elementor"),
218
+ plural: (0, import_i18n3.__)("Global CSS Classes", "elementor")
110
219
  }
111
220
  };
112
221
 
113
222
  // src/init.ts
114
223
  function init() {
115
- (0, import_store6.__registerSlice)(slice);
224
+ (0, import_store7.__registerSlice)(slice);
225
+ (0, import_editor_panels2.__registerPanel)(panel);
116
226
  import_editor_styles_repository.stylesRepository.register(globalClassesStylesProvider);
117
227
  (0, import_editor.injectIntoLogic)({
118
228
  id: "global-classes-hooks",
119
229
  component: LogicHooks
120
230
  });
231
+ (0, import_editor_editing_panel.injectIntoClassSelectorActions)({
232
+ id: "global-classes",
233
+ component: ClassManagerButton
234
+ });
121
235
  }
122
236
 
123
237
  // src/index.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/init.ts","../src/components/logic-hooks.tsx","../src/api.ts","../src/store.ts","../src/global-classes-styles-provider.ts","../src/index.ts"],"sourcesContent":["import { injectIntoLogic } from '@elementor/editor';\nimport { stylesRepository } from '@elementor/editor-styles-repository';\nimport { __registerSlice as registerSlice } from '@elementor/store';\n\nimport { LogicHooks } from './components/logic-hooks';\nimport { globalClassesStylesProvider } from './global-classes-styles-provider';\nimport { slice } from './store';\n\nexport function init() {\n\tregisterSlice( slice );\n\n\tstylesRepository.register( globalClassesStylesProvider );\n\n\tinjectIntoLogic( {\n\t\tid: 'global-classes-hooks',\n\t\tcomponent: LogicHooks,\n\t} );\n}\n","import { useEffect } from 'react';\nimport { __useDispatch as useDispatch } from '@elementor/store';\n\nimport { apiClient } from '../api';\nimport { slice } from '../store';\n\nexport function LogicHooks() {\n\tconst dispatch = useDispatch();\n\n\tuseEffect( () => {\n\t\tapiClient.all().then( ( res ) => {\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch( slice.actions.init( { items: data, order: meta.order } ) );\n\t\t} );\n\t}, [ dispatch ] );\n\n\treturn null;\n}\n","import { type StyleDefinition, type StyleDefinitionsMap } from '@elementor/editor-styles';\nimport { type CreateActionPayload, type UpdateActionPayload } from '@elementor/editor-styles-repository';\nimport { type HttpResponse, httpService } from '@elementor/http';\n\nconst RESOURCE_URL = '/global-classes';\n\nexport type GlobalClassesGetAllResponse = HttpResponse< StyleDefinitionsMap, { order: StyleDefinition[ 'id' ][] } >;\nexport type GlobalClassesPostResponse = HttpResponse< StyleDefinition, { order: StyleDefinition[ 'id' ][] } >;\nexport type GlobalClassesPutResponse = HttpResponse< StyleDefinition, { order: StyleDefinition[ 'id' ][] } >;\n\nexport const apiClient = {\n\tall: async () => {\n\t\treturn httpService().get< GlobalClassesGetAllResponse >( RESOURCE_URL );\n\t},\n\tpost: async ( data: CreateActionPayload ) => {\n\t\treturn httpService().post< GlobalClassesPostResponse >( RESOURCE_URL, data );\n\t},\n\tput: async ( id: string, data: UpdateActionPayload ) => {\n\t\treturn httpService().put< GlobalClassesPutResponse >( `${ RESOURCE_URL }/${ id }`, data );\n\t},\n};\n","import { type StyleDefinition, type StyleDefinitionID } from '@elementor/editor-styles';\nimport {\n\t__createSelector as createSelector,\n\t__createSlice as createSlice,\n\ttype PayloadAction,\n\ttype SliceState,\n} from '@elementor/store';\n\nexport type State = {\n\titems: Record< StyleDefinitionID, StyleDefinition >;\n\torder: StyleDefinitionID[];\n};\n\nconst initialState: State = {\n\titems: {},\n\torder: [],\n};\n\n// Slice\nexport const SLICE_NAME = 'globalClasses';\n\nexport const slice = createSlice( {\n\tname: SLICE_NAME,\n\tinitialState,\n\treducers: {\n\t\tinit( state, { payload }: PayloadAction< State > ) {\n\t\t\tstate.items = payload.items;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tadd( state, { payload }: PayloadAction< { style: StyleDefinition; order: State[ 'order' ] } > ) {\n\t\t\tstate.items[ payload.style.id ] = payload.style;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tupdate( state, { payload }: PayloadAction< { style: StyleDefinition; order: State[ 'order' ] } > ) {\n\t\t\tstate.items[ payload.style.id ] = payload.style;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t},\n} );\n\n// Selectors\nconst selectItems = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].items;\nconst selectOrder = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].order;\n\nexport const selectOrderedGlobalClasses = createSelector( selectItems, selectOrder, ( items, order ) =>\n\torder.map( ( id ) => items[ id ] )\n);\n\nexport const selectClass = ( state: SliceState< typeof slice >, id: StyleDefinitionID ) =>\n\tstate[ SLICE_NAME ].items[ id ];\n","import type { StylesProvider } from '@elementor/editor-styles-repository';\nimport { __dispatch as dispatch, __getState as getState, __subscribe as subscribe } from '@elementor/store';\nimport { __ } from '@wordpress/i18n';\n\nimport { apiClient } from './api';\nimport { selectClass, selectOrderedGlobalClasses, slice } from './store';\n\nexport const globalClassesStylesProvider: StylesProvider = {\n\tkey: 'global-classes',\n\tpriority: 30,\n\tactions: {\n\t\tget: () => selectOrderedGlobalClasses( getState() ),\n\t\tcreate: async ( style ) => {\n\t\t\tconst res = await apiClient.post( style );\n\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch(\n\t\t\t\tslice.actions.add( {\n\t\t\t\t\tstyle: data,\n\t\t\t\t\torder: meta.order,\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\treturn data;\n\t\t},\n\t\tupdate: async ( payload ) => {\n\t\t\tconst style = selectClass( getState(), payload.id );\n\t\t\tconst mergedData = { ...style, ...payload };\n\n\t\t\tconst res = await apiClient.put( payload.id, mergedData );\n\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch(\n\t\t\t\tslice.actions.update( {\n\t\t\t\t\tstyle: data,\n\t\t\t\t\torder: meta.order,\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\treturn data;\n\t\t},\n\t},\n\tsubscribe: ( cb ) => subscribe( cb ),\n\tlabels: {\n\t\tsingular: __( 'Global CSS Class', 'elementor' ),\n\t\tplural: __( 'Global CSS Classes', 'elementor' ),\n\t},\n};\n","import { init } from './init';\n\ninit();\n"],"mappings":"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","names":["import_store","import_store","createSlice","createSelector","dispatch","useDispatch","import_store","getState","dispatch","subscribe","registerSlice"]}
1
+ {"version":3,"sources":["../src/init.ts","../src/components/class-manager/class-manager-button.tsx","../src/components/class-manager/class-manager-panel.tsx","../src/components/class-manager/global-classes-list.tsx","../src/store.ts","../src/errors.ts","../src/components/logic-hooks.tsx","../src/api.ts","../src/global-classes-styles-provider.ts","../src/index.ts"],"sourcesContent":["import { injectIntoLogic } from '@elementor/editor';\nimport { injectIntoClassSelectorActions } from '@elementor/editor-editing-panel';\nimport { __registerPanel as registerPanel } from '@elementor/editor-panels';\nimport { stylesRepository } from '@elementor/editor-styles-repository';\nimport { __registerSlice as registerSlice } from '@elementor/store';\n\nimport { ClassManagerButton } from './components/class-manager/class-manager-button';\nimport { panel } from './components/class-manager/class-manager-panel';\nimport { LogicHooks } from './components/logic-hooks';\nimport { globalClassesStylesProvider } from './global-classes-styles-provider';\nimport { slice } from './store';\n\nexport function init() {\n\tregisterSlice( slice );\n\tregisterPanel( panel );\n\n\tstylesRepository.register( globalClassesStylesProvider );\n\n\tinjectIntoLogic( {\n\t\tid: 'global-classes-hooks',\n\t\tcomponent: LogicHooks,\n\t} );\n\n\tinjectIntoClassSelectorActions( {\n\t\tid: 'global-classes',\n\t\tcomponent: ClassManagerButton,\n\t} );\n}\n","import * as React from 'react';\nimport { ColorSwatchIcon } from '@elementor/icons';\nimport { IconButton, Tooltip } from '@elementor/ui';\nimport { __ } from '@wordpress/i18n';\n\nimport { usePanelActions } from './class-manager-panel';\n\nexport const ClassManagerButton = () => {\n\tconst { open } = usePanelActions();\n\n\treturn (\n\t\t<Tooltip title={ __( 'Class manager' ) } placement=\"top\">\n\t\t\t<IconButton onClick={ open }>\n\t\t\t\t<ColorSwatchIcon fontSize=\"tiny\" />\n\t\t\t</IconButton>\n\t\t</Tooltip>\n\t);\n};\n","import * as React from 'react';\nimport {\n\t__createPanel as createPanel,\n\tPanel,\n\tPanelBody,\n\tPanelHeader,\n\tPanelHeaderTitle,\n} from '@elementor/editor-panels';\nimport { ColorSwatchIcon, XIcon } from '@elementor/icons';\nimport { Alert, Box, ErrorBoundary, IconButton, type IconButtonProps, Stack } from '@elementor/ui';\nimport { __ } from '@wordpress/i18n';\n\nimport { GlobalClassesList } from './global-classes-list';\n\nexport const { panel, usePanelActions, usePanelStatus } = createPanel( {\n\tid: 'class-manager-panel',\n\tcomponent: ClassManagerPanel,\n} );\n\nfunction ClassManagerPanel() {\n\treturn (\n\t\t<ErrorBoundary fallback={ <ErrorBoundaryFallback /> }>\n\t\t\t<Panel>\n\t\t\t\t<PanelHeader>\n\t\t\t\t\t<Stack p={ 1 } width=\"100%\" direction=\"row\" alignItems=\"center\">\n\t\t\t\t\t\t<PanelHeaderTitle sx={ { display: 'flex', alignItems: 'center', gap: 0.5 } }>\n\t\t\t\t\t\t\t<ColorSwatchIcon fontSize=\"inherit\" sx={ { transform: 'rotate(90deg)' } } />\n\t\t\t\t\t\t\t{ __( 'CSS Class manager' ) }\n\t\t\t\t\t\t</PanelHeaderTitle>\n\t\t\t\t\t\t<CloseButton sx={ { marginLeft: 'auto' } } />\n\t\t\t\t\t</Stack>\n\t\t\t\t</PanelHeader>\n\t\t\t\t<PanelBody px={ 2 }>\n\t\t\t\t\t<GlobalClassesList />\n\t\t\t\t</PanelBody>\n\t\t\t</Panel>\n\t\t</ErrorBoundary>\n\t);\n}\n\nconst CloseButton = ( props: IconButtonProps ) => {\n\tconst { close } = usePanelActions();\n\n\treturn (\n\t\t<IconButton size=\"small\" color=\"secondary\" onClick={ close } { ...props }>\n\t\t\t<XIcon fontSize=\"small\" />\n\t\t</IconButton>\n\t);\n};\n\nconst ErrorBoundaryFallback = () => (\n\t<Box role=\"alert\" sx={ { minHeight: '100%', p: 2 } }>\n\t\t<Alert severity=\"error\" sx={ { mb: 2, maxWidth: 400, textAlign: 'center' } }>\n\t\t\t<strong>{ __( 'Something went wrong', 'elementor' ) }</strong>\n\t\t</Alert>\n\t</Box>\n);\n","import * as React from 'react';\nimport { EllipsisWithTooltip } from '@elementor/editor-ui';\nimport { List, ListItemButton, Stack, Typography } from '@elementor/ui';\n\nimport { useOrderedGlobalClasses } from '../../store';\n\nexport const GlobalClassesList = () => {\n\tconst cssClasses = useOrderedGlobalClasses();\n\n\treturn (\n\t\t<Stack>\n\t\t\t<List role=\"list\">\n\t\t\t\t{ cssClasses?.map( ( { id, label } ) => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Stack key={ id } direction=\"row\" alignItems=\"center\" gap={ 1 } role=\"listitem\">\n\t\t\t\t\t\t\t<ListItemButton sx={ { borderRadius: 1 } }>\n\t\t\t\t\t\t\t\t<EllipsisWithTooltip title={ label } as={ Typography } variant=\"caption\" />\n\t\t\t\t\t\t\t</ListItemButton>\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t);\n\t\t\t\t} ) }\n\t\t\t</List>\n\t\t</Stack>\n\t);\n};\n","import { mergeProps, type Props } from '@elementor/editor-props';\nimport {\n\tgetVariantByMeta,\n\ttype StyleDefinition,\n\ttype StyleDefinitionID,\n\ttype StyleDefinitionVariant,\n} from '@elementor/editor-styles';\nimport {\n\t__createSelector as createSelector,\n\t__createSlice as createSlice,\n\t__useSelector as useSelector,\n\ttype PayloadAction,\n\ttype SliceState,\n} from '@elementor/store';\n\nimport { GlobalClassNotFoundError } from './errors';\n\nexport type State = {\n\titems: Record< StyleDefinitionID, StyleDefinition >;\n\torder: StyleDefinitionID[];\n};\n\nconst initialState: State = {\n\titems: {},\n\torder: [],\n};\n\nexport type GlobalClassesState = SliceState< typeof slice >;\n\n// Slice\nexport const SLICE_NAME = 'globalClasses';\n\nexport const slice = createSlice( {\n\tname: SLICE_NAME,\n\tinitialState,\n\treducers: {\n\t\tinit( state, { payload }: PayloadAction< State > ) {\n\t\t\tstate.items = payload.items;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tadd( state, { payload }: PayloadAction< { style: StyleDefinition; order: State[ 'order' ] } > ) {\n\t\t\tstate.items[ payload.style.id ] = payload.style;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tupdate( state, { payload }: PayloadAction< { style: StyleDefinition; order: State[ 'order' ] } > ) {\n\t\t\tstate.items[ payload.style.id ] = payload.style;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tupdateProps(\n\t\t\tstate,\n\t\t\t{\n\t\t\t\tpayload,\n\t\t\t}: PayloadAction< { id: StyleDefinitionID; meta: StyleDefinitionVariant[ 'meta' ]; props: Props } >\n\t\t) {\n\t\t\tconst style = state.items[ payload.id ];\n\n\t\t\tif ( ! style ) {\n\t\t\t\tthrow new GlobalClassNotFoundError( { context: { styleId: payload.id } } );\n\t\t\t}\n\n\t\t\tconst variant = getVariantByMeta( style, payload.meta );\n\n\t\t\tif ( variant ) {\n\t\t\t\tvariant.props = mergeProps( variant.props, payload.props );\n\t\t\t} else {\n\t\t\t\tstyle.variants.push( { meta: payload.meta, props: payload.props } );\n\t\t\t}\n\t\t},\n\t},\n} );\n\n// Selectors\nconst selectItems = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].items;\nconst selectOrder = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].order;\n\nexport const selectOrderedGlobalClasses = createSelector( selectItems, selectOrder, ( items, order ) =>\n\torder.map( ( id ) => items[ id ] )\n);\n\nexport const selectClass = ( state: SliceState< typeof slice >, id: StyleDefinitionID ) =>\n\tstate[ SLICE_NAME ].items[ id ] ?? null;\n\nexport const useOrderedGlobalClasses = () => {\n\tconst items = useSelector( selectOrderedGlobalClasses );\n\n\treturn items;\n};\n","import { createError } from '@elementor/utils';\n\nexport const GlobalClassNotFoundError = createError< { styleId: string } >( {\n\tcode: 'global_class_not_found',\n\tmessage: 'Global class not found.',\n} );\n","import { useEffect } from 'react';\nimport { __useDispatch as useDispatch } from '@elementor/store';\n\nimport { apiClient } from '../api';\nimport { slice } from '../store';\n\nexport function LogicHooks() {\n\tconst dispatch = useDispatch();\n\n\tuseEffect( () => {\n\t\tapiClient.all().then( ( res ) => {\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch( slice.actions.init( { items: data, order: meta.order } ) );\n\t\t} );\n\t}, [ dispatch ] );\n\n\treturn null;\n}\n","import { type StyleDefinition, type StyleDefinitionsMap } from '@elementor/editor-styles';\nimport { type CreateActionPayload, type UpdateActionPayload } from '@elementor/editor-styles-repository';\nimport { type HttpResponse, httpService } from '@elementor/http';\n\nconst RESOURCE_URL = '/global-classes';\n\nexport type GlobalClassesGetAllResponse = HttpResponse< StyleDefinitionsMap, { order: StyleDefinition[ 'id' ][] } >;\nexport type GlobalClassesPostResponse = HttpResponse< StyleDefinition, { order: StyleDefinition[ 'id' ][] } >;\nexport type GlobalClassesPutResponse = HttpResponse< StyleDefinition, { order: StyleDefinition[ 'id' ][] } >;\n\nexport const apiClient = {\n\tall: async () => {\n\t\treturn httpService().get< GlobalClassesGetAllResponse >( RESOURCE_URL );\n\t},\n\tpost: async ( data: CreateActionPayload ) => {\n\t\treturn httpService().post< GlobalClassesPostResponse >( RESOURCE_URL, data );\n\t},\n\tput: async ( id: string, data: UpdateActionPayload ) => {\n\t\treturn httpService().put< GlobalClassesPutResponse >( `${ RESOURCE_URL }/${ id }`, data );\n\t},\n};\n","import type { StylesProvider } from '@elementor/editor-styles-repository';\nimport {\n\t__dispatch as dispatch,\n\t__getState as getState,\n\t__subscribeWithSelector as subscribeWithSelector,\n} from '@elementor/store';\nimport { __ } from '@wordpress/i18n';\n\nimport { apiClient } from './api';\nimport { type GlobalClassesState, selectClass, selectOrderedGlobalClasses, slice } from './store';\n\nexport const globalClassesStylesProvider = {\n\tkey: 'global-classes',\n\tpriority: 30,\n\tactions: {\n\t\tget: () => selectOrderedGlobalClasses( getState() ),\n\t\tgetById: ( id ) => selectClass( getState(), id ),\n\t\tcreate: async ( style ) => {\n\t\t\tconst res = await apiClient.post( style );\n\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch(\n\t\t\t\tslice.actions.add( {\n\t\t\t\t\tstyle: data,\n\t\t\t\t\torder: meta.order,\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\treturn data;\n\t\t},\n\t\tupdate: async ( payload ) => {\n\t\t\tconst style = selectClass( getState(), payload.id );\n\t\t\tconst mergedData = { ...style, ...payload };\n\n\t\t\tconst res = await apiClient.put( payload.id, mergedData );\n\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch(\n\t\t\t\tslice.actions.update( {\n\t\t\t\t\tstyle: data,\n\t\t\t\t\torder: meta.order,\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\treturn data;\n\t\t},\n\n\t\tupdateProps: ( args ) => {\n\t\t\tdispatch(\n\t\t\t\tslice.actions.updateProps( {\n\t\t\t\t\tid: args.id,\n\t\t\t\t\tmeta: args.meta,\n\t\t\t\t\tprops: args.props,\n\t\t\t\t} )\n\t\t\t);\n\t\t},\n\t},\n\tsubscribe: ( cb ) => subscribeWithSelector( ( state: GlobalClassesState ) => state.globalClasses, cb ),\n\tlabels: {\n\t\tsingular: __( 'Global CSS Class', 'elementor' ),\n\t\tplural: __( 'Global CSS Classes', 'elementor' ),\n\t},\n} satisfies StylesProvider;\n","import { init } from './init';\n\ninit();\n"],"mappings":"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","names":["import_editor_panels","import_store","React","import_icons","import_ui","import_i18n","React","import_ui","createSlice","createSelector","useSelector","createPanel","import_store","dispatch","useDispatch","import_store","import_i18n","getState","dispatch","subscribeWithSelector","registerSlice","registerPanel"]}
package/dist/index.mjs CHANGED
@@ -1,32 +1,53 @@
1
1
  // src/init.ts
2
2
  import { injectIntoLogic } from "@elementor/editor";
3
+ import { injectIntoClassSelectorActions } from "@elementor/editor-editing-panel";
4
+ import { __registerPanel as registerPanel } from "@elementor/editor-panels";
3
5
  import { stylesRepository } from "@elementor/editor-styles-repository";
4
6
  import { __registerSlice as registerSlice } from "@elementor/store";
5
7
 
6
- // src/components/logic-hooks.tsx
7
- import { useEffect } from "react";
8
- import { __useDispatch as useDispatch } from "@elementor/store";
8
+ // src/components/class-manager/class-manager-button.tsx
9
+ import * as React3 from "react";
10
+ import { ColorSwatchIcon as ColorSwatchIcon2 } from "@elementor/icons";
11
+ import { IconButton as IconButton2, Tooltip } from "@elementor/ui";
12
+ import { __ as __2 } from "@wordpress/i18n";
9
13
 
10
- // src/api.ts
11
- import { httpService } from "@elementor/http";
12
- var RESOURCE_URL = "/global-classes";
13
- var apiClient = {
14
- all: async () => {
15
- return httpService().get(RESOURCE_URL);
16
- },
17
- post: async (data) => {
18
- return httpService().post(RESOURCE_URL, data);
19
- },
20
- put: async (id, data) => {
21
- return httpService().put(`${RESOURCE_URL}/${id}`, data);
22
- }
23
- };
14
+ // src/components/class-manager/class-manager-panel.tsx
15
+ import * as React2 from "react";
16
+ import {
17
+ __createPanel as createPanel,
18
+ Panel,
19
+ PanelBody,
20
+ PanelHeader,
21
+ PanelHeaderTitle
22
+ } from "@elementor/editor-panels";
23
+ import { ColorSwatchIcon, XIcon } from "@elementor/icons";
24
+ import { Alert, Box, ErrorBoundary, IconButton, Stack as Stack2 } from "@elementor/ui";
25
+ import { __ } from "@wordpress/i18n";
26
+
27
+ // src/components/class-manager/global-classes-list.tsx
28
+ import * as React from "react";
29
+ import { EllipsisWithTooltip } from "@elementor/editor-ui";
30
+ import { List, ListItemButton, Stack, Typography } from "@elementor/ui";
24
31
 
25
32
  // src/store.ts
33
+ import { mergeProps } from "@elementor/editor-props";
34
+ import {
35
+ getVariantByMeta
36
+ } from "@elementor/editor-styles";
26
37
  import {
27
38
  __createSelector as createSelector,
28
- __createSlice as createSlice
39
+ __createSlice as createSlice,
40
+ __useSelector as useSelector
29
41
  } from "@elementor/store";
42
+
43
+ // src/errors.ts
44
+ import { createError } from "@elementor/utils";
45
+ var GlobalClassNotFoundError = createError({
46
+ code: "global_class_not_found",
47
+ message: "Global class not found."
48
+ });
49
+
50
+ // src/store.ts
30
51
  var initialState = {
31
52
  items: {},
32
53
  order: []
@@ -47,6 +68,20 @@ var slice = createSlice({
47
68
  update(state, { payload }) {
48
69
  state.items[payload.style.id] = payload.style;
49
70
  state.order = payload.order;
71
+ },
72
+ updateProps(state, {
73
+ payload
74
+ }) {
75
+ const style = state.items[payload.id];
76
+ if (!style) {
77
+ throw new GlobalClassNotFoundError({ context: { styleId: payload.id } });
78
+ }
79
+ const variant = getVariantByMeta(style, payload.meta);
80
+ if (variant) {
81
+ variant.props = mergeProps(variant.props, payload.props);
82
+ } else {
83
+ style.variants.push({ meta: payload.meta, props: payload.props });
84
+ }
50
85
  }
51
86
  }
52
87
  });
@@ -57,7 +92,58 @@ var selectOrderedGlobalClasses = createSelector(
57
92
  selectOrder,
58
93
  (items, order) => order.map((id) => items[id])
59
94
  );
60
- var selectClass = (state, id) => state[SLICE_NAME].items[id];
95
+ var selectClass = (state, id) => state[SLICE_NAME].items[id] ?? null;
96
+ var useOrderedGlobalClasses = () => {
97
+ const items = useSelector(selectOrderedGlobalClasses);
98
+ return items;
99
+ };
100
+
101
+ // src/components/class-manager/global-classes-list.tsx
102
+ var GlobalClassesList = () => {
103
+ const cssClasses = useOrderedGlobalClasses();
104
+ return /* @__PURE__ */ React.createElement(Stack, null, /* @__PURE__ */ React.createElement(List, { role: "list" }, cssClasses?.map(({ id, label }) => {
105
+ return /* @__PURE__ */ React.createElement(Stack, { key: id, direction: "row", alignItems: "center", gap: 1, role: "listitem" }, /* @__PURE__ */ React.createElement(ListItemButton, { sx: { borderRadius: 1 } }, /* @__PURE__ */ React.createElement(EllipsisWithTooltip, { title: label, as: Typography, variant: "caption" })));
106
+ })));
107
+ };
108
+
109
+ // src/components/class-manager/class-manager-panel.tsx
110
+ var { panel, usePanelActions, usePanelStatus } = createPanel({
111
+ id: "class-manager-panel",
112
+ component: ClassManagerPanel
113
+ });
114
+ function ClassManagerPanel() {
115
+ return /* @__PURE__ */ React2.createElement(ErrorBoundary, { fallback: /* @__PURE__ */ React2.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React2.createElement(Panel, null, /* @__PURE__ */ React2.createElement(PanelHeader, null, /* @__PURE__ */ React2.createElement(Stack2, { p: 1, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React2.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React2.createElement(ColorSwatchIcon, { fontSize: "inherit", sx: { transform: "rotate(90deg)" } }), __("CSS Class manager")), /* @__PURE__ */ React2.createElement(CloseButton, { sx: { marginLeft: "auto" } }))), /* @__PURE__ */ React2.createElement(PanelBody, { px: 2 }, /* @__PURE__ */ React2.createElement(GlobalClassesList, null))));
116
+ }
117
+ var CloseButton = (props) => {
118
+ const { close } = usePanelActions();
119
+ return /* @__PURE__ */ React2.createElement(IconButton, { size: "small", color: "secondary", onClick: close, ...props }, /* @__PURE__ */ React2.createElement(XIcon, { fontSize: "small" }));
120
+ };
121
+ var ErrorBoundaryFallback = () => /* @__PURE__ */ React2.createElement(Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React2.createElement(Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React2.createElement("strong", null, __("Something went wrong", "elementor"))));
122
+
123
+ // src/components/class-manager/class-manager-button.tsx
124
+ var ClassManagerButton = () => {
125
+ const { open } = usePanelActions();
126
+ return /* @__PURE__ */ React3.createElement(Tooltip, { title: __2("Class manager"), placement: "top" }, /* @__PURE__ */ React3.createElement(IconButton2, { onClick: open }, /* @__PURE__ */ React3.createElement(ColorSwatchIcon2, { fontSize: "tiny" })));
127
+ };
128
+
129
+ // src/components/logic-hooks.tsx
130
+ import { useEffect } from "react";
131
+ import { __useDispatch as useDispatch } from "@elementor/store";
132
+
133
+ // src/api.ts
134
+ import { httpService } from "@elementor/http";
135
+ var RESOURCE_URL = "/global-classes";
136
+ var apiClient = {
137
+ all: async () => {
138
+ return httpService().get(RESOURCE_URL);
139
+ },
140
+ post: async (data) => {
141
+ return httpService().post(RESOURCE_URL, data);
142
+ },
143
+ put: async (id, data) => {
144
+ return httpService().put(`${RESOURCE_URL}/${id}`, data);
145
+ }
146
+ };
61
147
 
62
148
  // src/components/logic-hooks.tsx
63
149
  function LogicHooks() {
@@ -72,13 +158,18 @@ function LogicHooks() {
72
158
  }
73
159
 
74
160
  // src/global-classes-styles-provider.ts
75
- import { __dispatch as dispatch, __getState as getState, __subscribe as subscribe } from "@elementor/store";
76
- import { __ } from "@wordpress/i18n";
161
+ import {
162
+ __dispatch as dispatch,
163
+ __getState as getState,
164
+ __subscribeWithSelector as subscribeWithSelector
165
+ } from "@elementor/store";
166
+ import { __ as __3 } from "@wordpress/i18n";
77
167
  var globalClassesStylesProvider = {
78
168
  key: "global-classes",
79
169
  priority: 30,
80
170
  actions: {
81
171
  get: () => selectOrderedGlobalClasses(getState()),
172
+ getById: (id) => selectClass(getState(), id),
82
173
  create: async (style) => {
83
174
  const res = await apiClient.post(style);
84
175
  const { data, meta } = res.data;
@@ -102,23 +193,37 @@ var globalClassesStylesProvider = {
102
193
  })
103
194
  );
104
195
  return data;
196
+ },
197
+ updateProps: (args) => {
198
+ dispatch(
199
+ slice.actions.updateProps({
200
+ id: args.id,
201
+ meta: args.meta,
202
+ props: args.props
203
+ })
204
+ );
105
205
  }
106
206
  },
107
- subscribe: (cb) => subscribe(cb),
207
+ subscribe: (cb) => subscribeWithSelector((state) => state.globalClasses, cb),
108
208
  labels: {
109
- singular: __("Global CSS Class", "elementor"),
110
- plural: __("Global CSS Classes", "elementor")
209
+ singular: __3("Global CSS Class", "elementor"),
210
+ plural: __3("Global CSS Classes", "elementor")
111
211
  }
112
212
  };
113
213
 
114
214
  // src/init.ts
115
215
  function init() {
116
216
  registerSlice(slice);
217
+ registerPanel(panel);
117
218
  stylesRepository.register(globalClassesStylesProvider);
118
219
  injectIntoLogic({
119
220
  id: "global-classes-hooks",
120
221
  component: LogicHooks
121
222
  });
223
+ injectIntoClassSelectorActions({
224
+ id: "global-classes",
225
+ component: ClassManagerButton
226
+ });
122
227
  }
123
228
 
124
229
  // src/index.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/init.ts","../src/components/logic-hooks.tsx","../src/api.ts","../src/store.ts","../src/global-classes-styles-provider.ts","../src/index.ts"],"sourcesContent":["import { injectIntoLogic } from '@elementor/editor';\nimport { stylesRepository } from '@elementor/editor-styles-repository';\nimport { __registerSlice as registerSlice } from '@elementor/store';\n\nimport { LogicHooks } from './components/logic-hooks';\nimport { globalClassesStylesProvider } from './global-classes-styles-provider';\nimport { slice } from './store';\n\nexport function init() {\n\tregisterSlice( slice );\n\n\tstylesRepository.register( globalClassesStylesProvider );\n\n\tinjectIntoLogic( {\n\t\tid: 'global-classes-hooks',\n\t\tcomponent: LogicHooks,\n\t} );\n}\n","import { useEffect } from 'react';\nimport { __useDispatch as useDispatch } from '@elementor/store';\n\nimport { apiClient } from '../api';\nimport { slice } from '../store';\n\nexport function LogicHooks() {\n\tconst dispatch = useDispatch();\n\n\tuseEffect( () => {\n\t\tapiClient.all().then( ( res ) => {\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch( slice.actions.init( { items: data, order: meta.order } ) );\n\t\t} );\n\t}, [ dispatch ] );\n\n\treturn null;\n}\n","import { type StyleDefinition, type StyleDefinitionsMap } from '@elementor/editor-styles';\nimport { type CreateActionPayload, type UpdateActionPayload } from '@elementor/editor-styles-repository';\nimport { type HttpResponse, httpService } from '@elementor/http';\n\nconst RESOURCE_URL = '/global-classes';\n\nexport type GlobalClassesGetAllResponse = HttpResponse< StyleDefinitionsMap, { order: StyleDefinition[ 'id' ][] } >;\nexport type GlobalClassesPostResponse = HttpResponse< StyleDefinition, { order: StyleDefinition[ 'id' ][] } >;\nexport type GlobalClassesPutResponse = HttpResponse< StyleDefinition, { order: StyleDefinition[ 'id' ][] } >;\n\nexport const apiClient = {\n\tall: async () => {\n\t\treturn httpService().get< GlobalClassesGetAllResponse >( RESOURCE_URL );\n\t},\n\tpost: async ( data: CreateActionPayload ) => {\n\t\treturn httpService().post< GlobalClassesPostResponse >( RESOURCE_URL, data );\n\t},\n\tput: async ( id: string, data: UpdateActionPayload ) => {\n\t\treturn httpService().put< GlobalClassesPutResponse >( `${ RESOURCE_URL }/${ id }`, data );\n\t},\n};\n","import { type StyleDefinition, type StyleDefinitionID } from '@elementor/editor-styles';\nimport {\n\t__createSelector as createSelector,\n\t__createSlice as createSlice,\n\ttype PayloadAction,\n\ttype SliceState,\n} from '@elementor/store';\n\nexport type State = {\n\titems: Record< StyleDefinitionID, StyleDefinition >;\n\torder: StyleDefinitionID[];\n};\n\nconst initialState: State = {\n\titems: {},\n\torder: [],\n};\n\n// Slice\nexport const SLICE_NAME = 'globalClasses';\n\nexport const slice = createSlice( {\n\tname: SLICE_NAME,\n\tinitialState,\n\treducers: {\n\t\tinit( state, { payload }: PayloadAction< State > ) {\n\t\t\tstate.items = payload.items;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tadd( state, { payload }: PayloadAction< { style: StyleDefinition; order: State[ 'order' ] } > ) {\n\t\t\tstate.items[ payload.style.id ] = payload.style;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tupdate( state, { payload }: PayloadAction< { style: StyleDefinition; order: State[ 'order' ] } > ) {\n\t\t\tstate.items[ payload.style.id ] = payload.style;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t},\n} );\n\n// Selectors\nconst selectItems = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].items;\nconst selectOrder = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].order;\n\nexport const selectOrderedGlobalClasses = createSelector( selectItems, selectOrder, ( items, order ) =>\n\torder.map( ( id ) => items[ id ] )\n);\n\nexport const selectClass = ( state: SliceState< typeof slice >, id: StyleDefinitionID ) =>\n\tstate[ SLICE_NAME ].items[ id ];\n","import type { StylesProvider } from '@elementor/editor-styles-repository';\nimport { __dispatch as dispatch, __getState as getState, __subscribe as subscribe } from '@elementor/store';\nimport { __ } from '@wordpress/i18n';\n\nimport { apiClient } from './api';\nimport { selectClass, selectOrderedGlobalClasses, slice } from './store';\n\nexport const globalClassesStylesProvider: StylesProvider = {\n\tkey: 'global-classes',\n\tpriority: 30,\n\tactions: {\n\t\tget: () => selectOrderedGlobalClasses( getState() ),\n\t\tcreate: async ( style ) => {\n\t\t\tconst res = await apiClient.post( style );\n\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch(\n\t\t\t\tslice.actions.add( {\n\t\t\t\t\tstyle: data,\n\t\t\t\t\torder: meta.order,\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\treturn data;\n\t\t},\n\t\tupdate: async ( payload ) => {\n\t\t\tconst style = selectClass( getState(), payload.id );\n\t\t\tconst mergedData = { ...style, ...payload };\n\n\t\t\tconst res = await apiClient.put( payload.id, mergedData );\n\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch(\n\t\t\t\tslice.actions.update( {\n\t\t\t\t\tstyle: data,\n\t\t\t\t\torder: meta.order,\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\treturn data;\n\t\t},\n\t},\n\tsubscribe: ( cb ) => subscribe( cb ),\n\tlabels: {\n\t\tsingular: __( 'Global CSS Class', 'elementor' ),\n\t\tplural: __( 'Global CSS Classes', 'elementor' ),\n\t},\n};\n","import { init } from './init';\n\ninit();\n"],"mappings":"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","names":["dispatch"]}
1
+ {"version":3,"sources":["../src/init.ts","../src/components/class-manager/class-manager-button.tsx","../src/components/class-manager/class-manager-panel.tsx","../src/components/class-manager/global-classes-list.tsx","../src/store.ts","../src/errors.ts","../src/components/logic-hooks.tsx","../src/api.ts","../src/global-classes-styles-provider.ts","../src/index.ts"],"sourcesContent":["import { injectIntoLogic } from '@elementor/editor';\nimport { injectIntoClassSelectorActions } from '@elementor/editor-editing-panel';\nimport { __registerPanel as registerPanel } from '@elementor/editor-panels';\nimport { stylesRepository } from '@elementor/editor-styles-repository';\nimport { __registerSlice as registerSlice } from '@elementor/store';\n\nimport { ClassManagerButton } from './components/class-manager/class-manager-button';\nimport { panel } from './components/class-manager/class-manager-panel';\nimport { LogicHooks } from './components/logic-hooks';\nimport { globalClassesStylesProvider } from './global-classes-styles-provider';\nimport { slice } from './store';\n\nexport function init() {\n\tregisterSlice( slice );\n\tregisterPanel( panel );\n\n\tstylesRepository.register( globalClassesStylesProvider );\n\n\tinjectIntoLogic( {\n\t\tid: 'global-classes-hooks',\n\t\tcomponent: LogicHooks,\n\t} );\n\n\tinjectIntoClassSelectorActions( {\n\t\tid: 'global-classes',\n\t\tcomponent: ClassManagerButton,\n\t} );\n}\n","import * as React from 'react';\nimport { ColorSwatchIcon } from '@elementor/icons';\nimport { IconButton, Tooltip } from '@elementor/ui';\nimport { __ } from '@wordpress/i18n';\n\nimport { usePanelActions } from './class-manager-panel';\n\nexport const ClassManagerButton = () => {\n\tconst { open } = usePanelActions();\n\n\treturn (\n\t\t<Tooltip title={ __( 'Class manager' ) } placement=\"top\">\n\t\t\t<IconButton onClick={ open }>\n\t\t\t\t<ColorSwatchIcon fontSize=\"tiny\" />\n\t\t\t</IconButton>\n\t\t</Tooltip>\n\t);\n};\n","import * as React from 'react';\nimport {\n\t__createPanel as createPanel,\n\tPanel,\n\tPanelBody,\n\tPanelHeader,\n\tPanelHeaderTitle,\n} from '@elementor/editor-panels';\nimport { ColorSwatchIcon, XIcon } from '@elementor/icons';\nimport { Alert, Box, ErrorBoundary, IconButton, type IconButtonProps, Stack } from '@elementor/ui';\nimport { __ } from '@wordpress/i18n';\n\nimport { GlobalClassesList } from './global-classes-list';\n\nexport const { panel, usePanelActions, usePanelStatus } = createPanel( {\n\tid: 'class-manager-panel',\n\tcomponent: ClassManagerPanel,\n} );\n\nfunction ClassManagerPanel() {\n\treturn (\n\t\t<ErrorBoundary fallback={ <ErrorBoundaryFallback /> }>\n\t\t\t<Panel>\n\t\t\t\t<PanelHeader>\n\t\t\t\t\t<Stack p={ 1 } width=\"100%\" direction=\"row\" alignItems=\"center\">\n\t\t\t\t\t\t<PanelHeaderTitle sx={ { display: 'flex', alignItems: 'center', gap: 0.5 } }>\n\t\t\t\t\t\t\t<ColorSwatchIcon fontSize=\"inherit\" sx={ { transform: 'rotate(90deg)' } } />\n\t\t\t\t\t\t\t{ __( 'CSS Class manager' ) }\n\t\t\t\t\t\t</PanelHeaderTitle>\n\t\t\t\t\t\t<CloseButton sx={ { marginLeft: 'auto' } } />\n\t\t\t\t\t</Stack>\n\t\t\t\t</PanelHeader>\n\t\t\t\t<PanelBody px={ 2 }>\n\t\t\t\t\t<GlobalClassesList />\n\t\t\t\t</PanelBody>\n\t\t\t</Panel>\n\t\t</ErrorBoundary>\n\t);\n}\n\nconst CloseButton = ( props: IconButtonProps ) => {\n\tconst { close } = usePanelActions();\n\n\treturn (\n\t\t<IconButton size=\"small\" color=\"secondary\" onClick={ close } { ...props }>\n\t\t\t<XIcon fontSize=\"small\" />\n\t\t</IconButton>\n\t);\n};\n\nconst ErrorBoundaryFallback = () => (\n\t<Box role=\"alert\" sx={ { minHeight: '100%', p: 2 } }>\n\t\t<Alert severity=\"error\" sx={ { mb: 2, maxWidth: 400, textAlign: 'center' } }>\n\t\t\t<strong>{ __( 'Something went wrong', 'elementor' ) }</strong>\n\t\t</Alert>\n\t</Box>\n);\n","import * as React from 'react';\nimport { EllipsisWithTooltip } from '@elementor/editor-ui';\nimport { List, ListItemButton, Stack, Typography } from '@elementor/ui';\n\nimport { useOrderedGlobalClasses } from '../../store';\n\nexport const GlobalClassesList = () => {\n\tconst cssClasses = useOrderedGlobalClasses();\n\n\treturn (\n\t\t<Stack>\n\t\t\t<List role=\"list\">\n\t\t\t\t{ cssClasses?.map( ( { id, label } ) => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Stack key={ id } direction=\"row\" alignItems=\"center\" gap={ 1 } role=\"listitem\">\n\t\t\t\t\t\t\t<ListItemButton sx={ { borderRadius: 1 } }>\n\t\t\t\t\t\t\t\t<EllipsisWithTooltip title={ label } as={ Typography } variant=\"caption\" />\n\t\t\t\t\t\t\t</ListItemButton>\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t);\n\t\t\t\t} ) }\n\t\t\t</List>\n\t\t</Stack>\n\t);\n};\n","import { mergeProps, type Props } from '@elementor/editor-props';\nimport {\n\tgetVariantByMeta,\n\ttype StyleDefinition,\n\ttype StyleDefinitionID,\n\ttype StyleDefinitionVariant,\n} from '@elementor/editor-styles';\nimport {\n\t__createSelector as createSelector,\n\t__createSlice as createSlice,\n\t__useSelector as useSelector,\n\ttype PayloadAction,\n\ttype SliceState,\n} from '@elementor/store';\n\nimport { GlobalClassNotFoundError } from './errors';\n\nexport type State = {\n\titems: Record< StyleDefinitionID, StyleDefinition >;\n\torder: StyleDefinitionID[];\n};\n\nconst initialState: State = {\n\titems: {},\n\torder: [],\n};\n\nexport type GlobalClassesState = SliceState< typeof slice >;\n\n// Slice\nexport const SLICE_NAME = 'globalClasses';\n\nexport const slice = createSlice( {\n\tname: SLICE_NAME,\n\tinitialState,\n\treducers: {\n\t\tinit( state, { payload }: PayloadAction< State > ) {\n\t\t\tstate.items = payload.items;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tadd( state, { payload }: PayloadAction< { style: StyleDefinition; order: State[ 'order' ] } > ) {\n\t\t\tstate.items[ payload.style.id ] = payload.style;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tupdate( state, { payload }: PayloadAction< { style: StyleDefinition; order: State[ 'order' ] } > ) {\n\t\t\tstate.items[ payload.style.id ] = payload.style;\n\t\t\tstate.order = payload.order;\n\t\t},\n\t\tupdateProps(\n\t\t\tstate,\n\t\t\t{\n\t\t\t\tpayload,\n\t\t\t}: PayloadAction< { id: StyleDefinitionID; meta: StyleDefinitionVariant[ 'meta' ]; props: Props } >\n\t\t) {\n\t\t\tconst style = state.items[ payload.id ];\n\n\t\t\tif ( ! style ) {\n\t\t\t\tthrow new GlobalClassNotFoundError( { context: { styleId: payload.id } } );\n\t\t\t}\n\n\t\t\tconst variant = getVariantByMeta( style, payload.meta );\n\n\t\t\tif ( variant ) {\n\t\t\t\tvariant.props = mergeProps( variant.props, payload.props );\n\t\t\t} else {\n\t\t\t\tstyle.variants.push( { meta: payload.meta, props: payload.props } );\n\t\t\t}\n\t\t},\n\t},\n} );\n\n// Selectors\nconst selectItems = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].items;\nconst selectOrder = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].order;\n\nexport const selectOrderedGlobalClasses = createSelector( selectItems, selectOrder, ( items, order ) =>\n\torder.map( ( id ) => items[ id ] )\n);\n\nexport const selectClass = ( state: SliceState< typeof slice >, id: StyleDefinitionID ) =>\n\tstate[ SLICE_NAME ].items[ id ] ?? null;\n\nexport const useOrderedGlobalClasses = () => {\n\tconst items = useSelector( selectOrderedGlobalClasses );\n\n\treturn items;\n};\n","import { createError } from '@elementor/utils';\n\nexport const GlobalClassNotFoundError = createError< { styleId: string } >( {\n\tcode: 'global_class_not_found',\n\tmessage: 'Global class not found.',\n} );\n","import { useEffect } from 'react';\nimport { __useDispatch as useDispatch } from '@elementor/store';\n\nimport { apiClient } from '../api';\nimport { slice } from '../store';\n\nexport function LogicHooks() {\n\tconst dispatch = useDispatch();\n\n\tuseEffect( () => {\n\t\tapiClient.all().then( ( res ) => {\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch( slice.actions.init( { items: data, order: meta.order } ) );\n\t\t} );\n\t}, [ dispatch ] );\n\n\treturn null;\n}\n","import { type StyleDefinition, type StyleDefinitionsMap } from '@elementor/editor-styles';\nimport { type CreateActionPayload, type UpdateActionPayload } from '@elementor/editor-styles-repository';\nimport { type HttpResponse, httpService } from '@elementor/http';\n\nconst RESOURCE_URL = '/global-classes';\n\nexport type GlobalClassesGetAllResponse = HttpResponse< StyleDefinitionsMap, { order: StyleDefinition[ 'id' ][] } >;\nexport type GlobalClassesPostResponse = HttpResponse< StyleDefinition, { order: StyleDefinition[ 'id' ][] } >;\nexport type GlobalClassesPutResponse = HttpResponse< StyleDefinition, { order: StyleDefinition[ 'id' ][] } >;\n\nexport const apiClient = {\n\tall: async () => {\n\t\treturn httpService().get< GlobalClassesGetAllResponse >( RESOURCE_URL );\n\t},\n\tpost: async ( data: CreateActionPayload ) => {\n\t\treturn httpService().post< GlobalClassesPostResponse >( RESOURCE_URL, data );\n\t},\n\tput: async ( id: string, data: UpdateActionPayload ) => {\n\t\treturn httpService().put< GlobalClassesPutResponse >( `${ RESOURCE_URL }/${ id }`, data );\n\t},\n};\n","import type { StylesProvider } from '@elementor/editor-styles-repository';\nimport {\n\t__dispatch as dispatch,\n\t__getState as getState,\n\t__subscribeWithSelector as subscribeWithSelector,\n} from '@elementor/store';\nimport { __ } from '@wordpress/i18n';\n\nimport { apiClient } from './api';\nimport { type GlobalClassesState, selectClass, selectOrderedGlobalClasses, slice } from './store';\n\nexport const globalClassesStylesProvider = {\n\tkey: 'global-classes',\n\tpriority: 30,\n\tactions: {\n\t\tget: () => selectOrderedGlobalClasses( getState() ),\n\t\tgetById: ( id ) => selectClass( getState(), id ),\n\t\tcreate: async ( style ) => {\n\t\t\tconst res = await apiClient.post( style );\n\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch(\n\t\t\t\tslice.actions.add( {\n\t\t\t\t\tstyle: data,\n\t\t\t\t\torder: meta.order,\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\treturn data;\n\t\t},\n\t\tupdate: async ( payload ) => {\n\t\t\tconst style = selectClass( getState(), payload.id );\n\t\t\tconst mergedData = { ...style, ...payload };\n\n\t\t\tconst res = await apiClient.put( payload.id, mergedData );\n\n\t\t\tconst { data, meta } = res.data;\n\n\t\t\tdispatch(\n\t\t\t\tslice.actions.update( {\n\t\t\t\t\tstyle: data,\n\t\t\t\t\torder: meta.order,\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\treturn data;\n\t\t},\n\n\t\tupdateProps: ( args ) => {\n\t\t\tdispatch(\n\t\t\t\tslice.actions.updateProps( {\n\t\t\t\t\tid: args.id,\n\t\t\t\t\tmeta: args.meta,\n\t\t\t\t\tprops: args.props,\n\t\t\t\t} )\n\t\t\t);\n\t\t},\n\t},\n\tsubscribe: ( cb ) => subscribeWithSelector( ( state: GlobalClassesState ) => state.globalClasses, cb ),\n\tlabels: {\n\t\tsingular: __( 'Global CSS Class', 'elementor' ),\n\t\tplural: __( 'Global CSS Classes', 'elementor' ),\n\t},\n} satisfies StylesProvider;\n","import { init } from './init';\n\ninit();\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,sCAAsC;AAC/C,SAAS,mBAAmB,qBAAqB;AACjD,SAAS,wBAAwB;AACjC,SAAS,mBAAmB,qBAAqB;;;ACJjD,YAAYA,YAAW;AACvB,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,cAAAC,aAAY,eAAe;AACpC,SAAS,MAAAC,WAAU;;;ACHnB,YAAYC,YAAW;AACvB;AAAA,EACC,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,iBAAiB,aAAa;AACvC,SAAS,OAAO,KAAK,eAAe,YAAkC,SAAAC,cAAa;AACnF,SAAS,UAAU;;;ACVnB,YAAY,WAAW;AACvB,SAAS,2BAA2B;AACpC,SAAS,MAAM,gBAAgB,OAAO,kBAAkB;;;ACFxD,SAAS,kBAA8B;AACvC;AAAA,EACC;AAAA,OAIM;AACP;AAAA,EACC,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,OAGX;;;ACbP,SAAS,mBAAmB;AAErB,IAAM,2BAA2B,YAAoC;AAAA,EAC3E,MAAM;AAAA,EACN,SAAS;AACV,CAAE;;;ADiBF,IAAM,eAAsB;AAAA,EAC3B,OAAO,CAAC;AAAA,EACR,OAAO,CAAC;AACT;AAKO,IAAM,aAAa;AAEnB,IAAM,QAAQ,YAAa;AAAA,EACjC,MAAM;AAAA,EACN;AAAA,EACA,UAAU;AAAA,IACT,KAAM,OAAO,EAAE,QAAQ,GAA4B;AAClD,YAAM,QAAQ,QAAQ;AACtB,YAAM,QAAQ,QAAQ;AAAA,IACvB;AAAA,IACA,IAAK,OAAO,EAAE,QAAQ,GAA0E;AAC/F,YAAM,MAAO,QAAQ,MAAM,EAAG,IAAI,QAAQ;AAC1C,YAAM,QAAQ,QAAQ;AAAA,IACvB;AAAA,IACA,OAAQ,OAAO,EAAE,QAAQ,GAA0E;AAClG,YAAM,MAAO,QAAQ,MAAM,EAAG,IAAI,QAAQ;AAC1C,YAAM,QAAQ,QAAQ;AAAA,IACvB;AAAA,IACA,YACC,OACA;AAAA,MACC;AAAA,IACD,GACC;AACD,YAAM,QAAQ,MAAM,MAAO,QAAQ,EAAG;AAEtC,UAAK,CAAE,OAAQ;AACd,cAAM,IAAI,yBAA0B,EAAE,SAAS,EAAE,SAAS,QAAQ,GAAG,EAAE,CAAE;AAAA,MAC1E;AAEA,YAAM,UAAU,iBAAkB,OAAO,QAAQ,IAAK;AAEtD,UAAK,SAAU;AACd,gBAAQ,QAAQ,WAAY,QAAQ,OAAO,QAAQ,KAAM;AAAA,MAC1D,OAAO;AACN,cAAM,SAAS,KAAM,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM,CAAE;AAAA,MACnE;AAAA,IACD;AAAA,EACD;AACD,CAAE;AAGF,IAAM,cAAc,CAAE,UAAuC,MAAO,UAAW,EAAE;AACjF,IAAM,cAAc,CAAE,UAAuC,MAAO,UAAW,EAAE;AAE1E,IAAM,6BAA6B;AAAA,EAAgB;AAAA,EAAa;AAAA,EAAa,CAAE,OAAO,UAC5F,MAAM,IAAK,CAAE,OAAQ,MAAO,EAAG,CAAE;AAClC;AAEO,IAAM,cAAc,CAAE,OAAmC,OAC/D,MAAO,UAAW,EAAE,MAAO,EAAG,KAAK;AAE7B,IAAM,0BAA0B,MAAM;AAC5C,QAAM,QAAQ,YAAa,0BAA2B;AAEtD,SAAO;AACR;;;ADhFO,IAAM,oBAAoB,MAAM;AACtC,QAAM,aAAa,wBAAwB;AAE3C,SACC,oCAAC,aACA,oCAAC,QAAK,MAAK,UACR,YAAY,IAAK,CAAE,EAAE,IAAI,MAAM,MAAO;AACvC,WACC,oCAAC,SAAM,KAAM,IAAK,WAAU,OAAM,YAAW,UAAS,KAAM,GAAI,MAAK,cACpE,oCAAC,kBAAe,IAAK,EAAE,cAAc,EAAE,KACtC,oCAAC,uBAAoB,OAAQ,OAAQ,IAAK,YAAa,SAAQ,WAAU,CAC1E,CACD;AAAA,EAEF,CAAE,CACH,CACD;AAEF;;;ADVO,IAAM,EAAE,OAAO,iBAAiB,eAAe,IAAI,YAAa;AAAA,EACtE,IAAI;AAAA,EACJ,WAAW;AACZ,CAAE;AAEF,SAAS,oBAAoB;AAC5B,SACC,qCAAC,iBAAc,UAAW,qCAAC,2BAAsB,KAChD,qCAAC,aACA,qCAAC,mBACA,qCAACC,QAAA,EAAM,GAAI,GAAI,OAAM,QAAO,WAAU,OAAM,YAAW,YACtD,qCAAC,oBAAiB,IAAK,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,IAAI,KACxE,qCAAC,mBAAgB,UAAS,WAAU,IAAK,EAAE,WAAW,gBAAgB,GAAI,GACxE,GAAI,mBAAoB,CAC3B,GACA,qCAAC,eAAY,IAAK,EAAE,YAAY,OAAO,GAAI,CAC5C,CACD,GACA,qCAAC,aAAU,IAAK,KACf,qCAAC,uBAAkB,CACpB,CACD,CACD;AAEF;AAEA,IAAM,cAAc,CAAE,UAA4B;AACjD,QAAM,EAAE,MAAM,IAAI,gBAAgB;AAElC,SACC,qCAAC,cAAW,MAAK,SAAQ,OAAM,aAAY,SAAU,OAAU,GAAG,SACjE,qCAAC,SAAM,UAAS,SAAQ,CACzB;AAEF;AAEA,IAAM,wBAAwB,MAC7B,qCAAC,OAAI,MAAK,SAAQ,IAAK,EAAE,WAAW,QAAQ,GAAG,EAAE,KAChD,qCAAC,SAAM,UAAS,SAAQ,IAAK,EAAE,IAAI,GAAG,UAAU,KAAK,WAAW,SAAS,KACxE,qCAAC,gBAAS,GAAI,wBAAwB,WAAY,CAAG,CACtD,CACD;;;ADhDM,IAAM,qBAAqB,MAAM;AACvC,QAAM,EAAE,KAAK,IAAI,gBAAgB;AAEjC,SACC,qCAAC,WAAQ,OAAQC,IAAI,eAAgB,GAAI,WAAU,SAClD,qCAACC,aAAA,EAAW,SAAU,QACrB,qCAACC,kBAAA,EAAgB,UAAS,QAAO,CAClC,CACD;AAEF;;;AKjBA,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB,mBAAmB;;;ACC7C,SAA4B,mBAAmB;AAE/C,IAAM,eAAe;AAMd,IAAM,YAAY;AAAA,EACxB,KAAK,YAAY;AAChB,WAAO,YAAY,EAAE,IAAoC,YAAa;AAAA,EACvE;AAAA,EACA,MAAM,OAAQ,SAA+B;AAC5C,WAAO,YAAY,EAAE,KAAmC,cAAc,IAAK;AAAA,EAC5E;AAAA,EACA,KAAK,OAAQ,IAAY,SAA+B;AACvD,WAAO,YAAY,EAAE,IAAiC,GAAI,YAAa,IAAK,EAAG,IAAI,IAAK;AAAA,EACzF;AACD;;;ADdO,SAAS,aAAa;AAC5B,QAAMC,YAAW,YAAY;AAE7B,YAAW,MAAM;AAChB,cAAU,IAAI,EAAE,KAAM,CAAE,QAAS;AAChC,YAAM,EAAE,MAAM,KAAK,IAAI,IAAI;AAE3B,MAAAA,UAAU,MAAM,QAAQ,KAAM,EAAE,OAAO,MAAM,OAAO,KAAK,MAAM,CAAE,CAAE;AAAA,IACpE,CAAE;AAAA,EACH,GAAG,CAAEA,SAAS,CAAE;AAEhB,SAAO;AACR;;;AEjBA;AAAA,EACC,cAAc;AAAA,EACd,cAAc;AAAA,EACd,2BAA2B;AAAA,OACrB;AACP,SAAS,MAAAC,WAAU;AAKZ,IAAM,8BAA8B;AAAA,EAC1C,KAAK;AAAA,EACL,UAAU;AAAA,EACV,SAAS;AAAA,IACR,KAAK,MAAM,2BAA4B,SAAS,CAAE;AAAA,IAClD,SAAS,CAAE,OAAQ,YAAa,SAAS,GAAG,EAAG;AAAA,IAC/C,QAAQ,OAAQ,UAAW;AAC1B,YAAM,MAAM,MAAM,UAAU,KAAM,KAAM;AAExC,YAAM,EAAE,MAAM,KAAK,IAAI,IAAI;AAE3B;AAAA,QACC,MAAM,QAAQ,IAAK;AAAA,UAClB,OAAO;AAAA,UACP,OAAO,KAAK;AAAA,QACb,CAAE;AAAA,MACH;AAEA,aAAO;AAAA,IACR;AAAA,IACA,QAAQ,OAAQ,YAAa;AAC5B,YAAM,QAAQ,YAAa,SAAS,GAAG,QAAQ,EAAG;AAClD,YAAM,aAAa,EAAE,GAAG,OAAO,GAAG,QAAQ;AAE1C,YAAM,MAAM,MAAM,UAAU,IAAK,QAAQ,IAAI,UAAW;AAExD,YAAM,EAAE,MAAM,KAAK,IAAI,IAAI;AAE3B;AAAA,QACC,MAAM,QAAQ,OAAQ;AAAA,UACrB,OAAO;AAAA,UACP,OAAO,KAAK;AAAA,QACb,CAAE;AAAA,MACH;AAEA,aAAO;AAAA,IACR;AAAA,IAEA,aAAa,CAAE,SAAU;AACxB;AAAA,QACC,MAAM,QAAQ,YAAa;AAAA,UAC1B,IAAI,KAAK;AAAA,UACT,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,QACb,CAAE;AAAA,MACH;AAAA,IACD;AAAA,EACD;AAAA,EACA,WAAW,CAAE,OAAQ,sBAAuB,CAAE,UAA+B,MAAM,eAAe,EAAG;AAAA,EACrG,QAAQ;AAAA,IACP,UAAUC,IAAI,oBAAoB,WAAY;AAAA,IAC9C,QAAQA,IAAI,sBAAsB,WAAY;AAAA,EAC/C;AACD;;;ARpDO,SAAS,OAAO;AACtB,gBAAe,KAAM;AACrB,gBAAe,KAAM;AAErB,mBAAiB,SAAU,2BAA4B;AAEvD,kBAAiB;AAAA,IAChB,IAAI;AAAA,IACJ,WAAW;AAAA,EACZ,CAAE;AAEF,iCAAgC;AAAA,IAC/B,IAAI;AAAA,IACJ,WAAW;AAAA,EACZ,CAAE;AACH;;;ASzBA,KAAK;","names":["React","ColorSwatchIcon","IconButton","__","React","Stack","Stack","__","IconButton","ColorSwatchIcon","dispatch","__","__"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-global-classes",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -39,10 +39,18 @@
39
39
  "dev": "tsup --config=../../tsup.dev.ts"
40
40
  },
41
41
  "dependencies": {
42
- "@elementor/editor": "0.17.3",
43
- "@elementor/editor-styles-repository": "0.4.1",
42
+ "@elementor/editor": "0.17.5",
43
+ "@elementor/editor-editing-panel": "1.10.0",
44
+ "@elementor/editor-panels": "0.10.5",
45
+ "@elementor/editor-props": "0.8.0",
46
+ "@elementor/editor-styles": "0.5.4",
47
+ "@elementor/editor-styles-repository": "0.6.0",
48
+ "@elementor/editor-ui": "0.1.0",
44
49
  "@elementor/http": "0.1.3",
45
- "@elementor/store": "0.8.6",
50
+ "@elementor/icons": "1.26.0",
51
+ "@elementor/store": "0.9.0",
52
+ "@elementor/ui": "1.24.1",
53
+ "@elementor/utils": "0.3.0",
46
54
  "@wordpress/i18n": "^5.13.0"
47
55
  },
48
56
  "peerDependencies": {
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+ import { ColorSwatchIcon } from '@elementor/icons';
3
+ import { IconButton, Tooltip } from '@elementor/ui';
4
+ import { __ } from '@wordpress/i18n';
5
+
6
+ import { usePanelActions } from './class-manager-panel';
7
+
8
+ export const ClassManagerButton = () => {
9
+ const { open } = usePanelActions();
10
+
11
+ return (
12
+ <Tooltip title={ __( 'Class manager' ) } placement="top">
13
+ <IconButton onClick={ open }>
14
+ <ColorSwatchIcon fontSize="tiny" />
15
+ </IconButton>
16
+ </Tooltip>
17
+ );
18
+ };
@@ -0,0 +1,57 @@
1
+ import * as React from 'react';
2
+ import {
3
+ __createPanel as createPanel,
4
+ Panel,
5
+ PanelBody,
6
+ PanelHeader,
7
+ PanelHeaderTitle,
8
+ } from '@elementor/editor-panels';
9
+ import { ColorSwatchIcon, XIcon } from '@elementor/icons';
10
+ import { Alert, Box, ErrorBoundary, IconButton, type IconButtonProps, Stack } from '@elementor/ui';
11
+ import { __ } from '@wordpress/i18n';
12
+
13
+ import { GlobalClassesList } from './global-classes-list';
14
+
15
+ export const { panel, usePanelActions, usePanelStatus } = createPanel( {
16
+ id: 'class-manager-panel',
17
+ component: ClassManagerPanel,
18
+ } );
19
+
20
+ function ClassManagerPanel() {
21
+ return (
22
+ <ErrorBoundary fallback={ <ErrorBoundaryFallback /> }>
23
+ <Panel>
24
+ <PanelHeader>
25
+ <Stack p={ 1 } width="100%" direction="row" alignItems="center">
26
+ <PanelHeaderTitle sx={ { display: 'flex', alignItems: 'center', gap: 0.5 } }>
27
+ <ColorSwatchIcon fontSize="inherit" sx={ { transform: 'rotate(90deg)' } } />
28
+ { __( 'CSS Class manager' ) }
29
+ </PanelHeaderTitle>
30
+ <CloseButton sx={ { marginLeft: 'auto' } } />
31
+ </Stack>
32
+ </PanelHeader>
33
+ <PanelBody px={ 2 }>
34
+ <GlobalClassesList />
35
+ </PanelBody>
36
+ </Panel>
37
+ </ErrorBoundary>
38
+ );
39
+ }
40
+
41
+ const CloseButton = ( props: IconButtonProps ) => {
42
+ const { close } = usePanelActions();
43
+
44
+ return (
45
+ <IconButton size="small" color="secondary" onClick={ close } { ...props }>
46
+ <XIcon fontSize="small" />
47
+ </IconButton>
48
+ );
49
+ };
50
+
51
+ const ErrorBoundaryFallback = () => (
52
+ <Box role="alert" sx={ { minHeight: '100%', p: 2 } }>
53
+ <Alert severity="error" sx={ { mb: 2, maxWidth: 400, textAlign: 'center' } }>
54
+ <strong>{ __( 'Something went wrong', 'elementor' ) }</strong>
55
+ </Alert>
56
+ </Box>
57
+ );
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+ import { EllipsisWithTooltip } from '@elementor/editor-ui';
3
+ import { List, ListItemButton, Stack, Typography } from '@elementor/ui';
4
+
5
+ import { useOrderedGlobalClasses } from '../../store';
6
+
7
+ export const GlobalClassesList = () => {
8
+ const cssClasses = useOrderedGlobalClasses();
9
+
10
+ return (
11
+ <Stack>
12
+ <List role="list">
13
+ { cssClasses?.map( ( { id, label } ) => {
14
+ return (
15
+ <Stack key={ id } direction="row" alignItems="center" gap={ 1 } role="listitem">
16
+ <ListItemButton sx={ { borderRadius: 1 } }>
17
+ <EllipsisWithTooltip title={ label } as={ Typography } variant="caption" />
18
+ </ListItemButton>
19
+ </Stack>
20
+ );
21
+ } ) }
22
+ </List>
23
+ </Stack>
24
+ );
25
+ };
package/src/errors.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { createError } from '@elementor/utils';
2
+
3
+ export const GlobalClassNotFoundError = createError< { styleId: string } >( {
4
+ code: 'global_class_not_found',
5
+ message: 'Global class not found.',
6
+ } );
@@ -1,15 +1,20 @@
1
1
  import type { StylesProvider } from '@elementor/editor-styles-repository';
2
- import { __dispatch as dispatch, __getState as getState, __subscribe as subscribe } from '@elementor/store';
2
+ import {
3
+ __dispatch as dispatch,
4
+ __getState as getState,
5
+ __subscribeWithSelector as subscribeWithSelector,
6
+ } from '@elementor/store';
3
7
  import { __ } from '@wordpress/i18n';
4
8
 
5
9
  import { apiClient } from './api';
6
- import { selectClass, selectOrderedGlobalClasses, slice } from './store';
10
+ import { type GlobalClassesState, selectClass, selectOrderedGlobalClasses, slice } from './store';
7
11
 
8
- export const globalClassesStylesProvider: StylesProvider = {
12
+ export const globalClassesStylesProvider = {
9
13
  key: 'global-classes',
10
14
  priority: 30,
11
15
  actions: {
12
16
  get: () => selectOrderedGlobalClasses( getState() ),
17
+ getById: ( id ) => selectClass( getState(), id ),
13
18
  create: async ( style ) => {
14
19
  const res = await apiClient.post( style );
15
20
 
@@ -41,10 +46,20 @@ export const globalClassesStylesProvider: StylesProvider = {
41
46
 
42
47
  return data;
43
48
  },
49
+
50
+ updateProps: ( args ) => {
51
+ dispatch(
52
+ slice.actions.updateProps( {
53
+ id: args.id,
54
+ meta: args.meta,
55
+ props: args.props,
56
+ } )
57
+ );
58
+ },
44
59
  },
45
- subscribe: ( cb ) => subscribe( cb ),
60
+ subscribe: ( cb ) => subscribeWithSelector( ( state: GlobalClassesState ) => state.globalClasses, cb ),
46
61
  labels: {
47
62
  singular: __( 'Global CSS Class', 'elementor' ),
48
63
  plural: __( 'Global CSS Classes', 'elementor' ),
49
64
  },
50
- };
65
+ } satisfies StylesProvider;
package/src/init.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  import { injectIntoLogic } from '@elementor/editor';
2
+ import { injectIntoClassSelectorActions } from '@elementor/editor-editing-panel';
3
+ import { __registerPanel as registerPanel } from '@elementor/editor-panels';
2
4
  import { stylesRepository } from '@elementor/editor-styles-repository';
3
5
  import { __registerSlice as registerSlice } from '@elementor/store';
4
6
 
7
+ import { ClassManagerButton } from './components/class-manager/class-manager-button';
8
+ import { panel } from './components/class-manager/class-manager-panel';
5
9
  import { LogicHooks } from './components/logic-hooks';
6
10
  import { globalClassesStylesProvider } from './global-classes-styles-provider';
7
11
  import { slice } from './store';
8
12
 
9
13
  export function init() {
10
14
  registerSlice( slice );
15
+ registerPanel( panel );
11
16
 
12
17
  stylesRepository.register( globalClassesStylesProvider );
13
18
 
@@ -15,4 +20,9 @@ export function init() {
15
20
  id: 'global-classes-hooks',
16
21
  component: LogicHooks,
17
22
  } );
23
+
24
+ injectIntoClassSelectorActions( {
25
+ id: 'global-classes',
26
+ component: ClassManagerButton,
27
+ } );
18
28
  }
package/src/store.ts CHANGED
@@ -1,11 +1,20 @@
1
- import { type StyleDefinition, type StyleDefinitionID } from '@elementor/editor-styles';
1
+ import { mergeProps, type Props } from '@elementor/editor-props';
2
+ import {
3
+ getVariantByMeta,
4
+ type StyleDefinition,
5
+ type StyleDefinitionID,
6
+ type StyleDefinitionVariant,
7
+ } from '@elementor/editor-styles';
2
8
  import {
3
9
  __createSelector as createSelector,
4
10
  __createSlice as createSlice,
11
+ __useSelector as useSelector,
5
12
  type PayloadAction,
6
13
  type SliceState,
7
14
  } from '@elementor/store';
8
15
 
16
+ import { GlobalClassNotFoundError } from './errors';
17
+
9
18
  export type State = {
10
19
  items: Record< StyleDefinitionID, StyleDefinition >;
11
20
  order: StyleDefinitionID[];
@@ -16,6 +25,8 @@ const initialState: State = {
16
25
  order: [],
17
26
  };
18
27
 
28
+ export type GlobalClassesState = SliceState< typeof slice >;
29
+
19
30
  // Slice
20
31
  export const SLICE_NAME = 'globalClasses';
21
32
 
@@ -35,6 +46,26 @@ export const slice = createSlice( {
35
46
  state.items[ payload.style.id ] = payload.style;
36
47
  state.order = payload.order;
37
48
  },
49
+ updateProps(
50
+ state,
51
+ {
52
+ payload,
53
+ }: PayloadAction< { id: StyleDefinitionID; meta: StyleDefinitionVariant[ 'meta' ]; props: Props } >
54
+ ) {
55
+ const style = state.items[ payload.id ];
56
+
57
+ if ( ! style ) {
58
+ throw new GlobalClassNotFoundError( { context: { styleId: payload.id } } );
59
+ }
60
+
61
+ const variant = getVariantByMeta( style, payload.meta );
62
+
63
+ if ( variant ) {
64
+ variant.props = mergeProps( variant.props, payload.props );
65
+ } else {
66
+ style.variants.push( { meta: payload.meta, props: payload.props } );
67
+ }
68
+ },
38
69
  },
39
70
  } );
40
71
 
@@ -47,4 +78,10 @@ export const selectOrderedGlobalClasses = createSelector( selectItems, selectOrd
47
78
  );
48
79
 
49
80
  export const selectClass = ( state: SliceState< typeof slice >, id: StyleDefinitionID ) =>
50
- state[ SLICE_NAME ].items[ id ];
81
+ state[ SLICE_NAME ].items[ id ] ?? null;
82
+
83
+ export const useOrderedGlobalClasses = () => {
84
+ const items = useSelector( selectOrderedGlobalClasses );
85
+
86
+ return items;
87
+ };