@elementor/editor-global-classes 0.3.0 → 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,38 @@
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
+
3
36
  ## 0.3.0
4
37
 
5
38
  ### Minor Changes
package/dist/index.js CHANGED
@@ -27,59 +27,39 @@ var import_editor = require("@elementor/editor");
27
27
  var import_editor_editing_panel = require("@elementor/editor-editing-panel");
28
28
  var import_editor_panels2 = require("@elementor/editor-panels");
29
29
  var import_editor_styles_repository = require("@elementor/editor-styles-repository");
30
- var import_store6 = require("@elementor/store");
30
+ var import_store7 = require("@elementor/store");
31
31
 
32
32
  // src/components/class-manager/class-manager-button.tsx
33
- var React2 = __toESM(require("react"));
33
+ var React3 = __toESM(require("react"));
34
34
  var import_icons2 = require("@elementor/icons");
35
- var import_ui2 = require("@elementor/ui");
35
+ var import_ui3 = require("@elementor/ui");
36
+ var import_i18n2 = require("@wordpress/i18n");
36
37
 
37
38
  // src/components/class-manager/class-manager-panel.tsx
38
- var React = __toESM(require("react"));
39
+ var React2 = __toESM(require("react"));
39
40
  var import_editor_panels = require("@elementor/editor-panels");
40
41
  var import_icons = require("@elementor/icons");
41
- var import_ui = require("@elementor/ui");
42
+ var import_ui2 = require("@elementor/ui");
42
43
  var import_i18n = require("@wordpress/i18n");
43
- var { panel, usePanelActions, usePanelStatus } = (0, import_editor_panels.__createPanel)({
44
- id: "class-manager-panel",
45
- component: ClassManagerPanel
46
- });
47
- function ClassManagerPanel() {
48
- return /* @__PURE__ */ React.createElement(import_ui.ErrorBoundary, { fallback: /* @__PURE__ */ React.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React.createElement(import_editor_panels.Panel, null, /* @__PURE__ */ React.createElement(import_editor_panels.PanelHeader, null, /* @__PURE__ */ React.createElement(import_ui.Stack, { p: 1, width: "100%", direction: "row", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React.createElement(import_editor_panels.PanelHeaderTitle, null, (0, import_i18n.__)("CSS Class manager")), /* @__PURE__ */ React.createElement(CloseButton, null))), /* @__PURE__ */ React.createElement(import_editor_panels.PanelBody, null)));
49
- }
50
- var CloseButton = () => {
51
- const { close } = usePanelActions();
52
- return /* @__PURE__ */ React.createElement(import_ui.IconButton, { size: "small", color: "secondary", onClick: close }, /* @__PURE__ */ React.createElement(import_icons.XIcon, { fontSize: "small" }));
53
- };
54
- var ErrorBoundaryFallback = () => /* @__PURE__ */ React.createElement(import_ui.Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React.createElement(import_ui.Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React.createElement("strong", null, (0, import_i18n.__)("Something went wrong", "elementor"))));
55
44
 
56
- // src/components/class-manager/class-manager-button.tsx
57
- var ClassManagerButton = () => {
58
- const { open } = usePanelActions();
59
- return /* @__PURE__ */ React2.createElement(import_ui2.IconButton, { onClick: open }, /* @__PURE__ */ React2.createElement(import_icons2.AppsIcon, { fontSize: "tiny" }));
60
- };
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");
61
49
 
62
- // src/components/logic-hooks.tsx
63
- var import_react = require("react");
64
- var import_store2 = require("@elementor/store");
50
+ // src/store.ts
51
+ var import_editor_props = require("@elementor/editor-props");
52
+ var import_editor_styles = require("@elementor/editor-styles");
53
+ var import_store = require("@elementor/store");
65
54
 
66
- // src/api.ts
67
- var import_http = require("@elementor/http");
68
- var RESOURCE_URL = "/global-classes";
69
- var apiClient = {
70
- all: async () => {
71
- return (0, import_http.httpService)().get(RESOURCE_URL);
72
- },
73
- post: async (data) => {
74
- return (0, import_http.httpService)().post(RESOURCE_URL, data);
75
- },
76
- put: async (id, data) => {
77
- return (0, import_http.httpService)().put(`${RESOURCE_URL}/${id}`, data);
78
- }
79
- };
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
+ });
80
61
 
81
62
  // src/store.ts
82
- var import_store = require("@elementor/store");
83
63
  var initialState = {
84
64
  items: {},
85
65
  order: []
@@ -100,6 +80,20 @@ var slice = (0, import_store.__createSlice)({
100
80
  update(state, { payload }) {
101
81
  state.items[payload.style.id] = payload.style;
102
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
+ }
103
97
  }
104
98
  }
105
99
  });
@@ -110,11 +104,62 @@ var selectOrderedGlobalClasses = (0, import_store.__createSelector)(
110
104
  selectOrder,
111
105
  (items, order) => order.map((id) => items[id])
112
106
  );
113
- 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
+ };
114
159
 
115
160
  // src/components/logic-hooks.tsx
116
161
  function LogicHooks() {
117
- const dispatch2 = (0, import_store2.__useDispatch)();
162
+ const dispatch2 = (0, import_store3.__useDispatch)();
118
163
  (0, import_react.useEffect)(() => {
119
164
  apiClient.all().then((res) => {
120
165
  const { data, meta } = res.data;
@@ -125,17 +170,18 @@ function LogicHooks() {
125
170
  }
126
171
 
127
172
  // src/global-classes-styles-provider.ts
128
- var import_store4 = require("@elementor/store");
129
- var import_i18n2 = require("@wordpress/i18n");
173
+ var import_store5 = require("@elementor/store");
174
+ var import_i18n3 = require("@wordpress/i18n");
130
175
  var globalClassesStylesProvider = {
131
176
  key: "global-classes",
132
177
  priority: 30,
133
178
  actions: {
134
- get: () => selectOrderedGlobalClasses((0, import_store4.__getState)()),
179
+ get: () => selectOrderedGlobalClasses((0, import_store5.__getState)()),
180
+ getById: (id) => selectClass((0, import_store5.__getState)(), id),
135
181
  create: async (style) => {
136
182
  const res = await apiClient.post(style);
137
183
  const { data, meta } = res.data;
138
- (0, import_store4.__dispatch)(
184
+ (0, import_store5.__dispatch)(
139
185
  slice.actions.add({
140
186
  style: data,
141
187
  order: meta.order
@@ -144,29 +190,38 @@ var globalClassesStylesProvider = {
144
190
  return data;
145
191
  },
146
192
  update: async (payload) => {
147
- const style = selectClass((0, import_store4.__getState)(), payload.id);
193
+ const style = selectClass((0, import_store5.__getState)(), payload.id);
148
194
  const mergedData = { ...style, ...payload };
149
195
  const res = await apiClient.put(payload.id, mergedData);
150
196
  const { data, meta } = res.data;
151
- (0, import_store4.__dispatch)(
197
+ (0, import_store5.__dispatch)(
152
198
  slice.actions.update({
153
199
  style: data,
154
200
  order: meta.order
155
201
  })
156
202
  );
157
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
+ );
158
213
  }
159
214
  },
160
- subscribe: (cb) => (0, import_store4.__subscribe)(cb),
215
+ subscribe: (cb) => (0, import_store5.__subscribeWithSelector)((state) => state.globalClasses, cb),
161
216
  labels: {
162
- singular: (0, import_i18n2.__)("Global CSS Class", "elementor"),
163
- plural: (0, import_i18n2.__)("Global CSS Classes", "elementor")
217
+ singular: (0, import_i18n3.__)("Global CSS Class", "elementor"),
218
+ plural: (0, import_i18n3.__)("Global CSS Classes", "elementor")
164
219
  }
165
220
  };
166
221
 
167
222
  // src/init.ts
168
223
  function init() {
169
- (0, import_store6.__registerSlice)(slice);
224
+ (0, import_store7.__registerSlice)(slice);
170
225
  (0, import_editor_panels2.__registerPanel)(panel);
171
226
  import_editor_styles_repository.stylesRepository.register(globalClassesStylesProvider);
172
227
  (0, import_editor.injectIntoLogic)({
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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/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 { 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 { AppsIcon } from '@elementor/icons';\nimport { IconButton } from '@elementor/ui';\n\nimport { usePanelActions } from './class-manager-panel';\n\nexport const ClassManagerButton = () => {\n\tconst { open } = usePanelActions();\n\n\treturn (\n\t\t<IconButton onClick={ open }>\n\t\t\t<AppsIcon fontSize=\"tiny\" />\n\t\t</IconButton>\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 { XIcon } from '@elementor/icons';\nimport { Alert, Box, ErrorBoundary, IconButton, Stack } from '@elementor/ui';\nimport { __ } from '@wordpress/i18n';\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\" justifyContent=\"space-between\" alignItems=\"center\">\n\t\t\t\t\t\t<PanelHeaderTitle>{ __( 'CSS Class manager' ) }</PanelHeaderTitle>\n\t\t\t\t\t\t<CloseButton />\n\t\t\t\t\t</Stack>\n\t\t\t\t</PanelHeader>\n\t\t\t\t<PanelBody></PanelBody>\n\t\t\t</Panel>\n\t\t</ErrorBoundary>\n\t);\n}\n\nconst CloseButton = () => {\n\tconst { close } = usePanelActions();\n\n\treturn (\n\t\t<IconButton size=\"small\" color=\"secondary\" onClick={ close }>\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 { 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_editor_panels","import_store","React","import_icons","import_ui","createPanel","import_store","createSlice","createSelector","dispatch","useDispatch","import_store","import_i18n","getState","dispatch","subscribe","registerSlice","registerPanel"]}
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
@@ -6,12 +6,13 @@ import { stylesRepository } from "@elementor/editor-styles-repository";
6
6
  import { __registerSlice as registerSlice } from "@elementor/store";
7
7
 
8
8
  // src/components/class-manager/class-manager-button.tsx
9
- import * as React2 from "react";
10
- import { AppsIcon } from "@elementor/icons";
11
- import { IconButton as IconButton2 } from "@elementor/ui";
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";
12
13
 
13
14
  // src/components/class-manager/class-manager-panel.tsx
14
- import * as React from "react";
15
+ import * as React2 from "react";
15
16
  import {
16
17
  __createPanel as createPanel,
17
18
  Panel,
@@ -19,52 +20,34 @@ import {
19
20
  PanelHeader,
20
21
  PanelHeaderTitle
21
22
  } from "@elementor/editor-panels";
22
- import { XIcon } from "@elementor/icons";
23
- import { Alert, Box, ErrorBoundary, IconButton, Stack } from "@elementor/ui";
23
+ import { ColorSwatchIcon, XIcon } from "@elementor/icons";
24
+ import { Alert, Box, ErrorBoundary, IconButton, Stack as Stack2 } from "@elementor/ui";
24
25
  import { __ } from "@wordpress/i18n";
25
- var { panel, usePanelActions, usePanelStatus } = createPanel({
26
- id: "class-manager-panel",
27
- component: ClassManagerPanel
28
- });
29
- function ClassManagerPanel() {
30
- return /* @__PURE__ */ React.createElement(ErrorBoundary, { fallback: /* @__PURE__ */ React.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React.createElement(Panel, null, /* @__PURE__ */ React.createElement(PanelHeader, null, /* @__PURE__ */ React.createElement(Stack, { p: 1, width: "100%", direction: "row", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React.createElement(PanelHeaderTitle, null, __("CSS Class manager")), /* @__PURE__ */ React.createElement(CloseButton, null))), /* @__PURE__ */ React.createElement(PanelBody, null)));
31
- }
32
- var CloseButton = () => {
33
- const { close } = usePanelActions();
34
- return /* @__PURE__ */ React.createElement(IconButton, { size: "small", color: "secondary", onClick: close }, /* @__PURE__ */ React.createElement(XIcon, { fontSize: "small" }));
35
- };
36
- var ErrorBoundaryFallback = () => /* @__PURE__ */ React.createElement(Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React.createElement(Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React.createElement("strong", null, __("Something went wrong", "elementor"))));
37
-
38
- // src/components/class-manager/class-manager-button.tsx
39
- var ClassManagerButton = () => {
40
- const { open } = usePanelActions();
41
- return /* @__PURE__ */ React2.createElement(IconButton2, { onClick: open }, /* @__PURE__ */ React2.createElement(AppsIcon, { fontSize: "tiny" }));
42
- };
43
26
 
44
- // src/components/logic-hooks.tsx
45
- import { useEffect } from "react";
46
- import { __useDispatch as useDispatch } from "@elementor/store";
47
-
48
- // src/api.ts
49
- import { httpService } from "@elementor/http";
50
- var RESOURCE_URL = "/global-classes";
51
- var apiClient = {
52
- all: async () => {
53
- return httpService().get(RESOURCE_URL);
54
- },
55
- post: async (data) => {
56
- return httpService().post(RESOURCE_URL, data);
57
- },
58
- put: async (id, data) => {
59
- return httpService().put(`${RESOURCE_URL}/${id}`, data);
60
- }
61
- };
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";
62
31
 
63
32
  // src/store.ts
33
+ import { mergeProps } from "@elementor/editor-props";
34
+ import {
35
+ getVariantByMeta
36
+ } from "@elementor/editor-styles";
64
37
  import {
65
38
  __createSelector as createSelector,
66
- __createSlice as createSlice
39
+ __createSlice as createSlice,
40
+ __useSelector as useSelector
67
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
68
51
  var initialState = {
69
52
  items: {},
70
53
  order: []
@@ -85,6 +68,20 @@ var slice = createSlice({
85
68
  update(state, { payload }) {
86
69
  state.items[payload.style.id] = payload.style;
87
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
+ }
88
85
  }
89
86
  }
90
87
  });
@@ -95,7 +92,58 @@ var selectOrderedGlobalClasses = createSelector(
95
92
  selectOrder,
96
93
  (items, order) => order.map((id) => items[id])
97
94
  );
98
- 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
+ };
99
147
 
100
148
  // src/components/logic-hooks.tsx
101
149
  function LogicHooks() {
@@ -110,13 +158,18 @@ function LogicHooks() {
110
158
  }
111
159
 
112
160
  // src/global-classes-styles-provider.ts
113
- import { __dispatch as dispatch, __getState as getState, __subscribe as subscribe } from "@elementor/store";
114
- import { __ as __2 } 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";
115
167
  var globalClassesStylesProvider = {
116
168
  key: "global-classes",
117
169
  priority: 30,
118
170
  actions: {
119
171
  get: () => selectOrderedGlobalClasses(getState()),
172
+ getById: (id) => selectClass(getState(), id),
120
173
  create: async (style) => {
121
174
  const res = await apiClient.post(style);
122
175
  const { data, meta } = res.data;
@@ -140,12 +193,21 @@ var globalClassesStylesProvider = {
140
193
  })
141
194
  );
142
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
+ );
143
205
  }
144
206
  },
145
- subscribe: (cb) => subscribe(cb),
207
+ subscribe: (cb) => subscribeWithSelector((state) => state.globalClasses, cb),
146
208
  labels: {
147
- singular: __2("Global CSS Class", "elementor"),
148
- plural: __2("Global CSS Classes", "elementor")
209
+ singular: __3("Global CSS Class", "elementor"),
210
+ plural: __3("Global CSS Classes", "elementor")
149
211
  }
150
212
  };
151
213
 
@@ -1 +1 @@
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/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 { 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 { AppsIcon } from '@elementor/icons';\nimport { IconButton } from '@elementor/ui';\n\nimport { usePanelActions } from './class-manager-panel';\n\nexport const ClassManagerButton = () => {\n\tconst { open } = usePanelActions();\n\n\treturn (\n\t\t<IconButton onClick={ open }>\n\t\t\t<AppsIcon fontSize=\"tiny\" />\n\t\t</IconButton>\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 { XIcon } from '@elementor/icons';\nimport { Alert, Box, ErrorBoundary, IconButton, Stack } from '@elementor/ui';\nimport { __ } from '@wordpress/i18n';\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\" justifyContent=\"space-between\" alignItems=\"center\">\n\t\t\t\t\t\t<PanelHeaderTitle>{ __( 'CSS Class manager' ) }</PanelHeaderTitle>\n\t\t\t\t\t\t<CloseButton />\n\t\t\t\t\t</Stack>\n\t\t\t\t</PanelHeader>\n\t\t\t\t<PanelBody></PanelBody>\n\t\t\t</Panel>\n\t\t</ErrorBoundary>\n\t);\n}\n\nconst CloseButton = () => {\n\tconst { close } = usePanelActions();\n\n\treturn (\n\t\t<IconButton size=\"small\" color=\"secondary\" onClick={ close }>\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 { 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":["React","IconButton","IconButton","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":"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","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.3.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -39,14 +39,18 @@
39
39
  "dev": "tsup --config=../../tsup.dev.ts"
40
40
  },
41
41
  "dependencies": {
42
- "@elementor/editor": "0.17.4",
43
- "@elementor/editor-editing-panel": "1.9.0",
44
- "@elementor/editor-panels": "0.10.4",
45
- "@elementor/editor-styles-repository": "0.5.0",
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",
46
49
  "@elementor/http": "0.1.3",
47
- "@elementor/icons": "1.24.0",
48
- "@elementor/store": "0.8.6",
49
- "@elementor/ui": "1.23.3",
50
+ "@elementor/icons": "1.26.0",
51
+ "@elementor/store": "0.9.0",
52
+ "@elementor/ui": "1.24.1",
53
+ "@elementor/utils": "0.3.0",
50
54
  "@wordpress/i18n": "^5.13.0"
51
55
  },
52
56
  "peerDependencies": {
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
- import { AppsIcon } from '@elementor/icons';
3
- import { IconButton } from '@elementor/ui';
2
+ import { ColorSwatchIcon } from '@elementor/icons';
3
+ import { IconButton, Tooltip } from '@elementor/ui';
4
+ import { __ } from '@wordpress/i18n';
4
5
 
5
6
  import { usePanelActions } from './class-manager-panel';
6
7
 
@@ -8,8 +9,10 @@ export const ClassManagerButton = () => {
8
9
  const { open } = usePanelActions();
9
10
 
10
11
  return (
11
- <IconButton onClick={ open }>
12
- <AppsIcon fontSize="tiny" />
13
- </IconButton>
12
+ <Tooltip title={ __( 'Class manager' ) } placement="top">
13
+ <IconButton onClick={ open }>
14
+ <ColorSwatchIcon fontSize="tiny" />
15
+ </IconButton>
16
+ </Tooltip>
14
17
  );
15
18
  };
@@ -6,10 +6,12 @@ import {
6
6
  PanelHeader,
7
7
  PanelHeaderTitle,
8
8
  } from '@elementor/editor-panels';
9
- import { XIcon } from '@elementor/icons';
10
- import { Alert, Box, ErrorBoundary, IconButton, Stack } from '@elementor/ui';
9
+ import { ColorSwatchIcon, XIcon } from '@elementor/icons';
10
+ import { Alert, Box, ErrorBoundary, IconButton, type IconButtonProps, Stack } from '@elementor/ui';
11
11
  import { __ } from '@wordpress/i18n';
12
12
 
13
+ import { GlobalClassesList } from './global-classes-list';
14
+
13
15
  export const { panel, usePanelActions, usePanelStatus } = createPanel( {
14
16
  id: 'class-manager-panel',
15
17
  component: ClassManagerPanel,
@@ -20,22 +22,27 @@ function ClassManagerPanel() {
20
22
  <ErrorBoundary fallback={ <ErrorBoundaryFallback /> }>
21
23
  <Panel>
22
24
  <PanelHeader>
23
- <Stack p={ 1 } width="100%" direction="row" justifyContent="space-between" alignItems="center">
24
- <PanelHeaderTitle>{ __( 'CSS Class manager' ) }</PanelHeaderTitle>
25
- <CloseButton />
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' } } />
26
31
  </Stack>
27
32
  </PanelHeader>
28
- <PanelBody></PanelBody>
33
+ <PanelBody px={ 2 }>
34
+ <GlobalClassesList />
35
+ </PanelBody>
29
36
  </Panel>
30
37
  </ErrorBoundary>
31
38
  );
32
39
  }
33
40
 
34
- const CloseButton = () => {
41
+ const CloseButton = ( props: IconButtonProps ) => {
35
42
  const { close } = usePanelActions();
36
43
 
37
44
  return (
38
- <IconButton size="small" color="secondary" onClick={ close }>
45
+ <IconButton size="small" color="secondary" onClick={ close } { ...props }>
39
46
  <XIcon fontSize="small" />
40
47
  </IconButton>
41
48
  );
@@ -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/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
+ };