@aglyn/plugins-commerce 1.0.0-beta.236 → 1.0.0-beta.238
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/package.json +13 -13
- package/src/lib/components/cart.d.ts +2 -1
- package/src/lib/components/cart.js +2 -1
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/product-detail.d.ts +76 -0
- package/src/lib/components/product-detail.js +258 -52
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/components/product-grid.d.ts +46 -0
- package/src/lib/components/product-grid.js +283 -79
- package/src/lib/components/product-grid.js.map +1 -1
- package/src/lib/components/product-image-placeholder.d.ts +31 -0
- package/src/lib/components/product-image-placeholder.js +72 -0
- package/src/lib/components/product-image-placeholder.js.map +1 -0
- package/src/lib/components/product-reviews.d.ts +13 -0
- package/src/lib/components/product-reviews.js +267 -13
- package/src/lib/components/product-reviews.js.map +1 -1
- package/src/lib/components/related-products.d.ts +6 -0
- package/src/lib/components/related-products.js +73 -20
- package/src/lib/components/related-products.js.map +1 -1
- package/src/lib/constants/cart-events.d.ts +23 -0
- package/src/lib/constants/cart-events.js +23 -0
- package/src/lib/constants/cart-events.js.map +1 -0
- package/src/lib/server/catalog.d.ts +14 -0
- package/src/lib/server/catalog.js +25 -5
- package/src/lib/server/catalog.js.map +1 -1
- package/src/lib/server/reviews.d.ts +35 -0
- package/src/lib/server/reviews.js +120 -1
- package/src/lib/server/reviews.js.map +1 -1
- package/src/lib/server/site-page-resolver.d.ts +15 -3
- package/src/lib/server/site-page-resolver.js +78 -24
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/utils/add-to-cart.d.ts +35 -0
- package/src/lib/utils/add-to-cart.js +53 -0
- package/src/lib/utils/add-to-cart.js.map +1 -0
|
@@ -37,8 +37,29 @@ import { forwardRef, useCallback, useEffect, useRef, useState } from "react";
|
|
|
37
37
|
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
38
38
|
import { STOREFRONT_CATALOG_DECLARATION, STOREFRONT_CATALOG_HEADERS, STOREFRONT_CATALOG_OPTIONS } from "../constants/storefront-catalog-query.js";
|
|
39
39
|
import { generatePresetId } from "../utils/generate-preset-id.js";
|
|
40
|
+
import { addToCart } from "../utils/add-to-cart.js";
|
|
41
|
+
import { ProductImagePlaceholder } from "./product-image-placeholder.js";
|
|
40
42
|
// Component ids are persisted in screen documents; never rename.
|
|
41
43
|
export const ID = 'product-grid';
|
|
44
|
+
/** What a card's quick add offers for one product. */ export function quickAddAction(item) {
|
|
45
|
+
var _item_variantCount;
|
|
46
|
+
if (item.priceComingSoon || item.soldOut) return null;
|
|
47
|
+
if (item.defaultVariantId) return 'add';
|
|
48
|
+
if (((_item_variantCount = item.variantCount) != null ? _item_variantCount : 0) > 1) return 'options';
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The chip and tag a browsing grid opens on, from the page's address:
|
|
53
|
+
* `?category=<slug>` and `?tag=<tag>`. Read after hydration only — the
|
|
54
|
+
* server renders the unfiltered first page and has no address to read.
|
|
55
|
+
*/ export function browseParamsFromSearch(search) {
|
|
56
|
+
var _params_get, _params_get1;
|
|
57
|
+
const params = new URLSearchParams(search);
|
|
58
|
+
return {
|
|
59
|
+
categorySlug: ((_params_get = params.get('category')) != null ? _params_get : '').trim(),
|
|
60
|
+
tag: ((_params_get1 = params.get('tag')) != null ? _params_get1 : '').trim()
|
|
61
|
+
};
|
|
62
|
+
}
|
|
42
63
|
/** What a card says where a product listed before it has a price would show one (AGL-3676). */ const PRICE_COMING_SOON_LABEL = 'Price coming soon';
|
|
43
64
|
const SAMPLE_ITEMS = [
|
|
44
65
|
{
|
|
@@ -141,7 +162,7 @@ function priceLabel(item) {
|
|
|
141
162
|
*/ const ProductGrid = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
142
163
|
var _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
|
|
143
164
|
var _site_pageData_commerce_grids, _site_pageData_commerce, _site_pageData;
|
|
144
|
-
const { source, collectionId, collectionSlug: collectionSlugProp, categoryId, categorySlug, tag, sort: sortProp, columns, maxItems, emptyText, showFilters, showSearch, showCategories, showSort, showTypeFilter, showPriceFilter, pageSize, cardStyle } = props, rest = _object_without_properties_loose(props, [
|
|
165
|
+
const { source, collectionId, collectionSlug: collectionSlugProp, categoryId, categorySlug, tag, sort: sortProp, columns, maxItems, emptyText, emptyTitle, emptyActionLabel, emptyActionHref, showFilters, showSearch, showCategories, showSort, showTypeFilter, showPriceFilter, pageSize, cardStyle, quickAdd } = props, rest = _object_without_properties_loose(props, [
|
|
145
166
|
"source",
|
|
146
167
|
"collectionId",
|
|
147
168
|
"collectionSlug",
|
|
@@ -152,6 +173,9 @@ function priceLabel(item) {
|
|
|
152
173
|
"columns",
|
|
153
174
|
"maxItems",
|
|
154
175
|
"emptyText",
|
|
176
|
+
"emptyTitle",
|
|
177
|
+
"emptyActionLabel",
|
|
178
|
+
"emptyActionHref",
|
|
155
179
|
"showFilters",
|
|
156
180
|
"showSearch",
|
|
157
181
|
"showCategories",
|
|
@@ -159,7 +183,8 @@ function priceLabel(item) {
|
|
|
159
183
|
"showTypeFilter",
|
|
160
184
|
"showPriceFilter",
|
|
161
185
|
"pageSize",
|
|
162
|
-
"cardStyle"
|
|
186
|
+
"cardStyle",
|
|
187
|
+
"quickAdd"
|
|
163
188
|
]);
|
|
164
189
|
const photoCards = cardStyle === 'photo';
|
|
165
190
|
// Node styles ride the renderer-merged sx; recompose (stack.ts pattern).
|
|
@@ -167,7 +192,11 @@ function priceLabel(item) {
|
|
|
167
192
|
props['sx']
|
|
168
193
|
];
|
|
169
194
|
const site = Aglyn.useSite();
|
|
195
|
+
const siteFetch = Aglyn.useSiteFetch();
|
|
170
196
|
const { hostId } = site;
|
|
197
|
+
// Quick add (AGL-3676 follow-up): which card is adding, which just did.
|
|
198
|
+
const [quickAdding, setQuickAdding] = useState('');
|
|
199
|
+
const [quickAdded, setQuickAdded] = useState('');
|
|
171
200
|
// Server-rendered first page (AGL-659). The site-page enricher ran this
|
|
172
201
|
// grid's own query on the server and keyed the result by node id — two
|
|
173
202
|
// grids on a page have different queries, so an unkeyed seed would put
|
|
@@ -205,6 +234,29 @@ function priceLabel(item) {
|
|
|
205
234
|
const collectionSlug = source === 'collection' ? collectionSlugProp || collectionSlugFromLocation() : collectionSlugProp;
|
|
206
235
|
const pageLimit = pageSize && Number(pageSize) > 0 ? Math.floor(Number(pageSize)) : 0;
|
|
207
236
|
const pinnedCategoryId = source === 'category' ? categoryId != null ? categoryId : '' : '';
|
|
237
|
+
// A browsing grid opens on the address's `?category=` / `?tag=`: a shop
|
|
238
|
+
// page linked as /shop?category=candles shows that chip picked. Read in
|
|
239
|
+
// an effect, so the server and the first client render agree.
|
|
240
|
+
const [urlCategorySlug, setUrlCategorySlug] = useState('');
|
|
241
|
+
useEffect(()=>{
|
|
242
|
+
if (!hostId || typeof window === 'undefined') return;
|
|
243
|
+
const asked = browseParamsFromSearch(window.location.search);
|
|
244
|
+
if (showCategories && asked.categorySlug) setUrlCategorySlug(asked.categorySlug);
|
|
245
|
+
if (showFilters && asked.tag) setActiveTag(asked.tag);
|
|
246
|
+
// Once, on arrival: later chip picks are the visitor's.
|
|
247
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
248
|
+
}, [
|
|
249
|
+
hostId
|
|
250
|
+
]);
|
|
251
|
+
useEffect(()=>{
|
|
252
|
+
if (!urlCategorySlug || !categories.length) return;
|
|
253
|
+
const match = categories.find((category)=>category.slug === urlCategorySlug);
|
|
254
|
+
if (match) setActiveCategoryId(match.id);
|
|
255
|
+
setUrlCategorySlug('');
|
|
256
|
+
}, [
|
|
257
|
+
urlCategorySlug,
|
|
258
|
+
categories
|
|
259
|
+
]);
|
|
208
260
|
// Debounce keystrokes so large catalogs aren't fetched per letter.
|
|
209
261
|
useEffect(()=>{
|
|
210
262
|
const timer = setTimeout(()=>setQuery(searchInput.trim()), 300);
|
|
@@ -552,8 +604,58 @@ function priceLabel(item) {
|
|
|
552
604
|
}) : null
|
|
553
605
|
]
|
|
554
606
|
}) : null;
|
|
555
|
-
|
|
556
|
-
|
|
607
|
+
const filtering = Boolean(query || activeType || selectedCategoryId || activeTag || inStockOnly || priceFilter);
|
|
608
|
+
const emptyCopy = emptyText || 'No products here yet — check back soon.';
|
|
609
|
+
// A store with nothing listed yet (AGL-3676): a headline, a line and one
|
|
610
|
+
// way to hear more — never sample products, never a sort over nothing.
|
|
611
|
+
const emptyPanel = emptyTitle ? /*#__PURE__*/ _jsxs(Box, {
|
|
612
|
+
sx: {
|
|
613
|
+
display: 'flex',
|
|
614
|
+
flexDirection: 'column',
|
|
615
|
+
alignItems: 'center',
|
|
616
|
+
gap: 1.5,
|
|
617
|
+
px: 3,
|
|
618
|
+
py: {
|
|
619
|
+
xs: 6,
|
|
620
|
+
md: 10
|
|
621
|
+
},
|
|
622
|
+
textAlign: 'center',
|
|
623
|
+
borderRadius: 2,
|
|
624
|
+
bgcolor: 'action.hover'
|
|
625
|
+
},
|
|
626
|
+
children: [
|
|
627
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
628
|
+
variant: "h5",
|
|
629
|
+
component: "h3",
|
|
630
|
+
children: emptyTitle
|
|
631
|
+
}),
|
|
632
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
633
|
+
variant: "body1",
|
|
634
|
+
color: "text.secondary",
|
|
635
|
+
sx: {
|
|
636
|
+
maxWidth: 480
|
|
637
|
+
},
|
|
638
|
+
children: emptyCopy
|
|
639
|
+
}),
|
|
640
|
+
emptyActionLabel && emptyActionHref ? /*#__PURE__*/ _jsx(Button, {
|
|
641
|
+
variant: "outlined",
|
|
642
|
+
href: emptyActionHref,
|
|
643
|
+
sx: {
|
|
644
|
+
mt: 1
|
|
645
|
+
},
|
|
646
|
+
children: emptyActionLabel
|
|
647
|
+
}) : null
|
|
648
|
+
]
|
|
649
|
+
}) : null;
|
|
650
|
+
// An empty catalog with nothing asked of it shows its empty state alone:
|
|
651
|
+
// controls are for narrowing products, and there are none to narrow.
|
|
652
|
+
if (visible && visible.length === 0 && (!hasCatalogControls || !filtering)) {
|
|
653
|
+
return emptyPanel ? /*#__PURE__*/ _jsx(Box, _extends({
|
|
654
|
+
ref: ref
|
|
655
|
+
}, rest, {
|
|
656
|
+
sx: nodeSx,
|
|
657
|
+
children: emptyPanel
|
|
658
|
+
})) : /*#__PURE__*/ _jsx(Box, _extends({
|
|
557
659
|
ref: ref
|
|
558
660
|
}, rest, {
|
|
559
661
|
sx: [
|
|
@@ -566,7 +668,7 @@ function priceLabel(item) {
|
|
|
566
668
|
children: /*#__PURE__*/ _jsx(Typography, {
|
|
567
669
|
variant: "body2",
|
|
568
670
|
color: "text.secondary",
|
|
569
|
-
children:
|
|
671
|
+
children: emptyCopy
|
|
570
672
|
})
|
|
571
673
|
}));
|
|
572
674
|
}
|
|
@@ -580,7 +682,7 @@ function priceLabel(item) {
|
|
|
580
682
|
children: /*#__PURE__*/ _jsx(Typography, {
|
|
581
683
|
variant: "body2",
|
|
582
684
|
color: "text.secondary",
|
|
583
|
-
children:
|
|
685
|
+
children: filtering ? 'No products match — try clearing a filter.' : emptyCopy
|
|
584
686
|
})
|
|
585
687
|
});
|
|
586
688
|
const loadMore = hostId && pageLimit && nextCursor != null ? /*#__PURE__*/ _jsx(Box, {
|
|
@@ -610,85 +712,118 @@ function priceLabel(item) {
|
|
|
610
712
|
const imageUrl = Aglyn.siteRelativeMediaSrc(item.imageUrl, {
|
|
611
713
|
hostId
|
|
612
714
|
});
|
|
613
|
-
return /*#__PURE__*/
|
|
715
|
+
return /*#__PURE__*/ _jsxs(Card, {
|
|
614
716
|
variant: photoCards ? 'elevation' : 'outlined',
|
|
615
717
|
elevation: 0,
|
|
616
718
|
sx: photoCards ? {
|
|
617
719
|
bgcolor: 'transparent',
|
|
618
720
|
overflow: 'visible'
|
|
619
721
|
} : undefined,
|
|
620
|
-
children:
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
},
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
},
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
722
|
+
children: [
|
|
723
|
+
/*#__PURE__*/ _jsxs(CardActionArea, {
|
|
724
|
+
href: hostId ? `/products/${item.slug}` : undefined,
|
|
725
|
+
disabled: !hostId,
|
|
726
|
+
sx: photoCards ? {
|
|
727
|
+
borderRadius: 2
|
|
728
|
+
} : undefined,
|
|
729
|
+
children: [
|
|
730
|
+
imageUrl ? /*#__PURE__*/ _jsx(CardMedia, _extends({
|
|
731
|
+
component: "img",
|
|
732
|
+
image: imageUrl,
|
|
733
|
+
alt: item.name,
|
|
734
|
+
sx: photoCards ? {
|
|
735
|
+
aspectRatio: '4 / 5',
|
|
736
|
+
objectFit: 'cover',
|
|
737
|
+
borderRadius: 2,
|
|
738
|
+
// A storefront's photo answers the pointer (AGL-3676).
|
|
739
|
+
transition: 'opacity 200ms ease',
|
|
740
|
+
'.MuiCardActionArea-root:hover &': {
|
|
741
|
+
opacity: 0.88
|
|
742
|
+
}
|
|
743
|
+
} : {
|
|
744
|
+
height: 160,
|
|
745
|
+
objectFit: 'cover'
|
|
746
|
+
}
|
|
747
|
+
}, Aglyn.DEFERRED_IMAGE_ATTRIBUTES)) : // Never a blank tile (AGL-3676 follow-up).
|
|
748
|
+
/*#__PURE__*/ _jsx(ProductImagePlaceholder, {
|
|
749
|
+
name: item.name,
|
|
750
|
+
sx: photoCards ? {
|
|
751
|
+
aspectRatio: '4 / 5',
|
|
752
|
+
borderRadius: 2
|
|
753
|
+
} : {
|
|
754
|
+
height: 160
|
|
755
|
+
}
|
|
756
|
+
}),
|
|
757
|
+
/*#__PURE__*/ _jsxs(CardContent, {
|
|
758
|
+
sx: photoCards ? {
|
|
759
|
+
px: 0.5,
|
|
760
|
+
pt: 1.5,
|
|
761
|
+
pb: 1
|
|
762
|
+
} : undefined,
|
|
763
|
+
children: [
|
|
764
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
765
|
+
variant: photoCards ? 'subtitle1' : 'subtitle2',
|
|
766
|
+
noWrap: true,
|
|
767
|
+
children: item.name
|
|
768
|
+
}),
|
|
769
|
+
/*#__PURE__*/ _jsxs(Box, {
|
|
770
|
+
sx: {
|
|
771
|
+
display: 'flex',
|
|
772
|
+
gap: 1,
|
|
773
|
+
alignItems: 'center'
|
|
774
|
+
},
|
|
775
|
+
children: [
|
|
776
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
777
|
+
variant: "body2",
|
|
778
|
+
color: "text.secondary",
|
|
779
|
+
children: priceLabel(item)
|
|
780
|
+
}),
|
|
781
|
+
item.compareAtPriceUsd ? /*#__PURE__*/ _jsx(Typography, {
|
|
782
|
+
variant: "caption",
|
|
783
|
+
color: "text.disabled",
|
|
784
|
+
sx: {
|
|
785
|
+
textDecoration: 'line-through'
|
|
786
|
+
},
|
|
787
|
+
children: `$${item.compareAtPriceUsd}`
|
|
788
|
+
}) : null,
|
|
789
|
+
item.soldOut ? /*#__PURE__*/ _jsx(Chip, {
|
|
790
|
+
label: "Sold out",
|
|
791
|
+
size: "small",
|
|
792
|
+
variant: "outlined"
|
|
793
|
+
}) : null
|
|
794
|
+
]
|
|
795
|
+
})
|
|
796
|
+
]
|
|
797
|
+
})
|
|
798
|
+
]
|
|
799
|
+
}),
|
|
800
|
+
quickAdd ? /*#__PURE__*/ _jsx(QuickAddButton, {
|
|
801
|
+
item: item,
|
|
802
|
+
inert: !hostId,
|
|
803
|
+
busy: quickAdding === item.id,
|
|
804
|
+
added: quickAdded === item.id,
|
|
805
|
+
photoCards: photoCards,
|
|
806
|
+
onAdd: async ()=>{
|
|
807
|
+
if (!hostId || !item.defaultVariantId || quickAdding) return;
|
|
808
|
+
setQuickAdding(item.id);
|
|
809
|
+
const ok = await addToCart({
|
|
810
|
+
hostId,
|
|
811
|
+
siteFetch,
|
|
812
|
+
productId: item.id,
|
|
813
|
+
variantId: item.defaultVariantId,
|
|
814
|
+
quantity: 1,
|
|
815
|
+
item: {
|
|
816
|
+
item_id: item.id,
|
|
817
|
+
item_name: item.name,
|
|
818
|
+
price: item.priceUsd,
|
|
819
|
+
quantity: 1
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
setQuickAdding('');
|
|
823
|
+
if (ok) setQuickAdded(item.id);
|
|
824
|
+
}
|
|
825
|
+
}) : null
|
|
826
|
+
]
|
|
692
827
|
}, item.id);
|
|
693
828
|
})
|
|
694
829
|
});
|
|
@@ -776,6 +911,50 @@ function priceLabel(item) {
|
|
|
776
911
|
]
|
|
777
912
|
}));
|
|
778
913
|
});
|
|
914
|
+
/**
|
|
915
|
+
* A card's quick add: outside the card's link, so a click never follows it.
|
|
916
|
+
* Sample cards on the canvas show the button inert.
|
|
917
|
+
*/ function QuickAddButton({ item, inert, busy, added, photoCards, onAdd }) {
|
|
918
|
+
const action = inert ? 'add' : quickAddAction(item);
|
|
919
|
+
if (!action) return null;
|
|
920
|
+
const sx = photoCards ? {
|
|
921
|
+
mt: 0.5,
|
|
922
|
+
mx: 0.5,
|
|
923
|
+
mb: 1
|
|
924
|
+
} : {
|
|
925
|
+
mx: 2,
|
|
926
|
+
mb: 2
|
|
927
|
+
};
|
|
928
|
+
if (action === 'options') {
|
|
929
|
+
return /*#__PURE__*/ _jsx(Box, {
|
|
930
|
+
sx: sx,
|
|
931
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
932
|
+
size: "small",
|
|
933
|
+
variant: "outlined",
|
|
934
|
+
fullWidth: true,
|
|
935
|
+
href: `/products/${item.slug}`,
|
|
936
|
+
onClick: (event)=>event.stopPropagation(),
|
|
937
|
+
children: 'Choose options'
|
|
938
|
+
})
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
return /*#__PURE__*/ _jsx(Box, {
|
|
942
|
+
sx: sx,
|
|
943
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
944
|
+
size: "small",
|
|
945
|
+
variant: "outlined",
|
|
946
|
+
fullWidth: true,
|
|
947
|
+
disabled: inert || busy,
|
|
948
|
+
"aria-label": `Add ${item.name} to cart`,
|
|
949
|
+
onClick: (event)=>{
|
|
950
|
+
event.preventDefault();
|
|
951
|
+
event.stopPropagation();
|
|
952
|
+
onAdd();
|
|
953
|
+
},
|
|
954
|
+
children: added ? 'Added ✓' : busy ? 'Adding…' : 'Add to cart'
|
|
955
|
+
})
|
|
956
|
+
});
|
|
957
|
+
}
|
|
779
958
|
ProductGrid.displayName = 'AglynProductGrid';
|
|
780
959
|
export const schema = {
|
|
781
960
|
$id: ID,
|
|
@@ -891,6 +1070,24 @@ export const schema = {
|
|
|
891
1070
|
description: 'Copy when nothing matches.',
|
|
892
1071
|
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
893
1072
|
},
|
|
1073
|
+
{
|
|
1074
|
+
name: 'emptyTitle',
|
|
1075
|
+
label: 'Empty headline',
|
|
1076
|
+
description: 'Headline while the store lists nothing yet; set, the empty state ' + 'is a full panel with the empty text and one button.',
|
|
1077
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
name: 'emptyActionLabel',
|
|
1081
|
+
label: 'Empty button label',
|
|
1082
|
+
description: 'The empty panel’s button, e.g. “Get in touch”.',
|
|
1083
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
1084
|
+
},
|
|
1085
|
+
{
|
|
1086
|
+
name: 'emptyActionHref',
|
|
1087
|
+
label: 'Empty button link',
|
|
1088
|
+
description: 'Where the empty panel’s button goes, e.g. /contact.',
|
|
1089
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
1090
|
+
},
|
|
894
1091
|
{
|
|
895
1092
|
name: 'showFilters',
|
|
896
1093
|
label: 'Show filters',
|
|
@@ -949,6 +1146,13 @@ export const schema = {
|
|
|
949
1146
|
value: 'photo'
|
|
950
1147
|
}
|
|
951
1148
|
]
|
|
1149
|
+
},
|
|
1150
|
+
{
|
|
1151
|
+
// Off by default, so no existing grid changes shape on deploy.
|
|
1152
|
+
name: 'quickAdd',
|
|
1153
|
+
label: 'Quick add to cart',
|
|
1154
|
+
description: 'An Add to cart button on each card for a product with one variant; ' + '"Choose options" for one with several.',
|
|
1155
|
+
component: Aglyn.FieldComponentType.CHECKBOX
|
|
952
1156
|
}
|
|
953
1157
|
]
|
|
954
1158
|
};
|