Skip to content

Commit a9eefe8

Browse files
authored
Feat: Wireframe design library (#2068)
* Added wireframes in the design library * Removed extra image padding, just adjust the screenshots
1 parent a584d24 commit a9eefe8

File tree

6 files changed

+139
-49
lines changed

6 files changed

+139
-49
lines changed

src/components/advanced-toolbar-control/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ const AdvancedToolbarControl = props => {
119119
return (
120120
<AdvancedControl
121121
{ ...controlProps }
122-
className={ classnames( 'ugb-advanced-toolbar-control', className ) }
122+
className={ classnames( 'ugb-advanced-toolbar-control', className, controlProps.className ) }
123123
>
124124
<ButtonGroup
125125
children={

src/components/design-library-list/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ import { __ } from '@wordpress/i18n'
1717

1818
const DesignLibraryList = props => {
1919
const {
20-
designs, isBusy, onSelect, apiVersion,
20+
className = '',
21+
designs,
22+
isBusy,
23+
onSelect,
24+
apiVersion,
2125
} = props
2226

2327
const listClasses = classnames( [
2428
'ugb-design-library-items',
29+
className,
2530
], {
2631
[ `ugb-design-library-items--columns-${ props.columns }` ]: ! isBusy && props.columns,
2732
} )

src/components/modal-design-library/block-list.js

Lines changed: 81 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
* External dependencies
1111
*/
1212
import { sortBy } from 'lodash'
13-
import { AdvancedToolbarControl } from '..'
1413
import { fetchDesignLibrary } from '~stackable/design-library'
1514
import { isPro, i18n } from 'stackable'
1615
import classnames from 'classnames'
@@ -24,12 +23,14 @@ import {
2423
import { __ } from '@wordpress/i18n'
2524
import { useLocalStorage } from '~stackable/util'
2625

26+
const isWireframe = design => design.uikit.toLowerCase() === 'wireframes'
27+
2728
const BlockList = props => {
2829
const [ uiKitList, setUiKitList ] = useState( [] )
2930
const [ categoryList, setCategoryList ] = useState( [] )
31+
const [ wireframeList, setWireframeList ] = useState( [] )
3032
const [ selected, setSelected ] = useLocalStorage( 'stk__design_library__block-list__selected', '' )
31-
const [ viewBy, setViewBy ] = useLocalStorage( 'stk__design_library__block-list__view_by', 'uikit' )
32-
const { apiVersion } = props
33+
const { viewBy, apiVersion } = props
3334

3435
// Create our block list.
3536
useEffect( () => {
@@ -38,7 +39,8 @@ const BlockList = props => {
3839
const design = designs[ name ]
3940
const { categories, uikit } = design
4041

41-
if ( typeof output.uikits[ uikit ] === 'undefined' ) {
42+
// Get all UI Kits. Don't include the Wireframe UI Kit.
43+
if ( typeof output.uikits[ uikit ] === 'undefined' && ! isWireframe( design ) ) {
4244
output.uikits[ uikit ] = {
4345
id: uikit,
4446
label: design.uikit,
@@ -47,18 +49,36 @@ const BlockList = props => {
4749
}
4850
}
4951

50-
categories.forEach( category => {
51-
if ( typeof output.categories[ category ] === 'undefined' ) {
52-
output.categories[ category ] = {
53-
id: category,
54-
label: category,
55-
count: 0,
52+
// Get all wireframe categories.
53+
if ( isWireframe( design ) ) {
54+
categories.forEach( category => {
55+
if ( typeof output.wireframes[ category ] === 'undefined' ) {
56+
output.wireframes[ category ] = {
57+
id: category,
58+
label: category,
59+
count: 0,
60+
}
5661
}
57-
}
58-
} )
62+
} )
63+
} else {
64+
// Get all block design categories.
65+
categories.forEach( category => {
66+
if ( typeof output.categories[ category ] === 'undefined' ) {
67+
output.categories[ category ] = {
68+
id: category,
69+
label: category,
70+
count: 0,
71+
}
72+
}
73+
} )
74+
}
5975

6076
return output
61-
}, { uikits: {}, categories: {} } )
77+
}, {
78+
uikits: {},
79+
categories: {},
80+
wireframes: {},
81+
} )
6282

6383
let uikitSort = [ 'label' ]
6484
if ( ! isPro ) {
@@ -72,16 +92,23 @@ const BlockList = props => {
7292
label: __( 'All', i18n ),
7393
count: 0,
7494
} )
95+
const wireframes = sortBy( Object.values( designList.wireframes ), 'label' )
96+
wireframes.unshift( {
97+
id: 'all',
98+
label: __( 'All', i18n ),
99+
count: 0,
100+
} )
75101

76102
setUiKitList( uikits )
77103
setCategoryList( categories )
104+
setWireframeList( wireframes )
78105
} )
79106
}, [ apiVersion ] )
80107

81108
// Update the counts of the designs, but don't update the list, only the counts.
82109
useEffect( () => {
83110
// If these are empty, then our component hasn't finished initializing.
84-
if ( ! uiKitList.length || ! categoryList.length ) {
111+
if ( ! uiKitList.length || ! categoryList.length || ! wireframeList.length ) {
85112
return
86113
}
87114

@@ -99,11 +126,31 @@ const BlockList = props => {
99126
}
100127
return categories
101128
}, {} )
129+
const newWireframes = wireframeList.reduce( ( categories, category ) => {
130+
categories[ category.id ] = {
131+
...category,
132+
count: 0,
133+
}
134+
return categories
135+
}, {} )
102136

103137
props.designs.forEach( design => {
138+
// Gather all wireframe designs.
139+
if ( isWireframe( design ) ) {
140+
design.categories.forEach( category => {
141+
if ( category && newWireframes[ category ] ) {
142+
newWireframes[ category ].count++
143+
}
144+
} )
145+
return
146+
}
147+
148+
// Gather all ui kit designs.
104149
if ( design.uikit && newUiKits[ design.uikit ] ) {
105150
newUiKits[ design.uikit ].count++
106151
}
152+
153+
// Gather all block design categories.
107154
design.categories.forEach( category => {
108155
if ( category && newCategories[ category ] ) {
109156
newCategories[ category ].count++
@@ -119,50 +166,47 @@ const BlockList = props => {
119166

120167
// Sort the categories so that the "All" is first.
121168
if ( newCategories.all ) {
122-
newCategories.all.count = props.designs.length
169+
newCategories.all.count = props.designs.filter( design => ! isWireframe( design ) ).length
123170
newCategories.all.label = ' ' // Spaces so we will be first when sorting.
124171
}
125172
const sorted = sortBy( Object.values( newCategories ), 'label' )
126173
if ( sorted[ 0 ] ) {
127174
sorted[ 0 ].label = __( 'All', i18n )
128175
}
129176
setCategoryList( sorted )
130-
}, [ props.designs.length, JSON.stringify( uiKitList ), JSON.stringify( categoryList ) ] )
177+
178+
// Sort the wireframes so that the "All" is first.
179+
if ( newWireframes.all ) {
180+
newWireframes.all.count = props.designs.filter( isWireframe ).length
181+
newWireframes.all.label = ' ' // Spaces so we will be first when sorting.
182+
}
183+
const sortedWireframes = sortBy( Object.values( newWireframes ), 'label' )
184+
if ( sortedWireframes[ 0 ] ) {
185+
sortedWireframes[ 0 ].label = __( 'All', i18n )
186+
}
187+
setWireframeList( sortedWireframes )
188+
}, [ props.designs.length, JSON.stringify( uiKitList ), JSON.stringify( categoryList ), JSON.stringify( wireframeList ) ] )
131189

132190
useEffect( () => {
133191
// If these are empty, then our component hasn't finished initializing.
134-
if ( ! uiKitList.length || ! categoryList.length ) {
192+
if ( ! uiKitList.length || ! categoryList.length || ! wireframeList.length ) {
135193
return
136194
}
137195

138196
setSelected( viewBy === 'uikit' ? uiKitList[ 0 ].id : 'all' )
139197
}, [ viewBy ] )
140198

141199
useEffect( () => {
142-
props.onSelect( { id: selected, type: viewBy } )
200+
props.onSelect( selected )
143201
}, [ selected ] )
144202

203+
const list = viewBy === 'uikit'
204+
? uiKitList : viewBy === 'category'
205+
? categoryList : wireframeList
206+
145207
return (
146208
<ul className="ugb-block-list">
147-
<AdvancedToolbarControl
148-
controls={ [
149-
{
150-
value: 'uikit',
151-
title: __( 'UI Kits', i18n ),
152-
},
153-
{
154-
value: 'category',
155-
title: __( 'Categories', i18n ),
156-
},
157-
] }
158-
value={ viewBy }
159-
onChange={ setViewBy }
160-
isSmall={ true }
161-
fullwidth={ false }
162-
isToggleOnly={ true }
163-
allowReset={ false }
164-
/>
165-
{ ( viewBy === 'uikit' ? uiKitList : categoryList ).reduce( ( list, itemData ) => {
209+
{ list.reduce( ( list, itemData ) => {
166210
const {
167211
id,
168212
label,

src/components/modal-design-library/editor.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,18 @@
186186
.stk-design-library__sidebar-item:focus {
187187
outline: 1px dashed #777;
188188
}
189+
190+
// Design library top tabs, switch between block categories, ui kit and wireframe.
191+
.stk-design-library-tabs .components-button {
192+
height: 60px;
193+
border: none !important;
194+
border-left: 1px solid #ddd !important;
195+
box-shadow: none !important;
196+
padding: 0 24px;
197+
background: transparent;
198+
&:hover,
199+
&.is-primary {
200+
color: #f00069 !important;
201+
background: rgba(229, 67, 118, 0.1) !important;
202+
}
203+
}

src/components/modal-design-library/modal.js

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const ModalDesignLibrary = props => {
3333
const [ isBusy, setIsBusy ] = useState( true )
3434
const [ doReset, setDoReset ] = useState( false )
3535
const [ selectedId, setSelectedId ] = useState( '' )
36-
const [ selectedType, setSelectedType ] = useState( '' )
36+
const [ selectedType, setSelectedType ] = useLocalStorage( 'stk__design_library__block-list__view_by', 'uikit' )
3737
const [ isDevMode, setIsDevMode ] = useLocalStorage( 'stk__design_library_dev_mode', false )
3838
// The sidebar designs are used to update the list of blocks in the sidebar.
3939
const [ sidebarDesigns, setSidebarDesigns ] = useState( [] )
@@ -85,8 +85,8 @@ export const ModalDesignLibrary = props => {
8585
getDesigns( {
8686
apiVersion: props.apiVersion,
8787
search: searchDebounced,
88-
uikit: selectedType === 'uikit' ? selectedId : '',
89-
categories: selectedType === 'category' && selectedId !== 'all' ? [ selectedId ] : [],
88+
uikit: selectedType === 'wireframe' ? 'Wireframes' : ( selectedType === 'uikit' ? selectedId : '' ),
89+
categories: [ 'category', 'wireframe' ].includes( selectedType ) && selectedId !== 'all' ? [ selectedId ] : [],
9090
} ).then( designs => {
9191
setDisplayDesigns( designs )
9292
} ).finally( () => {
@@ -99,6 +99,28 @@ export const ModalDesignLibrary = props => {
9999
title={ (
100100
<>
101101
{ __( 'Stackable Design Library', i18n ) }
102+
<AdvancedToolbarControl
103+
className="stk-design-library-tabs"
104+
controls={ [
105+
{
106+
value: 'category',
107+
title: __( 'Block Designs', i18n ),
108+
},
109+
{
110+
value: 'uikit',
111+
title: __( 'UI Kits', i18n ),
112+
},
113+
{
114+
value: 'wireframe',
115+
title: __( 'Wireframes', i18n ),
116+
},
117+
] }
118+
value={ selectedType }
119+
onChange={ setSelectedType }
120+
fullwidth={ false }
121+
isToggleOnly={ true }
122+
allowReset={ false }
123+
/>
102124
{ props.hasVersionSwitcher && (
103125
<AdvancedToolbarControl
104126
controls={ [
@@ -138,12 +160,8 @@ export const ModalDesignLibrary = props => {
138160
<BlockList
139161
apiVersion={ props.apiVersion }
140162
designs={ sidebarDesigns }
141-
onSelect={ ( {
142-
id, type,
143-
} ) => {
144-
setSelectedId( id )
145-
setSelectedType( type )
146-
} }
163+
viewBy={ selectedType }
164+
onSelect={ id => setSelectedId( id ) }
147165
/>
148166
</div>
149167
</aside>
@@ -192,6 +210,7 @@ export const ModalDesignLibrary = props => {
192210

193211
<div className="ugb-modal-design-library__designs">
194212
<DesignLibraryList
213+
className={ `stk-design-library__item-${ selectedType }` }
195214
columns={ columns }
196215
onSelect={ props.onSelect }
197216
isBusy={ isBusy }

src/design-library/init.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ public static function validate_string( $value, $request, $param ) {
3838
return true;
3939
}
4040

41+
public static function validate_boolean( $value, $request, $param ) {
42+
if ( ! is_bool( $value ) ) {
43+
return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be a boolean.', STACKABLE_I18N ), $param ) );
44+
}
45+
return true;
46+
}
47+
4148
/**
4249
* Register Rest API routes for the design library.
4350
*/
@@ -79,7 +86,7 @@ public function register_route() {
7986
},
8087
'args' => array(
8188
'devmode' => array(
82-
'validate_callback' => 'is_boolean'
89+
'validate_callback' => __CLASS__ . '::validate_boolean'
8390
),
8491
),
8592
) );

0 commit comments

Comments
 (0)