@bleedingdev/modern-js-create 3.2.0-ultramodern.52 → 3.2.0-ultramodern.53
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/dist/index.js +453 -857
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1436,6 +1436,8 @@ import { ultramodernLocalisedUrls } from './src/routes/ultramodern-route-metadat
|
|
|
1436
1436
|
type ZephyrRspackConfig = Parameters<ReturnType<typeof withZephyrRspack>>[0];
|
|
1437
1437
|
|
|
1438
1438
|
const zephyrEnabled = process.env['ULTRAMODERN_ZEPHYR'] !== 'false';
|
|
1439
|
+
const cloudflareDeployEnabled =
|
|
1440
|
+
process.env['MODERNJS_DEPLOY'] === 'cloudflare';
|
|
1439
1441
|
|
|
1440
1442
|
const zephyrRspackPlugin = () => ({
|
|
1441
1443
|
name: 'ultramodern-zephyr-rspack-plugin',
|
|
@@ -1526,13 +1528,17 @@ ${bffPluginEntry} moduleFederationPlugin(),
|
|
|
1526
1528
|
]);
|
|
1527
1529
|
},
|
|
1528
1530
|
},
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1531
|
+
...(cloudflareDeployEnabled
|
|
1532
|
+
? {
|
|
1533
|
+
deploy: {
|
|
1534
|
+
target: 'cloudflare',
|
|
1535
|
+
worker: {
|
|
1536
|
+
name: cloudflareWorkerName,
|
|
1537
|
+
ssr: true,
|
|
1538
|
+
},
|
|
1539
|
+
},
|
|
1540
|
+
}
|
|
1541
|
+
: {}),
|
|
1536
1542
|
server: {
|
|
1537
1543
|
port,
|
|
1538
1544
|
publicDir: './locales',
|
|
@@ -1983,6 +1989,10 @@ function createAppEnvDts(app, remotes = remoteApps) {
|
|
|
1983
1989
|
return `/// <reference types='@modern-js/app-tools/types' />
|
|
1984
1990
|
|
|
1985
1991
|
declare const ULTRAMODERN_SITE_URL: string;
|
|
1992
|
+
declare module '*.svg' {
|
|
1993
|
+
const url: string;
|
|
1994
|
+
export default url;
|
|
1995
|
+
}
|
|
1986
1996
|
${remoteModuleDeclarations ? `\n${remoteModuleDeclarations}` : ''}`;
|
|
1987
1997
|
}
|
|
1988
1998
|
function createServiceModernConfigFor(service = effectService) {
|
|
@@ -2066,522 +2076,13 @@ function createCssTokenImport(scope) {
|
|
|
2066
2076
|
return `@import '${ultramodern_workspace_packageName(scope, 'shared-design-tokens')}/tokens.css';\n`;
|
|
2067
2077
|
}
|
|
2068
2078
|
function createShellStyles(enableTailwind, scope) {
|
|
2069
|
-
return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
|
|
2070
|
-
|
|
2071
|
-
@layer ultramodern-shell-base {
|
|
2072
|
-
:root {
|
|
2073
|
-
color: var(--um-color-foreground);
|
|
2074
|
-
background: var(--um-color-canvas);
|
|
2075
|
-
font-family:
|
|
2076
|
-
Geist,
|
|
2077
|
-
Inter,
|
|
2078
|
-
ui-sans-serif,
|
|
2079
|
-
system-ui,
|
|
2080
|
-
-apple-system,
|
|
2081
|
-
BlinkMacSystemFont,
|
|
2082
|
-
"Segoe UI",
|
|
2083
|
-
sans-serif;
|
|
2084
|
-
}
|
|
2085
|
-
|
|
2086
|
-
body {
|
|
2087
|
-
margin: 0;
|
|
2079
|
+
return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}`;
|
|
2088
2080
|
}
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
min-height: 100vh;
|
|
2092
|
-
padding: 2rem;
|
|
2093
|
-
}
|
|
2094
|
-
|
|
2095
|
-
nav {
|
|
2096
|
-
display: flex;
|
|
2097
|
-
gap: 0.75rem;
|
|
2098
|
-
margin-bottom: 2rem;
|
|
2099
|
-
}
|
|
2100
|
-
|
|
2101
|
-
a {
|
|
2102
|
-
color: var(--um-color-link);
|
|
2103
|
-
}
|
|
2104
|
-
|
|
2105
|
-
.commerce-shell {
|
|
2106
|
-
background: #f1eadc;
|
|
2107
|
-
color: #0b0a08;
|
|
2108
|
-
min-height: 100vh;
|
|
2109
|
-
padding: 1.5rem clamp(1rem, 4vw, 3rem) 4rem;
|
|
2110
|
-
}
|
|
2111
|
-
|
|
2112
|
-
.commerce-shell-actions {
|
|
2113
|
-
align-items: center;
|
|
2114
|
-
display: flex;
|
|
2115
|
-
flex-wrap: wrap;
|
|
2116
|
-
gap: 0.75rem;
|
|
2117
|
-
justify-content: flex-end;
|
|
2118
|
-
margin: -4.25rem auto 3rem;
|
|
2119
|
-
max-width: 88rem;
|
|
2120
|
-
}
|
|
2121
|
-
|
|
2122
|
-
.commerce-language {
|
|
2123
|
-
margin: 0;
|
|
2124
|
-
}
|
|
2125
|
-
|
|
2126
|
-
.commerce-page {
|
|
2127
|
-
margin: 3rem auto 0;
|
|
2128
|
-
max-width: 88rem;
|
|
2129
|
-
}
|
|
2130
|
-
|
|
2131
|
-
.commerce-hero {
|
|
2132
|
-
padding: 4rem 0 2rem;
|
|
2133
|
-
}
|
|
2134
|
-
|
|
2135
|
-
.commerce-eyebrow {
|
|
2136
|
-
color: #00624b;
|
|
2137
|
-
font-size: 0.85rem;
|
|
2138
|
-
font-weight: 850;
|
|
2139
|
-
letter-spacing: 0.16rem;
|
|
2140
|
-
text-transform: uppercase;
|
|
2141
|
-
}
|
|
2142
|
-
|
|
2143
|
-
.commerce-title {
|
|
2144
|
-
font-size: clamp(2.5rem, 6vw, 4.8rem);
|
|
2145
|
-
line-height: 0.95;
|
|
2146
|
-
margin: 0.65rem 0 1.4rem;
|
|
2147
|
-
max-width: 58rem;
|
|
2148
|
-
}
|
|
2149
|
-
|
|
2150
|
-
.commerce-lede {
|
|
2151
|
-
color: #555149;
|
|
2152
|
-
font-size: 1.2rem;
|
|
2153
|
-
line-height: 1.65;
|
|
2154
|
-
max-width: 42rem;
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
|
-
.commerce-checkout {
|
|
2158
|
-
align-items: center;
|
|
2159
|
-
display: flex;
|
|
2160
|
-
flex-wrap: wrap;
|
|
2161
|
-
gap: 0.75rem;
|
|
2162
|
-
margin-top: 1.5rem;
|
|
2163
|
-
}
|
|
2164
|
-
|
|
2165
|
-
.commerce-pill,
|
|
2166
|
-
.commerce-button,
|
|
2167
|
-
.commerce-link-button,
|
|
2168
|
-
.commerce-cart-button {
|
|
2169
|
-
align-items: center;
|
|
2170
|
-
border-radius: 999px;
|
|
2171
|
-
border: 0.0625rem solid rgba(23, 23, 23, 0.14);
|
|
2172
|
-
box-shadow: 0 0.25rem 0.75rem rgba(20, 17, 10, 0.08);
|
|
2173
|
-
color: #14120d;
|
|
2174
|
-
display: inline-flex;
|
|
2175
|
-
font: inherit;
|
|
2176
|
-
font-weight: 750;
|
|
2177
|
-
justify-content: center;
|
|
2178
|
-
min-height: 2.5rem;
|
|
2179
|
-
padding: 0.65rem 1.05rem;
|
|
2180
|
-
text-decoration: none;
|
|
2181
|
-
}
|
|
2182
|
-
|
|
2183
|
-
.commerce-button {
|
|
2184
|
-
background: #00624b;
|
|
2185
|
-
border-color: #00624b;
|
|
2186
|
-
color: #ffffff;
|
|
2187
|
-
}
|
|
2188
|
-
|
|
2189
|
-
.commerce-link-button,
|
|
2190
|
-
.commerce-pill,
|
|
2191
|
-
.commerce-cart-button {
|
|
2192
|
-
background: rgba(255, 255, 255, 0.92);
|
|
2193
|
-
}
|
|
2194
|
-
|
|
2195
|
-
.commerce-boundary-toggle {
|
|
2196
|
-
align-items: center;
|
|
2197
|
-
background: rgba(255, 255, 255, 0.94);
|
|
2198
|
-
border: 0.0625rem solid rgba(23, 23, 23, 0.12);
|
|
2199
|
-
border-radius: 0.8rem;
|
|
2200
|
-
bottom: 1.5rem;
|
|
2201
|
-
box-shadow: 0 0.75rem 2rem rgba(18, 15, 10, 0.14);
|
|
2202
|
-
color: #14120d;
|
|
2203
|
-
display: flex;
|
|
2204
|
-
gap: 0.65rem;
|
|
2205
|
-
left: 1.5rem;
|
|
2206
|
-
padding: 0.8rem 1rem;
|
|
2207
|
-
position: fixed;
|
|
2208
|
-
z-index: 80;
|
|
2209
|
-
}
|
|
2210
|
-
|
|
2211
|
-
.commerce-boundary-toggle input {
|
|
2212
|
-
accent-color: #00624b;
|
|
2213
|
-
height: 1rem;
|
|
2214
|
-
width: 1rem;
|
|
2215
|
-
}
|
|
2216
|
-
|
|
2217
|
-
@media (max-width: 860px) {
|
|
2218
|
-
.commerce-shell-actions {
|
|
2219
|
-
justify-content: flex-start;
|
|
2220
|
-
margin-top: 1rem;
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
2223
|
-
}
|
|
2224
|
-
|
|
2225
|
-
@layer ultramodern-shell-overlay {
|
|
2226
|
-
.boundary-overlay {
|
|
2227
|
-
inset: 0;
|
|
2228
|
-
pointer-events: none;
|
|
2229
|
-
position: fixed;
|
|
2230
|
-
z-index: 70;
|
|
2081
|
+
function createRemoteStyles(enableTailwind, scope, _app) {
|
|
2082
|
+
return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}`;
|
|
2231
2083
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
border: 0.0625rem solid var(--boundary-color);
|
|
2235
|
-
border-radius: 0.55rem;
|
|
2236
|
-
box-shadow:
|
|
2237
|
-
0 0 0 0.0625rem rgba(255, 255, 255, 0.72),
|
|
2238
|
-
0 0.35rem 1.25rem color-mix(in srgb, var(--boundary-color) 20%, transparent);
|
|
2239
|
-
position: fixed;
|
|
2240
|
-
}
|
|
2241
|
-
|
|
2242
|
-
.boundary-overlay__label {
|
|
2243
|
-
background: color-mix(in srgb, var(--boundary-color) 88%, white);
|
|
2244
|
-
border-radius: 999px;
|
|
2245
|
-
color: #0b0a08;
|
|
2246
|
-
font-size: 0.7rem;
|
|
2247
|
-
font-weight: 850;
|
|
2248
|
-
line-height: 1;
|
|
2249
|
-
padding: 0.3rem 0.55rem;
|
|
2250
|
-
position: absolute;
|
|
2251
|
-
right: 0.35rem;
|
|
2252
|
-
top: 0.35rem;
|
|
2253
|
-
white-space: nowrap;
|
|
2254
|
-
}
|
|
2255
|
-
|
|
2256
|
-
.boundary-overlay__box[data-label-placement="above"] .boundary-overlay__label {
|
|
2257
|
-
bottom: calc(100% + 0.25rem);
|
|
2258
|
-
top: auto;
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
`;
|
|
2262
|
-
}
|
|
2263
|
-
function createRemoteStyles(enableTailwind, scope, app) {
|
|
2264
|
-
if ([
|
|
2265
|
-
'explore',
|
|
2266
|
-
'decide',
|
|
2267
|
-
'checkout'
|
|
2268
|
-
].includes(app.domain ?? '')) return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
|
|
2269
|
-
|
|
2270
|
-
@layer ultramodern-remote-${app.domain} {
|
|
2271
|
-
.commerce-shell {
|
|
2272
|
-
background: #f1eadc;
|
|
2273
|
-
color: #0b0a08;
|
|
2274
|
-
min-height: 100vh;
|
|
2275
|
-
padding: 1.5rem clamp(1rem, 4vw, 3rem) 4rem;
|
|
2276
|
-
}
|
|
2277
|
-
|
|
2278
|
-
.commerce-header,
|
|
2279
|
-
.commerce-footer {
|
|
2280
|
-
align-items: center;
|
|
2281
|
-
background: rgba(255, 255, 255, 0.86);
|
|
2282
|
-
box-shadow: 0 0.625rem 1.875rem rgba(25, 20, 12, 0.08);
|
|
2283
|
-
display: flex;
|
|
2284
|
-
gap: 1.25rem;
|
|
2285
|
-
justify-content: space-between;
|
|
2286
|
-
margin: 0 auto;
|
|
2287
|
-
max-width: 88rem;
|
|
2288
|
-
padding: 1.25rem 1.75rem;
|
|
2289
|
-
}
|
|
2290
|
-
|
|
2291
|
-
.commerce-logo {
|
|
2292
|
-
font-size: 1.35rem;
|
|
2293
|
-
font-weight: 800;
|
|
2294
|
-
}
|
|
2295
|
-
|
|
2296
|
-
.commerce-nav,
|
|
2297
|
-
.commerce-actions,
|
|
2298
|
-
.commerce-language {
|
|
2299
|
-
align-items: center;
|
|
2300
|
-
display: flex;
|
|
2301
|
-
flex-wrap: wrap;
|
|
2302
|
-
gap: 0.75rem;
|
|
2303
|
-
}
|
|
2304
|
-
|
|
2305
|
-
.commerce-nav {
|
|
2306
|
-
margin: 0;
|
|
2307
|
-
}
|
|
2308
|
-
|
|
2309
|
-
.commerce-pill,
|
|
2310
|
-
.commerce-button,
|
|
2311
|
-
.commerce-link-button,
|
|
2312
|
-
.commerce-cart-button,
|
|
2313
|
-
.commerce-quantity-button {
|
|
2314
|
-
align-items: center;
|
|
2315
|
-
border-radius: 999px;
|
|
2316
|
-
border: 0.0625rem solid rgba(23, 23, 23, 0.14);
|
|
2317
|
-
box-shadow: 0 0.25rem 0.75rem rgba(20, 17, 10, 0.08);
|
|
2318
|
-
color: #14120d;
|
|
2319
|
-
display: inline-flex;
|
|
2320
|
-
font: inherit;
|
|
2321
|
-
font-weight: 750;
|
|
2322
|
-
justify-content: center;
|
|
2323
|
-
min-height: 2.5rem;
|
|
2324
|
-
padding: 0.65rem 1.05rem;
|
|
2325
|
-
text-decoration: none;
|
|
2326
|
-
}
|
|
2327
|
-
|
|
2328
|
-
.commerce-button {
|
|
2329
|
-
background: #00624b;
|
|
2330
|
-
border-color: #00624b;
|
|
2331
|
-
color: #ffffff;
|
|
2332
|
-
}
|
|
2333
|
-
|
|
2334
|
-
.commerce-link-button,
|
|
2335
|
-
.commerce-pill,
|
|
2336
|
-
.commerce-cart-button,
|
|
2337
|
-
.commerce-quantity-button {
|
|
2338
|
-
background: rgba(255, 255, 255, 0.92);
|
|
2339
|
-
}
|
|
2340
|
-
|
|
2341
|
-
.commerce-page {
|
|
2342
|
-
margin: 3rem auto 0;
|
|
2343
|
-
max-width: 88rem;
|
|
2344
|
-
}
|
|
2345
|
-
|
|
2346
|
-
.commerce-product {
|
|
2347
|
-
align-items: center;
|
|
2348
|
-
display: grid;
|
|
2349
|
-
gap: clamp(2rem, 5vw, 4rem);
|
|
2350
|
-
grid-template-columns: minmax(0, 1fr) minmax(20rem, 0.95fr);
|
|
2351
|
-
}
|
|
2352
|
-
|
|
2353
|
-
.commerce-product-media {
|
|
2354
|
-
aspect-ratio: 1 / 0.92;
|
|
2355
|
-
background:
|
|
2356
|
-
linear-gradient(180deg, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0) 42%),
|
|
2357
|
-
linear-gradient(135deg, #97c66d 0 20%, #6f9748 20% 34%, #d6c15d 34% 36%, #6a8f3e 36% 46%, #315824 46% 64%, #8bb85e 64% 100%);
|
|
2358
|
-
border: 1.25rem solid #ffe987;
|
|
2359
|
-
border-radius: 1.6rem;
|
|
2360
|
-
box-shadow: inset 0 -7rem 8rem rgba(58, 77, 35, 0.22);
|
|
2361
|
-
overflow: hidden;
|
|
2362
|
-
}
|
|
2363
|
-
|
|
2364
|
-
.commerce-product-media::after {
|
|
2365
|
-
background:
|
|
2366
|
-
radial-gradient(circle at 27% 76%, #1e2422 0 5%, transparent 5.4%),
|
|
2367
|
-
radial-gradient(circle at 55% 76%, #1e2422 0 6%, transparent 6.4%),
|
|
2368
|
-
linear-gradient(0deg, #004b7b 0 100%);
|
|
2369
|
-
border-radius: 1.2rem;
|
|
2370
|
-
content: "";
|
|
2371
|
-
display: block;
|
|
2372
|
-
height: 19%;
|
|
2373
|
-
margin: 58% auto 0;
|
|
2374
|
-
width: 42%;
|
|
2375
|
-
}
|
|
2376
|
-
|
|
2377
|
-
.commerce-eyebrow {
|
|
2378
|
-
color: #00624b;
|
|
2379
|
-
font-size: 0.85rem;
|
|
2380
|
-
font-weight: 850;
|
|
2381
|
-
letter-spacing: 0.16rem;
|
|
2382
|
-
text-transform: uppercase;
|
|
2383
|
-
}
|
|
2384
|
-
|
|
2385
|
-
.commerce-title {
|
|
2386
|
-
font-size: clamp(2.5rem, 6vw, 4.8rem);
|
|
2387
|
-
line-height: 0.95;
|
|
2388
|
-
margin: 0.65rem 0 1.4rem;
|
|
2389
|
-
}
|
|
2390
|
-
|
|
2391
|
-
.commerce-lede {
|
|
2392
|
-
color: #555149;
|
|
2393
|
-
font-size: 1.2rem;
|
|
2394
|
-
line-height: 1.65;
|
|
2395
|
-
max-width: 42rem;
|
|
2396
|
-
}
|
|
2397
|
-
|
|
2398
|
-
.commerce-facts {
|
|
2399
|
-
display: grid;
|
|
2400
|
-
gap: 1rem;
|
|
2401
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
2402
|
-
margin: 2rem 0;
|
|
2403
|
-
}
|
|
2404
|
-
|
|
2405
|
-
.commerce-fact,
|
|
2406
|
-
.commerce-card,
|
|
2407
|
-
.commerce-cart-panel {
|
|
2408
|
-
background: rgba(255, 255, 255, 0.92);
|
|
2409
|
-
border-radius: 1rem;
|
|
2410
|
-
box-shadow: 0 0.5rem 1.25rem rgba(25, 20, 12, 0.08);
|
|
2411
|
-
padding: 1.25rem;
|
|
2412
|
-
}
|
|
2413
|
-
|
|
2414
|
-
.commerce-fact span,
|
|
2415
|
-
.commerce-card span {
|
|
2416
|
-
color: #767067;
|
|
2417
|
-
display: block;
|
|
2418
|
-
font-weight: 750;
|
|
2419
|
-
margin-bottom: 0.45rem;
|
|
2420
|
-
}
|
|
2421
|
-
|
|
2422
|
-
.commerce-fact strong {
|
|
2423
|
-
font-size: 1.1rem;
|
|
2424
|
-
}
|
|
2425
|
-
|
|
2426
|
-
.commerce-checkout {
|
|
2427
|
-
align-items: center;
|
|
2428
|
-
display: flex;
|
|
2429
|
-
flex-wrap: wrap;
|
|
2430
|
-
gap: 0.75rem;
|
|
2431
|
-
}
|
|
2432
|
-
|
|
2433
|
-
.commerce-section-title {
|
|
2434
|
-
font-size: 1.8rem;
|
|
2435
|
-
margin: 4.5rem 0 1.5rem;
|
|
2436
|
-
}
|
|
2437
|
-
|
|
2438
|
-
.commerce-grid {
|
|
2439
|
-
display: grid;
|
|
2440
|
-
gap: 1rem;
|
|
2441
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
2442
|
-
}
|
|
2443
|
-
|
|
2444
|
-
.commerce-card strong {
|
|
2445
|
-
display: block;
|
|
2446
|
-
font-size: 1.45rem;
|
|
2447
|
-
}
|
|
2448
|
-
|
|
2449
|
-
.commerce-cart-panel {
|
|
2450
|
-
margin-top: 2rem;
|
|
2451
|
-
}
|
|
2452
|
-
|
|
2453
|
-
.commerce-cart-line {
|
|
2454
|
-
align-items: center;
|
|
2455
|
-
border-top: 0.0625rem solid rgba(23, 23, 23, 0.12);
|
|
2456
|
-
display: grid;
|
|
2457
|
-
gap: 1rem;
|
|
2458
|
-
grid-template-columns: minmax(0, 1fr) auto;
|
|
2459
|
-
padding: 1rem 0;
|
|
2460
|
-
}
|
|
2461
|
-
|
|
2462
|
-
.commerce-cart-line:first-of-type {
|
|
2463
|
-
border-top: 0;
|
|
2464
|
-
}
|
|
2465
|
-
|
|
2466
|
-
.commerce-quantity {
|
|
2467
|
-
align-items: center;
|
|
2468
|
-
display: flex;
|
|
2469
|
-
gap: 0.45rem;
|
|
2470
|
-
}
|
|
2471
|
-
|
|
2472
|
-
.commerce-quantity-button {
|
|
2473
|
-
min-height: 2rem;
|
|
2474
|
-
min-width: 2rem;
|
|
2475
|
-
padding: 0.25rem;
|
|
2476
|
-
}
|
|
2477
|
-
|
|
2478
|
-
.commerce-boundary-toggle {
|
|
2479
|
-
align-items: center;
|
|
2480
|
-
background: rgba(255, 255, 255, 0.92);
|
|
2481
|
-
border-radius: 0.8rem;
|
|
2482
|
-
bottom: 1.5rem;
|
|
2483
|
-
box-shadow: 0 0.75rem 2rem rgba(18, 15, 10, 0.14);
|
|
2484
|
-
display: flex;
|
|
2485
|
-
gap: 0.65rem;
|
|
2486
|
-
left: 1.5rem;
|
|
2487
|
-
padding: 0.8rem 1rem;
|
|
2488
|
-
position: fixed;
|
|
2489
|
-
z-index: 80;
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
|
-
.commerce-boundary-toggle input {
|
|
2493
|
-
accent-color: #00624b;
|
|
2494
|
-
height: 1rem;
|
|
2495
|
-
width: 1rem;
|
|
2496
|
-
}
|
|
2497
|
-
|
|
2498
|
-
@media (max-width: 860px) {
|
|
2499
|
-
.commerce-header,
|
|
2500
|
-
.commerce-footer,
|
|
2501
|
-
.commerce-product,
|
|
2502
|
-
.commerce-grid,
|
|
2503
|
-
.commerce-facts {
|
|
2504
|
-
grid-template-columns: 1fr;
|
|
2505
|
-
}
|
|
2506
|
-
|
|
2507
|
-
.commerce-header,
|
|
2508
|
-
.commerce-footer {
|
|
2509
|
-
align-items: flex-start;
|
|
2510
|
-
flex-direction: column;
|
|
2511
|
-
}
|
|
2512
|
-
|
|
2513
|
-
.commerce-product-media {
|
|
2514
|
-
min-height: 20rem;
|
|
2515
|
-
}
|
|
2516
|
-
}
|
|
2517
|
-
}
|
|
2518
|
-
`;
|
|
2519
|
-
return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
|
|
2520
|
-
|
|
2521
|
-
@layer ultramodern-remote-${app.domain ?? app.id} {
|
|
2522
|
-
[data-app-id="${app.id}"] {
|
|
2523
|
-
color: var(--um-color-foreground);
|
|
2524
|
-
background: var(--um-color-surface);
|
|
2525
|
-
font-family:
|
|
2526
|
-
Geist,
|
|
2527
|
-
Inter,
|
|
2528
|
-
ui-sans-serif,
|
|
2529
|
-
system-ui,
|
|
2530
|
-
-apple-system,
|
|
2531
|
-
BlinkMacSystemFont,
|
|
2532
|
-
"Segoe UI",
|
|
2533
|
-
sans-serif;
|
|
2534
|
-
min-height: 100vh;
|
|
2535
|
-
}
|
|
2536
|
-
|
|
2537
|
-
[data-app-id="${app.id}"] main {
|
|
2538
|
-
min-height: 100vh;
|
|
2539
|
-
padding: 2rem;
|
|
2540
|
-
}
|
|
2541
|
-
|
|
2542
|
-
[data-app-id="${app.id}"] nav {
|
|
2543
|
-
display: flex;
|
|
2544
|
-
gap: 0.75rem;
|
|
2545
|
-
margin-bottom: 2rem;
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
[data-app-id="${app.id}"] a {
|
|
2549
|
-
color: var(--um-color-link);
|
|
2550
|
-
}
|
|
2551
|
-
|
|
2552
|
-
[data-mf-remote="${app.id}"] {
|
|
2553
|
-
border: 0.0625rem solid color-mix(in srgb, var(--um-color-accent) 30%, transparent);
|
|
2554
|
-
border-radius: 0.5rem;
|
|
2555
|
-
padding: 1rem;
|
|
2556
|
-
}
|
|
2557
|
-
}
|
|
2558
|
-
`;
|
|
2559
|
-
}
|
|
2560
|
-
function createServiceStyles(enableTailwind, scope, service) {
|
|
2561
|
-
return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
|
|
2562
|
-
|
|
2563
|
-
@layer ultramodern-effect-service {
|
|
2564
|
-
[data-app-id="${service.id}"] {
|
|
2565
|
-
color: var(--um-color-foreground);
|
|
2566
|
-
background: var(--um-color-surface);
|
|
2567
|
-
font-family:
|
|
2568
|
-
Geist,
|
|
2569
|
-
Inter,
|
|
2570
|
-
ui-sans-serif,
|
|
2571
|
-
system-ui,
|
|
2572
|
-
-apple-system,
|
|
2573
|
-
BlinkMacSystemFont,
|
|
2574
|
-
"Segoe UI",
|
|
2575
|
-
sans-serif;
|
|
2576
|
-
min-height: 100vh;
|
|
2577
|
-
}
|
|
2578
|
-
|
|
2579
|
-
[data-app-id="${service.id}"] main {
|
|
2580
|
-
min-height: 100vh;
|
|
2581
|
-
padding: 2rem;
|
|
2582
|
-
}
|
|
2583
|
-
}
|
|
2584
|
-
`;
|
|
2084
|
+
function createServiceStyles(enableTailwind, scope, _service) {
|
|
2085
|
+
return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}`;
|
|
2585
2086
|
}
|
|
2586
2087
|
function createAppStyles(enableTailwind, scope, app) {
|
|
2587
2088
|
return 'shell' === app.kind ? createShellStyles(enableTailwind, scope) : createRemoteStyles(enableTailwind, scope, app);
|
|
@@ -2602,6 +2103,86 @@ export default {
|
|
|
2602
2103
|
} satisfies Config;
|
|
2603
2104
|
`;
|
|
2604
2105
|
}
|
|
2106
|
+
function createCommerceAssetSvg(title, palette) {
|
|
2107
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900" viewBox="0 0 1440 900" role="img" aria-label="${title}">
|
|
2108
|
+
<defs>
|
|
2109
|
+
<linearGradient id="sky" x1="0" x2="0" y1="0" y2="1">
|
|
2110
|
+
<stop offset="0" stop-color="${palette.sky}"/>
|
|
2111
|
+
<stop offset="1" stop-color="#fff8dc"/>
|
|
2112
|
+
</linearGradient>
|
|
2113
|
+
<linearGradient id="field" x1="0" x2="1" y1="0" y2="1">
|
|
2114
|
+
<stop offset="0" stop-color="${palette.ground}"/>
|
|
2115
|
+
<stop offset="1" stop-color="${palette.accent}"/>
|
|
2116
|
+
</linearGradient>
|
|
2117
|
+
</defs>
|
|
2118
|
+
<rect width="1440" height="900" fill="url(#sky)"/>
|
|
2119
|
+
<path d="M0 566c172-78 330-102 474-72 125 26 219 91 340 106 170 21 339-74 626-43v343H0z" fill="url(#field)"/>
|
|
2120
|
+
<path d="M0 686c205-70 451-66 738 12 287 77 521 66 702-33v235H0z" fill="#4f7f38" opacity=".55"/>
|
|
2121
|
+
<g fill="none" stroke="#fff6b7" stroke-linecap="round" stroke-width="10" opacity=".55">
|
|
2122
|
+
<path d="M108 820c205-138 382-202 530-192"/>
|
|
2123
|
+
<path d="M322 862c176-134 338-198 486-193"/>
|
|
2124
|
+
<path d="M583 886c119-121 260-190 422-207"/>
|
|
2125
|
+
<path d="M868 878c95-94 207-153 336-176"/>
|
|
2126
|
+
</g>
|
|
2127
|
+
<g transform="translate(430 430)">
|
|
2128
|
+
<circle cx="170" cy="210" r="92" fill="#161616"/>
|
|
2129
|
+
<circle cx="170" cy="210" r="54" fill="#d7c46d"/>
|
|
2130
|
+
<circle cx="514" cy="214" r="108" fill="#161616"/>
|
|
2131
|
+
<circle cx="514" cy="214" r="63" fill="#d7c46d"/>
|
|
2132
|
+
<path d="M194 142h194l72-100h114c49 0 89 39 89 88v57H625l-51-90H452l-78 114H209z" fill="${palette.tractor}"/>
|
|
2133
|
+
<path d="M283 67h134l-54 73H249z" fill="#c9ecff" opacity=".72"/>
|
|
2134
|
+
<path d="M120 184h430v54H120z" fill="${palette.tractor}"/>
|
|
2135
|
+
<path d="M578 52l60-35M618 37l34 72" stroke="#171717" stroke-linecap="round" stroke-width="14"/>
|
|
2136
|
+
<path d="M90 236h578" stroke="#171717" stroke-linecap="round" stroke-width="18"/>
|
|
2137
|
+
</g>
|
|
2138
|
+
</svg>
|
|
2139
|
+
`;
|
|
2140
|
+
}
|
|
2141
|
+
function commerceAssetsForApp(app) {
|
|
2142
|
+
if ('shell' === app.kind) return {
|
|
2143
|
+
'src/assets/hero-field.svg': createCommerceAssetSvg('Tractor crossing cultivated fields', {
|
|
2144
|
+
accent: '#d6b85d',
|
|
2145
|
+
ground: '#84ad58',
|
|
2146
|
+
sky: '#9fd6e8',
|
|
2147
|
+
tractor: '#005f73'
|
|
2148
|
+
})
|
|
2149
|
+
};
|
|
2150
|
+
if ('remote-explore' === app.id) return {
|
|
2151
|
+
'src/assets/autonomy.svg': createCommerceAssetSvg('Autonomous tractor concept', {
|
|
2152
|
+
accent: '#c26a2e',
|
|
2153
|
+
ground: '#668f55',
|
|
2154
|
+
sky: '#d5e7de',
|
|
2155
|
+
tractor: '#f2a51a'
|
|
2156
|
+
}),
|
|
2157
|
+
'src/assets/field-loader.svg': createCommerceAssetSvg('Field Loader 112 tractor', {
|
|
2158
|
+
accent: '#d6b85d',
|
|
2159
|
+
ground: '#84ad58',
|
|
2160
|
+
sky: '#9fd6e8',
|
|
2161
|
+
tractor: '#00624b'
|
|
2162
|
+
}),
|
|
2163
|
+
'src/assets/orchard.svg': createCommerceAssetSvg('Orchard tractor between tight rows', {
|
|
2164
|
+
accent: '#b45b2d',
|
|
2165
|
+
ground: '#6f9b4a',
|
|
2166
|
+
sky: '#c9ebff',
|
|
2167
|
+
tractor: '#1d5d9b'
|
|
2168
|
+
}),
|
|
2169
|
+
'src/assets/vineyard.svg': createCommerceAssetSvg('Vineyard narrow tractor', {
|
|
2170
|
+
accent: '#b88d58',
|
|
2171
|
+
ground: '#5e8a45',
|
|
2172
|
+
sky: '#f1dcb9',
|
|
2173
|
+
tractor: '#914d76'
|
|
2174
|
+
})
|
|
2175
|
+
};
|
|
2176
|
+
if ('remote-decide' === app.id) return {
|
|
2177
|
+
'src/assets/field-loader.svg': createCommerceAssetSvg('Field Loader 112 tractor detail', {
|
|
2178
|
+
accent: '#d6b85d',
|
|
2179
|
+
ground: '#84ad58',
|
|
2180
|
+
sky: '#9fd6e8',
|
|
2181
|
+
tractor: '#00624b'
|
|
2182
|
+
})
|
|
2183
|
+
};
|
|
2184
|
+
return {};
|
|
2185
|
+
}
|
|
2605
2186
|
function createLocalizedHeadComponent() {
|
|
2606
2187
|
return `const fallbackLanguage = 'en';
|
|
2607
2188
|
const supportedLanguages = ['en', 'cs'] as const;
|
|
@@ -2756,302 +2337,269 @@ function createShellPage() {
|
|
|
2756
2337
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
2757
2338
|
import { Helmet } from '@modern-js/runtime/head';
|
|
2758
2339
|
import { useLocation } from '@modern-js/plugin-tanstack/runtime';
|
|
2759
|
-
import
|
|
2760
|
-
import
|
|
2340
|
+
import heroField from '../../assets/hero-field.svg';
|
|
2341
|
+
import ShellFrame from '../shell-frame';
|
|
2342
|
+
import { StorePicker } from '../remote-components';
|
|
2761
2343
|
import { ultramodernLocalisedUrls } from '../ultramodern-route-metadata';
|
|
2762
2344
|
import { ultramodernUiMarker } from '../../ultramodern-build';
|
|
2763
2345
|
|
|
2764
|
-
const languageCodes = ['en', 'cs'] as const;
|
|
2765
|
-
|
|
2766
2346
|
${createLocalizedHeadComponent()}
|
|
2767
|
-
type HomeRouteRemotes = {
|
|
2768
|
-
Header: ComponentType;
|
|
2769
|
-
MiniCart: ComponentType;
|
|
2770
|
-
StorePicker: ComponentType;
|
|
2771
|
-
};
|
|
2772
|
-
|
|
2773
|
-
const useHomeRouteRemotes = () => {
|
|
2774
|
-
const [remotes, setRemotes] = useState<HomeRouteRemotes | null>(null);
|
|
2775
|
-
|
|
2776
|
-
useEffect(() => {
|
|
2777
|
-
let mounted = true;
|
|
2778
|
-
import('../remote-components').then(({ Header, MiniCart, StorePicker }) => {
|
|
2779
|
-
if (mounted) {
|
|
2780
|
-
setRemotes({ Header, MiniCart, StorePicker });
|
|
2781
|
-
}
|
|
2782
|
-
});
|
|
2783
|
-
|
|
2784
|
-
return () => {
|
|
2785
|
-
mounted = false;
|
|
2786
|
-
};
|
|
2787
|
-
}, []);
|
|
2788
|
-
|
|
2789
|
-
return remotes;
|
|
2790
|
-
};
|
|
2791
|
-
|
|
2792
2347
|
export default function ShellHome() {
|
|
2793
2348
|
const { i18nInstance, language } = useModernI18n();
|
|
2794
2349
|
const t = i18nInstance['t'].bind(i18nInstance);
|
|
2795
|
-
const location = useLocation();
|
|
2796
|
-
const suffix = locationSuffix(location);
|
|
2797
|
-
const remotes = useHomeRouteRemotes();
|
|
2798
|
-
const Header = remotes?.Header;
|
|
2799
|
-
const MiniCart = remotes?.MiniCart;
|
|
2800
|
-
const StorePicker = remotes?.StorePicker;
|
|
2801
2350
|
|
|
2802
2351
|
return (
|
|
2803
|
-
<
|
|
2352
|
+
<ShellFrame>
|
|
2804
2353
|
<LocalizedHead />
|
|
2805
|
-
<
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
className="commerce-pill"
|
|
2813
|
-
href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
|
|
2814
|
-
key={code}
|
|
2815
|
-
>
|
|
2816
|
-
{t(\`shell.language.\${code}\`)}
|
|
2817
|
-
</a>
|
|
2818
|
-
))}
|
|
2819
|
-
</nav>
|
|
2820
|
-
{MiniCart ? <MiniCart /> : null}
|
|
2821
|
-
</div>
|
|
2822
|
-
<section className="commerce-page commerce-hero">
|
|
2823
|
-
<p className="commerce-eyebrow">{t('shell.hero.eyebrow')}</p>
|
|
2824
|
-
<h1 className="commerce-title">{t('shell.title')}</h1>
|
|
2825
|
-
<p className="commerce-lede">{t('shell.hero.lede')}</p>
|
|
2826
|
-
<div className="commerce-checkout">
|
|
2827
|
-
<a className="commerce-button" href={\`/\${language}/tractors/field-loader-112\`}>
|
|
2354
|
+
<section className="mx-auto grid max-w-7xl items-center gap-8 py-8 md:grid-cols-[0.9fr_1.1fr] lg:gap-14">
|
|
2355
|
+
<div className="min-w-0">
|
|
2356
|
+
<p className="text-xs font-black uppercase tracking-[0.18em] text-emerald-800">{t('shell.hero.eyebrow')}</p>
|
|
2357
|
+
<h1 className="mt-3 max-w-3xl text-5xl font-black leading-none tracking-normal text-stone-950 md:text-7xl">{t('shell.title')}</h1>
|
|
2358
|
+
<p className="mt-5 max-w-2xl text-lg leading-8 text-stone-600">{t('shell.hero.lede')}</p>
|
|
2359
|
+
<div className="mt-7 flex flex-wrap gap-3">
|
|
2360
|
+
<a className="inline-flex min-h-11 items-center justify-center rounded-full bg-emerald-800 px-5 font-bold text-white shadow-lg shadow-stone-900/10" href={\`/\${language}/tractors/field-loader-112\`}>
|
|
2828
2361
|
{t('shell.hero.primary')}
|
|
2829
|
-
|
|
2830
|
-
|
|
2362
|
+
</a>
|
|
2363
|
+
<a className="inline-flex min-h-11 items-center justify-center rounded-full border border-stone-900/15 bg-white/90 px-5 font-bold text-stone-950 shadow-lg shadow-stone-900/10" href={\`/\${language}/tractors\`}>
|
|
2831
2364
|
{t('shell.hero.secondary')}
|
|
2832
|
-
|
|
2365
|
+
</a>
|
|
2366
|
+
</div>
|
|
2833
2367
|
</div>
|
|
2368
|
+
<img alt="" className="aspect-[16/10] w-full rounded-3xl bg-stone-200 object-cover shadow-2xl shadow-stone-900/20" src={heroField} />
|
|
2834
2369
|
</section>
|
|
2835
|
-
|
|
2836
|
-
<p data-testid="ultramodern-preset">presetUltramodern workspace</p>
|
|
2837
|
-
<p data-build-marker={ultramodernUiMarker.build} data-testid="ultramodern-ui-marker">
|
|
2370
|
+
<StorePicker />
|
|
2371
|
+
<p className="sr-only" data-testid="ultramodern-preset">presetUltramodern workspace</p>
|
|
2372
|
+
<p className="sr-only" data-build-marker={ultramodernUiMarker.build} data-testid="ultramodern-ui-marker">
|
|
2838
2373
|
{ultramodernUiMarker.appId}:{ultramodernUiMarker.version}
|
|
2839
2374
|
</p>
|
|
2840
|
-
</
|
|
2375
|
+
</ShellFrame>
|
|
2841
2376
|
);
|
|
2842
2377
|
}
|
|
2843
2378
|
`;
|
|
2844
2379
|
}
|
|
2845
2380
|
function createShellTractorsPage() {
|
|
2846
|
-
return `import {
|
|
2847
|
-
import { Helmet } from '@modern-js/runtime/head';
|
|
2381
|
+
return `import { Helmet } from '@modern-js/runtime/head';
|
|
2848
2382
|
import { useLocation } from '@modern-js/plugin-tanstack/runtime';
|
|
2849
|
-
import
|
|
2850
|
-
import
|
|
2383
|
+
import ShellFrame from '../../shell-frame';
|
|
2384
|
+
import { Recommendations } from '../../remote-components';
|
|
2851
2385
|
import { ultramodernLocalisedUrls } from '../../ultramodern-route-metadata';
|
|
2852
2386
|
|
|
2853
|
-
const languageCodes = ['en', 'cs'] as const;
|
|
2854
|
-
|
|
2855
2387
|
${createLocalizedHeadComponent()}
|
|
2856
|
-
type TractorsRouteRemotes = {
|
|
2857
|
-
Header: ComponentType;
|
|
2858
|
-
MiniCart: ComponentType;
|
|
2859
|
-
Recommendations: ComponentType;
|
|
2860
|
-
};
|
|
2861
|
-
|
|
2862
|
-
const useTractorsRouteRemotes = () => {
|
|
2863
|
-
const [remotes, setRemotes] = useState<TractorsRouteRemotes | null>(null);
|
|
2864
|
-
|
|
2865
|
-
useEffect(() => {
|
|
2866
|
-
let mounted = true;
|
|
2867
|
-
import('../../remote-components').then(({ Header, MiniCart, Recommendations }) => {
|
|
2868
|
-
if (mounted) {
|
|
2869
|
-
setRemotes({ Header, MiniCart, Recommendations });
|
|
2870
|
-
}
|
|
2871
|
-
});
|
|
2872
|
-
|
|
2873
|
-
return () => {
|
|
2874
|
-
mounted = false;
|
|
2875
|
-
};
|
|
2876
|
-
}, []);
|
|
2877
|
-
|
|
2878
|
-
return remotes;
|
|
2879
|
-
};
|
|
2880
|
-
|
|
2881
2388
|
export default function ShellTractorsPage() {
|
|
2882
|
-
const { i18nInstance, language } = useModernI18n();
|
|
2883
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
2884
|
-
const location = useLocation();
|
|
2885
|
-
const suffix = locationSuffix(location);
|
|
2886
|
-
const remotes = useTractorsRouteRemotes();
|
|
2887
|
-
const Header = remotes?.Header;
|
|
2888
|
-
const MiniCart = remotes?.MiniCart;
|
|
2889
|
-
const Recommendations = remotes?.Recommendations;
|
|
2890
|
-
|
|
2891
2389
|
return (
|
|
2892
|
-
<
|
|
2390
|
+
<ShellFrame>
|
|
2893
2391
|
<LocalizedHead />
|
|
2894
|
-
<
|
|
2895
|
-
|
|
2896
|
-
<div className="commerce-shell-actions">
|
|
2897
|
-
<nav aria-label={t('shell.language.switcher')} className="commerce-language">
|
|
2898
|
-
{languageCodes.map(code => (
|
|
2899
|
-
<a
|
|
2900
|
-
aria-current={language === code ? 'page' : undefined}
|
|
2901
|
-
className="commerce-pill"
|
|
2902
|
-
href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
|
|
2903
|
-
key={code}
|
|
2904
|
-
>
|
|
2905
|
-
{t(\`shell.language.\${code}\`)}
|
|
2906
|
-
</a>
|
|
2907
|
-
))}
|
|
2908
|
-
</nav>
|
|
2909
|
-
{MiniCart ? <MiniCart /> : null}
|
|
2910
|
-
</div>
|
|
2911
|
-
{Recommendations ? <Recommendations /> : null}
|
|
2912
|
-
</main>
|
|
2392
|
+
<Recommendations />
|
|
2393
|
+
</ShellFrame>
|
|
2913
2394
|
);
|
|
2914
2395
|
}
|
|
2915
2396
|
`;
|
|
2916
2397
|
}
|
|
2917
2398
|
function createShellProductPage() {
|
|
2918
|
-
return `import {
|
|
2919
|
-
import { Helmet } from '@modern-js/runtime/head';
|
|
2399
|
+
return `import { Helmet } from '@modern-js/runtime/head';
|
|
2920
2400
|
import { useLocation } from '@modern-js/plugin-tanstack/runtime';
|
|
2921
|
-
import
|
|
2922
|
-
import
|
|
2401
|
+
import ShellFrame from '../../../shell-frame';
|
|
2402
|
+
import { ProductPage } from '../../../remote-components';
|
|
2923
2403
|
import { ultramodernLocalisedUrls } from '../../../ultramodern-route-metadata';
|
|
2924
2404
|
|
|
2925
|
-
const languageCodes = ['en', 'cs'] as const;
|
|
2926
|
-
|
|
2927
2405
|
${createLocalizedHeadComponent()}
|
|
2928
|
-
type ProductRouteRemotes = {
|
|
2929
|
-
Header: ComponentType;
|
|
2930
|
-
MiniCart: ComponentType;
|
|
2931
|
-
ProductPage: ComponentType;
|
|
2932
|
-
};
|
|
2933
|
-
|
|
2934
|
-
const useProductRouteRemotes = () => {
|
|
2935
|
-
const [remotes, setRemotes] = useState<ProductRouteRemotes | null>(null);
|
|
2936
|
-
|
|
2937
|
-
useEffect(() => {
|
|
2938
|
-
let mounted = true;
|
|
2939
|
-
import('../../../remote-components').then(
|
|
2940
|
-
({ Header, MiniCart, ProductPage }) => {
|
|
2941
|
-
if (mounted) {
|
|
2942
|
-
setRemotes({ Header, MiniCart, ProductPage });
|
|
2943
|
-
}
|
|
2944
|
-
},
|
|
2945
|
-
);
|
|
2946
|
-
|
|
2947
|
-
return () => {
|
|
2948
|
-
mounted = false;
|
|
2949
|
-
};
|
|
2950
|
-
}, []);
|
|
2951
|
-
|
|
2952
|
-
return remotes;
|
|
2953
|
-
};
|
|
2954
|
-
|
|
2955
2406
|
export default function ShellProductPage() {
|
|
2956
|
-
const { i18nInstance, language } = useModernI18n();
|
|
2957
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
2958
|
-
const location = useLocation();
|
|
2959
|
-
const suffix = locationSuffix(location);
|
|
2960
|
-
const remotes = useProductRouteRemotes();
|
|
2961
|
-
const Header = remotes?.Header;
|
|
2962
|
-
const MiniCart = remotes?.MiniCart;
|
|
2963
|
-
const ProductPage = remotes?.ProductPage;
|
|
2964
|
-
|
|
2965
2407
|
return (
|
|
2966
|
-
<
|
|
2408
|
+
<ShellFrame>
|
|
2967
2409
|
<LocalizedHead />
|
|
2968
|
-
<
|
|
2969
|
-
|
|
2970
|
-
<div className="commerce-shell-actions">
|
|
2971
|
-
<nav aria-label={t('shell.language.switcher')} className="commerce-language">
|
|
2972
|
-
{languageCodes.map(code => (
|
|
2973
|
-
<a
|
|
2974
|
-
aria-current={language === code ? 'page' : undefined}
|
|
2975
|
-
className="commerce-pill"
|
|
2976
|
-
href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
|
|
2977
|
-
key={code}
|
|
2978
|
-
>
|
|
2979
|
-
{t(\`shell.language.\${code}\`)}
|
|
2980
|
-
</a>
|
|
2981
|
-
))}
|
|
2982
|
-
</nav>
|
|
2983
|
-
{MiniCart ? <MiniCart /> : null}
|
|
2984
|
-
</div>
|
|
2985
|
-
{ProductPage ? <ProductPage /> : null}
|
|
2986
|
-
</main>
|
|
2410
|
+
<ProductPage />
|
|
2411
|
+
</ShellFrame>
|
|
2987
2412
|
);
|
|
2988
2413
|
}
|
|
2989
2414
|
`;
|
|
2990
2415
|
}
|
|
2991
2416
|
function createShellCartPage() {
|
|
2992
|
-
return `import {
|
|
2993
|
-
import { Helmet } from '@modern-js/runtime/head';
|
|
2417
|
+
return `import { Helmet } from '@modern-js/runtime/head';
|
|
2994
2418
|
import { useLocation } from '@modern-js/plugin-tanstack/runtime';
|
|
2995
|
-
import
|
|
2996
|
-
import
|
|
2419
|
+
import ShellFrame from '../../shell-frame';
|
|
2420
|
+
import { CartPage } from '../../remote-components';
|
|
2997
2421
|
import { ultramodernLocalisedUrls } from '../../ultramodern-route-metadata';
|
|
2998
2422
|
|
|
2999
|
-
const languageCodes = ['en', 'cs'] as const;
|
|
3000
|
-
|
|
3001
2423
|
${createLocalizedHeadComponent()}
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
2424
|
+
export default function ShellCartPage() {
|
|
2425
|
+
return (
|
|
2426
|
+
<ShellFrame showCart={false}>
|
|
2427
|
+
<LocalizedHead />
|
|
2428
|
+
<CartPage />
|
|
2429
|
+
</ShellFrame>
|
|
2430
|
+
);
|
|
2431
|
+
}
|
|
2432
|
+
`;
|
|
2433
|
+
}
|
|
2434
|
+
function createShellFrameComponent() {
|
|
2435
|
+
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
2436
|
+
import { useLocation } from '@modern-js/plugin-tanstack/runtime';
|
|
2437
|
+
import type { ReactNode } from 'react';
|
|
2438
|
+
import BoundaryOverlay from './boundary-overlay';
|
|
2439
|
+
import { Header, MiniCart } from './remote-components';
|
|
2440
|
+
import { ultramodernLocalisedUrls } from './ultramodern-route-metadata';
|
|
2441
|
+
|
|
2442
|
+
const supportedLanguages = ['en', 'cs'] as const;
|
|
2443
|
+
type SupportedLanguage = (typeof supportedLanguages)[number];
|
|
2444
|
+
|
|
2445
|
+
type ShellFrameProps = {
|
|
2446
|
+
children: ReactNode;
|
|
2447
|
+
showCart?: boolean;
|
|
3005
2448
|
};
|
|
3006
2449
|
|
|
3007
|
-
const
|
|
3008
|
-
|
|
2450
|
+
const localisedUrls = ultramodernLocalisedUrls as Record<
|
|
2451
|
+
string,
|
|
2452
|
+
Record<SupportedLanguage, string>
|
|
2453
|
+
>;
|
|
2454
|
+
|
|
2455
|
+
const isSupportedLanguage = (value: string): value is SupportedLanguage =>
|
|
2456
|
+
supportedLanguages.includes(value as SupportedLanguage);
|
|
3009
2457
|
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
2458
|
+
const normalisePath = (pathname: string) => {
|
|
2459
|
+
const normalised = pathname.replace(/\\/+$/u, '').replace(/\\/+/gu, '/');
|
|
2460
|
+
return normalised.length > 0 ? normalised : '/';
|
|
2461
|
+
};
|
|
2462
|
+
|
|
2463
|
+
const stripLanguagePrefix = (pathname: string) => {
|
|
2464
|
+
const segments = normalisePath(pathname).split('/').filter(Boolean);
|
|
2465
|
+
if (segments.length > 0 && isSupportedLanguage(segments[0] ?? '')) {
|
|
2466
|
+
segments.shift();
|
|
2467
|
+
}
|
|
2468
|
+
return \`/\${segments.join('/')}\`;
|
|
2469
|
+
};
|
|
2470
|
+
|
|
2471
|
+
const escapeRegExp = (value: string) =>
|
|
2472
|
+
value.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&');
|
|
2473
|
+
|
|
2474
|
+
const paramName = (segment: string) => segment.slice(1).replace(/\\?$/u, '');
|
|
2475
|
+
|
|
2476
|
+
const matchPattern = (pathname: string, pattern: string) => {
|
|
2477
|
+
const names: string[] = [];
|
|
2478
|
+
const source = normalisePath(pattern)
|
|
2479
|
+
.split('/')
|
|
2480
|
+
.filter(Boolean)
|
|
2481
|
+
.map(segment => {
|
|
2482
|
+
if (segment.startsWith(':')) {
|
|
2483
|
+
names.push(paramName(segment));
|
|
2484
|
+
return segment.endsWith('?') ? '(?:/([^/]+))?' : '/([^/]+)';
|
|
3015
2485
|
}
|
|
3016
|
-
|
|
2486
|
+
return \`/\${escapeRegExp(segment)}\`;
|
|
2487
|
+
})
|
|
2488
|
+
.join('');
|
|
2489
|
+
const match = new RegExp(\`^\${source || '/'}$\`).exec(normalisePath(pathname));
|
|
3017
2490
|
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
}, []);
|
|
2491
|
+
if (!match) {
|
|
2492
|
+
return undefined;
|
|
2493
|
+
}
|
|
3022
2494
|
|
|
3023
|
-
return
|
|
2495
|
+
return names.reduce<Record<string, string>>((params, name, index) => {
|
|
2496
|
+
params[name] = decodeURIComponent(match[index + 1] ?? '');
|
|
2497
|
+
return params;
|
|
2498
|
+
}, {});
|
|
3024
2499
|
};
|
|
3025
2500
|
|
|
3026
|
-
|
|
2501
|
+
const buildPath = (pattern: string, params: Record<string, string>) => {
|
|
2502
|
+
const path = normalisePath(pattern)
|
|
2503
|
+
.split('/')
|
|
2504
|
+
.filter(Boolean)
|
|
2505
|
+
.map(segment => {
|
|
2506
|
+
if (!segment.startsWith(':')) {
|
|
2507
|
+
return segment;
|
|
2508
|
+
}
|
|
2509
|
+
const value = params[paramName(segment)];
|
|
2510
|
+
return value ? encodeURIComponent(value) : '';
|
|
2511
|
+
})
|
|
2512
|
+
.filter(Boolean)
|
|
2513
|
+
.join('/');
|
|
2514
|
+
|
|
2515
|
+
return \`/\${path}\`;
|
|
2516
|
+
};
|
|
2517
|
+
|
|
2518
|
+
const resolveLocalisedPath = (
|
|
2519
|
+
pathname: string,
|
|
2520
|
+
targetLanguage: SupportedLanguage,
|
|
2521
|
+
) => {
|
|
2522
|
+
const pathWithoutLanguage = stripLanguagePrefix(pathname);
|
|
2523
|
+
|
|
2524
|
+
for (const entry of Object.values(localisedUrls)) {
|
|
2525
|
+
const targetPattern = entry[targetLanguage];
|
|
2526
|
+
if (!targetPattern) {
|
|
2527
|
+
continue;
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
for (const language of supportedLanguages) {
|
|
2531
|
+
const sourcePattern = entry[language];
|
|
2532
|
+
const params = sourcePattern
|
|
2533
|
+
? matchPattern(pathWithoutLanguage, sourcePattern)
|
|
2534
|
+
: undefined;
|
|
2535
|
+
if (params) {
|
|
2536
|
+
return buildPath(targetPattern, params);
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
return pathWithoutLanguage;
|
|
2542
|
+
};
|
|
2543
|
+
|
|
2544
|
+
const localizedPath = (pathname: string, language: SupportedLanguage) => {
|
|
2545
|
+
const pathWithoutLanguage = resolveLocalisedPath(pathname, language);
|
|
2546
|
+
return pathWithoutLanguage === '/' ? \`/\${language}\` : \`/\${language}\${pathWithoutLanguage}\`;
|
|
2547
|
+
};
|
|
2548
|
+
|
|
2549
|
+
const locationSuffix = (location: {
|
|
2550
|
+
hash?: unknown;
|
|
2551
|
+
search?: unknown;
|
|
2552
|
+
searchStr?: unknown;
|
|
2553
|
+
}) => {
|
|
2554
|
+
const locationSearch =
|
|
2555
|
+
typeof location.searchStr === 'string'
|
|
2556
|
+
? location.searchStr
|
|
2557
|
+
: typeof location.search === 'string'
|
|
2558
|
+
? location.search
|
|
2559
|
+
: '';
|
|
2560
|
+
const locationHash = typeof location.hash === 'string' ? location.hash : '';
|
|
2561
|
+
|
|
2562
|
+
return \`\${locationSearch}\${locationHash}\`;
|
|
2563
|
+
};
|
|
2564
|
+
|
|
2565
|
+
export default function ShellFrame({ children, showCart = true }: ShellFrameProps) {
|
|
3027
2566
|
const { i18nInstance, language } = useModernI18n();
|
|
3028
2567
|
const t = i18nInstance['t'].bind(i18nInstance);
|
|
3029
2568
|
const location = useLocation();
|
|
3030
2569
|
const suffix = locationSuffix(location);
|
|
3031
|
-
const remotes = useCartRouteRemotes();
|
|
3032
|
-
const Header = remotes?.Header;
|
|
3033
|
-
const CartPage = remotes?.CartPage;
|
|
3034
2570
|
|
|
3035
2571
|
return (
|
|
3036
|
-
<main className="
|
|
3037
|
-
<LocalizedHead />
|
|
2572
|
+
<main className="min-h-screen bg-um-canvas px-4 py-5 text-um-foreground sm:px-6 lg:px-12">
|
|
3038
2573
|
<BoundaryOverlay />
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
<
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
2574
|
+
<div className="mx-auto flex min-h-20 max-w-7xl flex-wrap items-center justify-between gap-3 bg-white/90 px-4 py-3 shadow-xl shadow-stone-900/10 sm:px-6">
|
|
2575
|
+
<Header />
|
|
2576
|
+
<div className="ml-auto flex min-w-0 items-center gap-2">
|
|
2577
|
+
<label className="sr-only" htmlFor="ultramodern-language">
|
|
2578
|
+
{t('shell.language.switcher')}
|
|
2579
|
+
</label>
|
|
2580
|
+
<select
|
|
2581
|
+
className="h-10 rounded-full border border-stone-900/15 bg-white px-3 text-sm font-extrabold text-stone-950 shadow-lg shadow-stone-900/5"
|
|
2582
|
+
id="ultramodern-language"
|
|
2583
|
+
onChange={event => {
|
|
2584
|
+
const nextLanguage = event.currentTarget.value;
|
|
2585
|
+
if (isSupportedLanguage(nextLanguage)) {
|
|
2586
|
+
window.location.assign(
|
|
2587
|
+
\`\${localizedPath(location.pathname, nextLanguage)}\${suffix}\`,
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2590
|
+
}}
|
|
2591
|
+
value={language}
|
|
2592
|
+
>
|
|
2593
|
+
{supportedLanguages.map(code => (
|
|
2594
|
+
<option key={code} value={code}>
|
|
2595
|
+
{t(\`shell.language.\${code}\`)}
|
|
2596
|
+
</option>
|
|
2597
|
+
))}
|
|
2598
|
+
</select>
|
|
2599
|
+
{showCart ? <MiniCart /> : null}
|
|
2600
|
+
</div>
|
|
3053
2601
|
</div>
|
|
3054
|
-
{
|
|
2602
|
+
{children}
|
|
3055
2603
|
</main>
|
|
3056
2604
|
);
|
|
3057
2605
|
}
|
|
@@ -3179,8 +2727,9 @@ export default function BoundaryOverlay() {
|
|
|
3179
2727
|
|
|
3180
2728
|
return (
|
|
3181
2729
|
<>
|
|
3182
|
-
<label className="
|
|
2730
|
+
<label className="fixed bottom-5 left-5 z-[80] flex items-center gap-2 rounded-xl border border-stone-900/10 bg-white/95 px-4 py-3 text-sm font-semibold text-stone-950 shadow-2xl shadow-stone-900/15">
|
|
3183
2731
|
<input
|
|
2732
|
+
className="size-4 accent-emerald-800"
|
|
3184
2733
|
checked={enabled}
|
|
3185
2734
|
onChange={event => setEnabled(event.currentTarget.checked)}
|
|
3186
2735
|
type="checkbox"
|
|
@@ -3188,15 +2737,16 @@ export default function BoundaryOverlay() {
|
|
|
3188
2737
|
<span>{toggleLabel}</span>
|
|
3189
2738
|
</label>
|
|
3190
2739
|
{enabled ? (
|
|
3191
|
-
<div aria-hidden="true" className="
|
|
2740
|
+
<div aria-hidden="true" className="pointer-events-none fixed inset-0 z-[70]">
|
|
3192
2741
|
{boxes.map(box => (
|
|
3193
2742
|
<div
|
|
3194
|
-
className="
|
|
2743
|
+
className="fixed rounded-lg border"
|
|
3195
2744
|
data-label-placement={box.labelPlacement}
|
|
3196
2745
|
key={box.id}
|
|
3197
2746
|
style={
|
|
3198
2747
|
{
|
|
3199
|
-
|
|
2748
|
+
borderColor: box.color,
|
|
2749
|
+
boxShadow: \`0 0 0 1px rgba(255,255,255,.72), 0 6px 20px color-mix(in srgb, \${box.color} 20%, transparent)\`,
|
|
3200
2750
|
height: box.height,
|
|
3201
2751
|
left: box.left,
|
|
3202
2752
|
top: box.top,
|
|
@@ -3204,7 +2754,12 @@ export default function BoundaryOverlay() {
|
|
|
3204
2754
|
} as CSSProperties
|
|
3205
2755
|
}
|
|
3206
2756
|
>
|
|
3207
|
-
<span
|
|
2757
|
+
<span
|
|
2758
|
+
className={\`absolute right-1 top-1 whitespace-nowrap rounded-full px-2 py-1 text-[0.7rem] font-black leading-none text-stone-950 \${box.labelPlacement === 'above' ? 'bottom-[calc(100%+0.25rem)] top-auto' : ''}\`}
|
|
2759
|
+
style={{ backgroundColor: box.color }}
|
|
2760
|
+
>
|
|
2761
|
+
{box.label}
|
|
2762
|
+
</span>
|
|
3208
2763
|
</div>
|
|
3209
2764
|
))}
|
|
3210
2765
|
</div>
|
|
@@ -3233,55 +2788,70 @@ const loadRemoteComponent = async (specifier: string) => {
|
|
|
3233
2788
|
|
|
3234
2789
|
const remoteFallback =
|
|
3235
2790
|
({ error }: { error: Error }) =>
|
|
3236
|
-
<div data-remote-error={error.name}>Remote unavailable</div>;
|
|
2791
|
+
<div className="rounded-xl border border-red-900/20 bg-red-50 px-4 py-3 text-sm font-semibold text-red-900" data-remote-error={error.name}>Remote unavailable</div>;
|
|
2792
|
+
|
|
2793
|
+
const HeaderLoading = () => (
|
|
2794
|
+
<div className="flex min-w-0 flex-1 items-center gap-5" data-mf-boundary="explore">
|
|
2795
|
+
<div className="h-6 w-28 rounded-full bg-stone-200" />
|
|
2796
|
+
<div className="hidden h-5 w-44 rounded-full bg-stone-100 sm:block" />
|
|
2797
|
+
</div>
|
|
2798
|
+
);
|
|
2799
|
+
|
|
2800
|
+
const MiniCartLoading = () => (
|
|
2801
|
+
<div className="h-10 w-28 rounded-full bg-stone-100" data-mf-boundary="checkout" />
|
|
2802
|
+
);
|
|
2803
|
+
|
|
2804
|
+
const PanelLoading = () => (
|
|
2805
|
+
<section className="mx-auto mt-10 max-w-7xl rounded-2xl bg-white/75 p-6 shadow-xl shadow-stone-900/10">
|
|
2806
|
+
<div className="h-5 w-40 rounded-full bg-stone-200" />
|
|
2807
|
+
<div className="mt-5 grid gap-4 md:grid-cols-2">
|
|
2808
|
+
<div className="h-36 rounded-xl bg-stone-100" />
|
|
2809
|
+
<div className="h-36 rounded-xl bg-stone-100" />
|
|
2810
|
+
</div>
|
|
2811
|
+
</section>
|
|
2812
|
+
);
|
|
3237
2813
|
|
|
3238
2814
|
export const Header = createLazyComponent({
|
|
3239
2815
|
export: 'default',
|
|
3240
2816
|
fallback: remoteFallback,
|
|
3241
2817
|
instance: getInstance(),
|
|
3242
2818
|
loader: () => loadRemoteComponent('explore/Header'),
|
|
3243
|
-
loading:
|
|
3244
|
-
noSSR: true,
|
|
2819
|
+
loading: <HeaderLoading />,
|
|
3245
2820
|
});
|
|
3246
2821
|
export const StorePicker = createLazyComponent({
|
|
3247
2822
|
export: 'default',
|
|
3248
2823
|
fallback: remoteFallback,
|
|
3249
2824
|
instance: getInstance(),
|
|
3250
2825
|
loader: () => loadRemoteComponent('explore/StorePicker'),
|
|
3251
|
-
loading:
|
|
3252
|
-
noSSR: true,
|
|
2826
|
+
loading: <PanelLoading />,
|
|
3253
2827
|
});
|
|
3254
2828
|
export const Recommendations = createLazyComponent({
|
|
3255
2829
|
export: 'default',
|
|
3256
2830
|
fallback: remoteFallback,
|
|
3257
2831
|
instance: getInstance(),
|
|
3258
2832
|
loader: () => loadRemoteComponent('explore/Recommendations'),
|
|
3259
|
-
loading:
|
|
3260
|
-
noSSR: true,
|
|
2833
|
+
loading: <PanelLoading />,
|
|
3261
2834
|
});
|
|
3262
2835
|
export const ProductPage = createLazyComponent({
|
|
3263
2836
|
export: 'default',
|
|
3264
2837
|
fallback: remoteFallback,
|
|
3265
2838
|
instance: getInstance(),
|
|
3266
2839
|
loader: () => loadRemoteComponent('decide/ProductPage'),
|
|
3267
|
-
loading:
|
|
3268
|
-
noSSR: true,
|
|
2840
|
+
loading: <PanelLoading />,
|
|
3269
2841
|
});
|
|
3270
2842
|
export const MiniCart = createLazyComponent({
|
|
3271
2843
|
export: 'default',
|
|
3272
2844
|
fallback: remoteFallback,
|
|
3273
2845
|
instance: getInstance(),
|
|
3274
2846
|
loader: () => loadRemoteComponent('checkout/MiniCart'),
|
|
3275
|
-
loading:
|
|
3276
|
-
noSSR: true,
|
|
2847
|
+
loading: <MiniCartLoading />,
|
|
3277
2848
|
});
|
|
3278
2849
|
export const CartPage = createLazyComponent({
|
|
3279
2850
|
export: 'default',
|
|
3280
2851
|
fallback: remoteFallback,
|
|
3281
2852
|
instance: getInstance(),
|
|
3282
2853
|
loader: () => loadRemoteComponent('checkout/CartPage'),
|
|
3283
|
-
loading:
|
|
3284
|
-
noSSR: true,
|
|
2854
|
+
loading: <PanelLoading />,
|
|
3285
2855
|
});
|
|
3286
2856
|
`;
|
|
3287
2857
|
}
|
|
@@ -3327,12 +2897,13 @@ export default function ${toPascalCase(app.id)}Home() {
|
|
|
3327
2897
|
const location = useLocation();
|
|
3328
2898
|
const suffix = locationSuffix(location);
|
|
3329
2899
|
${effectBffState} return (
|
|
3330
|
-
<main>
|
|
2900
|
+
<main className="min-h-screen bg-um-canvas px-4 py-6 text-um-foreground sm:px-8">
|
|
3331
2901
|
<LocalizedHead />
|
|
3332
|
-
<nav aria-label={t('${app.domain}.language.switcher')}>
|
|
2902
|
+
<nav aria-label={t('${app.domain}.language.switcher')} className="flex gap-3">
|
|
3333
2903
|
{supportedLanguages.map(code => (
|
|
3334
2904
|
<a
|
|
3335
2905
|
aria-current={language === code ? 'page' : undefined}
|
|
2906
|
+
className="rounded-full border border-stone-900/15 bg-white px-4 py-2 text-sm font-bold text-stone-950 no-underline"
|
|
3336
2907
|
href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
|
|
3337
2908
|
key={code}
|
|
3338
2909
|
>
|
|
@@ -3340,9 +2911,9 @@ ${effectBffState} return (
|
|
|
3340
2911
|
</a>
|
|
3341
2912
|
))}
|
|
3342
2913
|
</nav>
|
|
3343
|
-
<h1>{t('${app.domain}.title')}</h1>
|
|
3344
|
-
<p data-mf-role="${app.kind}">{t('${app.domain}.role')}</p>
|
|
3345
|
-
<p data-build-marker={ultramodernUiMarker.build} data-testid="ultramodern-ui-marker">
|
|
2914
|
+
<h1 className="mt-10 text-5xl font-black">{t('${app.domain}.title')}</h1>
|
|
2915
|
+
<p className="mt-3 text-lg text-stone-600" data-mf-role="${app.kind}">{t('${app.domain}.role')}</p>
|
|
2916
|
+
<p className="sr-only" data-build-marker={ultramodernUiMarker.build} data-testid="ultramodern-ui-marker">
|
|
3346
2917
|
{ultramodernUiMarker.appId}:{ultramodernUiMarker.version}
|
|
3347
2918
|
</p>
|
|
3348
2919
|
${effectBffMarkup} </main>
|
|
@@ -3370,9 +2941,9 @@ function createRemoteEntry(app) {
|
|
|
3370
2941
|
`;
|
|
3371
2942
|
return `export default function ${toPascalCase(app.domain ?? app.id)}Route() {
|
|
3372
2943
|
return (
|
|
3373
|
-
<section data-mf-remote="${app.id}" data-mf-expose="./Route">
|
|
3374
|
-
<h2>${app.displayName}</h2>
|
|
3375
|
-
<p>Route surface for ${app.domain ?? app.id}.</p>
|
|
2944
|
+
<section className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10" data-mf-remote="${app.id}" data-mf-expose="./Route">
|
|
2945
|
+
<h2 className="text-2xl font-black">${app.displayName}</h2>
|
|
2946
|
+
<p className="mt-2 text-stone-600">Route surface for ${app.domain ?? app.id}.</p>
|
|
3376
2947
|
</section>
|
|
3377
2948
|
);
|
|
3378
2949
|
}
|
|
@@ -3383,9 +2954,9 @@ function createRemoteWidget(app) {
|
|
|
3383
2954
|
const body = 'vertical' === app.kind ? `Owns the ${app.domain} vertical route surface.` : 'Provides shared UI primitives for the workspace.';
|
|
3384
2955
|
return `export default function ${componentName}() {
|
|
3385
2956
|
return (
|
|
3386
|
-
<section data-mf-remote="${app.id}">
|
|
3387
|
-
<h2>${app.displayName}</h2>
|
|
3388
|
-
<p>${body}</p>
|
|
2957
|
+
<section className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10" data-mf-remote="${app.id}">
|
|
2958
|
+
<h2 className="text-2xl font-black">${app.displayName}</h2>
|
|
2959
|
+
<p className="mt-2 text-stone-600">${body}</p>
|
|
3389
2960
|
</section>
|
|
3390
2961
|
);
|
|
3391
2962
|
}
|
|
@@ -3399,23 +2970,27 @@ export default function Header() {
|
|
|
3399
2970
|
const t = i18nInstance['t'].bind(i18nInstance);
|
|
3400
2971
|
|
|
3401
2972
|
return (
|
|
3402
|
-
<header className="
|
|
3403
|
-
<a className="
|
|
3404
|
-
<nav aria-label={t('explore.header.navigation')} className="
|
|
3405
|
-
<a href={\`/\${language}/tractors\`}>{t('explore.header.machines')}</a>
|
|
3406
|
-
<a href={\`/\${language}/stores\`}>{t('explore.header.stores')}</a>
|
|
2973
|
+
<header className="flex min-w-0 flex-1 flex-wrap items-center gap-x-8 gap-y-2" data-mf-boundary="explore">
|
|
2974
|
+
<a className="whitespace-nowrap text-xl font-black tracking-normal text-stone-950 no-underline" href={\`/\${language}\`}>Acre & Iron</a>
|
|
2975
|
+
<nav aria-label={t('explore.header.navigation')} className="flex items-center gap-5">
|
|
2976
|
+
<a className="text-sm font-extrabold text-stone-900 no-underline" href={\`/\${language}/tractors\`}>{t('explore.header.machines')}</a>
|
|
2977
|
+
<a className="text-sm font-extrabold text-stone-900 no-underline" href={\`/\${language}/stores\`}>{t('explore.header.stores')}</a>
|
|
3407
2978
|
</nav>
|
|
3408
2979
|
</header>
|
|
3409
2980
|
);
|
|
3410
2981
|
}
|
|
3411
2982
|
`;
|
|
3412
2983
|
if ('remote-explore' === app.id && './Recommendations' === expose) return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
2984
|
+
import autonomyImage from '../assets/autonomy.svg';
|
|
2985
|
+
import fieldLoaderImage from '../assets/field-loader.svg';
|
|
2986
|
+
import orchardImage from '../assets/orchard.svg';
|
|
2987
|
+
import vineyardImage from '../assets/vineyard.svg';
|
|
3413
2988
|
|
|
3414
2989
|
const tractors = [
|
|
3415
|
-
{ badge: 'explore.recommendations.bestRows', name: 'Orchard Tractor', slug: 'orchard-tractor' },
|
|
3416
|
-
{ badge: 'explore.recommendations.aiFirst', name: 'Autonomy Retrofit Kit', slug: 'autonomy-retrofit-kit' },
|
|
3417
|
-
{ badge: 'explore.recommendations.loaderReady', name: 'Field Loader 112', slug: 'field-loader-112' },
|
|
3418
|
-
{ badge: 'explore.recommendations.vineyard', name: 'Vineyard Narrow 80', slug: 'vineyard-narrow-80' },
|
|
2990
|
+
{ badge: 'explore.recommendations.bestRows', image: orchardImage, name: 'Orchard Tractor', slug: 'orchard-tractor' },
|
|
2991
|
+
{ badge: 'explore.recommendations.aiFirst', image: autonomyImage, name: 'Autonomy Retrofit Kit', slug: 'autonomy-retrofit-kit' },
|
|
2992
|
+
{ badge: 'explore.recommendations.loaderReady', image: fieldLoaderImage, name: 'Field Loader 112', slug: 'field-loader-112' },
|
|
2993
|
+
{ badge: 'explore.recommendations.vineyard', image: vineyardImage, name: 'Vineyard Narrow 80', slug: 'vineyard-narrow-80' },
|
|
3419
2994
|
] as const;
|
|
3420
2995
|
|
|
3421
2996
|
export default function Recommendations() {
|
|
@@ -3423,13 +2998,14 @@ export default function Recommendations() {
|
|
|
3423
2998
|
const t = i18nInstance['t'].bind(i18nInstance);
|
|
3424
2999
|
|
|
3425
3000
|
return (
|
|
3426
|
-
<section className="
|
|
3427
|
-
<h2 className="
|
|
3428
|
-
<div className="
|
|
3001
|
+
<section className="mx-auto mt-12 max-w-7xl" data-mf-boundary="explore">
|
|
3002
|
+
<h2 className="text-3xl font-black tracking-normal text-stone-950">{t('explore.recommendations.title')}</h2>
|
|
3003
|
+
<div className="mt-5 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
3429
3004
|
{tractors.map(tractor => (
|
|
3430
|
-
<a className="
|
|
3431
|
-
<
|
|
3432
|
-
<
|
|
3005
|
+
<a className="block rounded-2xl bg-white/90 p-4 text-stone-950 no-underline shadow-xl shadow-stone-900/10 transition hover:-translate-y-0.5 hover:shadow-2xl" href={\`/\${language}/tractors/\${tractor.slug}\`} key={tractor.slug}>
|
|
3006
|
+
<img alt="" className="aspect-video w-full rounded-xl bg-stone-200 object-cover" src={tractor.image} />
|
|
3007
|
+
<span className="mt-4 block text-xs font-black uppercase tracking-[0.16em] text-amber-700">{t(tractor.badge)}</span>
|
|
3008
|
+
<strong className="mt-2 block text-xl font-black leading-tight">{tractor.name}</strong>
|
|
3433
3009
|
</a>
|
|
3434
3010
|
))}
|
|
3435
3011
|
</div>
|
|
@@ -3438,22 +3014,26 @@ export default function Recommendations() {
|
|
|
3438
3014
|
}
|
|
3439
3015
|
`;
|
|
3440
3016
|
if ('remote-explore' === app.id && './StorePicker' === expose) return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
3017
|
+
import fieldLoaderImage from '../assets/field-loader.svg';
|
|
3018
|
+
import vineyardImage from '../assets/vineyard.svg';
|
|
3441
3019
|
|
|
3442
3020
|
export default function StorePicker() {
|
|
3443
3021
|
const { i18nInstance } = useModernI18n();
|
|
3444
3022
|
const t = i18nInstance['t'].bind(i18nInstance);
|
|
3445
3023
|
|
|
3446
3024
|
return (
|
|
3447
|
-
<section className="
|
|
3448
|
-
<h2 className="
|
|
3449
|
-
<div className="
|
|
3450
|
-
<article className="
|
|
3451
|
-
<
|
|
3452
|
-
<
|
|
3025
|
+
<section className="mx-auto mt-12 max-w-7xl" data-mf-boundary="explore">
|
|
3026
|
+
<h2 className="text-3xl font-black tracking-normal text-stone-950">{t('explore.stores.title')}</h2>
|
|
3027
|
+
<div className="mt-5 grid gap-4 md:grid-cols-2">
|
|
3028
|
+
<article className="rounded-2xl bg-white/90 p-4 shadow-xl shadow-stone-900/10">
|
|
3029
|
+
<img alt="" className="aspect-video w-full rounded-xl bg-stone-200 object-cover" src={fieldLoaderImage} />
|
|
3030
|
+
<span className="mt-4 block text-xs font-black uppercase tracking-[0.16em] text-emerald-800">{t('explore.stores.northRegion')}</span>
|
|
3031
|
+
<strong className="mt-2 block text-2xl font-black">Bohemia Field Supply</strong>
|
|
3453
3032
|
</article>
|
|
3454
|
-
<article className="
|
|
3455
|
-
<
|
|
3456
|
-
<
|
|
3033
|
+
<article className="rounded-2xl bg-white/90 p-4 shadow-xl shadow-stone-900/10">
|
|
3034
|
+
<img alt="" className="aspect-video w-full rounded-xl bg-stone-200 object-cover" src={vineyardImage} />
|
|
3035
|
+
<span className="mt-4 block text-xs font-black uppercase tracking-[0.16em] text-emerald-800">{t('explore.stores.southRegion')}</span>
|
|
3036
|
+
<strong className="mt-2 block text-2xl font-black">Moravia Iron Works</strong>
|
|
3457
3037
|
</article>
|
|
3458
3038
|
</div>
|
|
3459
3039
|
</section>
|
|
@@ -3461,12 +3041,13 @@ export default function StorePicker() {
|
|
|
3461
3041
|
}
|
|
3462
3042
|
`;
|
|
3463
3043
|
if ('remote-explore' === app.id && './Footer' === expose) return `export default function Footer() {
|
|
3464
|
-
return <footer className="
|
|
3044
|
+
return <footer className="mx-auto mt-12 max-w-7xl text-sm font-bold text-stone-600" data-mf-boundary="explore">Acre & Iron</footer>;
|
|
3465
3045
|
}
|
|
3466
3046
|
`;
|
|
3467
3047
|
if ('./Widget' === expose) return createRemoteWidget(app);
|
|
3468
3048
|
const componentName = `${toPascalCase(app.domain ?? app.id)}${toPascalCase(expose.replace(/^\.\//u, ''))}`;
|
|
3469
3049
|
if ('remote-decide' === app.id && './ProductPage' === expose) return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
3050
|
+
import fieldLoaderImage from '../assets/field-loader.svg';
|
|
3470
3051
|
import { AddToCart, Recommendations } from './remote-components';
|
|
3471
3052
|
|
|
3472
3053
|
export default function ${componentName}() {
|
|
@@ -3475,16 +3056,16 @@ export default function ${componentName}() {
|
|
|
3475
3056
|
|
|
3476
3057
|
return (
|
|
3477
3058
|
<>
|
|
3478
|
-
<section className="
|
|
3479
|
-
<
|
|
3059
|
+
<section className="mx-auto mt-10 grid max-w-7xl items-center gap-8 md:grid-cols-[1fr_0.95fr] lg:gap-14" data-mf-boundary="decide" data-mf-remote="${app.id}" data-mf-expose="${expose}">
|
|
3060
|
+
<img alt="" className="aspect-[1/0.9] w-full rounded-3xl border-[18px] border-amber-200 bg-stone-200 object-cover shadow-2xl shadow-stone-900/20" src={fieldLoaderImage} />
|
|
3480
3061
|
<div>
|
|
3481
|
-
<p className="
|
|
3482
|
-
<h1 className="
|
|
3483
|
-
<p className="
|
|
3484
|
-
<div className="
|
|
3485
|
-
<article className="
|
|
3486
|
-
<article className="
|
|
3487
|
-
<article className="
|
|
3062
|
+
<p className="text-xs font-black uppercase tracking-[0.18em] text-emerald-800">{t('decide.product.eyebrow')}</p>
|
|
3063
|
+
<h1 className="mt-3 text-5xl font-black leading-none tracking-normal text-stone-950 md:text-7xl">Field Loader 112</h1>
|
|
3064
|
+
<p className="mt-5 max-w-2xl text-lg leading-8 text-stone-600">{t('decide.product.lede')}</p>
|
|
3065
|
+
<div className="mt-8 grid gap-4 sm:grid-cols-3">
|
|
3066
|
+
<article className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10"><span className="block text-sm font-bold text-stone-500">{t('decide.product.price')}</span><strong className="mt-2 block text-lg font-black">EUR 42,500</strong></article>
|
|
3067
|
+
<article className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10"><span className="block text-sm font-bold text-stone-500">{t('decide.product.power')}</span><strong className="mt-2 block text-lg font-black">112 hp</strong></article>
|
|
3068
|
+
<article className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10"><span className="block text-sm font-bold text-stone-500">{t('decide.product.availability')}</span><strong className="mt-2 block text-lg font-black">{t('decide.product.inStock')}</strong></article>
|
|
3488
3069
|
</div>
|
|
3489
3070
|
<AddToCart />
|
|
3490
3071
|
</div>
|
|
@@ -3503,11 +3084,11 @@ export default function ${componentName}() {
|
|
|
3503
3084
|
const cart = useCartLines();
|
|
3504
3085
|
|
|
3505
3086
|
return (
|
|
3506
|
-
<div className="
|
|
3507
|
-
<button className="
|
|
3087
|
+
<div className="mt-8 flex flex-wrap gap-3" data-mf-boundary="checkout">
|
|
3088
|
+
<button className="inline-flex min-h-11 items-center justify-center rounded-full bg-emerald-800 px-5 font-bold text-white shadow-lg shadow-stone-900/10" onClick={cart.addFieldLoader} type="button">
|
|
3508
3089
|
{t('checkout.actions.addToCart')}
|
|
3509
3090
|
</button>
|
|
3510
|
-
<a className="
|
|
3091
|
+
<a className="inline-flex min-h-11 items-center justify-center rounded-full border border-stone-900/15 bg-white/90 px-5 font-bold text-stone-950 shadow-lg shadow-stone-900/10" href={\`/\${language}/cart\`}>
|
|
3511
3092
|
{t('checkout.actions.viewCart')}
|
|
3512
3093
|
</a>
|
|
3513
3094
|
</div>
|
|
@@ -3524,7 +3105,7 @@ export default function ${componentName}() {
|
|
|
3524
3105
|
const count = cart.lines.reduce((sum, line) => sum + line.quantity, 0);
|
|
3525
3106
|
|
|
3526
3107
|
return (
|
|
3527
|
-
<a className="
|
|
3108
|
+
<a className="inline-flex h-10 shrink-0 items-center justify-center rounded-full border border-stone-900/15 bg-white px-4 text-sm font-extrabold text-stone-950 no-underline shadow-lg shadow-stone-900/5" data-mf-boundary="checkout" href={\`/\${language}/cart\`}>
|
|
3528
3109
|
{t('checkout.cart.title')} ({count})
|
|
3529
3110
|
</a>
|
|
3530
3111
|
);
|
|
@@ -3539,24 +3120,24 @@ export default function ${componentName}() {
|
|
|
3539
3120
|
const cart = useCartLines();
|
|
3540
3121
|
|
|
3541
3122
|
return (
|
|
3542
|
-
<section className="
|
|
3543
|
-
<h1 className="
|
|
3544
|
-
<div className="
|
|
3123
|
+
<section className="mx-auto mt-10 max-w-7xl" data-mf-boundary="checkout" data-mf-remote="${app.id}" data-mf-expose="${expose}">
|
|
3124
|
+
<h1 className="text-5xl font-black leading-none tracking-normal text-stone-950 md:text-7xl">{t('checkout.cart.title')}</h1>
|
|
3125
|
+
<div className="mt-8 rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10">
|
|
3545
3126
|
{cart.lines.length === 0 ? (
|
|
3546
3127
|
<p>{t('checkout.cart.empty')}</p>
|
|
3547
3128
|
) : (
|
|
3548
3129
|
<>
|
|
3549
3130
|
{cart.lines.map(line => (
|
|
3550
|
-
<article className="
|
|
3131
|
+
<article className="grid gap-4 border-t border-stone-900/10 py-4 first:border-t-0 sm:grid-cols-[1fr_auto] sm:items-center" key={line.id}>
|
|
3551
3132
|
<div>
|
|
3552
|
-
<strong>{line.name}</strong>
|
|
3553
|
-
<p>EUR {line.price.toLocaleString('en-US')}</p>
|
|
3133
|
+
<strong className="text-lg font-black">{line.name}</strong>
|
|
3134
|
+
<p className="text-stone-600">EUR {line.price.toLocaleString('en-US')}</p>
|
|
3554
3135
|
</div>
|
|
3555
|
-
<div className="
|
|
3556
|
-
<button className="
|
|
3557
|
-
<span>{line.quantity}</span>
|
|
3558
|
-
<button className="
|
|
3559
|
-
<button className="
|
|
3136
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
3137
|
+
<button className="inline-flex size-9 items-center justify-center rounded-full border border-stone-900/15 bg-white font-black" onClick={() => cart.decrement(line.id)} type="button">-</button>
|
|
3138
|
+
<span className="min-w-6 text-center font-black">{line.quantity}</span>
|
|
3139
|
+
<button className="inline-flex size-9 items-center justify-center rounded-full border border-stone-900/15 bg-white font-black" onClick={() => cart.increment(line.id)} type="button">+</button>
|
|
3140
|
+
<button className="inline-flex min-h-10 items-center justify-center rounded-full border border-stone-900/15 bg-white px-4 font-bold text-stone-950" onClick={() => cart.remove(line.id)} type="button">
|
|
3560
3141
|
{t('checkout.actions.remove')}
|
|
3561
3142
|
</button>
|
|
3562
3143
|
</div>
|
|
@@ -3572,9 +3153,9 @@ export default function ${componentName}() {
|
|
|
3572
3153
|
`;
|
|
3573
3154
|
return `export default function ${componentName}() {
|
|
3574
3155
|
return (
|
|
3575
|
-
<section data-mf-remote="${app.id}" data-mf-expose="${expose}">
|
|
3576
|
-
<h2>${app.displayName} ${expose.replace(/^\.\//u, '')}</h2>
|
|
3577
|
-
<p>Module Federation surface owned by ${app.ownership.team}.</p>
|
|
3156
|
+
<section className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10" data-mf-remote="${app.id}" data-mf-expose="${expose}">
|
|
3157
|
+
<h2 className="text-2xl font-black">${app.displayName} ${expose.replace(/^\.\//u, '')}</h2>
|
|
3158
|
+
<p className="mt-2 text-stone-600">Module Federation surface owned by ${app.ownership.team}.</p>
|
|
3578
3159
|
</section>
|
|
3579
3160
|
);
|
|
3580
3161
|
}
|
|
@@ -3599,23 +3180,40 @@ const loadRemoteComponent = async (specifier: string) => {
|
|
|
3599
3180
|
|
|
3600
3181
|
const remoteFallback =
|
|
3601
3182
|
({ error }: { error: Error }) =>
|
|
3602
|
-
<div data-remote-error={error.name}>Remote unavailable</div>;
|
|
3183
|
+
<div className="rounded-xl border border-red-900/20 bg-red-50 px-4 py-3 text-sm font-semibold text-red-900" data-remote-error={error.name}>Remote unavailable</div>;
|
|
3184
|
+
|
|
3185
|
+
const AddToCartLoading = () => (
|
|
3186
|
+
<div className="mt-8 flex gap-3" data-mf-boundary="checkout">
|
|
3187
|
+
<div className="h-11 w-32 rounded-full bg-stone-200" />
|
|
3188
|
+
<div className="h-11 w-28 rounded-full bg-white/80" />
|
|
3189
|
+
</div>
|
|
3190
|
+
);
|
|
3191
|
+
|
|
3192
|
+
const RecommendationsLoading = () => (
|
|
3193
|
+
<section className="mx-auto mt-12 max-w-7xl" data-mf-boundary="explore">
|
|
3194
|
+
<div className="h-8 w-64 rounded-full bg-stone-200" />
|
|
3195
|
+
<div className="mt-5 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
3196
|
+
<div className="h-48 rounded-2xl bg-white/80" />
|
|
3197
|
+
<div className="h-48 rounded-2xl bg-white/80" />
|
|
3198
|
+
<div className="h-48 rounded-2xl bg-white/80" />
|
|
3199
|
+
<div className="h-48 rounded-2xl bg-white/80" />
|
|
3200
|
+
</div>
|
|
3201
|
+
</section>
|
|
3202
|
+
);
|
|
3603
3203
|
|
|
3604
3204
|
export const AddToCart = createLazyComponent({
|
|
3605
3205
|
export: 'default',
|
|
3606
3206
|
fallback: remoteFallback,
|
|
3607
3207
|
instance: getInstance(),
|
|
3608
3208
|
loader: () => loadRemoteComponent('checkout/AddToCart'),
|
|
3609
|
-
loading:
|
|
3610
|
-
noSSR: true,
|
|
3209
|
+
loading: <AddToCartLoading />,
|
|
3611
3210
|
});
|
|
3612
3211
|
export const Recommendations = createLazyComponent({
|
|
3613
3212
|
export: 'default',
|
|
3614
3213
|
fallback: remoteFallback,
|
|
3615
3214
|
instance: getInstance(),
|
|
3616
3215
|
loader: () => loadRemoteComponent('explore/Recommendations'),
|
|
3617
|
-
loading:
|
|
3618
|
-
noSSR: true,
|
|
3216
|
+
loading: <RecommendationsLoading />,
|
|
3619
3217
|
});
|
|
3620
3218
|
`;
|
|
3621
3219
|
}
|
|
@@ -3749,17 +3347,9 @@ function createAppLocaleMessages(app, language) {
|
|
|
3749
3347
|
};
|
|
3750
3348
|
}
|
|
3751
3349
|
function createDesignButton() {
|
|
3752
|
-
return `
|
|
3753
|
-
|
|
3754
|
-
export default function Button({ label }: { label: string }) {
|
|
3350
|
+
return `export default function Button({ label }: { label: string }) {
|
|
3755
3351
|
return (
|
|
3756
|
-
<button
|
|
3757
|
-
type="button"
|
|
3758
|
-
style={{
|
|
3759
|
-
borderRadius: designTokens.radius.control,
|
|
3760
|
-
color: designTokens.color.foreground,
|
|
3761
|
-
}}
|
|
3762
|
-
>
|
|
3352
|
+
<button className="rounded-full text-um-foreground" type="button">
|
|
3763
3353
|
{label}
|
|
3764
3354
|
</button>
|
|
3765
3355
|
);
|
|
@@ -3875,14 +3465,12 @@ export function useCartLines() {
|
|
|
3875
3465
|
`;
|
|
3876
3466
|
}
|
|
3877
3467
|
function createSharedDesignTokensCss() {
|
|
3878
|
-
return `@
|
|
3879
|
-
:
|
|
3880
|
-
--um-
|
|
3881
|
-
--um-
|
|
3882
|
-
--um-
|
|
3883
|
-
--um-
|
|
3884
|
-
--um-color-surface: #f6fbf7;
|
|
3885
|
-
}
|
|
3468
|
+
return `@theme {
|
|
3469
|
+
--color-um-accent: #2f8f68;
|
|
3470
|
+
--color-um-canvas: #f1eadc;
|
|
3471
|
+
--color-um-foreground: #133225;
|
|
3472
|
+
--color-um-link: #166b4b;
|
|
3473
|
+
--color-um-surface: #f6fbf7;
|
|
3886
3474
|
}
|
|
3887
3475
|
`;
|
|
3888
3476
|
}
|
|
@@ -5788,10 +5376,12 @@ function writeApp(targetDir, scope, app, packageSource, enableTailwind) {
|
|
|
5788
5376
|
}
|
|
5789
5377
|
writeFile(targetDir, `${app.directory}/module-federation.config.ts`, 'shell' === app.kind ? createShellModuleFederationConfig() : createRemoteModuleFederationConfig(app));
|
|
5790
5378
|
writeFile(targetDir, `${app.directory}/src/routes/layout.tsx`, createLayout(app.id));
|
|
5379
|
+
for (const [relativePath, content] of Object.entries(commerceAssetsForApp(app)))writeFile(targetDir, `${app.directory}/${relativePath}`, content);
|
|
5791
5380
|
writeFile(targetDir, `${app.directory}/src/routes/[lang]/page.tsx`, 'shell' === app.kind ? createShellPage() : createRemotePage(app));
|
|
5792
5381
|
for (const route of createRouteOwnedI18nPaths(app))if ('/' !== route.canonicalPath && 'shell' !== app.kind) writeFile(targetDir, createRoutePageFilePath(app, route.canonicalPath), createRouteAliasPage(route.canonicalPath));
|
|
5793
5382
|
if ('shell' === app.kind) {
|
|
5794
5383
|
writeFile(targetDir, `${app.directory}/src/routes/remote-components.tsx`, createShellRemoteComponents());
|
|
5384
|
+
writeFile(targetDir, `${app.directory}/src/routes/shell-frame.tsx`, createShellFrameComponent());
|
|
5795
5385
|
writeFile(targetDir, `${app.directory}/src/routes/boundary-overlay.tsx`, createShellBoundaryOverlay());
|
|
5796
5386
|
writeFile(targetDir, `${app.directory}/src/effect/recommendations-client.ts`, createShellEffectClient(scope));
|
|
5797
5387
|
writeFile(targetDir, `${app.directory}/src/routes/[lang]/tractors/page.tsx`, createShellTractorsPage());
|
|
@@ -5824,7 +5414,13 @@ function writeEffectService(targetDir, scope, packageSource, enableTailwind, ser
|
|
|
5824
5414
|
writeFile(targetDir, `${service.directory}/src/ultramodern-build.ts`, createUltramodernBuildModule(scope, service));
|
|
5825
5415
|
writeFile(targetDir, `${service.directory}/src/routes/layout.tsx`, createLayout(service.id));
|
|
5826
5416
|
writeFile(targetDir, `${service.directory}/src/routes/page.tsx`, `export default function ${toPascalCase(service.id)}Home() {
|
|
5827
|
-
return
|
|
5417
|
+
return (
|
|
5418
|
+
<main className="min-h-screen bg-um-canvas px-4 py-6 text-um-foreground sm:px-8">
|
|
5419
|
+
<section className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10">
|
|
5420
|
+
<h1 className="text-3xl font-black">${service.id} Effect service</h1>
|
|
5421
|
+
</section>
|
|
5422
|
+
</main>
|
|
5423
|
+
);
|
|
5828
5424
|
}
|
|
5829
5425
|
`);
|
|
5830
5426
|
writeFile(targetDir, `${service.directory}/src/routes/index.css`, createServiceStyles(enableTailwind, scope, service));
|