@commercebuild/extension 0.0.18 → 0.0.19

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercebuild/extension",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "types": "./types/index.d.ts",
5
5
  "exports": {
6
6
  ".": {
@@ -36,6 +36,7 @@
36
36
  "commercebuild-extension": "./scripts/cli.js"
37
37
  },
38
38
  "scripts": {
39
- "test": "node scripts/test-build.mjs"
39
+ "test": "node scripts/test-build.mjs",
40
+ "release": "npm whoami || npm login && pnpm publish --no-git-checks"
40
41
  }
41
42
  }
@@ -31,9 +31,8 @@
31
31
  "enum": ["firebase"]
32
32
  },
33
33
  "scope": {
34
- "description": "\"store\" (the default): the merchant supplies the config per store under Installed Apps → Configure data — do not put a config here. \"app\": the config is fixed in this declaration (required below), owned by the app and not merchant-overridable.",
35
- "enum": ["store", "app"],
36
- "default": "store"
34
+ "description": "\"store\": the merchant supplies the config per store under Installed Apps → Configure data — do not put a config here. \"app\": the config is fixed in this declaration (required below), owned by the app and not merchant-overridable. Omitted: inferred — a declaration with a \"config\" is app-scoped, one without is store-scoped.",
35
+ "enum": ["store", "app"]
37
36
  },
38
37
  "label": {
39
38
  "type": "string",
@@ -45,6 +44,10 @@
45
44
  },
46
45
  "config": {
47
46
  "$ref": "#/$defs/firebaseConfig"
47
+ },
48
+ "oidcEnabled": {
49
+ "type": "boolean",
50
+ "description": "Federate the signed-in shopper's CB Store identity into this connection's Firebase Auth (Firestore Rules then read the cb_* claims). App-scoped declarations only — the merchant accepts an identity-sharing notice once at install/first configuration. On a store-scoped connection the merchant controls this from Installed Apps → Configure data instead, and a flag here is ignored."
48
51
  }
49
52
  },
50
53
  "additionalProperties": false,
@@ -89,6 +92,9 @@
89
92
  },
90
93
  "measurementId": {
91
94
  "type": "string"
95
+ },
96
+ "databaseId": {
97
+ "type": "string"
92
98
  }
93
99
  },
94
100
  "additionalProperties": true
package/types/global.d.ts CHANGED
@@ -28,7 +28,7 @@ declare function useLanagueTranslater(): {
28
28
  _t: (k: string, obj?: any) => string | undefined;
29
29
  t: (k: string) => string;
30
30
  tt: (k: string, obj?: any) => (kk: string) => string;
31
- tmsg: (k: string) => any;
31
+ tmsg: (kk: string) => string;
32
32
  tlink: (uri: string) => string;
33
33
  talink: (uri: string) => string;
34
34
  trlink: (uri: string) => string;
@@ -48,6 +48,7 @@ type CartRequestItem = Omit<
48
48
  unitPrice?: number;
49
49
  detailPageUrl?: string;
50
50
  };
51
+ type PostItemsSearchRequest = catalog_v1.PostItemsSearchRequest;
51
52
  type PostItemsSearchItem = catalog_v1.PostItemsSearchItem;
52
53
  type PostItemsSearchResponse = catalog_v1.PostItemsSearchResponse;
53
54
  type GetItemDetailResponse = catalog_v1.GetItemDetailResponse;
@@ -81,12 +82,95 @@ declare function AddToCart({
81
82
  fullWidth,
82
83
  }: AddToCartProps): React.JSX.Element;
83
84
 
85
+ interface GroupSectionItem {
86
+ sectionKey: "group";
87
+ id?: string;
88
+ visible?:
89
+ | boolean
90
+ | {
91
+ value?: boolean;
92
+ default?: boolean;
93
+ };
94
+ gap?: string;
95
+ justify?: string;
96
+ align?: string;
97
+ items?: SectionItem[];
98
+ }
99
+ interface LeafSectionItem {
100
+ sectionKey: string;
101
+ id?: string;
102
+ visible?:
103
+ | boolean
104
+ | {
105
+ value?: boolean;
106
+ default?: boolean;
107
+ };
108
+ }
109
+ /**
110
+ * A leaf section that renders authored rich-text using the variable
111
+ * resolution pipeline. Carried by the `customText` discriminator so the
112
+ * variant-specific fields stay off the shared base.
113
+ */
114
+ interface CustomTextLeafSectionItem extends LeafSectionItem {
115
+ sectionKey: "customText";
116
+ customLabel?: string;
117
+ customLabelVisible?: boolean;
118
+ customValue?: string;
119
+ }
120
+ type SectionItem =
121
+ | GroupSectionItem
122
+ | CustomTextLeafSectionItem
123
+ | LeafSectionItem;
124
+
125
+ interface StandardCardLeafField extends LeafSectionItem {
126
+ sectionKey:
127
+ | "image"
128
+ | "item_code"
129
+ | "title"
130
+ | "stock"
131
+ | "price"
132
+ | "add_to_cart";
133
+ }
134
+ type CardLeafField = StandardCardLeafField | CustomTextLeafSectionItem;
135
+ type CardField = CardLeafField | GroupSectionItem;
136
+ /**
137
+ * One column of a list-view row. Columns sit left-to-right; the entries inside
138
+ * a column stack vertically, and a `group` entry puts several of them on one
139
+ * row (the same primitive the tile card uses).
140
+ */
141
+ interface CardColumn {
142
+ id?: string;
143
+ visible?:
144
+ | boolean
145
+ | {
146
+ value?: boolean;
147
+ default?: boolean;
148
+ };
149
+ /** Key into LIST_COLUMN_WIDTH. */
150
+ width?: string;
151
+ /** Key into LIST_COLUMN_ALIGN. */
152
+ align?: string;
153
+ items?: CardField[];
154
+ }
155
+
84
156
  declare function CategoryProduct({
85
157
  product,
86
158
  imagePriority,
159
+ schemeKey,
160
+ fields,
161
+ listColumns,
162
+ imageSizes,
87
163
  }: {
88
164
  product: PostItemsSearchItem;
89
165
  imagePriority?: boolean;
166
+ /** Product Card theme scheme chosen on the listing block. */
167
+ schemeKey?: string;
168
+ /** Per-block field override; undefined leaves the scheme in charge. */
169
+ fields?: CardField[];
170
+ /** List-view columns; undefined renders the stacked tile card. */
171
+ listColumns?: CardColumn[];
172
+ /** Overrides the card's default `sizes` (list thumbnails are much smaller). */
173
+ imageSizes?: string;
90
174
  }): React.JSX.Element;
91
175
 
92
176
  declare function CategoryBreadcrumb({
@@ -107,13 +191,22 @@ declare function CategorySidebar({
107
191
  aggregation,
108
192
  currentFilters,
109
193
  isDrawer,
194
+ sections,
195
+ showCounts,
110
196
  }: {
111
197
  category: Category;
112
198
  url: string;
113
199
  aggregation?: PostItemsSearchResponse["aggregation"];
114
200
  currentFilters: Record<string, string[]>;
115
201
  isDrawer?: boolean;
116
- }): React.JSX.Element | null;
202
+ /**
203
+ * Structural elements to render, in order, from the listing block's
204
+ * `filterSections` repeater. Undefined keeps the historic order.
205
+ */
206
+ sections?: string[];
207
+ /** Show the match count beside each facet name and value. */
208
+ showCounts?: boolean;
209
+ }): React__default.JSX.Element | null;
117
210
 
118
211
  declare function CategorySort({
119
212
  url,
@@ -130,9 +223,36 @@ declare function CategorySort({
130
223
  declare function CategoryProducts({
131
224
  hasSiderbar,
132
225
  items,
226
+ columnsClass,
227
+ schemeKey,
228
+ fields,
229
+ listColumns,
230
+ autoScroll,
231
+ total,
133
232
  }: {
134
233
  hasSiderbar?: boolean;
135
234
  items: PostItemsSearchItem[];
235
+ /**
236
+ * Literal Tailwind column classes from the listing block's frozen map.
237
+ * Never interpolated — `grid-cols-${n}` compiles to nothing.
238
+ * The default reproduces the pre-CMS grid exactly.
239
+ */
240
+ columnsClass?: string;
241
+ schemeKey?: string;
242
+ fields?: CardField[];
243
+ /**
244
+ * List-view columns. Non-empty switches the grid to a single column of rows
245
+ * and hands each card its own layout — `columnsClass` is then unused.
246
+ */
247
+ listColumns?: CardColumn[];
248
+ /**
249
+ * The route's own search request, replayed a page at a time as the shopper
250
+ * scrolls. `null` keeps the grid to the server-rendered page, which is what
251
+ * page-number pagination wants.
252
+ */
253
+ autoScroll?: PostItemsSearchRequest | null;
254
+ /** Total matches, so auto-scroll knows when to stop. */
255
+ total?: number;
136
256
  }): React.JSX.Element;
137
257
 
138
258
  declare function CategoryProductsPageSize({
@@ -154,13 +274,120 @@ declare function ProductTitle({
154
274
  product: GetItemDetailResponse;
155
275
  }): React.JSX.Element;
156
276
 
277
+ /**
278
+ * Shared Constants Types
279
+ *
280
+ * Type definitions for constants used across the theme editor.
281
+ * These establish common interfaces for Tailwind CSS constants and configuration.
282
+ */
283
+
284
+ /**
285
+ * Box Shadow Config Interface
286
+ * Configuration for box shadow utilities
287
+ * Consolidated from cms/utils/tailwind-utils.ts
288
+ */
289
+ interface BoxShadowConfig {
290
+ preset?: string;
291
+ custom?: {
292
+ offsetX: string;
293
+ offsetY: string;
294
+ blurRadius: string;
295
+ spreadRadius?: string;
296
+ color: string;
297
+ opacity?: string;
298
+ inset?: boolean;
299
+ };
300
+ useCustom?: boolean;
301
+ }
302
+
303
+ /**
304
+ * Border Width Interface
305
+ * Interface for border width configuration
306
+ * Consolidated from cms/components/property/border-controller.tsx
307
+ */
308
+ interface BorderWidth {
309
+ top: string;
310
+ right: string;
311
+ bottom: string;
312
+ left: string;
313
+ }
314
+ /**
315
+ * Border Radius Interface
316
+ * Interface for border radius configuration
317
+ * Consolidated from cms/components/property/border-controller.tsx
318
+ */
319
+ interface BorderRadius {
320
+ topLeft: string;
321
+ topRight: string;
322
+ bottomRight: string;
323
+ bottomLeft: string;
324
+ }
325
+ /**
326
+ * Border Interface
327
+ * Interface for border configuration
328
+ * Consolidated from cms/components/property/border-controller.tsx
329
+ */
330
+ interface Border {
331
+ width: BorderWidth;
332
+ style: string;
333
+ color: string;
334
+ /** Border color opacity 0–100 (UN-3049). Optional; undefined ⇒ fully opaque. */
335
+ opacity?: string;
336
+ radius: BorderRadius;
337
+ }
338
+
339
+ type ImageFit = "cover" | "contain" | "fill" | "none";
340
+ /** Aspect vocabulary shared with the Product Card scheme (UN-3049). */
341
+ type ImageAspect = "square" | "landscape" | "portrait" | "wide";
342
+ interface ImageSurfaceSettings {
343
+ border?: Border;
344
+ shadow?: BoxShadowConfig;
345
+ bgColor?: string;
346
+ }
347
+
157
348
  type ThumbnailPosition = "top" | "right" | "bottom" | "left";
349
+ /**
350
+ * How the desktop thumbnail strip presents itself (UN-3295).
351
+ *
352
+ * `carousel` is the shipped behaviour: one scrollable rail with prev/next.
353
+ * `stack` shows a fixed number of thumbnails and expands the rest in place.
354
+ * Stack applies to `top` and `bottom` only — a `left`/`right` strip is one
355
+ * `--thumb-w` column wide (80px by default), too narrow for the control.
356
+ */
357
+ type ThumbnailLayout = "carousel" | "stack";
358
+ /** Main-image controls (UN-3285): presentation + its own Border/Shadow. */
359
+ interface ProductImageDisplaySettings extends ImageSurfaceSettings {
360
+ aspect?: ImageAspect;
361
+ fit?: ImageFit;
362
+ }
363
+ /**
364
+ * Thumbnail controls (UN-3285). Width and height are independent px values;
365
+ * both default to the legacy 80px box. Desktop-only (sm+) — on mobile the
366
+ * carousel IS the gallery and its slides stay full-width.
367
+ */
368
+ interface ProductThumbnailDisplaySettings extends ImageSurfaceSettings {
369
+ width?: number | "";
370
+ height?: number | "";
371
+ /** Gap between thumbnails, px. Unset = the 10px default; explicit 0 holds. */
372
+ gap?: number | "";
373
+ /** Gap between the strip and the main image, px. Unset = the 10px default. */
374
+ imageGap?: number | "";
375
+ fit?: ImageFit;
376
+ /** Desktop strip presentation (UN-3295). Unset = the shipped carousel. */
377
+ layout?: ThumbnailLayout;
378
+ /** Thumbnails shown before "Show more", stack layout only. Unset = 4. */
379
+ showMoreAfter?: number | "";
380
+ }
158
381
  declare const ProductImages: ({
159
382
  product,
160
383
  thumbnailPosition,
384
+ imageSettings,
385
+ thumbnailSettings,
161
386
  }: {
162
387
  product: GetItemDetailResponse;
163
388
  thumbnailPosition?: ThumbnailPosition;
389
+ imageSettings?: ProductImageDisplaySettings;
390
+ thumbnailSettings?: ProductThumbnailDisplaySettings;
164
391
  }) => React.JSX.Element;
165
392
 
166
393
  declare function ProductPrice({
@@ -311,31 +538,27 @@ interface FirebaseConnectionConfig {
311
538
  messagingSenderId?: string;
312
539
  appId?: string;
313
540
  measurementId?: string;
541
+ /**
542
+ * Firestore database to use when the project has more than one. NOT part
543
+ * of the console's firebaseConfig snippet — the SDK has no notion of a
544
+ * default database in its options, so this rides along as an extra key
545
+ * (initializeApp keeps unknown keys on `app.options`) and the app passes
546
+ * it to `getFirestore(app, databaseId)`. Empty/absent = `(default)`.
547
+ */
548
+ databaseId?: string;
314
549
  }
315
550
 
316
551
  /**
317
- * Per-extension render scope.
318
- *
319
- * Extension code has no runtime identity of its own — components are
320
- * bare functions and `cb` is one page-global object, while a single
321
- * React tree can hold components from several different extensions at
322
- * once. This context supplies that identity lexically: the host wraps
323
- * every extension render site (renderExtensionComponent's boundary and
324
- * the extension page route) in a provider carrying the registration id
325
- * and the extension's resolved per-store configuration. Contract hooks
326
- * like cb.utils.useFirebaseApp() read it, so the same component gets
327
- * its own extension's connections wherever it renders — including the
328
- * synthetic "preview" / "local" registrations, which just carry their
329
- * own scope value.
552
+ * Shared implementation — see @commercebuild/extension-host-libs
553
+ * (extension-scope.tsx). Only the TYPE re-exports below stay special:
554
+ * they are re-exported into the generated author-facing declaration,
555
+ * and tsup's dts build force-externalizes anything imported by package
556
+ * name (a storefront dependency) authors can't install the workspace
557
+ * package, so its types must inline via a RELATIVE path. A type-only
558
+ * import is erased at runtime, so the bundler never sees this path;
559
+ * runtime members keep importing the package normally.
330
560
  */
331
561
 
332
- /**
333
- * The provider type family (config shapes, the ResolvedConnection
334
- * discriminated union) is owned by the provider registry in
335
- * @commercebuild/extension-host-libs — one place declares them for the
336
- * storefront, storeadmin and the config JSON Schema alike. This module
337
- * re-exports the contract-facing names.
338
- */
339
562
  type CbFirebaseConfig = FirebaseConnectionConfig;
340
563
 
341
564
  /**
@@ -572,7 +795,9 @@ interface CbHostApi {
572
795
  * render a fallback for that case. With no argument: the store's
573
796
  * only connection when exactly one is configured, else the one
574
797
  * named "default". Never call initializeApp yourself; pass this app
575
- * to the product entry points (e.g. getFirestore(app)).
798
+ * to the product entry points. Honour a named database:
799
+ * `const id = (app.options as { databaseId?: string }).databaseId;`
800
+ * `const db = id ? getFirestore(app, id) : getFirestore(app);`
576
801
  */
577
802
  useFirebaseApp: (
578
803
  connection?: string,