create-theokit 1.23.5 → 1.23.6
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/package.json
CHANGED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Cross-platform desktop release — builds {{name}} for macOS (Apple Silicon + Intel),
|
|
2
|
+
# Linux (x64 + arm64) and Windows, then drafts a GitHub release with the installers.
|
|
3
|
+
#
|
|
4
|
+
# WHY a matrix of native runners: Tauri does NOT support cross-compiling between operating
|
|
5
|
+
# systems (macOS/Linux bundles REQUIRE their own host; only Windows-NSIS-from-Linux is a
|
|
6
|
+
# last-resort exception). Each target therefore builds on its own runner — the documented
|
|
7
|
+
# best practice: https://v2.tauri.app/distribute/pipelines/github/
|
|
8
|
+
#
|
|
9
|
+
# ⚠️ PREREQUISITE — the sidecar must be a real binary, not the dev shim.
|
|
10
|
+
# `tauri build` runs `scripts/build-sidecar.mjs`, which in DEV writes a POSIX shell shim
|
|
11
|
+
# that execs this repo's local `tsx` (absolute build-time paths, requires Node on the user's
|
|
12
|
+
# machine). That shim is NOT portable to end users, and `build-sidecar.mjs` intentionally
|
|
13
|
+
# FAILS on Windows (Tauri needs a `.exe`). Before this workflow can ship a working app you
|
|
14
|
+
# MUST compile `sidecar/sidecar.ts` to a self-contained per-platform binary at
|
|
15
|
+
# `src-tauri/binaries/theo-sidecar-<target-triple>[.exe]`. See README-surface.md § Packaging.
|
|
16
|
+
#
|
|
17
|
+
# Trigger: push to the `release` branch, or run manually (Actions → Run workflow).
|
|
18
|
+
name: release-desktop
|
|
19
|
+
|
|
20
|
+
on:
|
|
21
|
+
workflow_dispatch:
|
|
22
|
+
push:
|
|
23
|
+
branches: [release]
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
permissions:
|
|
28
|
+
contents: write
|
|
29
|
+
strategy:
|
|
30
|
+
fail-fast: false
|
|
31
|
+
matrix:
|
|
32
|
+
include:
|
|
33
|
+
- platform: macos-latest # Apple Silicon → .app / .dmg
|
|
34
|
+
args: --target aarch64-apple-darwin
|
|
35
|
+
- platform: macos-latest # Intel → .app / .dmg
|
|
36
|
+
args: --target x86_64-apple-darwin
|
|
37
|
+
- platform: ubuntu-22.04 # Linux x64 → .deb / .AppImage / .rpm
|
|
38
|
+
args: ''
|
|
39
|
+
- platform: ubuntu-22.04-arm # Linux arm64
|
|
40
|
+
args: ''
|
|
41
|
+
- platform: windows-latest # Windows → .exe (NSIS) / .msi
|
|
42
|
+
args: ''
|
|
43
|
+
|
|
44
|
+
runs-on: ${{ matrix.platform }}
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@v4
|
|
47
|
+
|
|
48
|
+
- name: Install Linux system dependencies
|
|
49
|
+
if: startsWith(matrix.platform, 'ubuntu')
|
|
50
|
+
run: |
|
|
51
|
+
sudo apt-get update
|
|
52
|
+
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils
|
|
53
|
+
|
|
54
|
+
- name: Setup Node
|
|
55
|
+
uses: actions/setup-node@v4
|
|
56
|
+
with:
|
|
57
|
+
node-version: lts/*
|
|
58
|
+
cache: npm
|
|
59
|
+
|
|
60
|
+
- name: Install Rust (stable)
|
|
61
|
+
uses: dtolnay/rust-toolchain@stable
|
|
62
|
+
with:
|
|
63
|
+
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
|
64
|
+
|
|
65
|
+
- name: Rust cache
|
|
66
|
+
uses: swatinem/rust-cache@v2
|
|
67
|
+
with:
|
|
68
|
+
workspaces: ./src-tauri -> target
|
|
69
|
+
|
|
70
|
+
- name: Install frontend dependencies
|
|
71
|
+
run: npm install
|
|
72
|
+
|
|
73
|
+
- name: Build + release with Tauri
|
|
74
|
+
uses: tauri-apps/tauri-action@v0
|
|
75
|
+
env:
|
|
76
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
77
|
+
with:
|
|
78
|
+
tagName: {{name}}-v__VERSION__
|
|
79
|
+
releaseName: '{{name}} v__VERSION__'
|
|
80
|
+
releaseBody: 'See the assets below to download and install this version.'
|
|
81
|
+
releaseDraft: true
|
|
82
|
+
prerelease: false
|
|
83
|
+
args: ${{ matrix.args }}
|
|
@@ -53,3 +53,17 @@ externalBin that a shell shim cannot satisfy (`build:sidecar` fails loud on win3
|
|
|
53
53
|
before building. Options: **Node SEA** (single-executable app — runs under Node, where the stream works),
|
|
54
54
|
or `bun build --compile`/`pkg` (verify the ai-sdk token stream survives your bundler first). Replace the
|
|
55
55
|
`build:sidecar` script with your compile command and keep the same output path.
|
|
56
|
+
|
|
57
|
+
### Cross-platform release (macOS · Linux · Windows)
|
|
58
|
+
|
|
59
|
+
Tauri does **not** cross-compile between operating systems — macOS/Linux bundles must be built on their own
|
|
60
|
+
host, and only Windows-NSIS-from-Linux is a fragile last resort ([docs](https://v2.tauri.app/distribute/pipelines/github/)).
|
|
61
|
+
The best practice is a **matrix of native CI runners**, so this surface ships
|
|
62
|
+
`.github/workflows/release.yml`: on push to a `release` branch (or a manual run) it builds `{{name}}` on
|
|
63
|
+
`macos-latest` (Apple Silicon **and** Intel), `ubuntu-22.04` (x64 + arm64) and `windows-latest`, then drafts
|
|
64
|
+
a GitHub release with the installers (`.dmg`/`.app`, `.deb`/`.AppImage`/`.rpm`, `.msi`/NSIS `.exe`).
|
|
65
|
+
|
|
66
|
+
Before that workflow can ship a **working** app, resolve the sidecar gap above (the CI `tauri build` runs the
|
|
67
|
+
same `build:sidecar`, which fails on the Windows runner and produces a non-portable shim on macOS/Linux). For
|
|
68
|
+
public distribution you also need **code signing** — macOS notarization (Apple Developer ID) and a Windows
|
|
69
|
+
signing certificate; see [Tauri › Distribute](https://v2.tauri.app/distribute/).
|
|
@@ -42,7 +42,6 @@ const transport = new ChannelTransport({ source: createTauriChannelSource(tauri.
|
|
|
42
42
|
|
|
43
43
|
// The window is frameless (`decorations: false` in tauri.conf.json) so the OS title bar can't clash with
|
|
44
44
|
// the app background — the app owns its top bar. These drive the native window from our custom controls.
|
|
45
|
-
// (The drag + these calls need `core:window:*` permissions in `src-tauri/capabilities/default.json`.)
|
|
46
45
|
const appWindow = (
|
|
47
46
|
globalThis as {
|
|
48
47
|
__TAURI__?: {
|
|
@@ -75,40 +74,30 @@ const STARTERS: QuickAction[] = [
|
|
|
75
74
|
]
|
|
76
75
|
|
|
77
76
|
// App-level layout in inline styles (the desktop bundle has no Tailwind). Colors read the theme CSS vars
|
|
78
|
-
// `@theokit/ui` sets
|
|
77
|
+
// `@theokit/ui` sets — and those vars are `oklch()` colors, so wrap them in `color-mix(in oklch, …)` for
|
|
78
|
+
// alpha (NOT `hsl(var(--x) / a)`, which is invalid CSS and silently renders transparent).
|
|
79
79
|
const styles = {
|
|
80
80
|
page: {
|
|
81
81
|
display: 'flex',
|
|
82
82
|
flexDirection: 'column',
|
|
83
83
|
height: '100vh',
|
|
84
|
-
background: '
|
|
85
|
-
color: '
|
|
84
|
+
background: 'var(--background)',
|
|
85
|
+
color: 'var(--foreground)',
|
|
86
86
|
},
|
|
87
87
|
header: {
|
|
88
88
|
display: 'flex',
|
|
89
89
|
alignItems: 'center',
|
|
90
90
|
justifyContent: 'space-between',
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
background: '
|
|
94
|
-
borderBottom: '1px solid
|
|
95
|
-
padding
|
|
91
|
+
// The frameless title bar is its own DISTINCT band: the `--muted` surface reads clearly apart
|
|
92
|
+
// from the content background (adapts to light/dark), with a border to seal the strip.
|
|
93
|
+
background: 'var(--muted)',
|
|
94
|
+
borderBottom: '1px solid var(--border)',
|
|
95
|
+
// Slim title bar — thin vertical padding keeps the strip compact.
|
|
96
|
+
padding: '3px 12px',
|
|
96
97
|
},
|
|
97
98
|
brand: { display: 'inline-flex', alignItems: 'center', gap: 8 },
|
|
98
|
-
brandName: { fontWeight: 600, fontSize:
|
|
99
|
-
headerRight: { display: 'inline-flex', alignItems: 'center', gap:
|
|
100
|
-
winBtn: {
|
|
101
|
-
display: 'inline-flex',
|
|
102
|
-
alignItems: 'center',
|
|
103
|
-
justifyContent: 'center',
|
|
104
|
-
width: 28,
|
|
105
|
-
height: 28,
|
|
106
|
-
border: 'none',
|
|
107
|
-
borderRadius: 6,
|
|
108
|
-
background: 'transparent',
|
|
109
|
-
color: 'hsl(var(--muted-foreground))',
|
|
110
|
-
cursor: 'pointer',
|
|
111
|
-
},
|
|
99
|
+
brandName: { fontWeight: 600, fontSize: 12, letterSpacing: '-0.01em' },
|
|
100
|
+
headerRight: { display: 'inline-flex', alignItems: 'center', gap: 2 },
|
|
112
101
|
scroll: { flex: 1, overflowY: 'auto', minHeight: 0 },
|
|
113
102
|
column: {
|
|
114
103
|
margin: '0 auto',
|
|
@@ -120,8 +109,8 @@ const styles = {
|
|
|
120
109
|
padding: 24,
|
|
121
110
|
},
|
|
122
111
|
composerBar: {
|
|
123
|
-
borderTop: '1px solid
|
|
124
|
-
background: '
|
|
112
|
+
borderTop: '1px solid color-mix(in oklch, var(--border) 60%, transparent)',
|
|
113
|
+
background: 'color-mix(in oklch, var(--background) 50%, transparent)',
|
|
125
114
|
},
|
|
126
115
|
composerInner: { margin: '0 auto', width: '100%', maxWidth: 768, padding: '16px 24px' },
|
|
127
116
|
} satisfies Record<string, CSSProperties>
|
|
@@ -151,43 +140,55 @@ export function App(): ReactElement {
|
|
|
151
140
|
|
|
152
141
|
return (
|
|
153
142
|
<TheoUIProvider>
|
|
143
|
+
{/* Window controls need :hover feedback — inline styles can't do pseudo-classes, so the button
|
|
144
|
+
appearance (incl. hover, and the classic red close) lives in this small stylesheet. */}
|
|
145
|
+
<style>{`
|
|
146
|
+
.tk-winbtn {
|
|
147
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
148
|
+
width: 20px; height: 20px; border: none; border-radius: 6px;
|
|
149
|
+
background: transparent; color: var(--muted-foreground); cursor: pointer;
|
|
150
|
+
transition: background 0.12s ease, color 0.12s ease;
|
|
151
|
+
}
|
|
152
|
+
.tk-winbtn:hover { background: color-mix(in oklch, var(--foreground) 12%, transparent); color: var(--foreground); }
|
|
153
|
+
.tk-winbtn--close:hover { background: #e5484d; color: #fff; }
|
|
154
|
+
`}</style>
|
|
154
155
|
<div style={styles.page}>
|
|
155
156
|
{/* Frameless title bar: `data-tauri-drag-region` makes the whole strip drag the window; the
|
|
156
|
-
background is the
|
|
157
|
-
|
|
157
|
+
background is the `--muted` band, so the bar reads as a distinct strip. Interactive
|
|
158
|
+
children (theme switcher, window buttons) still receive clicks. */}
|
|
158
159
|
<header style={styles.header} data-tauri-drag-region>
|
|
159
160
|
<span style={styles.brand}>
|
|
160
|
-
<Bot size={18} style={{ color: '
|
|
161
|
-
<span style={styles.brandName}>{{name}}
|
|
161
|
+
<Bot size={18} style={{ color: 'var(--primary)' }} aria-hidden />
|
|
162
|
+
<span style={styles.brandName}>{{name}}</span>
|
|
162
163
|
</span>
|
|
163
164
|
<span style={styles.headerRight}>
|
|
164
165
|
<ThemeSwitcher />
|
|
165
166
|
<button
|
|
166
167
|
type="button"
|
|
167
|
-
|
|
168
|
+
className="tk-winbtn"
|
|
168
169
|
onClick={minimizeWindow}
|
|
169
170
|
aria-label="Minimize"
|
|
170
171
|
title="Minimize"
|
|
171
172
|
>
|
|
172
|
-
<Minus size={
|
|
173
|
+
<Minus size={15} />
|
|
173
174
|
</button>
|
|
174
175
|
<button
|
|
175
176
|
type="button"
|
|
176
|
-
|
|
177
|
+
className="tk-winbtn"
|
|
177
178
|
onClick={maximizeWindow}
|
|
178
179
|
aria-label="Maximize"
|
|
179
180
|
title="Maximize"
|
|
180
181
|
>
|
|
181
|
-
<Square size={
|
|
182
|
+
<Square size={12} />
|
|
182
183
|
</button>
|
|
183
184
|
<button
|
|
184
185
|
type="button"
|
|
185
|
-
|
|
186
|
+
className="tk-winbtn tk-winbtn--close"
|
|
186
187
|
onClick={closeWindow}
|
|
187
188
|
aria-label="Close"
|
|
188
189
|
title="Close"
|
|
189
190
|
>
|
|
190
|
-
<X size={
|
|
191
|
+
<X size={15} />
|
|
191
192
|
</button>
|
|
192
193
|
</span>
|
|
193
194
|
</header>
|