efficient-storefront-blocks 0.0.0 → 0.12.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.
@@ -0,0 +1,145 @@
1
+ /**
2
+ * The public types of `efficient-storefront-blocks/links` (published as dist/links.d.ts).
3
+ *
4
+ * Written out, like `contract.public.d.ts`, and kept honest the same way:
5
+ * `types.check.ts` pairs each declaration with the code it describes.
6
+ *
7
+ * This entry is plain data and pure functions. It imports nothing, so a host
8
+ * can load it beside its own UI without the editor.
9
+ */
10
+
11
+ /** What a link is. */
12
+ export type LinkKind = "page" | "anchor" | "blog" | "product" | "custom";
13
+
14
+ /** The kinds, in menu order. `needs` names the block set a kind's targets come
15
+ * from; a kind without it is offered everywhere. */
16
+ export const LINK_KINDS: readonly { value: LinkKind; label: string; needs?: "commerce" | "service" }[];
17
+
18
+ /** The kinds a host lists, given whether it offers products and services. */
19
+ export function linkKindsFor(offers: { offersCommerce: boolean; offersService: boolean }): typeof LINK_KINDS;
20
+
21
+ /** A page's path; the Home page (`homepage`) is "/". */
22
+ export function pagePath(slug: string): string;
23
+ /** A blog post's path: `/journal/<slug>`. */
24
+ export function postPath(slug: string): string;
25
+ /** A product's path: `/wheels/<slug>`. */
26
+ export function wheelPath(slug: string): string;
27
+ /** A section anchor on a page: the page's path and `#<hash>`. */
28
+ export function anchorPath(pageSlug: string, hash: string): string;
29
+ /** Anchor name → URL hash id, exactly as the page renders it. */
30
+ export function slugifyAnchor(name: string): string;
31
+ /** The section anchors across a page's documents (published, then draft), in
32
+ * order, each slug once. */
33
+ export function pageAnchors(...docs: unknown[]): { slug: string; name: string }[];
34
+
35
+ /** The built-in listing route every site answers on: "/wheels". */
36
+ export const BUILT_IN_LISTING_PATH: "/wheels";
37
+ /** What the Page list calls the listing page: "Products". */
38
+ export const LISTING_PAGE_LABEL: "Products";
39
+ /** The Page list's name for a listing page; "Products · <page>" when a site has several. */
40
+ export function listingPageLabel(pageTitle: string, listingCount: number): string;
41
+ /** The listing section's props on a page (published document first), or null. */
42
+ export function listingNode(...docs: unknown[]): Record<string, unknown> | null;
43
+ /** Does this page hold the listing? */
44
+ export function isProductListingPage(...docs: unknown[]): boolean;
45
+ /** Every listing page's path; with none and `fallback`, the built-in route. */
46
+ export function productListingPaths(
47
+ pages: readonly { slug: string; docs: readonly unknown[] }[],
48
+ opts: { fallback: boolean },
49
+ ): string[];
50
+
51
+ /** Every param a listing link may carry: `type`, then the listing's facets
52
+ * except tyre size. */
53
+ export const LISTING_FILTER_PARAMS: readonly string[];
54
+ /** One filter on a listing link, or none. */
55
+ export type ListingFilter = { param: string; value: string } | null;
56
+ /** The filter a saved link opens the listing on (the type first), or null. */
57
+ export function readListingFilter(url: string): ListingFilter;
58
+ /** Write or clear the filter: every listing param cleared first, the rest kept,
59
+ * a space written as `%20`. */
60
+ export function withListingFilter(url: string, filter: ListingFilter): string;
61
+ /** The listing page a link points at with its filter off — only when that is a
62
+ * listing page; any other link comes back as it is. */
63
+ export function listingTarget(url: string, listingPaths: readonly string[]): string;
64
+
65
+ /** A saved URL → its kind. A listing link with its filter reads as a Page. */
66
+ export function inferLinkKind(url: string, pagePaths: readonly string[], listingPaths?: readonly string[]): LinkKind;
67
+
68
+ /** May this typed address be saved? `/…`, `#…`, http(s), mailto: or tel:. */
69
+ export function isSafeLink(url: string): boolean;
70
+
71
+ /** The Filter list's name for the product type: "Product type". */
72
+ export const PRODUCT_TYPE_FILTER_LABEL: "Product type";
73
+ export type LinkFilterValue = { value: string; label: string };
74
+ export type LinkFilterField = { param: string; label: string; values: LinkFilterValue[] };
75
+ /** One Product Types answer, as much as the filter list reads. */
76
+ export type LinkFieldUsage = {
77
+ kind?: string;
78
+ fieldKey: string;
79
+ filter?: boolean;
80
+ filterOrder?: number | null;
81
+ };
82
+ /** The filters a listing link may offer, with the values this catalogue has. */
83
+ export function listingFilterFields(
84
+ catalogue: readonly unknown[],
85
+ opts: { listing: Record<string, unknown> | null; fieldUsage: readonly LinkFieldUsage[] },
86
+ ): LinkFilterField[];
87
+
88
+ /** One option of a target box (efficient-easel `LinkOption`). */
89
+ export type LinkPickerOption = { value: string; label: string };
90
+ /** What a kind's target box is: a list, a list in groups, or a typed address
91
+ * (efficient-easel `LinkTarget`). */
92
+ export type LinkPickerTarget =
93
+ | { type: "select"; options: readonly LinkPickerOption[]; placeholder: string }
94
+ | { type: "groups"; groups: readonly { label: string; options: readonly LinkPickerOption[] }[]; placeholder: string }
95
+ | { type: "text" };
96
+ /** One entry of the Link type list (efficient-easel `LinkKindChoice`). */
97
+ export type LinkPickerKind = {
98
+ value: string;
99
+ label: string;
100
+ target: LinkPickerTarget;
101
+ hint?: string;
102
+ hideWhenEmpty?: boolean;
103
+ };
104
+ /** The URL rules the picker is handed (efficient-easel `LinkRules`). */
105
+ export type LinkPickerRules = {
106
+ kindOf: (url: string) => string;
107
+ targetOf: (url: string) => string;
108
+ readFilter: (url: string) => ListingFilter;
109
+ withFilter: (url: string, filter: ListingFilter) => string;
110
+ isSafe: (url: string) => boolean;
111
+ };
112
+ export type LinkPickerSetupInput = {
113
+ /** The pages a link may point at (no system pages); `docs` = published, then draft. */
114
+ pages: readonly { slug: string; title: string; docs: readonly unknown[] }[];
115
+ posts: readonly { slug: string; title: string }[];
116
+ products: readonly { slug: string; name: string }[];
117
+ /** The site's products, as `GET /api/storefront/products/?kind=…` sends them. */
118
+ catalogue: readonly unknown[];
119
+ fieldUsage: readonly LinkFieldUsage[];
120
+ offers: { offersCommerce: boolean; offersService: boolean };
121
+ };
122
+ export type LinkPickerSetup = {
123
+ kinds: LinkPickerKind[];
124
+ rules: LinkPickerRules;
125
+ filtersFor: (target: string) => readonly { param: string; label: string; values: readonly LinkPickerOption[] }[] | null;
126
+ };
127
+ /**
128
+ * What the shared picker (efficient-easel `LinkPicker`) is handed, from a
129
+ * host's own data: the kinds with their options (the listing page called
130
+ * "Products"), the URL rules, and the filters a listing link may carry. The
131
+ * website editor's Link field calls the same function.
132
+ */
133
+ export function linkPickerSetup(input: LinkPickerSetupInput): LinkPickerSetup;
134
+
135
+ /** One answer as the admin's read sends it (`GET /api/storefront/field-usage/?site=`). */
136
+ export type AdminFieldUsageRow = {
137
+ /** The backend's rule: the kind the row's product type sells as, or null. */
138
+ kind?: string | null;
139
+ field_key: string;
140
+ filter?: boolean | null;
141
+ filter_order?: number | null;
142
+ };
143
+ /** The admin's rows → the answers the Filter list reads: a row with no kind is
144
+ * left out, and an unanswered place stays absent (a null `filter` is not false). */
145
+ export function fieldUsageFromAdminRows(rows: readonly AdminFieldUsageRow[] | null | undefined): LinkFieldUsage[];
package/dist/links.js ADDED
@@ -0,0 +1 @@
1
+ var j=["width","profile","rim"];var _e=/^\s*(\d{2,3})\s*\/\s*(\d{2,3})\s*[A-Za-z]*\s*(\d{2}(?:\.\d+)?)\s*$/,Ae={width:[100,500],profile:[20,100],rim:[10,30]};function N(e){let n=_e.exec(e??"");if(!n)return null;let t={width:Number(n[1]),profile:Number(n[2]),rim:Number(n[3])};return j.every(o=>{let[l,a]=Ae[o];return t[o]>=l&&t[o]<=a})?t:null}function k(e){if(e.width==null)return"";if(e.profile==null)return String(e.width);let n=`${e.width}/${e.profile}`;return e.rim==null?n:`${n} R${e.rim}`}function V(e){return[k({width:e.width}),k({width:e.width,profile:e.profile}),k(e)]}var h=["alloy-wheel","tyre"],Z=["alloy-wheel"],x={"alloy-wheel":"Alloy wheels",tyre:"Tyres"};var Qe=h.map(e=>({value:e,label:x[e]}));function O(e){return e==null?[...Z]:Array.isArray(e)?h.filter(n=>e.includes(n)):[...Z]}var f=e=>e;function d(e){return f(e).kind==="tyre"?"tyre":"alloy-wheel"}function U(e){return f(e).brand??""}function X(e){return f(e).prices??void 0}function J(e){return f(e).inStock!==!1}function Q(e){let n=f(e),t=d(e)==="tyre"?n.rimDiameters:n.sizes;return Array.isArray(t)?t.filter(r=>typeof r=="number"&&Number.isFinite(r)):[]}function D(e){return d(e)==="tyre"?[]:(f(e).finishes??[]).filter(n=>typeof n?.family=="string").map(n=>({family:n.family,color:n.color??null}))}function ee(e){return D(e).map(n=>n.family)}function ne(e){if(d(e)==="tyre")return[];let n=f(e),t=n.categories;return t&&t.length>0?t:n.process?[n.process]:[]}function te(e){return d(e)==="tyre"?[]:f(e).spec?.pcds??[]}function re(e){return d(e)!=="tyre"?[]:f(e).tyreTypes??[]}function ie(e){return d(e)!=="tyre"?[]:f(e).speedRatings??[]}function oe(e){if(d(e)!=="tyre")return[];let n=f(e).sizes;return Array.isArray(n)?n.map(t=>N(typeof t=="string"?t:null)).filter(t=>t!==null):[]}var se="homepage";function le(e){return(e??"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}var L=[{value:"page",label:"Page"},{value:"anchor",label:"Anchor"},{value:"blog",label:"Blog post",needs:"service"},{value:"product",label:"Product",needs:"commerce"},{value:"custom",label:"Custom URL"}];function F(e){return e.offersCommerce&&e.offersService?L:L.filter(n=>!n.needs||(n.needs==="commerce"?e.offersCommerce:e.offersService))}function g(e){return e===se?"/":`/${e}`}function w(e){return`/journal/${e}`}function T(e){return`/wheels/${e}`}function _(e,n){return`${g(e)}#${n}`}function z(e){return le(e)}function Ke(e){return typeof e=="string"?e.trim():e&&typeof e=="object"&&typeof e.text=="string"?e.text.trim():""}function A(...e){let n=new Set,t=[];for(let r of e)for(let o of r?.content??[]){let l=Ke(o?.props?.anchor);if(!l)continue;let a=z(l);!a||n.has(a)||(n.add(a),t.push({slug:a,name:l}))}return t}var Ie=["http","https","mailto","tel"];function S(e){let n=e.trim();if(!n||/\s/.test(n))return!1;let t=/^([a-z][a-z0-9+.-]*):/i.exec(n);return!t||Ie.includes(t[1].toLowerCase())}var P={choosePage:"Choose a page",chooseSection:"Choose a section",noSections:"No section anchors yet",sectionHint:"Jumps to a section on that page.",choosePost:"Choose a post",chooseProduct:"Choose a product"};function K(e,n,t){if(!e)return"page";if(e.startsWith("/journal/"))return"blog";if(e.startsWith("/wheels/"))return"product";if(e.includes("#")){let r=e.slice(0,e.indexOf("#"));if(r===""||r==="/"||n.includes(r))return"anchor"}return e==="/"||n.includes(e)||t&&t.listingPaths.includes(t.targetOf(e))?"page":"custom"}function ae(e,n){let t=e.pages.map(i=>({value:g(i.slug),label:i.title})),r=n?.pageOptions?n.pageOptions(t):t,o=r.map(i=>i.value),l=e.pages.map(i=>({label:i.title,options:A(...i.docs).map(u=>({value:_(i.slug,u.slug),label:u.name}))})).filter(i=>i.options.length>0),a=i=>{switch(i){case"page":return{type:"select",options:r,placeholder:P.choosePage};case"anchor":return{type:"groups",groups:l,placeholder:l.length?P.chooseSection:P.noSections};case"blog":return{type:"select",options:e.posts.map(u=>({value:w(u.slug),label:u.title||u.slug})),placeholder:P.choosePost};case"product":return{type:"select",options:e.products.map(u=>({value:u.href,label:u.name||u.href})),placeholder:P.chooseProduct};case"custom":return{type:"text"}}},c=F(e.offers).map(i=>({value:i.value,label:i.label,target:a(i.value),...i.value==="anchor"?{hint:P.sectionHint}:{},...i.value==="blog"||i.value==="product"?{hideWhenEmpty:!0}:{}}));if(!n)return{kinds:c,rules:{kindOf:i=>K(i,o),targetOf:i=>i,readFilter:()=>null,withFilter:i=>i,isSafe:S}};let s=i=>{let u=n.withFilter(i,null);return n.listingPaths.includes(u)?u:i};return{kinds:c,rules:{kindOf:i=>K(i,o,{listingPaths:n.listingPaths,targetOf:s}),targetOf:s,readFilter:n.readFilter,withFilter:n.withFilter,isSafe:S},filtersFor:i=>n.listingPaths.includes(i)?n.filtersFor(i):null}}function v(e,n){return e.length===0?e:e.filter(t=>t.kind===void 0||t.kind===n)}function ue(e,n){let t=n==="filter"?"filterOrder":"cardOrder",r=new Map;for(let o of e){let l=o[t];if(typeof l!="number"||!Number.isFinite(l))continue;let a=r.get(o.fieldKey);(a===void 0||l<a)&&r.set(o.fieldKey,l)}return o=>o?r.get(o):void 0}function ce(e,n,t,r){let o=new Map;for(let s of t){let i=s[r];typeof i=="number"&&o.set(s.fieldKey,i)}if(o.size===0)return e;let l=[],a=[];e.forEach((s,i)=>{let u=n(s);u&&(l.push(i),a.push({item:s,index:i,order:o.get(u)}))}),a.sort((s,i)=>s.order!==void 0&&i.order!==void 0?s.order-i.order||s.index-i.index:s.order!==void 0?-1:i.order!==void 0?1:s.index-i.index);let c=[...e];return l.forEach((s,i)=>{c[s]=a[i].item}),c.every((s,i)=>s===e[i])?e:c}function pe(e){return Ce(e,"filter")}var Re="collection";function M(e,n){return{tyreSizes:{},brands:{"alloy-wheel":"brand",tyre:"brand"},finishes:{"alloy-wheel":"wheel_finish_ref"},diameters:{"alloy-wheel":"diameter",tyre:"rim_diameter"},collections:{"alloy-wheel":Re},pcds:{"alloy-wheel":"pcd"},tyreTypes:{tyre:"tire_type"},speedRatings:{tyre:"speed_rating"}}[e]?.[n]}function Ce(e,n){let t=new Set(e.filter(r=>r[n]===!1).map(r=>r.fieldKey));return r=>!r||!t.has(r)}function Ee(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function de(e,n){let t=e?.[n];return Ee(t)?t:null}function fe(e,n,t,r){if(t==null&&r==null)return!0;let o=de(e,n);return!(o===null||t!=null&&o<t||r!=null&&o>r)}var Ne={recommended:"Recommended","price-asc":"Price \xB7 low to high","price-desc":"Price \xB7 high to low",new:"Newest",name:"Name A\u2013Z"},Rn=Object.keys(Ne);var me=["tyreSizes","brands","finishes","diameters","collections","pcds","tyreTypes","speedRatings"],Oe={tyreSizes:["tyre"],brands:["alloy-wheel","tyre"],finishes:["alloy-wheel"],diameters:["alloy-wheel","tyre"],collections:["alloy-wheel"],pcds:["alloy-wheel"],tyreTypes:["tyre"],speedRatings:["tyre"]},Ue={diameters:"tyreSizes"};function De(e){if(e.length===0)return[];let n=me.filter(t=>e.every(r=>Oe[t].includes(r)));return n.filter(t=>{let r=Ue[t];return!r||!n.includes(r)})}function ze(e){let n=new Set;for(let t of e)n.add(d(t));return[...n]}var ge={tyreSizes:[],brands:[],finishes:[],diameters:[],collections:[],pcds:[],tyreTypes:[],speedRatings:[],priceMax:null,inStockOnly:!1,kind:null,sort:"recommended",page:1};function ve(e,n,t,r=null){if(r!=="kind"&&n.kind&&d(e)!==n.kind)return!1;for(let o of me){if(r===o)continue;let l=n[o];if(l.length===0)continue;let a=l.map(String);if(!ye(e,o).some(c=>a.includes(c)))return!1}return!(r!=="price"&&!fe(X(e),t,null,n.priceMax)||r!=="inStock"&&n.inStockOnly&&!J(e))}var Me={tyreSizes:"Size",brands:"Brand",finishes:"Colour",diameters:"Size \xB7 diameter",collections:"Collection",pcds:"PCD \xB7 fitment",tyreTypes:"Tyre type",speedRatings:"Speed rating"};function ye(e,n){switch(n){case"tyreSizes":return[...new Set(oe(e).flatMap(V))];case"brands":return U(e)?[U(e)]:[];case"finishes":return ee(e);case"diameters":return Q(e).map(String);case"collections":return ne(e);case"pcds":return te(e);case"tyreTypes":return re(e);case"speedRatings":return ie(e)}}function Be(e){let n=new Map;for(let t of e)for(let r of D(t))r.color&&!n.has(r.family)&&n.set(r.family,r.color);return n}function Pe(e,n,t,r=ze(e),o=[]){let l=i=>$e(i,r,o),a=Be(e),c=De(r).filter(i=>i!=="tyreSizes").filter(l).map(i=>{let u=n[i].map(String),q=new Set,E=new Map,b=new Map;for(let p of e){let y=ye(p,i);for(let m of y)q.add(m);for(let m of new Set(y))b.set(m,(b.get(m)??0)+1);if(ve(p,n,t,i))for(let m of new Set(y))E.set(m,(E.get(m)??0)+1)}let Te=[...q].map(p=>({value:p,label:i==="diameters"?`${p}\u2033`:p,count:E.get(p)??0,checked:u.includes(p),swatch:i==="finishes"?a.get(p)??null:null})).sort((p,y)=>{if(i==="diameters")return Number(p.value)-Number(y.value);let m=(b.get(y.value)??0)-(b.get(p.value)??0);return m!==0?m:p.value.localeCompare(y.value)});return{key:i,label:Me[i],options:Te}}).filter(i=>i.options.length>We),s=[];for(let i of c){let u=Ye(i.key,r,o);u!==void 0&&s.push({fieldKey:i.key,filterOrder:u})}return[...ce(c,i=>i.key,s,"filterOrder")]}var We=1;function he(e){return e.showCollection===!1?["collections"]:[]}function $e(e,n,t){return n.length===0||t.length===0?!0:n.some(r=>pe(v(t,r))(M(e,r)))}function Ye(e,n,t){if(t.length===0)return;let r;for(let o of n){let l=ue(v(t,o),"filter")(M(e,o));l!==void 0&&(r===void 0||l<r)&&(r=l)}return r}var B={tyreSizes:"tyreSize",brands:"brand",finishes:"colour",diameters:"size",collections:"collection",pcds:"pcd",tyreTypes:"tyreType",speedRatings:"speed"},W="type";var Se="AlloyWheelsListing";var I="/wheels",R="Products";function be(e,n){return n>1?`${R} \xB7 ${e}`:R}function $(...e){for(let n of e){let t=(n?.content??[]).find(r=>r?.type===Se);if(t)return t.props??{}}return null}function C(...e){return $(...e)!==null}function ke(e,n){let t=e.filter(r=>C(...r.docs)).map(r=>g(r.slug));return t.length===0&&n.fallback?[I]:t}var Y=[W,...Object.entries(B).filter(([e])=>e!=="tyreSizes").map(([,e])=>e)];function xe(e){let n=e.indexOf("#"),t=n===-1?"":e.slice(n),r=n===-1?e:e.slice(0,n),o=r.indexOf("?");return{path:o===-1?r:r.slice(0,o),query:o===-1?"":r.slice(o+1),hash:t}}function Ge(e){try{return decodeURIComponent(e.replace(/\+/g," "))}catch{return e}}function Le(e){let n=new URLSearchParams(xe(e).query);for(let t of Y){let r=n.get(t);if(r)return{param:t,value:r}}return null}function G(e,n){let{path:t,query:r,hash:o}=xe(e),l=r.split("&").filter(a=>a&&!Y.includes(Ge(a.split("=")[0])));return n?.value&&l.push(`${encodeURIComponent(n.param)}=${encodeURIComponent(n.value)}`),`${t}${l.length?`?${l.join("&")}`:""}${o}`}function Fe(e,n){let t=G(e,null);return n.includes(t)?t:e}function He(e,n,t=[]){return K(e,n,{listingPaths:t,targetOf:r=>Fe(r,t)})}function qe(e){return Array.isArray(e)?e.filter(n=>typeof n?.kind=="string"&&typeof n.field_key=="string").map(n=>({kind:n.kind,fieldKey:n.field_key,...typeof n.filter=="boolean"?{filter:n.filter}:{},filterOrder:n.filter_order??null})):[]}var we="Product type",je="AUD";function H(e,n){let t=n.listing??{},r=O(t.kinds),o=e.filter(s=>r.includes(d(s))),l=he(t),a=Pe(o,ge,je,r,n.fieldUsage).filter(s=>!l.includes(s.key)).map(s=>({param:B[s.key],label:s.label,values:s.options.filter(i=>!i.value.includes(",")).map(i=>({value:i.value,label:i.label}))})).filter(s=>s.values.length>0),c=h.filter(s=>r.includes(s)&&o.some(i=>d(i)===s));return c.length>1&&a.unshift({param:W,label:we,values:c.map(s=>({value:s,label:x[s]}))}),a}function Ve(e){return n=>{let t=ke(n,{fallback:e.offersCommerce}),r=n.filter(o=>C(...o.docs)).length;return{listingPaths:t,pageOptions:o=>{let l=o.map(a=>{let c=n.find(s=>g(s.slug)===a.value);return c&&C(...c.docs)?{...a,label:be(c.title,r)}:a});return r===0&&e.offersCommerce&&!l.some(a=>a.value===I)&&l.push({value:I,label:R}),l},filtersFor:o=>{if(!t.includes(o))return null;let l=n.find(a=>g(a.slug)===o);return H(e.catalogue,{listing:l?$(...l.docs):null,fieldUsage:e.fieldUsage})},readFilter:Le,withFilter:G}}}function Ze(e){let n=Ve({catalogue:e.catalogue,fieldUsage:e.fieldUsage,offersCommerce:e.offers.offersCommerce})(e.pages),t=ae({pages:e.pages,posts:e.posts,products:e.products.map(r=>({href:T(r.slug),name:r.name||r.slug})),offers:e.offers},n);return{...t,filtersFor:t.filtersFor??(()=>null)}}function qn(e,n){return H(e,n)}export{I as BUILT_IN_LISTING_PATH,L as LINK_KINDS,Y as LISTING_FILTER_PARAMS,R as LISTING_PAGE_LABEL,we as PRODUCT_TYPE_FILTER_LABEL,_ as anchorPath,qe as fieldUsageFromAdminRows,He as inferLinkKind,C as isProductListingPage,S as isSafeLink,F as linkKindsFor,Ze as linkPickerSetup,qn as listingFilterFields,$ as listingNode,be as listingPageLabel,Fe as listingTarget,A as pageAnchors,g as pagePath,w as postPath,ke as productListingPaths,Le as readListingFilter,z as slugifyAnchor,T as wheelPath,G as withListingFilter};
package/package.json CHANGED
@@ -1,8 +1,59 @@
1
1
  {
2
2
  "name": "efficient-storefront-blocks",
3
- "version": "0.0.0",
4
- "description": "Reserved for the EFFICIENT storefront's sections for efficient-web-builder (Efficient Pty Ltd).",
3
+ "version": "0.12.0",
4
+ "description": "The EFFICIENT storefront's website editor — the website builder assembled with the storefront's own sections — for an app that edits a storefront website inside its own page. Built from the efficient-storefront repository's own source.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Efficient Pty Ltd",
7
- "files": ["README.md"]
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Efficient-Pty-Ltd/efficient-storefront.git",
10
+ "directory": "packages/website"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "type": "module",
16
+ "sideEffects": [
17
+ "**/*.css"
18
+ ],
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js",
23
+ "default": "./dist/index.js"
24
+ },
25
+ "./contract": {
26
+ "types": "./dist/contract.d.ts",
27
+ "import": "./dist/contract.js",
28
+ "default": "./dist/contract.js"
29
+ },
30
+ "./links": {
31
+ "types": "./dist/links.d.ts",
32
+ "import": "./dist/links.js",
33
+ "default": "./dist/links.js"
34
+ },
35
+ "./editor.css": "./dist/editor.css"
36
+ },
37
+ "files": [
38
+ "dist/index.js",
39
+ "dist/index.d.ts",
40
+ "dist/contract.js",
41
+ "dist/contract.d.ts",
42
+ "dist/links.js",
43
+ "dist/links.d.ts",
44
+ "dist/editor.css",
45
+ "dist/chunks",
46
+ "README.md",
47
+ "CHANGELOG.md",
48
+ "LICENSE"
49
+ ],
50
+ "peerDependencies": {
51
+ "efficient-easel": "^0.102.0",
52
+ "efficient-shell": "^4.131.0",
53
+ "react": ">=19",
54
+ "react-dom": ">=19"
55
+ },
56
+ "scripts": {
57
+ "build": "node build.mjs && cp src/public.d.ts dist/index.d.ts"
58
+ }
8
59
  }