@squadbase/vantage-template 0.0.2 → 0.1.0-dev.0faf4cb
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/README.md +9 -7
- package/base-template/.squadbase/skills/project-storage/SKILL.md +157 -0
- package/base-template/.squadbase/skills/vantage-app/SKILL.md +6 -6
- package/base-template/.squadbase/skills/vantage-design/SKILL.md +127 -0
- package/base-template/.squadbase/skills/vantage-design/references/extract.md +110 -0
- package/base-template/.squadbase/skills/vantage-design/references/format.md +172 -0
- package/base-template/.squadbase/skills/vantage-design/references/presets.md +82 -0
- package/base-template/.squadbase/skills/vantage-design/scripts/contrast.mjs +166 -0
- package/base-template/.squadbase/skills/vantage-pitfalls/SKILL.md +22 -0
- package/base-template/AGENTS.md +98 -218
- package/base-template/DESIGN.md +108 -0
- package/base-template/agents/api.md +49 -0
- package/base-template/agents/csv.md +32 -0
- package/base-template/agents/doc.md +73 -0
- package/base-template/agents/page.md +187 -0
- package/base-template/agents/slide.md +41 -0
- package/base-template/agents/xlsx.md +33 -0
- package/base-template/automations/.gitkeep +0 -0
- package/base-template/bun.lock +907 -0
- package/base-template/package.json +3 -3
- package/base-template/pipelines/pyproject.toml +5 -0
- package/base-template/squadbase.yml +1 -0
- package/base-template/src/_error.tsx +7 -11
- package/base-template/src/_layout.tsx +8 -1
- package/base-template/src/components/build-recovery.tsx +219 -0
- package/base-template/src/styles.css +19 -0
- package/dist/index.js +16 -7
- package/package.json +18 -12
- package/ui-templates/chart-grid/pages/index.tsx +1 -1
- package/ui-templates/chart-grid/preview-square.png +0 -0
- package/ui-templates/chart-grid/preview-wide.png +0 -0
- package/ui-templates/chart-grid-ja/pages/index.tsx +1 -1
- package/ui-templates/chart-grid-ja/preview-square.png +0 -0
- package/ui-templates/chart-grid-ja/preview-wide.png +0 -0
- package/ui-templates/funnel/pages/index.tsx +2 -2
- package/ui-templates/funnel/preview-square.png +0 -0
- package/ui-templates/funnel/preview-wide.png +0 -0
- package/ui-templates/funnel-ja/pages/index.tsx +2 -2
- package/ui-templates/funnel-ja/preview-square.png +0 -0
- package/ui-templates/funnel-ja/preview-wide.png +0 -0
- package/ui-templates/kpi-chart-advanced/preview-square.png +0 -0
- package/ui-templates/kpi-chart-advanced/preview-wide.png +0 -0
- package/ui-templates/kpi-chart-advanced-ja/preview-square.png +0 -0
- package/ui-templates/kpi-chart-advanced-ja/preview-wide.png +0 -0
- package/ui-templates/kpi-chart-simple/preview-square.png +0 -0
- package/ui-templates/kpi-chart-simple/preview-wide.png +0 -0
- package/ui-templates/kpi-chart-simple-ja/preview-square.png +0 -0
- package/ui-templates/kpi-chart-simple-ja/preview-wide.png +0 -0
- package/ui-templates/table-focus/preview-square.png +0 -0
- package/ui-templates/table-focus/preview-wide.png +0 -0
- package/ui-templates/table-focus-ja/preview-square.png +0 -0
- package/ui-templates/table-focus-ja/preview-wide.png +0 -0
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"routes": "vantage routes"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@squadbase/react": "^0.0
|
|
15
|
-
"@squadbase/vantage": "
|
|
16
|
-
"@squadbase/vantage-sdk": "^0.1.0
|
|
14
|
+
"@squadbase/react": "^0.1.0",
|
|
15
|
+
"@squadbase/vantage": "0.6.1-dev.90c1a41",
|
|
16
|
+
"@squadbase/vantage-sdk": "^0.1.0",
|
|
17
17
|
"date-fns": "^4.1.0",
|
|
18
18
|
"lucide-react": "^0.468.0",
|
|
19
19
|
"react": "^19.2.7",
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RecoveringState } from "./components/build-recovery"
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* ルートルート(= `_layout.tsx`)が throw したときの画面。ページのレンダリングエラーは
|
|
5
|
+
* ここには来ない — フレームワークの既定エラー画面が受け止め、その上を `BuildRecovery` が
|
|
6
|
+
* 覆う(→ `components/build-recovery.tsx`)。どちらも見た目と復帰の仕方は揃えてある。
|
|
7
|
+
*/
|
|
3
8
|
export default function RouteError({ error }: { error: unknown }) {
|
|
4
|
-
|
|
5
|
-
return (
|
|
6
|
-
<div className="flex min-h-[50vh] items-center justify-center">
|
|
7
|
-
<ErrorState
|
|
8
|
-
title="This page failed to render"
|
|
9
|
-
message={message}
|
|
10
|
-
action={<Button onClick={() => window.location.reload()}>Reload</Button>}
|
|
11
|
-
/>
|
|
12
|
-
</div>
|
|
13
|
-
)
|
|
9
|
+
return <RecoveringState error={error} />
|
|
14
10
|
}
|
|
@@ -4,6 +4,7 @@ import { Link, Outlet, useCurrentRoute, useRoutes } from "@squadbase/vantage/rou
|
|
|
4
4
|
import { AppShell } from "@squadbase/vantage/components"
|
|
5
5
|
import type { NavGroup } from "@squadbase/vantage/components"
|
|
6
6
|
|
|
7
|
+
import { BuildRecovery } from "./components/build-recovery"
|
|
7
8
|
import { UserCard } from "./components/user-card"
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -43,6 +44,10 @@ function useNavGroups(): NavGroup[] {
|
|
|
43
44
|
* the React root, so there is no `main.tsx` to wrap. `SquadbaseProvider` supplies
|
|
44
45
|
* the signed-in user to `useUser()`; the QueryClient provider is already
|
|
45
46
|
* installed by the runtime.
|
|
47
|
+
*
|
|
48
|
+
* `BuildRecovery` は構築中の一時的なエラーを「進行中」表示に見せて自動復帰させる
|
|
49
|
+
* (→ `components/build-recovery.tsx`)。外すと、書き込み途中の一瞬のエラーが
|
|
50
|
+
* 「Something went wrong」のままリロードするまで残る。
|
|
46
51
|
*/
|
|
47
52
|
export default function RootLayout() {
|
|
48
53
|
return (
|
|
@@ -53,7 +58,9 @@ export default function RootLayout() {
|
|
|
53
58
|
actions={<UserCard />}
|
|
54
59
|
linkComponent={RouterLink}
|
|
55
60
|
>
|
|
56
|
-
<
|
|
61
|
+
<BuildRecovery>
|
|
62
|
+
<Outlet />
|
|
63
|
+
</BuildRecovery>
|
|
57
64
|
</AppShell>
|
|
58
65
|
</SquadbaseProvider>
|
|
59
66
|
)
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { useEffect, useRef, useState, type ReactNode } from "react"
|
|
2
|
+
import { Check, Copy } from "lucide-react"
|
|
3
|
+
import { Button, Spinner } from "@squadbase/vantage/ui"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ダッシュボードを組み立てている最中は、ファイルが書き終わる順番の都合で一瞬だけ
|
|
7
|
+
* ページが throw することがある(存在しないモジュールの import、まだ書き終わっていない
|
|
8
|
+
* コンポーネント)。それ自体は通り過ぎる状態なのに、ユーザーには 2 つの形で残ってしまう。
|
|
9
|
+
*
|
|
10
|
+
* 1. **見た目が「失敗」に見える。** ページのレンダリングエラーを受け止めるのは
|
|
11
|
+
* Vantage の既定エラー画面("Something went wrong")で、これはテンプレートからは
|
|
12
|
+
* 差し替えられない — `_error.tsx` はルートルート専用で、ページごとの
|
|
13
|
+
* `errorComponent` は現行プロトタイプではまだ結線されていない。
|
|
14
|
+
* 2. **直しても戻らない。** エラーを掴んでいるのは TanStack の CatchBoundary で、
|
|
15
|
+
* そのリセットはルートの再ロードに紐づいている。HMR でソースが差し替わっても
|
|
16
|
+
* リセットされないので、リロードするまでエラー画面が貼り付いたままになる。
|
|
17
|
+
*
|
|
18
|
+
* そこで、既定エラー画面が出たことを DOM から検知して「進行中」表示を被せ、dev では
|
|
19
|
+
* 短い待ち時間のあと自動でリロードして復帰させる(回数は上限つき)。旧 Vite テンプレートの
|
|
20
|
+
* `_router.tsx` と同じ考え方で、一時的なエラーを失敗ではなく更新中として見せる。
|
|
21
|
+
*
|
|
22
|
+
* `_layout.tsx` が `<Outlet />` を包む形で 1 度だけ使う。**外さないこと** — 外すと
|
|
23
|
+
* 構築中のエラーがそのまま「Something went wrong」として残る。
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 既定エラー画面の目印。`role="alert"` の中の `h2` は Vantage の `DefaultError` だけが
|
|
28
|
+
* 持つ(`@squadbase/vantage/ui` の `ErrorState` は見出しを `<p>` で描くので当たらない)。
|
|
29
|
+
*/
|
|
30
|
+
const FRAMEWORK_ERROR_SELECTOR = '[role="alert"] h2'
|
|
31
|
+
|
|
32
|
+
/** 書き込みの連鎖が落ち着くのを待ってからリロードする。 */
|
|
33
|
+
const RELOAD_DELAY_MS = 1200
|
|
34
|
+
|
|
35
|
+
/** 直らないエラーで無限リロードしないための上限。使い切ったら手動の案内に降りる。 */
|
|
36
|
+
const MAX_RELOADS = 3
|
|
37
|
+
|
|
38
|
+
/** これだけ待っても復帰しなければ、「進行中」表示から控えめな再読み込み案内へ降格する。 */
|
|
39
|
+
const DEGRADE_AFTER_MS = 6000
|
|
40
|
+
|
|
41
|
+
/** エラーなしでこれだけ描画できたら、自動リロードの回数を使い切っていない扱いに戻す。 */
|
|
42
|
+
const SETTLE_MS = 5000
|
|
43
|
+
|
|
44
|
+
const RELOAD_COUNT_KEY = "vantage:build-recovery-reloads"
|
|
45
|
+
|
|
46
|
+
/** コピーしたことが伝わればいいので、確認表示はすぐ元に戻す。 */
|
|
47
|
+
const COPIED_FEEDBACK_MS = 2000
|
|
48
|
+
|
|
49
|
+
function errorMessage(error: unknown): string {
|
|
50
|
+
if (error == null) return ""
|
|
51
|
+
return error instanceof Error ? (error.stack ?? error.message) : String(error)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function readReloadCount(): number {
|
|
55
|
+
try {
|
|
56
|
+
return Number(sessionStorage.getItem(RELOAD_COUNT_KEY)) || 0
|
|
57
|
+
} catch {
|
|
58
|
+
// sessionStorage が使えない環境では自動リロードを諦める(上限を超えた扱い)。
|
|
59
|
+
return MAX_RELOADS
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function writeReloadCount(count: number): void {
|
|
64
|
+
try {
|
|
65
|
+
sessionStorage.setItem(RELOAD_COUNT_KEY, String(count))
|
|
66
|
+
} catch {
|
|
67
|
+
// 書けなくても致命ではない。次の判定で MAX_RELOADS 扱いになるだけ。
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function clearReloadCount(): void {
|
|
72
|
+
try {
|
|
73
|
+
sessionStorage.removeItem(RELOAD_COUNT_KEY)
|
|
74
|
+
} catch {
|
|
75
|
+
// 同上。
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 「進行中」表示。最初はローディングと見分けのつかない穏やかな見た目で、一定時間
|
|
81
|
+
* 復帰しなければ控えめな再読み込み案内に降格する。dev では降格の前に自動リロードを試す。
|
|
82
|
+
*/
|
|
83
|
+
export function RecoveringState({ error }: { error?: unknown }) {
|
|
84
|
+
const [degraded, setDegraded] = useState(false)
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
// dev の構築中は、少し待てばファイルが揃って直っていることがほとんど。
|
|
88
|
+
// リロードすれば CatchBoundary も lazy import のキャッシュもまとめて捨てられる。
|
|
89
|
+
if (import.meta.env.DEV) {
|
|
90
|
+
const attempts = readReloadCount()
|
|
91
|
+
if (attempts < MAX_RELOADS) {
|
|
92
|
+
const timer = setTimeout(() => {
|
|
93
|
+
writeReloadCount(attempts + 1)
|
|
94
|
+
window.location.reload()
|
|
95
|
+
}, RELOAD_DELAY_MS)
|
|
96
|
+
return () => clearTimeout(timer)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const timer = setTimeout(() => setDegraded(true), DEGRADE_AFTER_MS)
|
|
100
|
+
return () => clearTimeout(timer)
|
|
101
|
+
}, [])
|
|
102
|
+
|
|
103
|
+
if (!degraded) {
|
|
104
|
+
return (
|
|
105
|
+
<div
|
|
106
|
+
className="flex min-h-[50vh] flex-col items-center justify-center gap-3"
|
|
107
|
+
role="status"
|
|
108
|
+
aria-live="polite"
|
|
109
|
+
>
|
|
110
|
+
<Spinner className="size-6 text-muted-foreground" />
|
|
111
|
+
<p className="text-base text-muted-foreground">Working on it…</p>
|
|
112
|
+
</div>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const message = errorMessage(error)
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div className="flex min-h-[50vh] flex-col items-center justify-center gap-4 p-8">
|
|
120
|
+
<p className="text-center text-base text-muted-foreground">
|
|
121
|
+
This view is taking longer than expected to update.
|
|
122
|
+
</p>
|
|
123
|
+
<div className="flex items-center gap-2">
|
|
124
|
+
<Button onClick={() => window.location.reload()}>Reload</Button>
|
|
125
|
+
{message ? <CopyLogButton message={message} /> : null}
|
|
126
|
+
</div>
|
|
127
|
+
{/*
|
|
128
|
+
ここまで来た人はエラー本文を AI に貼り戻して直してもらう。畳んでおくと辿り着けない
|
|
129
|
+
ので開いたまま出す。フレームワークの既定エラー画面も同じ本文を隠さず出しているので、
|
|
130
|
+
これで新しく何かが露出するわけではない。
|
|
131
|
+
*/}
|
|
132
|
+
{message ? (
|
|
133
|
+
<pre className="max-h-64 w-full max-w-2xl select-text overflow-auto whitespace-pre-wrap break-words rounded-md border border-border bg-muted p-4 text-left text-xs text-muted-foreground">
|
|
134
|
+
{message}
|
|
135
|
+
</pre>
|
|
136
|
+
) : null}
|
|
137
|
+
</div>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* エラー本文をクリップボードへ。`<pre>` は選択できるので、これが失敗しても手で
|
|
143
|
+
* コピーする道は残る — 失敗しても黙って何もしない。
|
|
144
|
+
*/
|
|
145
|
+
function CopyLogButton({ message }: { message: string }) {
|
|
146
|
+
const [copied, setCopied] = useState(false)
|
|
147
|
+
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
if (!copied) return
|
|
150
|
+
const timer = setTimeout(() => setCopied(false), COPIED_FEEDBACK_MS)
|
|
151
|
+
return () => clearTimeout(timer)
|
|
152
|
+
}, [copied])
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<Button
|
|
156
|
+
variant="outline"
|
|
157
|
+
onClick={() => {
|
|
158
|
+
navigator.clipboard?.writeText(message).then(
|
|
159
|
+
() => setCopied(true),
|
|
160
|
+
() => {},
|
|
161
|
+
)
|
|
162
|
+
}}
|
|
163
|
+
>
|
|
164
|
+
{copied ? <Check className="size-4" /> : <Copy className="size-4" />}
|
|
165
|
+
{copied ? "Copied" : "Copy log"}
|
|
166
|
+
</Button>
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 子の中に既定エラー画面が現れたら、その上に「進行中」表示を被せる。エラー画面自体は
|
|
172
|
+
* DOM に残したまま覆うだけなので、復帰したかどうかは同じ MutationObserver で追える。
|
|
173
|
+
*/
|
|
174
|
+
export function BuildRecovery({ children }: { children: ReactNode }) {
|
|
175
|
+
const hostRef = useRef<HTMLDivElement>(null)
|
|
176
|
+
// エラー本文。`null` は「壊れていない」を兼ねる。既定エラー画面は throw された値を
|
|
177
|
+
// 保持していないので、DOM に描かれた本文を読み取るのが唯一の入手経路になる。
|
|
178
|
+
const [message, setMessage] = useState<string | null>(null)
|
|
179
|
+
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
const host = hostRef.current
|
|
182
|
+
if (!host) return
|
|
183
|
+
const sync = () => {
|
|
184
|
+
const heading = host.querySelector(FRAMEWORK_ERROR_SELECTOR)
|
|
185
|
+
// 覆って見えなくする以上、支援技術にも読ませない。`role="alert"` のままだと
|
|
186
|
+
// 「Something went wrong」がそのまま読み上げられてしまう。属性は observe の
|
|
187
|
+
// 対象外(childList / subtree のみ)なので、この書き換えでは再入しない。
|
|
188
|
+
heading?.closest('[role="alert"]')?.setAttribute("aria-hidden", "true")
|
|
189
|
+
// 既定エラー画面は見出しの直後の段落に本文を描く。取れなくても覆う判断は変えない。
|
|
190
|
+
setMessage(heading === null ? null : (heading.nextElementSibling?.textContent ?? ""))
|
|
191
|
+
}
|
|
192
|
+
sync()
|
|
193
|
+
const observer = new MutationObserver(sync)
|
|
194
|
+
observer.observe(host, { childList: true, subtree: true })
|
|
195
|
+
return () => observer.disconnect()
|
|
196
|
+
}, [])
|
|
197
|
+
|
|
198
|
+
const crashed = message !== null
|
|
199
|
+
|
|
200
|
+
useEffect(() => {
|
|
201
|
+
if (crashed) return
|
|
202
|
+
// 無事に描けている状態がしばらく続いたら、自動リロードの残数を戻す。
|
|
203
|
+
const timer = setTimeout(clearReloadCount, SETTLE_MS)
|
|
204
|
+
return () => clearTimeout(timer)
|
|
205
|
+
}, [crashed])
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
// 通常時は `relative` を足すだけでレイアウトに影響させない。覆うときだけ、
|
|
209
|
+
// 被せる「進行中」表示が収まる高さを確保する。
|
|
210
|
+
<div ref={hostRef} className={crashed ? "relative min-h-[50vh]" : "relative"}>
|
|
211
|
+
{children}
|
|
212
|
+
{crashed ? (
|
|
213
|
+
<div className="absolute inset-0 z-10 overflow-auto bg-background">
|
|
214
|
+
<RecoveringState error={message} />
|
|
215
|
+
</div>
|
|
216
|
+
) : null}
|
|
217
|
+
</div>
|
|
218
|
+
)
|
|
219
|
+
}
|
|
@@ -16,3 +16,22 @@
|
|
|
16
16
|
/* --primary: hsl(221 83% 53%); */
|
|
17
17
|
/* --radius: 0.625rem; */
|
|
18
18
|
}
|
|
19
|
+
|
|
20
|
+
/* vantage-template:chart-preset — regenerated by `chart`; edits here are lost */
|
|
21
|
+
:root {
|
|
22
|
+
--chart-1: var(--color-blue-600);
|
|
23
|
+
--chart-2: var(--color-teal-500);
|
|
24
|
+
--chart-3: var(--color-fuchsia-500);
|
|
25
|
+
--chart-4: var(--color-violet-500);
|
|
26
|
+
--chart-5: var(--color-gray-400);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.dark,
|
|
30
|
+
[data-theme="dark"] {
|
|
31
|
+
--chart-1: var(--color-blue-400);
|
|
32
|
+
--chart-2: var(--color-teal-400);
|
|
33
|
+
--chart-3: var(--color-fuchsia-400);
|
|
34
|
+
--chart-4: var(--color-violet-400);
|
|
35
|
+
--chart-5: var(--color-gray-500);
|
|
36
|
+
}
|
|
37
|
+
/* vantage-template:chart-preset:end */
|
package/dist/index.js
CHANGED
|
@@ -391,7 +391,7 @@ async function relabelFile(generateObject, jsonSchema, model, intent, path, cont
|
|
|
391
391
|
system: SYSTEM_PROMPT,
|
|
392
392
|
prompt: userPrompt,
|
|
393
393
|
temperature: 0.3,
|
|
394
|
-
|
|
394
|
+
maxOutputTokens: 8e3
|
|
395
395
|
});
|
|
396
396
|
const object = result.object;
|
|
397
397
|
if (process.env.SQUADBASE_AI_DEBUG) {
|
|
@@ -1022,27 +1022,36 @@ function initProject(options) {
|
|
|
1022
1022
|
applyChartPreset(targetDir, options.chart);
|
|
1023
1023
|
log("cyan", ` chart preset: ${options.chart}`);
|
|
1024
1024
|
}
|
|
1025
|
+
const packageManager = isBunAvailable() ? "bun" : "npm";
|
|
1025
1026
|
if (options.skipInstall) {
|
|
1026
1027
|
log("green", "\nProject initialized successfully!");
|
|
1027
1028
|
log("dim", "\nNext steps:");
|
|
1028
|
-
log("dim",
|
|
1029
|
-
log("dim",
|
|
1029
|
+
log("dim", ` ${packageManager} install`);
|
|
1030
|
+
log("dim", ` ${packageManager} run dev`);
|
|
1030
1031
|
return;
|
|
1031
1032
|
}
|
|
1032
|
-
log("green",
|
|
1033
|
-
|
|
1033
|
+
log("green", `
|
|
1034
|
+
Installing dependencies with ${packageManager}...`);
|
|
1035
|
+
const install = spawnSync(packageManager, ["install"], {
|
|
1034
1036
|
cwd: targetDir,
|
|
1035
1037
|
stdio: "inherit",
|
|
1036
1038
|
shell: process.platform === "win32"
|
|
1037
1039
|
});
|
|
1038
1040
|
if (install.error || install.status !== 0) {
|
|
1039
1041
|
log("red", "\nDependency installation failed.");
|
|
1040
|
-
log("yellow",
|
|
1042
|
+
log("yellow", `Run '${packageManager} install' manually in the project directory.`);
|
|
1041
1043
|
process.exit(1);
|
|
1042
1044
|
}
|
|
1043
1045
|
log("green", "\nProject initialized successfully!");
|
|
1044
1046
|
log("dim", "\nNext steps:");
|
|
1045
|
-
log("dim",
|
|
1047
|
+
log("dim", ` ${packageManager} run dev`);
|
|
1048
|
+
}
|
|
1049
|
+
function isBunAvailable() {
|
|
1050
|
+
const probe = spawnSync("bun", ["--version"], {
|
|
1051
|
+
stdio: "ignore",
|
|
1052
|
+
shell: process.platform === "win32"
|
|
1053
|
+
});
|
|
1054
|
+
return !probe.error && probe.status === 0;
|
|
1046
1055
|
}
|
|
1047
1056
|
|
|
1048
1057
|
// src/commands/list.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squadbase/vantage-template",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.1.0-dev.0faf4cb",
|
|
4
4
|
"description": "CLI tool for initializing and customizing Squadbase Vantage projects.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"squadbase",
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
],
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/squadbase/squadbase-
|
|
16
|
-
"directory": "vantage-template"
|
|
15
|
+
"url": "git+https://github.com/squadbase/squadbase-monorepo.git",
|
|
16
|
+
"directory": "packages/vantage-template"
|
|
17
17
|
},
|
|
18
|
-
"homepage": "https://github.com/squadbase/squadbase-
|
|
18
|
+
"homepage": "https://github.com/squadbase/squadbase-monorepo/tree/main/packages/vantage-template#readme",
|
|
19
19
|
"bugs": {
|
|
20
|
-
"url": "https://github.com/squadbase/squadbase-
|
|
20
|
+
"url": "https://github.com/squadbase/squadbase-monorepo/issues"
|
|
21
21
|
},
|
|
22
22
|
"type": "module",
|
|
23
23
|
"engines": {
|
|
@@ -33,12 +33,18 @@
|
|
|
33
33
|
"chart-presets"
|
|
34
34
|
],
|
|
35
35
|
"publishConfig": {
|
|
36
|
-
"access": "public"
|
|
36
|
+
"access": "public",
|
|
37
|
+
"registry": "https://registry.npmjs.org"
|
|
37
38
|
},
|
|
38
39
|
"scripts": {
|
|
39
|
-
"sync-base": "rsync -a --delete --exclude='node_modules' --exclude='dist' --exclude='.vantage' --exclude='
|
|
40
|
+
"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",
|
|
40
41
|
"build": "npm run sync-base && tsup",
|
|
41
|
-
"
|
|
42
|
+
"type-check": "tsc",
|
|
43
|
+
"agents": "node scripts/build-agents.cjs",
|
|
44
|
+
"agents:check": "node scripts/build-agents.cjs --check",
|
|
45
|
+
"template:install": "bun install --cwd template --frozen-lockfile",
|
|
46
|
+
"template:build": "npm --prefix template run build",
|
|
47
|
+
"prepublishOnly": "npm run agents:check && npm run build",
|
|
42
48
|
"release": "npm publish --@squadbase:registry=https://registry.npmjs.org",
|
|
43
49
|
"dev": "node scripts/dev.mjs",
|
|
44
50
|
"screenshot": "node scripts/screenshot.mjs"
|
|
@@ -50,9 +56,9 @@
|
|
|
50
56
|
"typescript": "~5.7.0"
|
|
51
57
|
},
|
|
52
58
|
"optionalDependencies": {
|
|
53
|
-
"@ai-sdk/anthropic": "^
|
|
54
|
-
"@ai-sdk/google": "^
|
|
55
|
-
"@ai-sdk/openai": "^
|
|
56
|
-
"ai": "^
|
|
59
|
+
"@ai-sdk/anthropic": "^2.0.0",
|
|
60
|
+
"@ai-sdk/google": "^2.0.0",
|
|
61
|
+
"@ai-sdk/openai": "^2.0.0",
|
|
62
|
+
"ai": "^5.0.52"
|
|
57
63
|
}
|
|
58
64
|
}
|
|
@@ -223,7 +223,7 @@ function heatmapOption(
|
|
|
223
223
|
type: "heatmap",
|
|
224
224
|
data: data.map((c) => [xAxis.indexOf(c.x), yAxis.indexOf(c.y), c.value]),
|
|
225
225
|
label: { show: false },
|
|
226
|
-
emphasis: { itemStyle: { shadowBlur: 8
|
|
226
|
+
emphasis: { itemStyle: { shadowBlur: 8 } },
|
|
227
227
|
},
|
|
228
228
|
],
|
|
229
229
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -223,7 +223,7 @@ function heatmapOption(
|
|
|
223
223
|
type: "heatmap",
|
|
224
224
|
data: data.map((c) => [xAxis.indexOf(c.x), yAxis.indexOf(c.y), c.value]),
|
|
225
225
|
label: { show: false },
|
|
226
|
-
emphasis: { itemStyle: { shadowBlur: 8
|
|
226
|
+
emphasis: { itemStyle: { shadowBlur: 8 } },
|
|
227
227
|
},
|
|
228
228
|
],
|
|
229
229
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -113,13 +113,13 @@ const summaryCards = [
|
|
|
113
113
|
label: "Best step",
|
|
114
114
|
value: "31.9%",
|
|
115
115
|
sub: "Highest step conversion",
|
|
116
|
-
icon: <TrendingUp className="size-4 text-
|
|
116
|
+
icon: <TrendingUp className="size-4 text-chart-2" />,
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
label: "Biggest drop",
|
|
120
120
|
value: "68.2%",
|
|
121
121
|
sub: "Largest step drop-off",
|
|
122
|
-
icon: <TrendingDown className="size-4 text-
|
|
122
|
+
icon: <TrendingDown className="size-4 text-destructive" />,
|
|
123
123
|
},
|
|
124
124
|
]
|
|
125
125
|
|
|
Binary file
|
|
Binary file
|
|
@@ -112,13 +112,13 @@ const summaryCards = [
|
|
|
112
112
|
label: "最良ステップ",
|
|
113
113
|
value: "31.9%",
|
|
114
114
|
sub: "最も高いステップ転換率",
|
|
115
|
-
icon: <TrendingUp className="size-4 text-
|
|
115
|
+
icon: <TrendingUp className="size-4 text-chart-2" />,
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
label: "最大の離脱",
|
|
119
119
|
value: "68.2%",
|
|
120
120
|
sub: "最大のステップ離脱率",
|
|
121
|
-
icon: <TrendingDown className="size-4 text-
|
|
121
|
+
icon: <TrendingDown className="size-4 text-destructive" />,
|
|
122
122
|
},
|
|
123
123
|
]
|
|
124
124
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|