create-skybridge 0.0.0-dev.e9f6a8d → 0.0.0-dev.ea09368
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 +46 -24
- package/package.json +4 -4
- package/templates/blank/Dockerfile +2 -2
- package/templates/blank/node_modules/.bin/alpic +2 -2
- package/templates/blank/node_modules/.bin/tsc +2 -2
- package/templates/blank/node_modules/.bin/tsserver +2 -2
- package/templates/blank/node_modules/.bin/tsx +2 -2
- package/templates/blank/node_modules/.bin/vite +2 -2
- package/templates/blank/package.json +8 -8
- package/templates/demo/Dockerfile +2 -2
- package/templates/demo/node_modules/.bin/alpic +2 -2
- package/templates/demo/node_modules/.bin/tsc +2 -2
- package/templates/demo/node_modules/.bin/tsserver +2 -2
- package/templates/demo/node_modules/.bin/tsx +2 -2
- package/templates/demo/node_modules/.bin/vite +2 -2
- package/templates/demo/package.json +17 -17
- package/templates/ecom/.dockerignore +4 -0
- package/templates/ecom/.env.template +2 -0
- package/templates/ecom/.ladle/components.tsx +26 -0
- package/templates/ecom/.ladle/config.mjs +11 -0
- package/templates/ecom/.ladle/vite.config.ts +11 -0
- package/templates/ecom/AGENTS.md +2 -0
- package/templates/ecom/Dockerfile +53 -0
- package/templates/ecom/README.md +92 -0
- package/templates/ecom/_gitignore +9 -0
- package/templates/ecom/alpic.json +3 -0
- package/templates/ecom/node_modules/.bin/alpic +21 -0
- package/templates/ecom/node_modules/.bin/ladle +21 -0
- package/templates/ecom/node_modules/.bin/sb +21 -0
- package/templates/ecom/node_modules/.bin/skybridge +21 -0
- package/templates/ecom/node_modules/.bin/tsc +21 -0
- package/templates/ecom/node_modules/.bin/tsserver +21 -0
- package/templates/ecom/node_modules/.bin/tsx +21 -0
- package/templates/ecom/node_modules/.bin/vite +21 -0
- package/templates/ecom/package.json +41 -0
- package/templates/ecom/src/components/empty-state.stories.tsx +3 -0
- package/templates/ecom/src/components/empty-state.tsx +12 -0
- package/templates/ecom/src/components/product-card.css.ts +136 -0
- package/templates/ecom/src/components/product-card.stories.tsx +58 -0
- package/templates/ecom/src/components/product-card.tsx +101 -0
- package/templates/ecom/src/components/product-carousel.css.ts +134 -0
- package/templates/ecom/src/components/product-carousel.stories.tsx +64 -0
- package/templates/ecom/src/components/product-carousel.tsx +195 -0
- package/templates/ecom/src/components/view-frame.css.ts +22 -0
- package/templates/ecom/src/components/view-frame.tsx +27 -0
- package/templates/ecom/src/config.ts +12 -0
- package/templates/ecom/src/design/contract.css.ts +39 -0
- package/templates/ecom/src/design/fonts.css +15 -0
- package/templates/ecom/src/design/primitives.css.ts +101 -0
- package/templates/ecom/src/design/recipes/typography.css.ts +75 -0
- package/templates/ecom/src/design/sprinkles.css.ts +128 -0
- package/templates/ecom/src/design/themes/dark.css.ts +36 -0
- package/templates/ecom/src/design/themes/light.css.ts +36 -0
- package/templates/ecom/src/design/tokens.ts +8 -0
- package/templates/ecom/src/helpers.ts +4 -0
- package/templates/ecom/src/i18n.ts +27 -0
- package/templates/ecom/src/index.css +9 -0
- package/templates/ecom/src/lib/cx.ts +9 -0
- package/templates/ecom/src/lib/format.ts +9 -0
- package/templates/ecom/src/server.ts +43 -0
- package/templates/ecom/src/tools/render-carousel.ts +234 -0
- package/templates/ecom/src/tools/search-products.ts +182 -0
- package/templates/ecom/src/types.ts +13 -0
- package/templates/ecom/src/views/carousel/index.tsx +94 -0
- package/templates/ecom/tsconfig.json +11 -0
- package/templates/ecom/vite.config.ts +8 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import "../../index.css";
|
|
2
|
+
|
|
3
|
+
import { type ReactNode, useState } from "react";
|
|
4
|
+
import { EmptyState } from "../../components/empty-state";
|
|
5
|
+
import {
|
|
6
|
+
ProductCard,
|
|
7
|
+
ProductCardSkeleton,
|
|
8
|
+
} from "../../components/product-card";
|
|
9
|
+
import { ProductCarousel } from "../../components/product-carousel";
|
|
10
|
+
import { ViewFrame } from "../../components/view-frame";
|
|
11
|
+
import { sprinkles } from "../../design/tokens";
|
|
12
|
+
import { useToolInfo } from "../../helpers.js";
|
|
13
|
+
import { useLabels } from "../../i18n";
|
|
14
|
+
import { formatPrice } from "../../lib/format";
|
|
15
|
+
import type { Product } from "../../tools/render-carousel.js";
|
|
16
|
+
|
|
17
|
+
const SKELETON_COUNT = 4;
|
|
18
|
+
|
|
19
|
+
// One narration line per on-screen product. `id` ties the card back to its full
|
|
20
|
+
// record in structuredContent.
|
|
21
|
+
function narrate(product: Product, index: number): string {
|
|
22
|
+
const { card } = product;
|
|
23
|
+
const price = card.price ? ` - ${formatPrice(card.price)}` : "";
|
|
24
|
+
const oos = card.outOfStock ? " [out of stock]" : "";
|
|
25
|
+
return `${index + 1}. ${card.title} (id: ${product.id})${price}${oos}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Carousel view for the `render-carousel` tool. Reads the full products from
|
|
30
|
+
* `_meta` (via useToolInfo().responseMetadata) and renders one card each.
|
|
31
|
+
* `structuredContent` is the model's grounding and is not used to render.
|
|
32
|
+
*/
|
|
33
|
+
function Carousel() {
|
|
34
|
+
const { responseMetadata } = useToolInfo<"render-carousel">();
|
|
35
|
+
const [visibleIndices, setVisibleIndices] = useState<number[]>([]);
|
|
36
|
+
const labels = useLabels();
|
|
37
|
+
|
|
38
|
+
// Tool still resolving: reserve the layout with skeleton cards.
|
|
39
|
+
if (responseMetadata == null) {
|
|
40
|
+
const skeletons: ReactNode[] = [];
|
|
41
|
+
for (let i = 0; i < SKELETON_COUNT; i++) {
|
|
42
|
+
skeletons.push(<ProductCardSkeleton key={i} />);
|
|
43
|
+
}
|
|
44
|
+
return (
|
|
45
|
+
<ViewFrame>
|
|
46
|
+
<div className={sprinkles({ p: "3xs" })}>
|
|
47
|
+
<ProductCarousel loading>{skeletons}</ProductCarousel>
|
|
48
|
+
</div>
|
|
49
|
+
</ViewFrame>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const products = responseMetadata?.products ?? [];
|
|
54
|
+
|
|
55
|
+
if (products.length === 0) {
|
|
56
|
+
return (
|
|
57
|
+
<ViewFrame>
|
|
58
|
+
<EmptyState message={labels.noProducts} />
|
|
59
|
+
</ViewFrame>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const cards: ReactNode[] = [];
|
|
64
|
+
for (const [index, product] of products.entries()) {
|
|
65
|
+
const { card } = product;
|
|
66
|
+
cards.push(
|
|
67
|
+
<ProductCard
|
|
68
|
+
key={product.id}
|
|
69
|
+
data-llm={visibleIndices.includes(index) ? narrate(product, index) : ""}
|
|
70
|
+
title={card.title}
|
|
71
|
+
price={card.price}
|
|
72
|
+
media={card.media}
|
|
73
|
+
outOfStock={card.outOfStock}
|
|
74
|
+
/>,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const narration = `Carousel of ${products.length} product(s); the user scrolls horizontally. On screen now:`;
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<ViewFrame>
|
|
82
|
+
<div className={sprinkles({ p: "3xs" })}>
|
|
83
|
+
<ProductCarousel
|
|
84
|
+
onVisibleChange={setVisibleIndices}
|
|
85
|
+
data-llm={narration}
|
|
86
|
+
>
|
|
87
|
+
{cards}
|
|
88
|
+
</ProductCarousel>
|
|
89
|
+
</div>
|
|
90
|
+
</ViewFrame>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default Carousel;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
import { skybridge } from "skybridge/vite";
|
|
4
|
+
import { defineConfig, type PluginOption } from "vite";
|
|
5
|
+
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
plugins: [skybridge() as PluginOption, react(), vanillaExtractPlugin()],
|
|
8
|
+
});
|