@elementor/editor-responsive 0.10.5 → 0.10.6
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 +14 -221
- package/dist/index.js +36 -47
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +36 -47
- package/dist/index.mjs.map +1 -1
- package/package.json +44 -44
- package/src/components/__tests__/breakpoints-switcher.test.tsx +11 -7
- package/src/components/breakpoints-switcher.tsx +38 -37
- package/src/hooks/__tests__/use-breakpoints-actions.test.tsx +1 -4
- package/src/hooks/__tests__/use-breakpoints.test.tsx +32 -23
- package/src/store/index.ts +21 -15
- package/src/store/selectors.ts +14 -25
- package/src/sync/__tests__/sync-store.test.ts +20 -16
- package/src/sync/sync-store.ts +11 -16
- package/src/types.ts +30 -27
package/dist/index.mjs
CHANGED
|
@@ -20,12 +20,15 @@ var slice = __createSlice({
|
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
function normalizeEntities(entities) {
|
|
23
|
-
return entities.reduce(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
return entities.reduce(
|
|
24
|
+
(acc, breakpoint) => {
|
|
25
|
+
return {
|
|
26
|
+
...acc,
|
|
27
|
+
[breakpoint.id]: breakpoint
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
{}
|
|
31
|
+
);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
// src/sync/sync-store.ts
|
|
@@ -38,25 +41,21 @@ function syncStore() {
|
|
|
38
41
|
}
|
|
39
42
|
function syncInitialization() {
|
|
40
43
|
const { init: init2 } = slice.actions;
|
|
41
|
-
listenTo(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
__dispatch(init2({
|
|
44
|
+
listenTo(v1ReadyEvent(), () => {
|
|
45
|
+
__dispatch(
|
|
46
|
+
init2({
|
|
45
47
|
entities: getBreakpoints(),
|
|
46
48
|
activeId: getActiveBreakpoint()
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
);
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
});
|
|
50
52
|
}
|
|
51
53
|
function syncOnChange() {
|
|
52
54
|
const { activateBreakpoint } = slice.actions;
|
|
53
|
-
listenTo(
|
|
54
|
-
|
|
55
|
-
()
|
|
56
|
-
|
|
57
|
-
__dispatch(activateBreakpoint(activeBreakpoint));
|
|
58
|
-
}
|
|
59
|
-
);
|
|
55
|
+
listenTo(deviceModeChangeEvent(), () => {
|
|
56
|
+
const activeBreakpoint = getActiveBreakpoint();
|
|
57
|
+
__dispatch(activateBreakpoint(activeBreakpoint));
|
|
58
|
+
});
|
|
60
59
|
}
|
|
61
60
|
function getBreakpoints() {
|
|
62
61
|
const { breakpoints } = window.elementor?.config?.responsive || {};
|
|
@@ -104,23 +103,16 @@ var selectActiveBreakpoint = __createSelector(
|
|
|
104
103
|
selectActiveId,
|
|
105
104
|
(entities, activeId) => activeId && entities[activeId] ? entities[activeId] : null
|
|
106
105
|
);
|
|
107
|
-
var selectSortedBreakpoints = __createSelector(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return [
|
|
118
|
-
...minWidth.sort(byWidth),
|
|
119
|
-
...defaults,
|
|
120
|
-
...maxWidth.sort(byWidth)
|
|
121
|
-
];
|
|
122
|
-
}
|
|
123
|
-
);
|
|
106
|
+
var selectSortedBreakpoints = __createSelector(selectEntities, (entities) => {
|
|
107
|
+
const byWidth = (a, b) => {
|
|
108
|
+
return a.width && b.width ? b.width - a.width : 0;
|
|
109
|
+
};
|
|
110
|
+
const all = Object.values(entities);
|
|
111
|
+
const defaults = all.filter((breakpoint) => !breakpoint.width);
|
|
112
|
+
const minWidth = all.filter((breakpoint) => breakpoint.type === "min-width");
|
|
113
|
+
const maxWidth = all.filter((breakpoint) => breakpoint.type === "max-width");
|
|
114
|
+
return [...minWidth.sort(byWidth), ...defaults, ...maxWidth.sort(byWidth)];
|
|
115
|
+
});
|
|
124
116
|
|
|
125
117
|
// src/hooks/use-breakpoints.ts
|
|
126
118
|
function useBreakpoints() {
|
|
@@ -167,16 +159,13 @@ function BreakpointsSwitcher() {
|
|
|
167
159
|
const extendedWindow = window;
|
|
168
160
|
const config = extendedWindow?.elementor?.editorEvents?.config;
|
|
169
161
|
if (config) {
|
|
170
|
-
extendedWindow.elementor.editorEvents.dispatchEvent(
|
|
171
|
-
config.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
mode: value
|
|
178
|
-
}
|
|
179
|
-
);
|
|
162
|
+
extendedWindow.elementor.editorEvents.dispatchEvent(config.names.topBar.responsiveControls, {
|
|
163
|
+
location: config.locations.topBar,
|
|
164
|
+
secondaryLocation: config.secondaryLocations.responsiveControls,
|
|
165
|
+
trigger: config.triggers.click,
|
|
166
|
+
element: config.elements.buttonIcon,
|
|
167
|
+
mode: value
|
|
168
|
+
});
|
|
180
169
|
}
|
|
181
170
|
activate(value);
|
|
182
171
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store/index.ts","../src/sync/sync-store.ts","../src/init.ts","../src/components/breakpoints-switcher.tsx","../src/hooks/use-breakpoints.ts","../src/store/selectors.ts","../src/hooks/use-breakpoints-actions.ts","../src/index.ts"],"sourcesContent":["import { __createSlice, PayloadAction } from '@elementor/store';\nimport { Breakpoint, BreakpointId } from '../types';\n\nexport type State = {\n\tentities: Record<BreakpointId, Breakpoint>,\n\tactiveId: BreakpointId | null,\n}\nconst initialState: State = {\n\tentities: {} as State['entities'],\n\tactiveId: null,\n};\n\nexport const slice = __createSlice( {\n\tname: 'breakpoints',\n\tinitialState,\n\treducers: {\n\t\tinit( state, action: PayloadAction<{\n\t\t\tentities: Breakpoint[],\n\t\t\tactiveId: State['activeId'],\n\t\t}> ) {\n\t\t\tstate.activeId = action.payload.activeId;\n\t\t\tstate.entities = normalizeEntities( action.payload.entities );\n\t\t},\n\n\t\tactivateBreakpoint( state, action: PayloadAction<BreakpointId> ) {\n\t\t\tif ( state.entities[ action.payload ] ) {\n\t\t\t\tstate.activeId = action.payload;\n\t\t\t}\n\t\t},\n\t},\n} );\n\nfunction normalizeEntities( entities: Breakpoint[] ) {\n\treturn entities.reduce( ( acc, breakpoint ) => {\n\t\treturn {\n\t\t\t...acc,\n\t\t\t[ breakpoint.id ]: breakpoint,\n\t\t};\n\t}, {} as State['entities'] );\n}\n","import { slice } from '../store';\nimport { __dispatch } from '@elementor/store';\nimport { Breakpoint, ExtendedWindow } from '../types';\nimport { __privateListenTo as listenTo, v1ReadyEvent, windowEvent } from '@elementor/editor-v1-adapters';\nimport { __ } from '@wordpress/i18n';\n\nexport default function syncStore() {\n\tsyncInitialization();\n\tsyncOnChange();\n}\n\nfunction syncInitialization() {\n\tconst { init } = slice.actions;\n\n\tlistenTo(\n\t\tv1ReadyEvent(),\n\t\t() => {\n\t\t\t__dispatch( init( {\n\t\t\t\tentities: getBreakpoints(),\n\t\t\t\tactiveId: getActiveBreakpoint(),\n\t\t\t} ) );\n\t\t}\n\t);\n}\n\nfunction syncOnChange() {\n\tconst { activateBreakpoint } = slice.actions;\n\n\tlistenTo(\n\t\tdeviceModeChangeEvent(),\n\t\t() => {\n\t\t\tconst activeBreakpoint = getActiveBreakpoint();\n\n\t\t\t__dispatch( activateBreakpoint( activeBreakpoint ) );\n\t\t},\n\t);\n}\n\nfunction getBreakpoints() {\n\tconst { breakpoints } = ( window as unknown as ExtendedWindow ).elementor?.config?.responsive || {};\n\n\tif ( ! breakpoints ) {\n\t\treturn [];\n\t}\n\n\tconst entities = Object\n\t\t.entries( breakpoints )\n\t\t.filter( ( [ , breakpoint ] ) => breakpoint.is_enabled )\n\t\t.map( ( [ id, { value, direction, label } ] ) => {\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tlabel,\n\t\t\t\twidth: value,\n\t\t\t\ttype: direction === 'min' ? 'min-width' : 'max-width',\n\t\t\t} as Breakpoint;\n\t\t} );\n\n\t// Desktop breakpoint is not included in V1 config.\n\tentities.push( {\n\t\tid: 'desktop',\n\t\tlabel: __( 'Desktop', 'elementor' ),\n\t} );\n\n\treturn entities;\n}\n\nfunction getActiveBreakpoint() {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn extendedWindow.elementor?.channels?.deviceMode?.request?.( 'currentMode' ) || null;\n}\n\nfunction deviceModeChangeEvent() {\n\treturn windowEvent( 'elementor/device-mode/change' );\n}\n","import { slice } from './store';\nimport syncStore from './sync/sync-store';\nimport { injectIntoResponsive } from '@elementor/editor-app-bar';\nimport BreakpointsSwitcher from './components/breakpoints-switcher';\nimport { __registerSlice } from '@elementor/store';\n\nexport default function init() {\n\tinitStore();\n\n\tregisterAppBarUI();\n}\n\nfunction initStore() {\n\t__registerSlice( slice );\n\n\tsyncStore();\n}\n\nfunction registerAppBarUI() {\n\tinjectIntoResponsive( {\n\t\tid: 'responsive-breakpoints-switcher',\n\t\tcomponent: BreakpointsSwitcher,\n\t\toptions: {\n\t\t\tpriority: 20, // After document indication.\n\t\t},\n\t} );\n}\n","import * as React from 'react';\nimport { __ } from '@wordpress/i18n';\nimport { BreakpointId, ExtendedWindow } from '../types';\nimport useBreakpoints from '../hooks/use-breakpoints';\nimport { Tab, Tabs, Tooltip as BaseTooltip, TooltipProps } from '@elementor/ui';\nimport {\n\tDesktopIcon,\n\tTabletPortraitIcon,\n\tMobilePortraitIcon,\n\tWidescreenIcon,\n\tLaptopIcon,\n\tTabletLandscapeIcon,\n\tMobileLandscapeIcon,\n} from '@elementor/icons';\nimport useBreakpointsActions from '../hooks/use-breakpoints-actions';\n\nexport default function BreakpointsSwitcher() {\n\tconst { all, active } = useBreakpoints();\n\tconst { activate } = useBreakpointsActions();\n\n\tif ( ! all.length || ! active ) {\n\t\treturn null;\n\t}\n\n\tconst onChange = ( _: unknown, value: BreakpointId ) => {\n\t\tconst extendedWindow = window as unknown as ExtendedWindow;\n\t\tconst config = extendedWindow?.elementor?.editorEvents?.config;\n\n\t\tif ( config ) {\n\t\t\textendedWindow.elementor.editorEvents.dispatchEvent(\n\t\t\t\tconfig.names.topBar.responsiveControls,\n\t\t\t\t{\n\t\t\t\t\tlocation: config.locations.topBar,\n\t\t\t\t\tsecondaryLocation: config.secondaryLocations.responsiveControls,\n\t\t\t\t\ttrigger: config.triggers.click,\n\t\t\t\t\telement: config.elements.buttonIcon,\n\t\t\t\t\tmode: value,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\tactivate( value );\n\t};\n\n\treturn (\n\t\t<Tabs\n\t\t\ttextColor=\"inherit\"\n\t\t\tindicatorColor=\"secondary\"\n\t\t\tvalue={ active.id }\n\t\t\tonChange={ onChange }\n\t\t\taria-label={ __( 'Switch Device', 'elementor' ) }\n\t\t\tsx={ {\n\t\t\t\t'& .MuiTabs-indicator': {\n\t\t\t\t\tbackgroundColor: 'text.primary',\n\t\t\t\t},\n\t\t\t} }\n\t\t>\n\t\t\t{\n\t\t\t\tall.map( ( { id, label, type, width } ) => {\n\t\t\t\t\tconst Icon = iconsMap[ id ];\n\n\t\t\t\t\tconst title = labelsMap[ type || 'default' ]\n\t\t\t\t\t\t.replace( '%s', label )\n\t\t\t\t\t\t.replace( '%d', width?.toString() || '' );\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Tab value={ id }\n\t\t\t\t\t\t\tkey={ id }\n\t\t\t\t\t\t\taria-label={ title }\n\t\t\t\t\t\t\ticon={ <Tooltip title={ title }><Icon /></Tooltip> }\n\t\t\t\t\t\t\tsx={ { minWidth: 'auto' } }\n\t\t\t\t\t\t\tdata-testid={ `switch-device-to-${ id }` }\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t} )\n\t\t\t}\n\t\t</Tabs>\n\n\t);\n}\n\nfunction Tooltip( props: TooltipProps ) {\n\treturn <BaseTooltip\n\t\tPopperProps={ {\n\t\t\tsx: {\n\t\t\t\t'&.MuiTooltip-popper .MuiTooltip-tooltip.MuiTooltip-tooltipPlacementBottom': {\n\t\t\t\t\tmt: 2.5,\n\t\t\t\t},\n\t\t\t},\n\t\t} }\n\t\t{ ...props }\n\t/>;\n}\n\nconst iconsMap = {\n\twidescreen: WidescreenIcon,\n\tdesktop: DesktopIcon,\n\tlaptop: LaptopIcon,\n\ttablet_extra: TabletLandscapeIcon,\n\ttablet: TabletPortraitIcon,\n\tmobile_extra: MobileLandscapeIcon,\n\tmobile: MobilePortraitIcon,\n};\n\nconst labelsMap = {\n\tdefault: '%s',\n\t// translators: %s: Breakpoint label, %d: Breakpoint size.\n\t'min-width': __( '%s (%dpx and up)', 'elementor' ),\n\n\t// translators: %s: Breakpoint label, %d: Breakpoint size.\n\t'max-width': __( '%s (up to %dpx)', 'elementor' ),\n} as const;\n","import { __useSelector as useSelector } from '@elementor/store';\nimport { selectActiveBreakpoint, selectSortedBreakpoints } from '../store/selectors';\n\nexport default function useBreakpoints() {\n\tconst all = useSelector( selectSortedBreakpoints );\n\tconst active = useSelector( selectActiveBreakpoint );\n\n\treturn {\n\t\tall,\n\t\tactive,\n\t};\n}\n","import { slice } from './index';\nimport { Breakpoint } from '../types';\nimport { __createSelector, SliceState } from '@elementor/store';\n\ntype State = SliceState<typeof slice>;\n\nexport const selectEntities = ( state: State ) => state.breakpoints.entities;\nexport const selectActiveId = ( state: State ) => state.breakpoints.activeId;\n\nexport const selectActiveBreakpoint = __createSelector(\n\tselectEntities,\n\tselectActiveId,\n\t( entities, activeId ) => activeId && entities[ activeId ]\n\t\t? entities[ activeId ]\n\t\t: null,\n);\n\nexport const selectSortedBreakpoints = __createSelector(\n\tselectEntities,\n\t( entities ) => {\n\t\tconst byWidth = ( a: Breakpoint, b: Breakpoint ) => {\n\t\t\treturn ( a.width && b.width ) ? b.width - a.width : 0;\n\t\t};\n\n\t\tconst all = Object.values( entities );\n\n\t\tconst defaults = all.filter( ( breakpoint ) => ! breakpoint.width ); // AKA Desktop.\n\t\tconst minWidth = all.filter( ( breakpoint ) => breakpoint.type === 'min-width' );\n\t\tconst maxWidth = all.filter( ( breakpoint ) => breakpoint.type === 'max-width' );\n\n\t\t// Sort by size, big to small.\n\t\treturn [\n\t\t\t...minWidth.sort( byWidth ),\n\t\t\t...defaults,\n\t\t\t...maxWidth.sort( byWidth ),\n\t\t];\n\t},\n);\n","import { useCallback } from 'react';\nimport { BreakpointId } from '../types';\nimport { __privateRunCommand as runCommand } from '@elementor/editor-v1-adapters';\n\nexport default function useBreakpointsActions() {\n\tconst activate = useCallback( ( device: BreakpointId ) => {\n\t\treturn runCommand( 'panel/change-device-mode', { device } );\n\t}, [] );\n\n\treturn {\n\t\tactivate,\n\t};\n}\n","import init from './init';\n\ninit();\n"],"mappings":"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","names":["init","__","__"]}
|
|
1
|
+
{"version":3,"sources":["../src/store/index.ts","../src/sync/sync-store.ts","../src/init.ts","../src/components/breakpoints-switcher.tsx","../src/hooks/use-breakpoints.ts","../src/store/selectors.ts","../src/hooks/use-breakpoints-actions.ts","../src/index.ts"],"sourcesContent":["import { __createSlice, PayloadAction } from '@elementor/store';\nimport { Breakpoint, BreakpointId } from '../types';\n\nexport type State = {\n\tentities: Record< BreakpointId, Breakpoint >;\n\tactiveId: BreakpointId | null;\n};\nconst initialState: State = {\n\tentities: {} as State[ 'entities' ],\n\tactiveId: null,\n};\n\nexport const slice = __createSlice( {\n\tname: 'breakpoints',\n\tinitialState,\n\treducers: {\n\t\tinit(\n\t\t\tstate,\n\t\t\taction: PayloadAction< {\n\t\t\t\tentities: Breakpoint[];\n\t\t\t\tactiveId: State[ 'activeId' ];\n\t\t\t} >\n\t\t) {\n\t\t\tstate.activeId = action.payload.activeId;\n\t\t\tstate.entities = normalizeEntities( action.payload.entities );\n\t\t},\n\n\t\tactivateBreakpoint( state, action: PayloadAction< BreakpointId > ) {\n\t\t\tif ( state.entities[ action.payload ] ) {\n\t\t\t\tstate.activeId = action.payload;\n\t\t\t}\n\t\t},\n\t},\n} );\n\nfunction normalizeEntities( entities: Breakpoint[] ) {\n\treturn entities.reduce(\n\t\t( acc, breakpoint ) => {\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[ breakpoint.id ]: breakpoint,\n\t\t\t};\n\t\t},\n\t\t{} as State[ 'entities' ]\n\t);\n}\n","import { slice } from '../store';\nimport { __dispatch } from '@elementor/store';\nimport { Breakpoint, ExtendedWindow } from '../types';\nimport { __privateListenTo as listenTo, v1ReadyEvent, windowEvent } from '@elementor/editor-v1-adapters';\nimport { __ } from '@wordpress/i18n';\n\nexport default function syncStore() {\n\tsyncInitialization();\n\tsyncOnChange();\n}\n\nfunction syncInitialization() {\n\tconst { init } = slice.actions;\n\n\tlistenTo( v1ReadyEvent(), () => {\n\t\t__dispatch(\n\t\t\tinit( {\n\t\t\t\tentities: getBreakpoints(),\n\t\t\t\tactiveId: getActiveBreakpoint(),\n\t\t\t} )\n\t\t);\n\t} );\n}\n\nfunction syncOnChange() {\n\tconst { activateBreakpoint } = slice.actions;\n\n\tlistenTo( deviceModeChangeEvent(), () => {\n\t\tconst activeBreakpoint = getActiveBreakpoint();\n\n\t\t__dispatch( activateBreakpoint( activeBreakpoint ) );\n\t} );\n}\n\nfunction getBreakpoints() {\n\tconst { breakpoints } = ( window as unknown as ExtendedWindow ).elementor?.config?.responsive || {};\n\n\tif ( ! breakpoints ) {\n\t\treturn [];\n\t}\n\n\tconst entities = Object.entries( breakpoints )\n\t\t.filter( ( [ , breakpoint ] ) => breakpoint.is_enabled )\n\t\t.map( ( [ id, { value, direction, label } ] ) => {\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tlabel,\n\t\t\t\twidth: value,\n\t\t\t\ttype: direction === 'min' ? 'min-width' : 'max-width',\n\t\t\t} as Breakpoint;\n\t\t} );\n\n\t// Desktop breakpoint is not included in V1 config.\n\tentities.push( {\n\t\tid: 'desktop',\n\t\tlabel: __( 'Desktop', 'elementor' ),\n\t} );\n\n\treturn entities;\n}\n\nfunction getActiveBreakpoint() {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn extendedWindow.elementor?.channels?.deviceMode?.request?.( 'currentMode' ) || null;\n}\n\nfunction deviceModeChangeEvent() {\n\treturn windowEvent( 'elementor/device-mode/change' );\n}\n","import { slice } from './store';\nimport syncStore from './sync/sync-store';\nimport { injectIntoResponsive } from '@elementor/editor-app-bar';\nimport BreakpointsSwitcher from './components/breakpoints-switcher';\nimport { __registerSlice } from '@elementor/store';\n\nexport default function init() {\n\tinitStore();\n\n\tregisterAppBarUI();\n}\n\nfunction initStore() {\n\t__registerSlice( slice );\n\n\tsyncStore();\n}\n\nfunction registerAppBarUI() {\n\tinjectIntoResponsive( {\n\t\tid: 'responsive-breakpoints-switcher',\n\t\tcomponent: BreakpointsSwitcher,\n\t\toptions: {\n\t\t\tpriority: 20, // After document indication.\n\t\t},\n\t} );\n}\n","import * as React from 'react';\nimport { __ } from '@wordpress/i18n';\nimport { BreakpointId, ExtendedWindow } from '../types';\nimport useBreakpoints from '../hooks/use-breakpoints';\nimport { Tab, Tabs, Tooltip as BaseTooltip, TooltipProps } from '@elementor/ui';\nimport {\n\tDesktopIcon,\n\tTabletPortraitIcon,\n\tMobilePortraitIcon,\n\tWidescreenIcon,\n\tLaptopIcon,\n\tTabletLandscapeIcon,\n\tMobileLandscapeIcon,\n} from '@elementor/icons';\nimport useBreakpointsActions from '../hooks/use-breakpoints-actions';\n\nexport default function BreakpointsSwitcher() {\n\tconst { all, active } = useBreakpoints();\n\tconst { activate } = useBreakpointsActions();\n\n\tif ( ! all.length || ! active ) {\n\t\treturn null;\n\t}\n\n\tconst onChange = ( _: unknown, value: BreakpointId ) => {\n\t\tconst extendedWindow = window as unknown as ExtendedWindow;\n\t\tconst config = extendedWindow?.elementor?.editorEvents?.config;\n\n\t\tif ( config ) {\n\t\t\textendedWindow.elementor.editorEvents.dispatchEvent( config.names.topBar.responsiveControls, {\n\t\t\t\tlocation: config.locations.topBar,\n\t\t\t\tsecondaryLocation: config.secondaryLocations.responsiveControls,\n\t\t\t\ttrigger: config.triggers.click,\n\t\t\t\telement: config.elements.buttonIcon,\n\t\t\t\tmode: value,\n\t\t\t} );\n\t\t}\n\n\t\tactivate( value );\n\t};\n\n\treturn (\n\t\t<Tabs\n\t\t\ttextColor=\"inherit\"\n\t\t\tindicatorColor=\"secondary\"\n\t\t\tvalue={ active.id }\n\t\t\tonChange={ onChange }\n\t\t\taria-label={ __( 'Switch Device', 'elementor' ) }\n\t\t\tsx={ {\n\t\t\t\t'& .MuiTabs-indicator': {\n\t\t\t\t\tbackgroundColor: 'text.primary',\n\t\t\t\t},\n\t\t\t} }\n\t\t>\n\t\t\t{ all.map( ( { id, label, type, width } ) => {\n\t\t\t\tconst Icon = iconsMap[ id ];\n\n\t\t\t\tconst title = labelsMap[ type || 'default' ]\n\t\t\t\t\t.replace( '%s', label )\n\t\t\t\t\t.replace( '%d', width?.toString() || '' );\n\n\t\t\t\treturn (\n\t\t\t\t\t<Tab\n\t\t\t\t\t\tvalue={ id }\n\t\t\t\t\t\tkey={ id }\n\t\t\t\t\t\taria-label={ title }\n\t\t\t\t\t\ticon={\n\t\t\t\t\t\t\t<Tooltip title={ title }>\n\t\t\t\t\t\t\t\t<Icon />\n\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsx={ { minWidth: 'auto' } }\n\t\t\t\t\t\tdata-testid={ `switch-device-to-${ id }` }\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t} ) }\n\t\t</Tabs>\n\t);\n}\n\nfunction Tooltip( props: TooltipProps ) {\n\treturn (\n\t\t<BaseTooltip\n\t\t\tPopperProps={ {\n\t\t\t\tsx: {\n\t\t\t\t\t'&.MuiTooltip-popper .MuiTooltip-tooltip.MuiTooltip-tooltipPlacementBottom': {\n\t\t\t\t\t\tmt: 2.5,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t} }\n\t\t\t{ ...props }\n\t\t/>\n\t);\n}\n\nconst iconsMap = {\n\twidescreen: WidescreenIcon,\n\tdesktop: DesktopIcon,\n\tlaptop: LaptopIcon,\n\ttablet_extra: TabletLandscapeIcon,\n\ttablet: TabletPortraitIcon,\n\tmobile_extra: MobileLandscapeIcon,\n\tmobile: MobilePortraitIcon,\n};\n\nconst labelsMap = {\n\tdefault: '%s',\n\t// translators: %s: Breakpoint label, %d: Breakpoint size.\n\t'min-width': __( '%s (%dpx and up)', 'elementor' ),\n\n\t// translators: %s: Breakpoint label, %d: Breakpoint size.\n\t'max-width': __( '%s (up to %dpx)', 'elementor' ),\n} as const;\n","import { __useSelector as useSelector } from '@elementor/store';\nimport { selectActiveBreakpoint, selectSortedBreakpoints } from '../store/selectors';\n\nexport default function useBreakpoints() {\n\tconst all = useSelector( selectSortedBreakpoints );\n\tconst active = useSelector( selectActiveBreakpoint );\n\n\treturn {\n\t\tall,\n\t\tactive,\n\t};\n}\n","import { slice } from './index';\nimport { Breakpoint } from '../types';\nimport { __createSelector, SliceState } from '@elementor/store';\n\ntype State = SliceState< typeof slice >;\n\nexport const selectEntities = ( state: State ) => state.breakpoints.entities;\nexport const selectActiveId = ( state: State ) => state.breakpoints.activeId;\n\nexport const selectActiveBreakpoint = __createSelector( selectEntities, selectActiveId, ( entities, activeId ) =>\n\tactiveId && entities[ activeId ] ? entities[ activeId ] : null\n);\n\nexport const selectSortedBreakpoints = __createSelector( selectEntities, ( entities ) => {\n\tconst byWidth = ( a: Breakpoint, b: Breakpoint ) => {\n\t\treturn a.width && b.width ? b.width - a.width : 0;\n\t};\n\n\tconst all = Object.values( entities );\n\n\tconst defaults = all.filter( ( breakpoint ) => ! breakpoint.width ); // AKA Desktop.\n\tconst minWidth = all.filter( ( breakpoint ) => breakpoint.type === 'min-width' );\n\tconst maxWidth = all.filter( ( breakpoint ) => breakpoint.type === 'max-width' );\n\n\t// Sort by size, big to small.\n\treturn [ ...minWidth.sort( byWidth ), ...defaults, ...maxWidth.sort( byWidth ) ];\n} );\n","import { useCallback } from 'react';\nimport { BreakpointId } from '../types';\nimport { __privateRunCommand as runCommand } from '@elementor/editor-v1-adapters';\n\nexport default function useBreakpointsActions() {\n\tconst activate = useCallback( ( device: BreakpointId ) => {\n\t\treturn runCommand( 'panel/change-device-mode', { device } );\n\t}, [] );\n\n\treturn {\n\t\tactivate,\n\t};\n}\n","import init from './init';\n\ninit();\n"],"mappings":"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","names":["init","__","__"]}
|
package/package.json
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
2
|
+
"name": "@elementor/editor-responsive",
|
|
3
|
+
"version": "0.10.6",
|
|
4
|
+
"private": false,
|
|
5
|
+
"author": "Elementor Team",
|
|
6
|
+
"homepage": "https://elementor.com/",
|
|
7
|
+
"license": "GPL-3.0-or-later",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"module": "dist/index.mjs",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/elementor/elementor-packages.git",
|
|
22
|
+
"directory": "packages/core/editor-responsive"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/elementor/elementor-packages/issues"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsup --config=../../tsup.build.ts",
|
|
32
|
+
"dev": "tsup --config=../../tsup.dev.ts"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@elementor/editor-app-bar": "^0.14.6",
|
|
36
|
+
"@elementor/editor-v1-adapters": "^0.8.0",
|
|
37
|
+
"@elementor/icons": "^0.8.2",
|
|
38
|
+
"@elementor/store": "^0.8.4",
|
|
39
|
+
"@elementor/ui": "^1.4.61",
|
|
40
|
+
"@wordpress/i18n": "^4.45.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"react": "^18.3.1"
|
|
44
|
+
},
|
|
45
|
+
"gitHead": "10fd8663495a9ced2521f27a74879684ed0cf322"
|
|
46
46
|
}
|
|
@@ -6,9 +6,11 @@ import BreakpointsSwitcher from '../breakpoints-switcher';
|
|
|
6
6
|
import useBreakpointsActions from '../../hooks/use-breakpoints-actions';
|
|
7
7
|
|
|
8
8
|
jest.mock( '../../hooks/use-breakpoints', () => jest.fn() );
|
|
9
|
-
jest.mock( '../../hooks/use-breakpoints-actions', () =>
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
jest.mock( '../../hooks/use-breakpoints-actions', () =>
|
|
10
|
+
jest.fn().mockReturnValue( {
|
|
11
|
+
activate: jest.fn(),
|
|
12
|
+
} )
|
|
13
|
+
);
|
|
12
14
|
|
|
13
15
|
describe( '@elementor/editor-responsive - Breakpoints Switcher', () => {
|
|
14
16
|
it( 'should not render when there are no breakpoints', () => {
|
|
@@ -32,10 +34,12 @@ describe( '@elementor/editor-responsive - Breakpoints Switcher', () => {
|
|
|
32
34
|
// Arrange.
|
|
33
35
|
jest.mocked( useBreakpoints ).mockReturnValue( {
|
|
34
36
|
active: null,
|
|
35
|
-
all: [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
all: [
|
|
38
|
+
{
|
|
39
|
+
id: 'desktop',
|
|
40
|
+
label: 'Desktop',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
39
43
|
} );
|
|
40
44
|
|
|
41
45
|
// Act.
|
|
@@ -27,16 +27,13 @@ export default function BreakpointsSwitcher() {
|
|
|
27
27
|
const config = extendedWindow?.elementor?.editorEvents?.config;
|
|
28
28
|
|
|
29
29
|
if ( config ) {
|
|
30
|
-
extendedWindow.elementor.editorEvents.dispatchEvent(
|
|
31
|
-
config.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
mode: value,
|
|
38
|
-
},
|
|
39
|
-
);
|
|
30
|
+
extendedWindow.elementor.editorEvents.dispatchEvent( config.names.topBar.responsiveControls, {
|
|
31
|
+
location: config.locations.topBar,
|
|
32
|
+
secondaryLocation: config.secondaryLocations.responsiveControls,
|
|
33
|
+
trigger: config.triggers.click,
|
|
34
|
+
element: config.elements.buttonIcon,
|
|
35
|
+
mode: value,
|
|
36
|
+
} );
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
activate( value );
|
|
@@ -55,41 +52,45 @@ export default function BreakpointsSwitcher() {
|
|
|
55
52
|
},
|
|
56
53
|
} }
|
|
57
54
|
>
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
const Icon = iconsMap[ id ];
|
|
55
|
+
{ all.map( ( { id, label, type, width } ) => {
|
|
56
|
+
const Icon = iconsMap[ id ];
|
|
61
57
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
const title = labelsMap[ type || 'default' ]
|
|
59
|
+
.replace( '%s', label )
|
|
60
|
+
.replace( '%d', width?.toString() || '' );
|
|
65
61
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
return (
|
|
63
|
+
<Tab
|
|
64
|
+
value={ id }
|
|
65
|
+
key={ id }
|
|
66
|
+
aria-label={ title }
|
|
67
|
+
icon={
|
|
68
|
+
<Tooltip title={ title }>
|
|
69
|
+
<Icon />
|
|
70
|
+
</Tooltip>
|
|
71
|
+
}
|
|
72
|
+
sx={ { minWidth: 'auto' } }
|
|
73
|
+
data-testid={ `switch-device-to-${ id }` }
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
} ) }
|
|
77
77
|
</Tabs>
|
|
78
|
-
|
|
79
78
|
);
|
|
80
79
|
}
|
|
81
80
|
|
|
82
81
|
function Tooltip( props: TooltipProps ) {
|
|
83
|
-
return
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
return (
|
|
83
|
+
<BaseTooltip
|
|
84
|
+
PopperProps={ {
|
|
85
|
+
sx: {
|
|
86
|
+
'&.MuiTooltip-popper .MuiTooltip-tooltip.MuiTooltip-tooltipPlacementBottom': {
|
|
87
|
+
mt: 2.5,
|
|
88
|
+
},
|
|
88
89
|
},
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
} }
|
|
91
|
+
{ ...props }
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
const iconsMap = {
|
|
@@ -15,9 +15,6 @@ describe( '@elementor/editor-responsive - useBreakpointsActions', () => {
|
|
|
15
15
|
|
|
16
16
|
// Assert.
|
|
17
17
|
expect( jest.mocked( runCommand ) ).toHaveBeenCalledTimes( 1 );
|
|
18
|
-
expect( jest.mocked( runCommand ) ).toHaveBeenCalledWith(
|
|
19
|
-
'panel/change-device-mode',
|
|
20
|
-
{ device: 'tablet' }
|
|
21
|
-
);
|
|
18
|
+
expect( jest.mocked( runCommand ) ).toHaveBeenCalledWith( 'panel/change-device-mode', { device: 'tablet' } );
|
|
22
19
|
} );
|
|
23
20
|
} );
|
|
@@ -3,14 +3,21 @@ import { PropsWithChildren } from 'react';
|
|
|
3
3
|
import { slice } from '../../store';
|
|
4
4
|
import useBreakpoints from '../use-breakpoints';
|
|
5
5
|
import { renderHook } from '@testing-library/react';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
__createStore,
|
|
8
|
+
__dispatch,
|
|
9
|
+
__registerSlice,
|
|
10
|
+
SliceState,
|
|
11
|
+
Store,
|
|
12
|
+
__StoreProvider as StoreProvider,
|
|
13
|
+
} from '@elementor/store';
|
|
7
14
|
|
|
8
15
|
jest.mock( '@elementor/editor-v1-adapters', () => ( {
|
|
9
16
|
__privateRunCommand: jest.fn(),
|
|
10
17
|
} ) );
|
|
11
18
|
|
|
12
19
|
describe( '@elementor/editor-responsive - useBreakpoints', () => {
|
|
13
|
-
let store: Store<SliceState<typeof slice
|
|
20
|
+
let store: Store< SliceState< typeof slice > >;
|
|
14
21
|
|
|
15
22
|
beforeEach( () => {
|
|
16
23
|
__registerSlice( slice );
|
|
@@ -19,15 +26,17 @@ describe( '@elementor/editor-responsive - useBreakpoints', () => {
|
|
|
19
26
|
|
|
20
27
|
it( 'should return all breakpoints sorted by size', () => {
|
|
21
28
|
// Arrange.
|
|
22
|
-
__dispatch(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
__dispatch(
|
|
30
|
+
slice.actions.init( {
|
|
31
|
+
activeId: null,
|
|
32
|
+
entities: [
|
|
33
|
+
{ id: 'tablet', label: 'Tablet Portrait', width: 1024, type: 'max-width' },
|
|
34
|
+
{ id: 'mobile', label: 'Mobile Portrait', width: 767, type: 'max-width' },
|
|
35
|
+
{ id: 'widescreen', label: 'Widescreen', width: 2400, type: 'min-width' },
|
|
36
|
+
{ id: 'desktop', label: 'Desktop' },
|
|
37
|
+
],
|
|
38
|
+
} )
|
|
39
|
+
);
|
|
31
40
|
|
|
32
41
|
// Act.
|
|
33
42
|
const { result } = renderHookWithStore( () => useBreakpoints(), store );
|
|
@@ -43,13 +52,15 @@ describe( '@elementor/editor-responsive - useBreakpoints', () => {
|
|
|
43
52
|
|
|
44
53
|
it( 'should return the active breakpoint', () => {
|
|
45
54
|
// Arrange.
|
|
46
|
-
__dispatch(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
__dispatch(
|
|
56
|
+
slice.actions.init( {
|
|
57
|
+
activeId: 'tablet',
|
|
58
|
+
entities: [
|
|
59
|
+
{ id: 'desktop', label: 'Desktop' },
|
|
60
|
+
{ id: 'tablet', label: 'Tablet Portrait', type: 'max-width', width: 1024 },
|
|
61
|
+
],
|
|
62
|
+
} )
|
|
63
|
+
);
|
|
53
64
|
|
|
54
65
|
// Act.
|
|
55
66
|
const { result } = renderHookWithStore( () => useBreakpoints(), store );
|
|
@@ -64,11 +75,9 @@ describe( '@elementor/editor-responsive - useBreakpoints', () => {
|
|
|
64
75
|
} );
|
|
65
76
|
} );
|
|
66
77
|
|
|
67
|
-
function renderHookWithStore<T>( hook: () => T, store: Store ) {
|
|
68
|
-
const wrapper = ( { children }: PropsWithChildren<unknown> ) => (
|
|
69
|
-
<StoreProvider store={ store }>
|
|
70
|
-
{ children }
|
|
71
|
-
</StoreProvider>
|
|
78
|
+
function renderHookWithStore< T >( hook: () => T, store: Store ) {
|
|
79
|
+
const wrapper = ( { children }: PropsWithChildren< unknown > ) => (
|
|
80
|
+
<StoreProvider store={ store }>{ children }</StoreProvider>
|
|
72
81
|
);
|
|
73
82
|
|
|
74
83
|
return renderHook( hook, { wrapper } );
|
package/src/store/index.ts
CHANGED
|
@@ -2,11 +2,11 @@ import { __createSlice, PayloadAction } from '@elementor/store';
|
|
|
2
2
|
import { Breakpoint, BreakpointId } from '../types';
|
|
3
3
|
|
|
4
4
|
export type State = {
|
|
5
|
-
entities: Record<BreakpointId, Breakpoint
|
|
6
|
-
activeId: BreakpointId | null
|
|
7
|
-
}
|
|
5
|
+
entities: Record< BreakpointId, Breakpoint >;
|
|
6
|
+
activeId: BreakpointId | null;
|
|
7
|
+
};
|
|
8
8
|
const initialState: State = {
|
|
9
|
-
entities: {} as State['entities'],
|
|
9
|
+
entities: {} as State[ 'entities' ],
|
|
10
10
|
activeId: null,
|
|
11
11
|
};
|
|
12
12
|
|
|
@@ -14,15 +14,18 @@ export const slice = __createSlice( {
|
|
|
14
14
|
name: 'breakpoints',
|
|
15
15
|
initialState,
|
|
16
16
|
reducers: {
|
|
17
|
-
init(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
init(
|
|
18
|
+
state,
|
|
19
|
+
action: PayloadAction< {
|
|
20
|
+
entities: Breakpoint[];
|
|
21
|
+
activeId: State[ 'activeId' ];
|
|
22
|
+
} >
|
|
23
|
+
) {
|
|
21
24
|
state.activeId = action.payload.activeId;
|
|
22
25
|
state.entities = normalizeEntities( action.payload.entities );
|
|
23
26
|
},
|
|
24
27
|
|
|
25
|
-
activateBreakpoint( state, action: PayloadAction<BreakpointId> ) {
|
|
28
|
+
activateBreakpoint( state, action: PayloadAction< BreakpointId > ) {
|
|
26
29
|
if ( state.entities[ action.payload ] ) {
|
|
27
30
|
state.activeId = action.payload;
|
|
28
31
|
}
|
|
@@ -31,10 +34,13 @@ export const slice = __createSlice( {
|
|
|
31
34
|
} );
|
|
32
35
|
|
|
33
36
|
function normalizeEntities( entities: Breakpoint[] ) {
|
|
34
|
-
return entities.reduce(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
return entities.reduce(
|
|
38
|
+
( acc, breakpoint ) => {
|
|
39
|
+
return {
|
|
40
|
+
...acc,
|
|
41
|
+
[ breakpoint.id ]: breakpoint,
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
{} as State[ 'entities' ]
|
|
45
|
+
);
|
|
40
46
|
}
|
package/src/store/selectors.ts
CHANGED
|
@@ -2,37 +2,26 @@ import { slice } from './index';
|
|
|
2
2
|
import { Breakpoint } from '../types';
|
|
3
3
|
import { __createSelector, SliceState } from '@elementor/store';
|
|
4
4
|
|
|
5
|
-
type State = SliceState<typeof slice>;
|
|
5
|
+
type State = SliceState< typeof slice >;
|
|
6
6
|
|
|
7
7
|
export const selectEntities = ( state: State ) => state.breakpoints.entities;
|
|
8
8
|
export const selectActiveId = ( state: State ) => state.breakpoints.activeId;
|
|
9
9
|
|
|
10
|
-
export const selectActiveBreakpoint = __createSelector(
|
|
11
|
-
|
|
12
|
-
selectActiveId,
|
|
13
|
-
( entities, activeId ) => activeId && entities[ activeId ]
|
|
14
|
-
? entities[ activeId ]
|
|
15
|
-
: null,
|
|
10
|
+
export const selectActiveBreakpoint = __createSelector( selectEntities, selectActiveId, ( entities, activeId ) =>
|
|
11
|
+
activeId && entities[ activeId ] ? entities[ activeId ] : null
|
|
16
12
|
);
|
|
17
13
|
|
|
18
|
-
export const selectSortedBreakpoints = __createSelector(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return ( a.width && b.width ) ? b.width - a.width : 0;
|
|
23
|
-
};
|
|
14
|
+
export const selectSortedBreakpoints = __createSelector( selectEntities, ( entities ) => {
|
|
15
|
+
const byWidth = ( a: Breakpoint, b: Breakpoint ) => {
|
|
16
|
+
return a.width && b.width ? b.width - a.width : 0;
|
|
17
|
+
};
|
|
24
18
|
|
|
25
|
-
|
|
19
|
+
const all = Object.values( entities );
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
const defaults = all.filter( ( breakpoint ) => ! breakpoint.width ); // AKA Desktop.
|
|
22
|
+
const minWidth = all.filter( ( breakpoint ) => breakpoint.type === 'min-width' );
|
|
23
|
+
const maxWidth = all.filter( ( breakpoint ) => breakpoint.type === 'max-width' );
|
|
30
24
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
...defaults,
|
|
35
|
-
...maxWidth.sort( byWidth ),
|
|
36
|
-
];
|
|
37
|
-
},
|
|
38
|
-
);
|
|
25
|
+
// Sort by size, big to small.
|
|
26
|
+
return [ ...minWidth.sort( byWidth ), ...defaults, ...maxWidth.sort( byWidth ) ];
|
|
27
|
+
} );
|