cloudcommerce 0.37.1 → 0.39.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.
Files changed (147) hide show
  1. package/.github/workflows/test-apps.yml +2 -2
  2. package/.vscode/settings.json +1 -1
  3. package/CHANGELOG.md +64 -0
  4. package/action.yml +2 -2
  5. package/ecomplus-stores/barra-doce/functions/many/package.json +3 -3
  6. package/ecomplus-stores/barra-doce/functions/ssr/package.json +6 -6
  7. package/ecomplus-stores/barra-doce/functions/ssr/src/layouts/PageHeader.astro +3 -6
  8. package/ecomplus-stores/barra-doce/functions/with-apps/package.json +3 -3
  9. package/ecomplus-stores/barra-doce/package.json +2 -2
  10. package/package.json +7 -7
  11. package/packages/api/lib/api.d.ts +2 -2
  12. package/packages/api/package.json +1 -1
  13. package/packages/api/types.d.ts +4 -1
  14. package/packages/apps/affilate-program/package.json +1 -1
  15. package/packages/apps/correios/package.json +1 -1
  16. package/packages/apps/custom-payment/package.json +1 -1
  17. package/packages/apps/custom-shipping/package.json +1 -1
  18. package/packages/apps/datafrete/package.json +1 -1
  19. package/packages/apps/discounts/package.json +1 -1
  20. package/packages/apps/emails/package.json +1 -1
  21. package/packages/apps/fb-conversions/package.json +1 -1
  22. package/packages/apps/flash-courier/package.json +1 -1
  23. package/packages/apps/frenet/package.json +1 -1
  24. package/packages/apps/galaxpay/package.json +1 -1
  25. package/packages/apps/google-analytics/package.json +1 -1
  26. package/packages/apps/jadlog/package.json +1 -1
  27. package/packages/apps/loyalty-points/package.json +1 -1
  28. package/packages/apps/mandae/package.json +1 -1
  29. package/packages/apps/melhor-envio/package.json +1 -1
  30. package/packages/apps/mercadopago/package.json +1 -1
  31. package/packages/apps/pagarme/package.json +1 -1
  32. package/packages/apps/pagarme-v5/package.json +1 -1
  33. package/packages/apps/paghiper/package.json +1 -1
  34. package/packages/apps/pix/package.json +1 -1
  35. package/packages/apps/tiny-erp/package.json +1 -1
  36. package/packages/apps/webhooks/package.json +1 -1
  37. package/packages/cli/config/firestore.rules +4 -1
  38. package/packages/cli/lib/cli.js +30 -9
  39. package/packages/cli/package.json +2 -1
  40. package/packages/cli/src/cli.ts +37 -9
  41. package/packages/config/package.json +1 -1
  42. package/packages/emails/package.json +1 -1
  43. package/packages/eslint/package.json +3 -3
  44. package/packages/events/package.json +1 -1
  45. package/packages/feeds/package.json +1 -1
  46. package/packages/firebase/package.json +1 -1
  47. package/packages/i18n/package.json +1 -1
  48. package/packages/modules/package.json +1 -1
  49. package/packages/passport/package.json +1 -1
  50. package/packages/ssr/package.json +5 -5
  51. package/packages/storefront/.auto-imports.d.ts +1 -0
  52. package/packages/storefront/client.d.ts +1 -0
  53. package/packages/storefront/config/storefront.tailwind.cjs +21 -20
  54. package/packages/storefront/config/storefront.unocss.cjs +11 -0
  55. package/packages/storefront/dist/client/_astro/{AccountPage.700be123.js → AccountPage.j0C5JBLY.js} +1 -1
  56. package/packages/storefront/dist/client/_astro/{CartSidebar.430b55df.js → CartSidebar.1kUFk9Xn.js} +1 -1
  57. package/packages/storefront/dist/client/_astro/HeroSlider.tR1dVXyu.js +1 -0
  58. package/packages/storefront/dist/client/_astro/{PitchBar.06e0f831.js → PitchBar.FelC04wE.js} +1 -1
  59. package/packages/storefront/dist/client/_astro/{Prices.0e829c31.js → Prices.PuQc6C7F.js} +1 -1
  60. package/packages/storefront/dist/client/_astro/ProductCard.ephJafAE.js +1 -0
  61. package/packages/storefront/dist/client/_astro/ProductDetails.B6Ih5MGf.js +7 -0
  62. package/packages/storefront/dist/client/_astro/ProductShelf.GESxuPZ_.js +1 -0
  63. package/packages/storefront/dist/client/_astro/{QuantitySelector.ebf60845.js → QuantitySelector.YNmWjN8y.js} +1 -1
  64. package/packages/storefront/dist/client/_astro/SearchContainer.BzixfU3R.js +1 -0
  65. package/packages/storefront/dist/client/_astro/SearchModal.F7vbwxIv.js +1 -0
  66. package/packages/storefront/dist/client/_astro/ShopHeader.5vR1LgSW.js +10 -0
  67. package/packages/storefront/dist/client/_astro/_plugin-vue_export-helper.sk5AFsEV.js +1 -0
  68. package/packages/storefront/dist/client/_astro/_slug_.r8QHNfdw.css +1 -0
  69. package/packages/storefront/dist/client/_astro/client.RF8UxjZd.js +1 -0
  70. package/packages/storefront/dist/client/_astro/customer-session._VkzXnXT.js +7 -0
  71. package/packages/storefront/dist/client/_astro/ecom-utils.gJYgRPRz.js +1 -0
  72. package/packages/storefront/dist/client/_astro/{firebase-app.992a296f.js → firebase-app.cPMfoOsn.js} +1 -1
  73. package/packages/storefront/dist/client/_astro/{format-money.9cf6b04d.js → format-money.FMQXgKHB.js} +1 -1
  74. package/packages/storefront/dist/client/_astro/{hoisted.c90fc6ab.js → hoisted.B6fKrLPR.js} +1 -1
  75. package/packages/storefront/dist/client/_astro/{hoisted.54eaab04.js → hoisted._FbzheVm.js} +1 -1
  76. package/packages/storefront/dist/client/_astro/{i18n.29216eeb.js → i18n.m7SpISxy.js} +1 -1
  77. package/packages/storefront/dist/client/_astro/{img.4f23a3dd.js → img.zh-Drf-O.js} +1 -1
  78. package/packages/storefront/dist/client/_astro/{index-61e5ac61.bdc8d0cd.js → index-dd468b12.D5s8VdAL.js} +92 -107
  79. package/packages/storefront/dist/client/_astro/{index.570b84fe.js → index.5PN-EYMS.js} +1 -1
  80. package/packages/storefront/dist/client/_astro/index.XrHFaN2F.js +1 -0
  81. package/packages/storefront/dist/client/_astro/{modules-info.55780599.js → modules-info.sD0tdb2b.js} +1 -1
  82. package/packages/storefront/dist/client/_astro/name.HU5l7TJo.js +1 -0
  83. package/packages/storefront/dist/client/_astro/{photoswipe-lightbox.esm.c157838f.js → photoswipe-lightbox.esm.dZBqKD9u.js} +1 -1
  84. package/packages/storefront/dist/client/_astro/{photoswipe.01431ec7.js → photoswipe.0V7m2jWu.js} +1 -2
  85. package/packages/storefront/dist/client/_astro/{photoswipe.esm.92c2d901.js → photoswipe.esm.Ylh9TGkz.js} +1 -1
  86. package/packages/storefront/dist/client/_astro/sf-utils.5t7r9A2G.js +1 -0
  87. package/packages/storefront/dist/client/_astro/{shopping-cart.d9f601dd.js → shopping-cart.A-1jhlKi.js} +1 -1
  88. package/packages/storefront/dist/client/_astro/use-analytics.1EVxbrS7.js +1 -0
  89. package/packages/storefront/dist/client/_astro/{use-product-card.437911bb.js → use-product-card.erbOV6Fv.js} +1 -1
  90. package/packages/storefront/dist/client/robots.txt +1 -0
  91. package/packages/storefront/dist/server/chunks/{CartSidebar_eab28771.mjs → CartSidebar_hAgJQJgm.mjs} +1 -1
  92. package/packages/storefront/dist/server/chunks/SearchModal_eWb5SdQM.mjs +351 -0
  93. package/packages/storefront/dist/server/chunks/{_.._5a781fb3.mjs → _.._S7DDBn_b.mjs} +1 -1
  94. package/packages/storefront/dist/server/chunks/{account_519edb70.mjs → account_3ySmGzMc.mjs} +1 -1
  95. package/packages/storefront/dist/server/chunks/astro/{assets-service_a9d9ab5f.mjs → assets-service_QlOZG8ov.mjs} +1 -1
  96. package/packages/storefront/dist/server/chunks/{astro_d98f7186.mjs → astro_zcC1GStV.mjs} +17 -34
  97. package/packages/storefront/dist/server/chunks/{index_5e3ed8a0.mjs → index_nIwq11oA.mjs} +1 -1
  98. package/packages/storefront/dist/server/chunks/{index_10e14f85.mjs → index_uAR5ZV4d.mjs} +1 -1
  99. package/packages/storefront/dist/server/chunks/{node_1119b0d1.mjs → node_2VvC7trl.mjs} +1 -1
  100. package/packages/storefront/dist/server/chunks/pages/{__93ade2dd.mjs → __MSibDuuV.mjs} +652 -255
  101. package/packages/storefront/dist/server/chunks/pages/{account_e5d410a7.mjs → account_iG-YqJ5q.mjs} +3 -2
  102. package/packages/storefront/dist/server/chunks/pages/{index_7e25afc1.mjs → index_BtDyKPh_.mjs} +3 -2
  103. package/packages/storefront/dist/server/chunks/pages/{node_bd378ac0.mjs → node_bKqL47eZ.mjs} +2 -2
  104. package/packages/storefront/dist/server/chunks/pages/{~fallback_73578d2f.mjs → ~fallback_73R5VA6j.mjs} +3 -2
  105. package/packages/storefront/dist/server/chunks/{photoswipe_9528923e.mjs → photoswipe_IcWDJiwc.mjs} +1 -1
  106. package/packages/storefront/dist/server/chunks/{~fallback_41122b9b.mjs → ~fallback_7q1dqY4e.mjs} +1 -1
  107. package/packages/storefront/dist/server/entry.mjs +970 -93
  108. package/packages/storefront/dist/server/manifest_dSwvaOdW.mjs +195 -0
  109. package/packages/storefront/dist/server/renderers.mjs +2 -2
  110. package/packages/storefront/package.json +12 -12
  111. package/packages/storefront/src/helpers/sf-utils.ts +29 -1
  112. package/packages/storefront/src/lib/components/SharedData.astro +2 -2
  113. package/packages/storefront/src/lib/composables/use-breadcrumbs.ts +1 -1
  114. package/packages/storefront/src/lib/composables/use-search-modal.ts +1 -1
  115. package/packages/storefront/src/lib/composables/use-search-showcase.ts +55 -0
  116. package/packages/storefront/src/lib/composables/use-shared-data.ts +10 -5
  117. package/packages/storefront/src/lib/composables/use-shop-header.ts +14 -5
  118. package/packages/storefront/src/lib/composables/use-sticky-header.ts +2 -0
  119. package/packages/storefront/src/lib/layouts/BaseHead.astro +8 -1
  120. package/packages/storefront/src/lib/layouts/use-page-header.ts +6 -3
  121. package/packages/storefront/src/lib/layouts/use-page-main.ts +45 -1
  122. package/packages/storefront/src/lib/scripts/firestore.ts +27 -0
  123. package/packages/storefront/src/lib/ssr-context.ts +14 -0
  124. package/packages/storefront/src/lib/state/search-engine.ts +65 -27
  125. package/packages/storefront/src/lib/state/use-analytics.ts +9 -10
  126. package/packages/test-base/package.json +1 -1
  127. package/packages/types/package.json +1 -1
  128. package/packages/storefront/dist/client/_astro/HeroSlider.bd684ed8.js +0 -1
  129. package/packages/storefront/dist/client/_astro/ProductDetails.06da998d.js +0 -1
  130. package/packages/storefront/dist/client/_astro/ProductShelf.3f4f38b5.js +0 -1
  131. package/packages/storefront/dist/client/_astro/ProductShelf.bf82838b.js +0 -1
  132. package/packages/storefront/dist/client/_astro/SearchModal.b6aa5ef7.js +0 -1
  133. package/packages/storefront/dist/client/_astro/ShopHeader.2d6e361a.js +0 -4
  134. package/packages/storefront/dist/client/_astro/_plugin-vue_export-helper.f75743ee.js +0 -1
  135. package/packages/storefront/dist/client/_astro/_slug_.e7cac999.css +0 -1
  136. package/packages/storefront/dist/client/_astro/client.41b42098.js +0 -1
  137. package/packages/storefront/dist/client/_astro/customer-session.5ab9ab1a.js +0 -1
  138. package/packages/storefront/dist/client/_astro/ecom-utils.5cbfb95e.js +0 -1
  139. package/packages/storefront/dist/client/_astro/index.8ac1db99.js +0 -1
  140. package/packages/storefront/dist/client/_astro/name.01410784.js +0 -1
  141. package/packages/storefront/dist/client/_astro/sf-utils.b04e1813.js +0 -1
  142. package/packages/storefront/dist/client/_astro/use-analytics.cc95e346.js +0 -1
  143. package/packages/storefront/dist/server/chunks/SearchModal_f66549d4.mjs +0 -147
  144. package/packages/storefront/dist/server/manifest_221d806b.mjs +0 -1069
  145. /package/packages/storefront/dist/client/_astro/{afetch.f4507208.js → afetch.5c8VmT0-.js} +0 -0
  146. /package/packages/storefront/dist/client/_astro/{img-sizes.41e0efe4.js → img-sizes.gxAI9JNh.js} +0 -0
  147. /package/packages/storefront/dist/client/_astro/{price.04ceb6c4.js → price.Easct8WC.js} +0 -0
@@ -0,0 +1,195 @@
1
+ import '@astrojs/internal-helpers/path';
2
+ import 'cookie';
3
+ import { bold, red, yellow, dim, blue } from 'kleur/colors';
4
+ import 'string-width';
5
+ import './chunks/astro_zcC1GStV.mjs';
6
+ import 'clsx';
7
+ import { compile } from 'path-to-regexp';
8
+
9
+ const dateTimeFormat = new Intl.DateTimeFormat([], {
10
+ hour: "2-digit",
11
+ minute: "2-digit",
12
+ second: "2-digit",
13
+ hour12: false
14
+ });
15
+ const levels = {
16
+ debug: 20,
17
+ info: 30,
18
+ warn: 40,
19
+ error: 50,
20
+ silent: 90
21
+ };
22
+ function log(opts, level, label, message) {
23
+ const logLevel = opts.level;
24
+ const dest = opts.dest;
25
+ const event = {
26
+ label,
27
+ level,
28
+ message
29
+ };
30
+ if (!isLogLevelEnabled(logLevel, level)) {
31
+ return;
32
+ }
33
+ dest.write(event);
34
+ }
35
+ function isLogLevelEnabled(configuredLogLevel, level) {
36
+ return levels[configuredLogLevel] <= levels[level];
37
+ }
38
+ function info(opts, label, message) {
39
+ return log(opts, "info", label, message);
40
+ }
41
+ function warn(opts, label, message) {
42
+ return log(opts, "warn", label, message);
43
+ }
44
+ function error(opts, label, message) {
45
+ return log(opts, "error", label, message);
46
+ }
47
+ function debug(...args) {
48
+ if ("_astroGlobalDebug" in globalThis) {
49
+ globalThis._astroGlobalDebug(...args);
50
+ }
51
+ }
52
+ function getEventPrefix({ level, label }) {
53
+ const timestamp = `${dateTimeFormat.format(/* @__PURE__ */ new Date())}`;
54
+ const prefix = [];
55
+ if (level === "error" || level === "warn") {
56
+ prefix.push(bold(timestamp));
57
+ prefix.push(`[${level.toUpperCase()}]`);
58
+ } else {
59
+ prefix.push(timestamp);
60
+ }
61
+ if (label) {
62
+ prefix.push(`[${label}]`);
63
+ }
64
+ if (level === "error") {
65
+ return red(prefix.join(" "));
66
+ }
67
+ if (level === "warn") {
68
+ return yellow(prefix.join(" "));
69
+ }
70
+ if (prefix.length === 1) {
71
+ return dim(prefix[0]);
72
+ }
73
+ return dim(prefix[0]) + " " + blue(prefix.splice(1).join(" "));
74
+ }
75
+ if (typeof process !== "undefined") {
76
+ let proc = process;
77
+ if ("argv" in proc && Array.isArray(proc.argv)) {
78
+ if (proc.argv.includes("--verbose")) ; else if (proc.argv.includes("--silent")) ; else ;
79
+ }
80
+ }
81
+ class Logger {
82
+ options;
83
+ constructor(options) {
84
+ this.options = options;
85
+ }
86
+ info(label, message) {
87
+ info(this.options, label, message);
88
+ }
89
+ warn(label, message) {
90
+ warn(this.options, label, message);
91
+ }
92
+ error(label, message) {
93
+ error(this.options, label, message);
94
+ }
95
+ debug(label, ...messages) {
96
+ debug(label, ...messages);
97
+ }
98
+ level() {
99
+ return this.options.level;
100
+ }
101
+ forkIntegrationLogger(label) {
102
+ return new AstroIntegrationLogger(this.options, label);
103
+ }
104
+ }
105
+ class AstroIntegrationLogger {
106
+ options;
107
+ label;
108
+ constructor(logging, label) {
109
+ this.options = logging;
110
+ this.label = label;
111
+ }
112
+ /**
113
+ * Creates a new logger instance with a new label, but the same log options.
114
+ */
115
+ fork(label) {
116
+ return new AstroIntegrationLogger(this.options, label);
117
+ }
118
+ info(message) {
119
+ info(this.options, this.label, message);
120
+ }
121
+ warn(message) {
122
+ warn(this.options, this.label, message);
123
+ }
124
+ error(message) {
125
+ error(this.options, this.label, message);
126
+ }
127
+ debug(message) {
128
+ debug(this.label, message);
129
+ }
130
+ }
131
+
132
+ function getRouteGenerator(segments, addTrailingSlash) {
133
+ const template = segments.map((segment) => {
134
+ return "/" + segment.map((part) => {
135
+ if (part.spread) {
136
+ return `:${part.content.slice(3)}(.*)?`;
137
+ } else if (part.dynamic) {
138
+ return `:${part.content}`;
139
+ } else {
140
+ return part.content.normalize().replace(/\?/g, "%3F").replace(/#/g, "%23").replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
141
+ }
142
+ }).join("");
143
+ }).join("");
144
+ let trailing = "";
145
+ if (addTrailingSlash === "always" && segments.length) {
146
+ trailing = "/";
147
+ }
148
+ const toPath = compile(template + trailing);
149
+ return toPath;
150
+ }
151
+
152
+ function deserializeRouteData(rawRouteData) {
153
+ return {
154
+ route: rawRouteData.route,
155
+ type: rawRouteData.type,
156
+ pattern: new RegExp(rawRouteData.pattern),
157
+ params: rawRouteData.params,
158
+ component: rawRouteData.component,
159
+ generate: getRouteGenerator(rawRouteData.segments, rawRouteData._meta.trailingSlash),
160
+ pathname: rawRouteData.pathname || void 0,
161
+ segments: rawRouteData.segments,
162
+ prerender: rawRouteData.prerender,
163
+ redirect: rawRouteData.redirect,
164
+ redirectRoute: rawRouteData.redirectRoute ? deserializeRouteData(rawRouteData.redirectRoute) : void 0,
165
+ fallbackRoutes: rawRouteData.fallbackRoutes.map((fallback) => {
166
+ return deserializeRouteData(fallback);
167
+ })
168
+ };
169
+ }
170
+
171
+ function deserializeManifest(serializedManifest) {
172
+ const routes = [];
173
+ for (const serializedRoute of serializedManifest.routes) {
174
+ routes.push({
175
+ ...serializedRoute,
176
+ routeData: deserializeRouteData(serializedRoute.routeData)
177
+ });
178
+ const route = serializedRoute;
179
+ route.routeData = deserializeRouteData(serializedRoute.routeData);
180
+ }
181
+ const assets = new Set(serializedManifest.assets);
182
+ const componentMetadata = new Map(serializedManifest.componentMetadata);
183
+ const clientDirectives = new Map(serializedManifest.clientDirectives);
184
+ return {
185
+ ...serializedManifest,
186
+ assets,
187
+ componentMetadata,
188
+ clientDirectives,
189
+ routes
190
+ };
191
+ }
192
+
193
+ const manifest = deserializeManifest({"adapterName":"@astrojs/node","routes":[{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"type":"endpoint","route":"/_image","pattern":"^\\/_image$","segments":[[{"content":"_image","dynamic":false,"spread":false}]],"params":[],"component":"../../node_modules/.pnpm/astro@4.0.4_@types+node@18.19.3_typescript@5.2.2/node_modules/astro/dist/assets/endpoint/node.js","pathname":"/_image","prerender":false,"fallbackRoutes":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"/_astro/hoisted._FbzheVm.js"}],"styles":[{"type":"external","src":"/_astro/_slug_.r8QHNfdw.css"}],"routeData":{"route":"/","type":"page","pattern":"^\\/$","segments":[],"params":[],"component":"src/pages/index.astro","pathname":"/","prerender":false,"fallbackRoutes":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"/_astro/hoisted._FbzheVm.js"}],"styles":[{"type":"external","src":"/_astro/_slug_.r8QHNfdw.css"}],"routeData":{"route":"/~fallback","type":"page","pattern":"^\\/~fallback\\/?$","segments":[[{"content":"~fallback","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/~fallback.astro","pathname":"/~fallback","prerender":false,"fallbackRoutes":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"/_astro/hoisted.B6fKrLPR.js"}],"styles":[{"type":"external","src":"/_astro/_slug_.r8QHNfdw.css"}],"routeData":{"route":"/app","type":"page","pattern":"^\\/app\\/?$","segments":[[{"content":"app","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/app/index.astro","pathname":"/app","prerender":false,"fallbackRoutes":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"/_astro/hoisted._FbzheVm.js"}],"styles":[{"type":"external","src":"/_astro/_slug_.r8QHNfdw.css"}],"routeData":{"route":"/app/account","type":"page","pattern":"^\\/app\\/account\\/?$","segments":[[{"content":"app","dynamic":false,"spread":false}],[{"content":"account","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/app/account.astro","pathname":"/app/account","prerender":false,"fallbackRoutes":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"/_astro/hoisted._FbzheVm.js"}],"styles":[{"type":"external","src":"/_astro/_slug_.r8QHNfdw.css"}],"routeData":{"route":"/[...slug]","type":"page","pattern":"^(?:\\/(.*?))?\\/?$","segments":[[{"content":"...slug","dynamic":true,"spread":true}]],"params":["...slug"],"component":"src/pages/[...slug].astro","prerender":false,"fallbackRoutes":[],"_meta":{"trailingSlash":"ignore"}}}],"site":"https://demo.ecomplus.app","base":"/","trailingSlash":"ignore","compressHTML":false,"componentMetadata":[["/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/lib/layouts/BaseHead.astro",{"propagation":"in-tree","containsHead":false}],["/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/pages/[...slug].astro",{"propagation":"in-tree","containsHead":false}],["\u0000@astro-page:src/pages/[...slug]@_@astro",{"propagation":"in-tree","containsHead":false}],["\u0000@astrojs-ssr-virtual-entry",{"propagation":"in-tree","containsHead":false}],["/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/pages/app/account.astro",{"propagation":"in-tree","containsHead":false}],["\u0000@astro-page:src/pages/app/account@_@astro",{"propagation":"in-tree","containsHead":false}],["/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/pages/app/index.astro",{"propagation":"in-tree","containsHead":false}],["\u0000@astro-page:src/pages/app/index@_@astro",{"propagation":"in-tree","containsHead":false}],["/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/pages/index.astro",{"propagation":"in-tree","containsHead":false}],["\u0000@astro-page:src/pages/index@_@astro",{"propagation":"in-tree","containsHead":false}],["/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/pages/~fallback.astro",{"propagation":"in-tree","containsHead":false}],["\u0000@astro-page:src/pages/~fallback@_@astro",{"propagation":"in-tree","containsHead":false}]],"renderers":[],"clientDirectives":[["idle","(()=>{var i=t=>{let e=async()=>{await(await t())()};\"requestIdleCallback\"in window?window.requestIdleCallback(e):setTimeout(e,200)};(self.Astro||(self.Astro={})).idle=i;window.dispatchEvent(new Event(\"astro:idle\"));})();"],["load","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event(\"astro:load\"));})();"],["media","(()=>{var s=(i,t)=>{let a=async()=>{await(await i())()};if(t.value){let e=matchMedia(t.value);e.matches?a():e.addEventListener(\"change\",a,{once:!0})}};(self.Astro||(self.Astro={})).media=s;window.dispatchEvent(new Event(\"astro:media\"));})();"],["only","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event(\"astro:only\"));})();"],["visible","(()=>{var r=(i,c,s)=>{let n=async()=>{await(await i())()},t=new IntersectionObserver(e=>{for(let o of e)if(o.isIntersecting){t.disconnect(),n();break}});for(let e of s.children)t.observe(e)};(self.Astro||(self.Astro={})).visible=r;window.dispatchEvent(new Event(\"astro:visible\"));})();"],["context","(()=>{var n=(d,i)=>{let t=async()=>{await(await d())()},e=()=>{if(i.value===\"idle\"){if(typeof window.requestIdleCallback==\"function\"){setTimeout(()=>window.requestIdleCallback(t),9);return}setTimeout(t,200);return}t()},o=window.$storefront?.apiContext?.doc._id||null;if(window._firstLoadContextId===o&&window._emitedContextId===o){console.log(\"[ctx] first load\"),e(),document.addEventListener(\"astro:beforeload\",()=>{delete window._firstLoadContextId},{once:!0});return}window.addEventListener(\"storefront:apiContext\",e,{once:!0})};(self.Astro||(self.Astro={})).context=n;window.dispatchEvent(new Event(\"astro:context\"));})();\n"]],"entryModules":{"\u0000@astrojs-ssr-virtual-entry":"entry.mjs","\u0000@astro-renderers":"renderers.mjs","\u0000empty-middleware":"_empty-middleware.mjs","/src/pages/app/account.astro":"chunks/pages/account_iG-YqJ5q.mjs","/../../node_modules/.pnpm/astro@4.0.4_@types+node@18.19.3_typescript@5.2.2/node_modules/astro/dist/assets/endpoint/node.js":"chunks/pages/node_bKqL47eZ.mjs","/src/pages/~fallback.astro":"chunks/pages/~fallback_73R5VA6j.mjs","\u0000@astrojs-manifest":"manifest_dSwvaOdW.mjs","\u0000@astro-page:../../node_modules/.pnpm/astro@4.0.4_@types+node@18.19.3_typescript@5.2.2/node_modules/astro/dist/assets/endpoint/node@_@js":"chunks/node_2VvC7trl.mjs","\u0000@astro-page:src/pages/index@_@astro":"chunks/index_nIwq11oA.mjs","\u0000@astro-page:src/pages/~fallback@_@astro":"chunks/~fallback_7q1dqY4e.mjs","\u0000@astro-page:src/pages/app/index@_@astro":"chunks/index_uAR5ZV4d.mjs","\u0000@astro-page:src/pages/app/account@_@astro":"chunks/account_3ySmGzMc.mjs","\u0000@astro-page:src/pages/[...slug]@_@astro":"chunks/_.._S7DDBn_b.mjs","/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/components/SearchModal.vue":"_astro/SearchModal.F7vbwxIv.js","/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/components/CartSidebar.vue":"_astro/CartSidebar.1kUFk9Xn.js","/home/leo/code/ecomplus/cloud-commerce/node_modules/photoswipe/dist/photoswipe.css?inline":"_astro/photoswipe.0V7m2jWu.js","/home/leo/code/ecomplus/cloud-commerce/node_modules/photoswipe/dist/photoswipe-lightbox.esm.js":"_astro/photoswipe-lightbox.esm.dZBqKD9u.js","/home/leo/code/ecomplus/cloud-commerce/packages/storefront/src/lib/scripts/firebase-app.ts":"_astro/firebase-app.cPMfoOsn.js","~/components/PitchBar.vue":"_astro/PitchBar.FelC04wE.js","~/components/SearchContainer.vue":"_astro/SearchContainer.BzixfU3R.js","~/components/AccountPage.vue":"_astro/AccountPage.j0C5JBLY.js","~/components/HeroSlider.vue":"_astro/HeroSlider.tR1dVXyu.js","/astro/hoisted.js?q=0":"_astro/hoisted.B6fKrLPR.js","~/components/ProductDetails.vue":"_astro/ProductDetails.B6Ih5MGf.js","~/components/ProductShelf.vue":"_astro/ProductShelf.GESxuPZ_.js","@astrojs/vue/client.js":"_astro/client.RF8UxjZd.js","/astro/hoisted.js?q=1":"_astro/hoisted._FbzheVm.js","/home/leo/code/ecomplus/cloud-commerce/node_modules/photoswipe/dist/photoswipe.esm.js":"_astro/photoswipe.esm.Ylh9TGkz.js","~/components/ShopHeader.vue":"_astro/ShopHeader.5vR1LgSW.js","astro:scripts/before-hydration.js":""},"assets":["/_astro/_slug_.r8QHNfdw.css","/robots.txt","/_astro/AccountPage.j0C5JBLY.js","/_astro/CartSidebar.1kUFk9Xn.js","/_astro/HeroSlider.tR1dVXyu.js","/_astro/PitchBar.FelC04wE.js","/_astro/Prices.PuQc6C7F.js","/_astro/ProductCard.ephJafAE.js","/_astro/ProductDetails.B6Ih5MGf.js","/_astro/ProductShelf.GESxuPZ_.js","/_astro/QuantitySelector.YNmWjN8y.js","/_astro/SearchContainer.BzixfU3R.js","/_astro/SearchModal.F7vbwxIv.js","/_astro/ShopHeader.5vR1LgSW.js","/_astro/_plugin-vue_export-helper.sk5AFsEV.js","/_astro/afetch.5c8VmT0-.js","/_astro/client.RF8UxjZd.js","/_astro/customer-session._VkzXnXT.js","/_astro/ecom-utils.gJYgRPRz.js","/_astro/firebase-app.cPMfoOsn.js","/_astro/format-money.FMQXgKHB.js","/_astro/hoisted.B6fKrLPR.js","/_astro/hoisted._FbzheVm.js","/_astro/i18n.m7SpISxy.js","/_astro/img-sizes.gxAI9JNh.js","/_astro/img.zh-Drf-O.js","/_astro/index-dd468b12.D5s8VdAL.js","/_astro/index.5PN-EYMS.js","/_astro/index.XrHFaN2F.js","/_astro/modules-info.sD0tdb2b.js","/_astro/name.HU5l7TJo.js","/_astro/photoswipe-lightbox.esm.dZBqKD9u.js","/_astro/photoswipe.0V7m2jWu.js","/_astro/photoswipe.esm.Ylh9TGkz.js","/_astro/price.Easct8WC.js","/_astro/sf-utils.5t7r9A2G.js","/_astro/shopping-cart.A-1jhlKi.js","/_astro/use-analytics.1EVxbrS7.js","/_astro/use-product-card.erbOV6Fv.js","/img/icon.png","/img/large-icon.png","/img/uploads/banner2.webp","/img/uploads/ecom-icon.png","/img/uploads/headphone.webp","/img/uploads/logo.png","/img/uploads/og-image.png","/img/uploads/passion.webp","/img/uploads/rect8589.png","/img/uploads/rect859.png","/img/uploads/rect89.webp"]});
194
+
195
+ export { AstroIntegrationLogger as A, Logger as L, getEventPrefix as g, levels as l, manifest };
@@ -1,7 +1,7 @@
1
1
  import { useSSRContext, defineComponent, computed, createVNode, resolveDynamicComponent, mergeProps, withCtx, renderSlot, inject, ref, watch, toRef, onMounted, onBeforeUnmount, provide, h, createSSRApp } from 'vue';
2
2
  import { ssrRenderSlotInner, ssrRenderVNode, ssrRenderSlot, ssrRenderAttrs, ssrRenderClass, ssrRenderComponent, renderToString } from 'vue/server-renderer';
3
3
  import { img, imgSizes, i18n, formatMoney } from '@ecomplus/utils';
4
- import { _ as _export_sfc } from './chunks/pages/__93ade2dd.mjs';
4
+ import { _ as _export_sfc } from './chunks/pages/__MSibDuuV.mjs';
5
5
  import { useScroll, useElementHover, useDebounceFn } from '@vueuse/core';
6
6
 
7
7
  const _sfc_main$5 = /* @__PURE__ */ defineComponent({
@@ -322,7 +322,7 @@ function _sfc_ssrRender$1(_ctx, _push, _parent, _attrs, $props, $setup, $data, $
322
322
  _push(`<button${ssrRenderAttrs(mergeProps({
323
323
  type: "button",
324
324
  "aria-label": !$props.isPrev ? "Pr\xF3ximo" : "Anterior",
325
- class: ["group absolute z-[2]", $setup.isX ? `${!$props.isPrev ? "right-0" : "left-0"} top-0` : `${!$props.isPrev ? "bottom-0" : "top-0"} left-0`],
325
+ class: ["group absolute z-[11]", $setup.isX ? `${!$props.isPrev ? "right-0" : "left-0"} top-0` : `${!$props.isPrev ? "bottom-0" : "top-0"} left-0`],
326
326
  "data-carousel-control": !$props.isPrev ? "next" : "previous"
327
327
  }, _attrs))}>`);
328
328
  ssrRenderSlot(_ctx.$slots, "default", {}, () => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/storefront",
3
3
  "type": "module",
4
- "version": "0.37.1",
4
+ "version": "0.39.0",
5
5
  "description": "E-Com Plus Cloud Commerce storefront with Astro",
6
6
  "bin": {
7
7
  "storefront": "./scripts/build-prod.sh"
@@ -29,8 +29,8 @@
29
29
  "prepare-monorepo": "bash scripts/prepare-monorepo.sh"
30
30
  },
31
31
  "dependencies": {
32
- "@astrojs/node": "6.1.0",
33
- "@astrojs/vue": "3.0.4",
32
+ "@astrojs/node": "7.0.1",
33
+ "@astrojs/vue": "4.0.3",
34
34
  "@cloudcommerce/api": "workspace:*",
35
35
  "@cloudcommerce/config": "workspace:*",
36
36
  "@cloudcommerce/i18n": "workspace:*",
@@ -40,24 +40,24 @@
40
40
  "@iconify-json/heroicons": "^1.1.15",
41
41
  "@iconify-json/logos": "^1.1.40",
42
42
  "@types/gtag.js": "^0.0.18",
43
- "@vite-pwa/astro": "^0.1.6",
44
- "@vueuse/core": "10.6.1",
45
- "astro": "3.6.4",
43
+ "@vite-pwa/astro": "^0.2.0",
44
+ "@vueuse/core": "10.7.0",
45
+ "astro": "4.0.4",
46
46
  "astro-capo": "^0.0.1",
47
47
  "chroma-js": "^2.4.2",
48
48
  "dotenv": "^16.3.1",
49
- "firebase": "^10.7.0",
49
+ "firebase": "^10.7.1",
50
50
  "image-size": "^1.0.2",
51
51
  "mime": "^3.0.0",
52
52
  "mitt": "^3.0.1",
53
53
  "semver": "^7.5.4",
54
54
  "sharp": "^0.32.6",
55
- "tailwindcss": "^3.3.5",
55
+ "tailwindcss": "^3.3.6",
56
56
  "unocss": "^0.57.7",
57
- "unplugin-auto-import": "^0.16.7",
58
- "vite": "^4.5.1",
59
- "vite-plugin-pwa": "^0.17.2",
60
- "vue": "3.3.10",
57
+ "unplugin-auto-import": "^0.17.2",
58
+ "vite": "^5.0.8",
59
+ "vite-plugin-pwa": "^0.17.4",
60
+ "vue": "3.3.11",
61
61
  "wade": "0.3.3"
62
62
  },
63
63
  "devDependencies": {
@@ -14,7 +14,7 @@ export const requestIdleCallback = (fn: (...args: any[]) => any, fallbackMs = 30
14
14
  export const clearAccents = (str: string) => {
15
15
  return str
16
16
  .replace(/[ÁáÃãÂâÀà]/g, 'a')
17
- .replace(/[Éé]/g, 'e')
17
+ .replace(/[ÉéÊê]/g, 'e')
18
18
  .replace(/[Íí]/g, 'i')
19
19
  .replace(/[ÕõÓóÔô]/g, 'o')
20
20
  .replace(/[Úú]/g, 'u')
@@ -28,3 +28,31 @@ export const slugify = (str: string) => {
28
28
  .replace(/-{2,}/g, '-')
29
29
  .replace(/(^-)|(-$)/g, '');
30
30
  };
31
+
32
+ export const toLowerCaseAccents = (str: string) => {
33
+ return str
34
+ .toLowerCase()
35
+ .replace(/Á/g, 'á')
36
+ .replace(/Ã/g, 'ã')
37
+ .replace(/Â/g, 'â')
38
+ .replace(/À/g, 'à')
39
+ .replace(/É/g, 'é')
40
+ .replace(/Ê/g, 'ê')
41
+ .replace(/Í/g, 'í')
42
+ .replace(/Õ/g, 'õ')
43
+ .replace(/Ó/g, 'ó')
44
+ .replace(/Ô/g, 'ô')
45
+ .replace(/Ú/g, 'ú')
46
+ .replace(/Ç/g, 'ç');
47
+ };
48
+
49
+ export const termify = (str: string) => {
50
+ return toLowerCaseAccents(str.trim())
51
+ .replace(/[\r\n]/gm, ' ')
52
+ .replace(/[^\w-&%áãâàéêíõóôúç]/g, ' ')
53
+ .replace(/\s{2,}/g, ' ');
54
+ };
55
+
56
+ export const getSearchUrl = (term: string, baseUrl = '/s/') => {
57
+ return `${baseUrl}${encodeURIComponent(termify(term))}`;
58
+ };
@@ -6,7 +6,7 @@ import {
6
6
 
7
7
  export interface Props extends UseSharedDataProps {}
8
8
 
9
- const { inlineClientJS } = await useSharedData(Astro.props);
9
+ const { getInlineClientJS } = await useSharedData(Astro.props);
10
10
  ---
11
11
 
12
- <script is:inline set:html={inlineClientJS} />
12
+ <script is:inline set:html={getInlineClientJS()} />
@@ -22,7 +22,7 @@ const useBreadcrumbs = async (props: Props = {}) => {
22
22
  apiDoc = apiContext?.doc,
23
23
  domain = settings.domain,
24
24
  } = props;
25
- let categories: Props['categories'] = props.categories || data.categories;
25
+ let categories: Props['categories'] | null = props.categories || data.categories;
26
26
  if (!categories) {
27
27
  categories = (await useSharedData({ field: 'categories' })).value;
28
28
  }
@@ -81,7 +81,7 @@ export const useSearchModal = (props: Props) => {
81
81
  searchHistory: filteredHistory,
82
82
  searchEngine,
83
83
  isFetching: searchEngine.isFetching,
84
- productHits: searchEngine.products,
84
+ products: searchEngine.products,
85
85
  productCount,
86
86
  linkHits,
87
87
  };
@@ -0,0 +1,55 @@
1
+ import type { SearchItem } from '@cloudcommerce/types';
2
+ import { watch, shallowReactive } from 'vue';
3
+ import { SearchEngine } from '@@sf/state/search-engine';
4
+
5
+ export interface Props {
6
+ searchEngine?: InstanceType<typeof SearchEngine>;
7
+ term?: string | null;
8
+ params?: Record<string, any>;
9
+ sort?: '-sales' | '-created_at' | 'price' | '-price' | '-price_discount' | string;
10
+ products?: SearchItem[];
11
+ ssrError?: string | null;
12
+ }
13
+
14
+ const useSearchShowcase = (props: Props) => {
15
+ let { term, searchEngine } = props;
16
+ if (props.ssrError && !import.meta.env.SSR) {
17
+ console.error(new Error(`SSR search error: ${props.ssrError}`));
18
+ if (window.location.pathname.startsWith('/s/')) {
19
+ window.location.href = `/s?q=${encodeURIComponent(term || '')}`;
20
+ }
21
+ }
22
+ const products = shallowReactive<SearchItem[]>(props.products || []);
23
+ if (!searchEngine) {
24
+ searchEngine = new SearchEngine({ debounce: 50 });
25
+ if (term === undefined && !import.meta.env.SSR) {
26
+ term = new URLSearchParams(window.location.search).get('q') || null;
27
+ }
28
+ if (term !== undefined) {
29
+ searchEngine.term.value = term;
30
+ }
31
+ if (props.params) {
32
+ Object.assign(searchEngine.params, props.params);
33
+ }
34
+ if (props.sort) {
35
+ searchEngine.params.sort = props.sort;
36
+ }
37
+ }
38
+ if (!searchEngine.wasFetched.value && !props.products) {
39
+ searchEngine.fetch().catch(console.error);
40
+ }
41
+ watch(searchEngine.products, () => {
42
+ products.splice(0);
43
+ searchEngine?.products.forEach((item) => products.push(item));
44
+ });
45
+ return {
46
+ searchEngine,
47
+ fetching: searchEngine.fetching.value,
48
+ isFetching: searchEngine.isFetching,
49
+ products,
50
+ };
51
+ };
52
+
53
+ export default useSearchShowcase;
54
+
55
+ export { useSearchShowcase };
@@ -1,14 +1,19 @@
1
+ import type { Categories, Brands } from '@cloudcommerce/api/types';
1
2
  import { EventEmitter } from 'node:events';
2
3
 
3
- export interface Props {
4
- field: string;
5
- value?: any;
4
+ export type Props<T extends string = string> = {
5
+ field: T;
6
+ value?: T extends 'categories' ? Partial<Categories>[]
7
+ : T extends 'brands' ? Partial<Brands>[]
8
+ : any;
6
9
  timeout?: number;
7
10
  }
8
11
 
9
12
  const emitter = new EventEmitter();
10
13
 
11
- const useSharedData = async ({ field, value, timeout = 1000 }: Props) => {
14
+ const useSharedData = async <T extends string = string>(props: Props<T>) => {
15
+ const { field, timeout = 1000 } = props;
16
+ let value: typeof props.value | null = props.value;
12
17
  const $data = global.$storefront.data;
13
18
  if (value) {
14
19
  $data[field] = value;
@@ -32,7 +37,7 @@ const useSharedData = async ({ field, value, timeout = 1000 }: Props) => {
32
37
  }
33
38
  return {
34
39
  value,
35
- inlineClientJS: `
40
+ getInlineClientJS: () => `
36
41
  window.$storefront.data['${field}'] = ${JSON.stringify(value)};`,
37
42
  };
38
43
  };
@@ -2,6 +2,7 @@ import type { Ref } from 'vue';
2
2
  import type { Categories } from '@cloudcommerce/api/types';
3
3
  import { ref, computed, watch } from 'vue';
4
4
  import { watchOnce } from '@vueuse/core';
5
+ import { getSearchUrl } from '@@sf/sf-lib';
5
6
  import { totalItems } from '@@sf/state/shopping-cart';
6
7
  import useStickyHeader from '@@sf/composables/use-sticky-header';
7
8
 
@@ -131,10 +132,15 @@ const useShopHeader = (props: Props) => {
131
132
  isSearchOpenOnce.value = true;
132
133
  });
133
134
  const searchTerm = ref('');
134
- const isSearchPage = !import.meta.env.SSR && window.location.pathname === '/s';
135
- const urlSearchQ = isSearchPage
136
- ? new URLSearchParams(window.location.search).get('q')
137
- : undefined;
135
+ const isSearchPage = !import.meta.env.SSR && /^\/s\/?/.test(window.location.pathname);
136
+ let urlSearchQ: string | null | undefined;
137
+ if (isSearchPage) {
138
+ const { pathname, search } = window.location;
139
+ urlSearchQ = new URLSearchParams(search).get('q');
140
+ if (!urlSearchQ && pathname.startsWith('/s/')) {
141
+ urlSearchQ = decodeURIComponent(pathname.split('/')[2]);
142
+ }
143
+ }
138
144
  if (typeof urlSearchQ === 'string') {
139
145
  searchTerm.value = urlSearchQ;
140
146
  }
@@ -146,8 +152,11 @@ const useShopHeader = (props: Props) => {
146
152
  return '';
147
153
  });
148
154
  const toggleSearch = (ev: Event) => {
149
- if (isSearchOpen.value && searchTerm.value) return;
150
155
  ev.preventDefault();
156
+ if (isSearchOpen.value && searchTerm.value) {
157
+ window.location.href = getSearchUrl(searchTerm.value);
158
+ return;
159
+ }
151
160
  isSearchOpen.value = !isSearchOpen.value;
152
161
  if (isSearchOpen.value && searchInput) {
153
162
  setTimeout(() => {
@@ -109,6 +109,8 @@ const useStickyHeader = (props: Props) => {
109
109
  const headerElm = header.value as HTMLElement;
110
110
  headerElm.style.opacity = opacity;
111
111
  headerElm.style.transform = transform;
112
+ const bodyClassAction = _isSticky && !opacity ? 'add' : 'remove';
113
+ document.body.classList[bodyClassAction]('StickyHeader');
112
114
  });
113
115
  watch(transition, (_transition) => {
114
116
  (header.value as HTMLElement).style.transition = _transition;
@@ -19,6 +19,7 @@ const getIconUrl = (size: number) => {
19
19
 
20
20
  const {
21
21
  storeId,
22
+ searchPageTerm,
22
23
  cmsContent,
23
24
  fetchingApiContext,
24
25
  apiContext,
@@ -38,11 +39,17 @@ if (fetchingApiContext) {
38
39
 
39
40
  const apiDoc = apiContext.doc;
40
41
  const state: Record<string, any> = apiDoc || cmsContent || {};
41
- const title = state.meta_title ||
42
+ let title = state.meta_title ||
42
43
  state.metaTitle ||
43
44
  (state.name && `${state.name} | ${settings.name}`) ||
44
45
  (state.title && `${state.title} | ${settings.name}`) ||
45
46
  settings.name;
47
+ if (searchPageTerm) {
48
+ title = title.replace('$term', searchPageTerm);
49
+ if (!title.includes(searchPageTerm)) {
50
+ title = `${searchPageTerm} | ${title}`;
51
+ }
52
+ }
46
53
  const description = state.meta_description ||
47
54
  state.metaDescription ||
48
55
  state.short_description ||
@@ -1,9 +1,10 @@
1
1
  import type { RouteContext } from '@@sf/ssr-context';
2
2
  import type { Props as UseShopHeaderProps } from '@@sf/composables/use-shop-header';
3
3
  import api from '@cloudcommerce/api';
4
+ import { useSharedData } from '@@sf/composables/use-shared-data';
4
5
  import { parseLayoutContent } from '@@sf/composables/use-pitch-bar';
5
6
 
6
- type ShopHeaderProps = Omit<UseShopHeaderProps, 'header'>;
7
+ type ShopHeaderProps = Omit<UseShopHeaderProps, 'header' | 'categories'>;
7
8
 
8
9
  export interface Props {
9
10
  routeContext: RouteContext;
@@ -21,7 +22,7 @@ const usePageHeader = async ({ routeContext, listedCategoryFields }: Props) => {
21
22
  } = layoutContent;
22
23
  const pitchBar = parseLayoutContent(layoutContent);
23
24
  let { categories } = apiState;
24
- if (!categories && listedCategoryFields !== null) {
25
+ if (listedCategoryFields !== null) {
25
26
  try {
26
27
  categories = (await api.get('categories', {
27
28
  fields: listedCategoryFields || ([
@@ -39,8 +40,10 @@ const usePageHeader = async ({ routeContext, listedCategoryFields }: Props) => {
39
40
  console.error(err);
40
41
  }
41
42
  }
43
+ if (categories) {
44
+ useSharedData({ field: 'categories', value: categories });
45
+ }
42
46
  const shopHeader: ShopHeaderProps = {
43
- categories,
44
47
  menuCategorySlugs: inlineMenuCategories?.featured,
45
48
  menuRandomCategories: inlineMenuCategories?.random,
46
49
  isAlphabeticalSortSubmenu,
@@ -1,9 +1,12 @@
1
- import type { ResourceId } from '@cloudcommerce/types';
1
+ import type { ResourceId, Collections } from '@cloudcommerce/types';
2
2
  import type { PageContent } from '@@sf/content';
3
3
  import type { RouteContext } from '@@sf/ssr-context';
4
4
  import type { Props as UseBannerProps } from '@@sf/composables/use-banner';
5
5
  import type { Props as UseProductShelfProps } from '@@sf/composables/use-product-shelf';
6
+ import type { Props as UseSearchShowcaseProps } from '@@sf/composables/use-search-showcase';
7
+ import { useSharedData } from '@@sf/composables/use-shared-data';
6
8
  import { useProductShelf } from '@@sf/composables/use-product-shelf';
9
+ import { useSearchShowcase } from '@@sf/composables/use-search-showcase';
7
10
 
8
11
  export interface Props {
9
12
  routeContext: RouteContext;
@@ -56,6 +59,7 @@ export const usePageSections = async <T extends CustomSection = CustomSection>
56
59
  | { type: 'related-products', props: {} }
57
60
  | { type: 'doc-description', props: {} }
58
61
  | { type: 'product-specifications', props: {} }
62
+ | { type: 'search-showcase' | 'context-showcase', props: UseSearchShowcaseProps }
59
63
  > = [];
60
64
  if (sectionsContent) {
61
65
  await Promise.all(sectionsContent.map(async ({ type, ...sectionContent }, index) => {
@@ -122,6 +126,46 @@ export const usePageSections = async <T extends CustomSection = CustomSection>
122
126
  return;
123
127
  }
124
128
 
129
+ if (type === 'search-showcase' || type === 'context-showcase') {
130
+ const props: UseSearchShowcaseProps = { ...sectionContent };
131
+ if (type === 'context-showcase') {
132
+ if (routeContext.fetchingApiContext) {
133
+ await routeContext.fetchingApiContext;
134
+ }
135
+ const { resource, doc } = routeContext.apiContext;
136
+ if (resource === 'categories' || resource === 'brands') {
137
+ const params = { [`${resource}.slug`]: [doc!.slug] };
138
+ if (resource === 'categories') {
139
+ const { value: categories } = await useSharedData({ field: 'categories' });
140
+ categories?.forEach(({ slug, parent }) => {
141
+ if (
142
+ slug && parent
143
+ && (parent._id === doc!._id || parent.slug === doc!.slug)
144
+ ) {
145
+ params[`categories.slug`].push(slug);
146
+ }
147
+ });
148
+ }
149
+ props.params = params;
150
+ } else if (resource === 'collections') {
151
+ const { products } = (doc as Collections);
152
+ if (products?.length) {
153
+ props.params = { _id: products };
154
+ }
155
+ }
156
+ } else if (routeContext.searchPageTerm !== undefined) {
157
+ props.term = routeContext.searchPageTerm || null;
158
+ }
159
+ if (props.term !== undefined || props.params) {
160
+ const { searchEngine, fetching } = useSearchShowcase(props);
161
+ await fetching;
162
+ props.products = searchEngine.products;
163
+ props.ssrError = searchEngine.fetchError.value?.message;
164
+ }
165
+ sections[index] = { type, props };
166
+ return;
167
+ }
168
+
125
169
  if (type === 'banners-grid') {
126
170
  sections[index] = {
127
171
  type,
@@ -0,0 +1,27 @@
1
+ import { getFirestore, collection, addDoc } from 'firebase/firestore/lite';
2
+ import { initializeAppCheck, ReCaptchaV3Provider } from 'firebase/app-check';
3
+ import firebaseApp from './firebase-app';
4
+
5
+ const firestore = getFirestore(firebaseApp);
6
+ if (window.$reCaptchaSiteKey) {
7
+ initializeAppCheck(firebaseApp, {
8
+ provider: new ReCaptchaV3Provider(window.$reCaptchaSiteKey),
9
+ isTokenAutoRefreshEnabled: true,
10
+ });
11
+ }
12
+
13
+ export default firestore;
14
+
15
+ export {
16
+ firestore,
17
+ collection,
18
+ addDoc,
19
+ };
20
+
21
+ export const getFormCollRef = (form: string) => {
22
+ return collection(firestore, `forms/p/${form}`);
23
+ };
24
+
25
+ export const addFormDoc = (form: string, data: Record<string, any>) => {
26
+ return addDoc(getFormCollRef(form), data);
27
+ };