@squadbase/vantage-template 0.1.1-dev1.7c71823 → 0.1.1-dev1.80c51bb
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.
|
@@ -112,6 +112,11 @@ if (q.isError) return <ErrorState message={q.error.message} /> // HttpError の
|
|
|
112
112
|
const rows = useApiQuery<Row[]>("/api/customers", { search: { segment } })
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
絞り込み(期間・セグメント)を持つページでは、この `ErrorState` の早期 return をデータを描く
|
|
116
|
+
子コンポーネントの中に置く。ページの先頭に置くと、失敗したときに絞り込みの欄ごと消えて条件を
|
|
117
|
+
直せなくなる。期間は `DateRangePicker` で選ばせる(→ `agents/page.md` の「絞り込みの欄は、
|
|
118
|
+
読み込み中も失敗したときも出し続ける」)。
|
|
119
|
+
|
|
115
120
|
書き込みは `useApiMutation(path, { method: "POST" })` — 変数がそのまま JSON ボディになる。
|
|
116
121
|
|
|
117
122
|
## UI コンポーネント / ブロックを追加する
|
|
@@ -32,6 +32,9 @@ export async function GET({ params, env }: ApiContext) {
|
|
|
32
32
|
(`!` で黙らせない)。
|
|
33
33
|
- **クライアントに見せたいエラーは `HttpError(status, msg)` を throw する。** それ以外の throw は
|
|
34
34
|
ログに記録され汎用の 500 に丸められる。
|
|
35
|
+
- **入力の誤りは 400 で返し、`msg` には何がどう誤りかを書く。** `msg` はそのまま `ErrorState` に
|
|
36
|
+
出る。「開始日(10/20)が終了日(10/01)より後です」のように、利用者が条件を直せる文にする。
|
|
37
|
+
許す範囲だけを並べた文(「最大366日で指定」)では、どこを直せばよいか伝わらない。
|
|
35
38
|
- **シークレットは `ApiContext.env` にだけ届く**(クライアントには決して届かない)。
|
|
36
39
|
|
|
37
40
|
クライアント側からは `useApiQuery` で `/api/*` を叩く。ベース URL の解決・JSON パース・
|
|
@@ -74,5 +77,9 @@ return <Chart sessions={sessions.data} metrics={metrics.data} />
|
|
|
74
77
|
カードごとに別々に読み込み中・エラーを出すなら、`data` を渡す側で `q.data ?? []` にするか、
|
|
75
78
|
カードのコンポーネントの中で上と同じ判定をする。
|
|
76
79
|
|
|
80
|
+
期間などの絞り込みを持つページでは、上の早期 return をページの先頭に置かない。失敗したときに
|
|
81
|
+
絞り込みの欄まで消え、条件を直せなくなる。判定はデータを描く子コンポーネントの中で行う
|
|
82
|
+
(→ `agents/page.md` の「絞り込みの欄は、読み込み中も失敗したときも出し続ける」)。
|
|
83
|
+
|
|
77
84
|
`ApiError` は `message`・`status`・`body`・`requestId` を持つ。hook が使えない場所では
|
|
78
85
|
`apiJson(path, init)`、生の `Response` が要るときは `apiFetch`。
|
|
@@ -147,6 +147,42 @@ const [segments, setSegments] = useSearchState<string[]>("segments", []) // JSON
|
|
|
147
147
|
デフォルト値(または `null`)を書くとキーは URL から消える。履歴は既定で `replace`
|
|
148
148
|
(`{ replace: false }` で push)。
|
|
149
149
|
|
|
150
|
+
### 絞り込みの欄は、読み込み中も失敗したときも出し続ける
|
|
151
|
+
|
|
152
|
+
ページの先頭で `if (q.isError) return <ErrorState …/>` と書くと、取得に失敗したときに
|
|
153
|
+
期間などの絞り込みの欄まで消える。利用者は条件を直せず、初期値に戻すしかなくなる。
|
|
154
|
+
絞り込みの欄はページに置いたままにし、取得と `Loading` / `ErrorState` はデータを描く
|
|
155
|
+
子コンポーネントに入れる:
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
export default function Traffic() {
|
|
159
|
+
const [from, setFrom] = useSearchParam("from", DEFAULT_FROM)
|
|
160
|
+
const [to, setTo] = useSearchParam("to", DEFAULT_TO)
|
|
161
|
+
return (
|
|
162
|
+
<>
|
|
163
|
+
{/* 失敗しても消えない。ここから条件を直せる */}
|
|
164
|
+
<PeriodFilter from={from} to={to} onChange={…} />
|
|
165
|
+
<TrafficBody from={from} to={to} />
|
|
166
|
+
</>
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function TrafficBody({ from, to }: { from: string; to: string }) {
|
|
171
|
+
const q = useApiQuery<Row[]>("/api/traffic", { search: { from, to } })
|
|
172
|
+
if (q.isPending) return <Loading />
|
|
173
|
+
if (q.isError) return <ErrorState message={q.error.message} />
|
|
174
|
+
return <BarChart data={q.data} index="channel" categories={["sessions"]} />
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
- **期間は `DateRangePicker`(`@squadbase/vantage/components`)で選ばせる。** カレンダーで
|
|
179
|
+
範囲を選ぶので開始と終了が逆にならず、選べる日を `minDate` / `maxDate` で絞れる。
|
|
180
|
+
`<input type="date">` を 2 つ並べて自前で組まない。
|
|
181
|
+
- 値をそのまま打ち込める欄を置くなら、開始が終了より後・選べる範囲の外といった誤りは、
|
|
182
|
+
API へ送る前に欄のそばで理由を出す。誤りがあるあいだはデータの子コンポーネントを描かない
|
|
183
|
+
(送れば失敗するだけで、`ErrorState` には直し方が出ない)。
|
|
184
|
+
- サーバー側の検証で弾くときも、`HttpError(400, …)` の文で何がどう誤りかを言う(→ `agents/api.md`)。
|
|
185
|
+
|
|
150
186
|
### 動的パラメータの「3 つの綴り」を同期させる
|
|
151
187
|
|
|
152
188
|
崩すと静かにマッチしなくなる不変条件:
|
package/base-template/bun.lock
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"name": "vibe-app",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@squadbase/react": "^0.1.0",
|
|
9
|
-
"@squadbase/vantage": "0.6.2-dev1.
|
|
9
|
+
"@squadbase/vantage": "0.6.2-dev1.a881d95",
|
|
10
10
|
"@squadbase/vantage-sdk": "0.1.1-dev1.54d3684",
|
|
11
11
|
"date-fns": "^4.1.0",
|
|
12
12
|
"lucide-react": "^0.468.0",
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
|
|
197
197
|
"@squadbase/react": ["@squadbase/react@0.1.0", "", { "dependencies": { "zod": "^4.3.6" }, "peerDependencies": { "@types/react": "17.x || 18.x || 19.x", "react": "17.x || 18.x || 19.x" }, "optionalPeers": ["@types/react"] }, "sha512-k+Dpyj7eH+Yjydw54iEluCjYDae086d12hWgBjNMpw4wLbQGz3CrJ6Yipodg8n1cKUt7zvwddlcTHd79bgKsXg=="],
|
|
198
198
|
|
|
199
|
-
"@squadbase/vantage": ["@squadbase/vantage@0.6.2-dev1.
|
|
199
|
+
"@squadbase/vantage": ["@squadbase/vantage@0.6.2-dev1.a881d95", "", { "dependencies": { "@base-ui/react": "^1.6.0", "@hono/node-server": "^2.1.5", "@streamdown/code": "^1.1.1", "@tailwindcss/vite": "^4.3.3", "@tanstack/react-query": "^5.101.2", "@tanstack/react-router": "^1.170.17", "@tanstack/react-table": "^8.21.3", "@vitejs/plugin-react": "^6.1.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "echarts": "^6.0.0", "esbuild": "0.28.1", "fflate": "^0.8.3", "hono": "^4.13.13", "html-to-image": "^1.11.13", "lucide-react": "^0.468.0", "papaparse": "^5.7.0", "picocolors": "^1.1.1", "react-day-picker": "^10.0.1", "read-excel-file": "^9.3.10", "shiki": "3.23.0", "streamdown": "^2.5.0", "tailwind-merge": "3.6.0", "tailwindcss": "^4.3.3", "tw-animate-css": "^1.0.0", "vite": "^8.3.4" }, "peerDependencies": { "react": ">=18.2.0", "react-dom": ">=18.2.0", "typescript": ">=5.0.0" }, "optionalPeers": ["typescript"], "bin": { "vantage": "dist/cli.js" } }, "sha512-6rZQrw/EyYAFhczGLRsQMjYrAxwDIbPyb2b8QZRh7TDIa5OzBFqcpdPCCnAh00BkX5cPwsa32ZuQNI8Ta71e/g=="],
|
|
200
200
|
|
|
201
201
|
"@squadbase/vantage-sdk": ["@squadbase/vantage-sdk@0.1.1-dev1.54d3684", "", {}, "sha512-dKwVlkeeyKn92zeF1GWwswLHmARsT5Nx2Pvi6Z+XfCzu3N02XmlxISr/YCAzAaXrdWEoAp3/ghlRZtLoPl30AQ=="],
|
|
202
202
|
|
|
@@ -512,7 +512,7 @@
|
|
|
512
512
|
|
|
513
513
|
"hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="],
|
|
514
514
|
|
|
515
|
-
"hono": ["hono@4.13.
|
|
515
|
+
"hono": ["hono@4.13.14", "", {}, "sha512-yhRLQ21U6qa9Hsu2N7Qcbh8tE+WKEcoErjIo56LeSGiGXGp9sA7UpE86Ui9uexb61KakiGwuHMn2QdV7w6i6kQ=="],
|
|
516
516
|
|
|
517
517
|
"html-to-image": ["html-to-image@1.11.13", "", {}, "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg=="],
|
|
518
518
|
|
|
@@ -700,7 +700,7 @@
|
|
|
700
700
|
|
|
701
701
|
"points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
|
|
702
702
|
|
|
703
|
-
"postcss": ["postcss@8.5.
|
|
703
|
+
"postcss": ["postcss@8.5.32", "", { "dependencies": { "nanoid": "^3.3.20", "picocolors": "^1.1.1", "source-map-js": "^1.2.2" } }, "sha512-LJlKCCAUFKOuZxipUdYw1NzIITEsPcgyOG9LkvRJvuKj/bRzbuRY0ARXvL0pWGpsZvn8jku+LMep2eU0seHp8g=="],
|
|
704
704
|
|
|
705
705
|
"property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="],
|
|
706
706
|
|
|
@@ -716,7 +716,7 @@
|
|
|
716
716
|
|
|
717
717
|
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
|
|
718
718
|
|
|
719
|
-
"read-excel-file": ["read-excel-file@9.3.
|
|
719
|
+
"read-excel-file": ["read-excel-file@9.3.13", "", { "dependencies": { "fflate": "^0.8.3", "saxen": "^11.1.0", "unzipper-esm": "^0.13.3", "worker-f": "^0.1.12" } }, "sha512-dzSGFNBVOk4QkFXE37cREK7DOEVAMNYyXO1QIOoquJ24HhA2hZAZ9WYwf4KddjiV6ZMtsY3OM2JSVLpCg++9jA=="],
|
|
720
720
|
|
|
721
721
|
"regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
|
|
722
722
|
|
|
@@ -834,7 +834,7 @@
|
|
|
834
834
|
|
|
835
835
|
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
|
|
836
836
|
|
|
837
|
-
"worker-f": ["worker-f@0.1.
|
|
837
|
+
"worker-f": ["worker-f@0.1.21", "", {}, "sha512-pMi7wCz3uZVxRvRSphyaIYoN7rm9bV0usifTib7u01kKU+hOo+/hFwhajYnpOCHyr0Xp3/2ulc4F+Jm2a3YIfg=="],
|
|
838
838
|
|
|
839
839
|
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
|
840
840
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@squadbase/react": "^0.1.0",
|
|
15
|
-
"@squadbase/vantage": "0.6.2-dev1.
|
|
15
|
+
"@squadbase/vantage": "0.6.2-dev1.a881d95",
|
|
16
16
|
"@squadbase/vantage-sdk": "0.1.1-dev1.54d3684",
|
|
17
17
|
"date-fns": "^4.1.0",
|
|
18
18
|
"lucide-react": "^0.468.0",
|
package/dist/index.js
CHANGED
|
@@ -1146,8 +1146,8 @@ var buildThemeCss = (cssVars) => [
|
|
|
1146
1146
|
var THEME_PRESETS_DATA = [
|
|
1147
1147
|
{
|
|
1148
1148
|
"id": "neutral",
|
|
1149
|
-
"title": "
|
|
1150
|
-
"description": "
|
|
1149
|
+
"title": "Neutral",
|
|
1150
|
+
"description": "A preset that restores the default neutral theme. It has the same values as the base theme and is the starting point when switching presets.",
|
|
1151
1151
|
"cssVars": {
|
|
1152
1152
|
"light": {
|
|
1153
1153
|
"radius": "0.5rem",
|
|
@@ -1253,8 +1253,8 @@ var THEME_PRESETS_DATA = [
|
|
|
1253
1253
|
},
|
|
1254
1254
|
{
|
|
1255
1255
|
"id": "ocean",
|
|
1256
|
-
"title": "
|
|
1257
|
-
"description": "
|
|
1256
|
+
"title": "Ocean",
|
|
1257
|
+
"description": "A blue preset with a calm, trustworthy palette and slightly smaller, squarer corners than the default.",
|
|
1258
1258
|
"cssVars": {
|
|
1259
1259
|
"light": {
|
|
1260
1260
|
"radius": "0.375rem",
|
|
@@ -1360,8 +1360,8 @@ var THEME_PRESETS_DATA = [
|
|
|
1360
1360
|
},
|
|
1361
1361
|
{
|
|
1362
1362
|
"id": "forest",
|
|
1363
|
-
"title": "
|
|
1364
|
-
"description": "
|
|
1363
|
+
"title": "Forest",
|
|
1364
|
+
"description": "A green preset with slightly smaller corners. The font is a rounded sans-serif (ui-rounded in Safari, Hiragino Maru Gothic on macOS and iOS, the default font elsewhere).",
|
|
1365
1365
|
"cssVars": {
|
|
1366
1366
|
"light": {
|
|
1367
1367
|
"radius": "0.5rem",
|
|
@@ -1467,8 +1467,8 @@ var THEME_PRESETS_DATA = [
|
|
|
1467
1467
|
},
|
|
1468
1468
|
{
|
|
1469
1469
|
"id": "sunset",
|
|
1470
|
-
"title": "
|
|
1471
|
-
"description": "
|
|
1470
|
+
"title": "Sunset",
|
|
1471
|
+
"description": "An orange preset with a warm palette and slightly larger corners.",
|
|
1472
1472
|
"cssVars": {
|
|
1473
1473
|
"light": {
|
|
1474
1474
|
"radius": "0.75rem",
|
|
@@ -1574,8 +1574,8 @@ var THEME_PRESETS_DATA = [
|
|
|
1574
1574
|
},
|
|
1575
1575
|
{
|
|
1576
1576
|
"id": "violet",
|
|
1577
|
-
"title": "
|
|
1578
|
-
"description": "
|
|
1577
|
+
"title": "Violet",
|
|
1578
|
+
"description": "A purple preset with large, soft corners.",
|
|
1579
1579
|
"cssVars": {
|
|
1580
1580
|
"light": {
|
|
1581
1581
|
"radius": "0.875rem",
|
|
@@ -1681,8 +1681,8 @@ var THEME_PRESETS_DATA = [
|
|
|
1681
1681
|
},
|
|
1682
1682
|
{
|
|
1683
1683
|
"id": "rose",
|
|
1684
|
-
"title": "
|
|
1685
|
-
"description": "
|
|
1684
|
+
"title": "Rose",
|
|
1685
|
+
"description": "A magenta-to-pink preset in muted tones that don't read as the destructive red, with large corners.",
|
|
1686
1686
|
"cssVars": {
|
|
1687
1687
|
"light": {
|
|
1688
1688
|
"radius": "1rem",
|
|
@@ -1788,8 +1788,8 @@ var THEME_PRESETS_DATA = [
|
|
|
1788
1788
|
},
|
|
1789
1789
|
{
|
|
1790
1790
|
"id": "mono",
|
|
1791
|
-
"title": "
|
|
1792
|
-
"description": "
|
|
1791
|
+
"title": "Mono",
|
|
1792
|
+
"description": "A near-grayscale preset with muted chart colors, the smallest corners and a monospace font (the system monospace font).",
|
|
1793
1793
|
"cssVars": {
|
|
1794
1794
|
"light": {
|
|
1795
1795
|
"radius": "0.25rem",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squadbase/vantage-template",
|
|
3
|
-
"version": "0.1.1-dev1.
|
|
3
|
+
"version": "0.1.1-dev1.80c51bb",
|
|
4
4
|
"description": "CLI tool for initializing and customizing Squadbase Vantage projects.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"squadbase",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@ai-sdk/openai": "2.0.122",
|
|
51
51
|
"ai": "^5.0.52"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "80c51bb5594930f164d4ac511b08a347c9844bc2",
|
|
54
54
|
"scripts": {
|
|
55
55
|
"sync-base": "rsync -a --delete --exclude='node_modules' --exclude='dist' --exclude='.vantage' --exclude='*.tsbuildinfo' --exclude='*.log' template/ base-template/ && mv base-template/.gitignore base-template/_gitignore",
|
|
56
56
|
"build": "pnpm run sync-base && tsup",
|