@tishlang/tish-desktop 1.0.0

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.
Files changed (37) hide show
  1. package/LICENSE +13 -0
  2. package/bin/mode.js +73 -0
  3. package/package.json +45 -0
  4. package/src/commands/build.tish +55 -0
  5. package/src/commands/dev.tish +222 -0
  6. package/src/commands/distribute.tish +56 -0
  7. package/src/commands/doctor.tish +91 -0
  8. package/src/commands/icon.tish +42 -0
  9. package/src/commands/info.tish +68 -0
  10. package/src/commands/init.tish +198 -0
  11. package/src/commands/ios.tish +124 -0
  12. package/src/main.tish +105 -0
  13. package/src/paths.tish +215 -0
  14. package/templates/app/bridge-boot.js +6 -0
  15. package/templates/app/index.html +20 -0
  16. package/templates/app/package.json +32 -0
  17. package/templates/app/package.registry.json +32 -0
  18. package/templates/app/public/assets/.gitkeep +0 -0
  19. package/templates/app/scripts/build-css.tish +25 -0
  20. package/templates/app/src/main.tish +27 -0
  21. package/templates/app/ui/main.tish +43 -0
  22. package/templates/app/vite.config.mjs +38 -0
  23. package/templates/app/vite.registry.config.mjs +14 -0
  24. package/templates/bare/app/App.tish +27 -0
  25. package/templates/bare/app/Button.tish +11 -0
  26. package/templates/bare/app/Button.web.tish +11 -0
  27. package/templates/bare/app/Button.webview.tish +11 -0
  28. package/templates/bare/bridge-boot.js +6 -0
  29. package/templates/bare/index.html +20 -0
  30. package/templates/bare/package.json +31 -0
  31. package/templates/bare/package.registry.json +31 -0
  32. package/templates/bare/public/assets/.gitkeep +0 -0
  33. package/templates/bare/scripts/build-css.tish +35 -0
  34. package/templates/bare/src/main.tish +34 -0
  35. package/templates/bare/ui/main.tish +8 -0
  36. package/templates/bare/vite.config.mjs +39 -0
  37. package/templates/bare/vite.registry.config.mjs +19 -0
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "__APP_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "tish": {
7
+ "source": "./src/main.tish",
8
+ "rustDependencies": {
9
+ "tishlang_desktop": { "path": "__ROOT__/crates/tish_desktop" }
10
+ }
11
+ },
12
+ "scripts": {
13
+ "build:css": "tish run --feature fs scripts/build-css.tish",
14
+ "build:ui": "npm run build:css && vite build",
15
+ "dev:ui": "npm run build:css && vite",
16
+ "build:shell": "tish build --target native --native-backend rust src/main.tish -o __SHELL_OUT__",
17
+ "dev": "mode dev",
18
+ "start": "npm run build:ui && npm run build:shell && ./__SHELL_OUT__"
19
+ },
20
+ "dependencies": {
21
+ "@tishlang/tish-desktop-api": "file:__ROOT__/packages/desktop-api",
22
+ "@tishlang/tish-desktop-shared": "file:__ROOT__/packages/shared",
23
+ "@tishlang/tish-desktop-ui-theme": "file:__ROOT__/packages/ui-theme",
24
+ "lattish": "file:__ROOT__/../lattish",
25
+ "tish-tailwind": "file:__ROOT__/../tish-tailwind"
26
+ },
27
+ "devDependencies": {
28
+ "@tishlang/tish-desktop": "file:__ROOT__/cli",
29
+ "@tishlang/vite-plugin-tish": "file:__ROOT__/../tish/npm/vite-plugin-tish",
30
+ "vite": "^6.0.0"
31
+ }
32
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "__APP_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "tish": {
7
+ "source": "./src/main.tish",
8
+ "rustDependencies": {
9
+ "tishlang_desktop": "__PKG_VERSION__"
10
+ }
11
+ },
12
+ "scripts": {
13
+ "build:css": "tish run --feature fs scripts/build-css.tish",
14
+ "build:ui": "npm run build:css && vite build",
15
+ "dev:ui": "npm run build:css && vite",
16
+ "build:shell": "tish build --target native --native-backend rust src/main.tish -o __SHELL_OUT__",
17
+ "dev": "mode dev",
18
+ "start": "npm run build:ui && npm run build:shell && ./__SHELL_OUT__"
19
+ },
20
+ "dependencies": {
21
+ "@tishlang/tish-desktop-api": "__PKG_VERSION__",
22
+ "@tishlang/tish-desktop-shared": "__PKG_VERSION__",
23
+ "@tishlang/tish-desktop-ui-theme": "__PKG_VERSION__",
24
+ "@tishlang/lattish": "latest",
25
+ "tish-tailwind": "latest"
26
+ },
27
+ "devDependencies": {
28
+ "@tishlang/tish-desktop": "__PKG_VERSION__",
29
+ "@tishlang/vite-plugin-tish": "^2.39.0",
30
+ "vite": "^6.0.0"
31
+ }
32
+ }
File without changes
@@ -0,0 +1,25 @@
1
+ import { emitStylesheet } from "tish-tailwind"
2
+ import { readFile, writeFile, mkdir } from "tish:fs"
3
+
4
+ await emitStylesheet({
5
+ sourceFiles: [
6
+ "ui/main.tish",
7
+ "__ROOT__/packages/ui-theme/src/ui/Button.tish",
8
+ "__ROOT__/packages/ui-theme/src/ui/Card.tish",
9
+ "__ROOT__/packages/ui-theme/src/ui/Section.tish",
10
+ "__ROOT__/packages/ui-theme/src/ui/Input.tish",
11
+ "__ROOT__/packages/ui-theme/src/ui/Badge.tish",
12
+ "__ROOT__/packages/ui-theme/src/ui/Separator.tish",
13
+ "__ROOT__/packages/ui-theme/src/ui/ScrollArea.tish",
14
+ "__ROOT__/packages/ui-theme/src/ui/Toolbar.tish",
15
+ ],
16
+ outputPath: "public/assets/app.tw.css",
17
+ })
18
+
19
+ mkdir("public/assets", { recursive: true })
20
+ let fonts = readFile("__ROOT__/packages/ui-theme/src/fonts.css")
21
+ let theme = readFile("__ROOT__/packages/ui-theme/src/theme.css")
22
+ let utils = readFile("__ROOT__/packages/ui-theme/src/theme-utilities.css")
23
+ let tw = readFile("public/assets/app.tw.css")
24
+ writeFile("public/assets/app.css", fonts + "\n" + theme + "\n" + utils + "\n" + tw)
25
+ console.log("wrote public/assets/app.css (theme + utilities + tailwind)")
@@ -0,0 +1,27 @@
1
+ // Minimal Tish Desktop shell — Tauri runs inside cargo:tishlang_desktop.
2
+ import { run, handle, createWindow } from "cargo:tishlang_desktop"
3
+
4
+ handle("app.hello", (args) => {
5
+ return { ok: true, message: "hello from shell Tish", args: args }
6
+ })
7
+
8
+ createWindow({
9
+ label: "main",
10
+ url: "http://localhost:__DEV_PORT__/",
11
+ title: "__APP_NAME__",
12
+ width: 900,
13
+ height: 600,
14
+ titleBarStyle: "transparent"
15
+ })
16
+
17
+ run({
18
+ tickMs: 1000,
19
+ plugins: {
20
+ dialog: true,
21
+ tray: true,
22
+ menu: true,
23
+ deepLink: true,
24
+ opener: true,
25
+ singleInstance: false
26
+ }
27
+ })
@@ -0,0 +1,43 @@
1
+ /** @jsxImportSource lattish */
2
+ import { createRoot, useState } from "lattish"
3
+ import { invoke } from "@tishlang/tish-desktop-api"
4
+ import { Button, Card, CardBody, CardHeader, Section, Badge } from "@tishlang/tish-desktop-ui-theme"
5
+
6
+ fn App() {
7
+ let [hello, setHello] = useState(null)
8
+ let [err, setErr] = useState(null)
9
+
10
+ fn onHello() {
11
+ invoke("app.hello", { from: "ui" }).then((r) => {
12
+ setHello(r)
13
+ setErr(null)
14
+ }, (e) => setErr(String(e)))
15
+ }
16
+
17
+ return <div class="min-h-screen p-8 bg-background text-foreground font-sans">
18
+ <div class="flex items-center gap-3 mb-6">
19
+ <h1 class="text-3xl font-bold">__APP_NAME__</h1>
20
+ <Badge tone="primary">desktop</Badge>
21
+ </div>
22
+ <p class="text-muted-foreground mb-8 text-sm">
23
+ Scaffolded by <code class="text-primary">mode init</code>.
24
+ </p>
25
+
26
+ <Section title="Shell bridge" hint="Invoke a handler registered in src/main.tish">
27
+ <Button onClick={onHello}>Hello</Button>
28
+ </Section>
29
+
30
+ {err !== null ? <pre class="text-destructive mb-4 text-sm whitespace-pre-wrap">{err}</pre> : null}
31
+
32
+ {hello !== null ? <Card class="mt-4">
33
+ <CardHeader>
34
+ <h2 class="font-semibold">Response</h2>
35
+ </CardHeader>
36
+ <CardBody>
37
+ <pre class="text-sm whitespace-pre-wrap">{JSON.stringify(hello, null, 2)}</pre>
38
+ </CardBody>
39
+ </Card> : null}
40
+ </div>
41
+ }
42
+
43
+ createRoot(document.getElementById("root")).render(App)
@@ -0,0 +1,38 @@
1
+ import { defineConfig } from "vite"
2
+ import path from "node:path"
3
+ import { fileURLToPath } from "node:url"
4
+ import tish from "@tishlang/vite-plugin-tish"
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
7
+ const root = path.resolve(__dirname, "__ROOT__")
8
+
9
+ export default defineConfig({
10
+ plugins: [tish({ jsxImportSource: "lattish" })],
11
+ resolve: {
12
+ alias: {
13
+ "@tishlang/tish-desktop-api/bridge": path.resolve(
14
+ root,
15
+ "packages/desktop-api/src/bridge.js"
16
+ ),
17
+ "@tishlang/tish-desktop-api": path.resolve(
18
+ root,
19
+ "packages/desktop-api/src/desktopHost.tish"
20
+ ),
21
+ "@tishlang/tish-desktop-shared": path.resolve(root, "packages/shared/src/index.tish"),
22
+ "@tishlang/tish-desktop-ui-theme": path.resolve(root, "packages/ui-theme/src/index.tish"),
23
+ lattish: path.resolve(root, "../lattish/src/Lattish.tish"),
24
+ "lattish/jsx-runtime": path.resolve(root, "../lattish/src/jsx-runtime.tish"),
25
+ "tish-tailwind/tw": path.resolve(root, "../tish-tailwind/src/tw.tish"),
26
+ "tish-tailwind": path.resolve(root, "../tish-tailwind/src/tw.tish"),
27
+ },
28
+ },
29
+ server: {
30
+ port: __DEV_PORT__,
31
+ strictPort: true,
32
+ fs: { allow: [root, path.resolve(root, "..")] },
33
+ },
34
+ build: {
35
+ outDir: "dist/ui",
36
+ emptyOutDir: true,
37
+ },
38
+ })
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from "vite"
2
+ import tish from "@tishlang/vite-plugin-tish"
3
+
4
+ export default defineConfig({
5
+ plugins: [tish({ jsxImportSource: "lattish" })],
6
+ server: {
7
+ port: __DEV_PORT__,
8
+ strictPort: true,
9
+ },
10
+ build: {
11
+ outDir: "dist/ui",
12
+ emptyOutDir: true,
13
+ },
14
+ })
@@ -0,0 +1,27 @@
1
+ // Shared App entry — BYO DOM mount (no lattish).
2
+ import { Button } from "./Button"
3
+ import { invoke } from "@tishlang/tish-app-api"
4
+
5
+ export fn mountApp(rootEl) {
6
+ rootEl.innerHTML = ""
7
+ let h1 = document.createElement("h1")
8
+ h1.textContent = "__APP_NAME__"
9
+ rootEl.appendChild(h1)
10
+ let p = document.createElement("p")
11
+ p.className = "muted"
12
+ p.textContent = "Bare scaffold (no lattish)."
13
+ rootEl.appendChild(p)
14
+ let out = document.createElement("pre")
15
+ let btn = Button({
16
+ title: "Hello",
17
+ onPress: () => {
18
+ invoke("app.hello", { from: "ui" }).then((r) => {
19
+ out.textContent = JSON.stringify(r, null, 2)
20
+ }, (e) => {
21
+ out.textContent = String(e)
22
+ })
23
+ },
24
+ })
25
+ rootEl.appendChild(btn)
26
+ rootEl.appendChild(out)
27
+ }
@@ -0,0 +1,11 @@
1
+ // Universal fallback — same export shape as Button.web / Button.webview.
2
+ export fn Button(props) {
3
+ let title = props.title === null ? "Button" : props.title
4
+ let el = document.createElement("button")
5
+ el.textContent = title
6
+ el.className = "btn"
7
+ if (props.onPress) {
8
+ el.onclick = () => props.onPress()
9
+ }
10
+ return el
11
+ }
@@ -0,0 +1,11 @@
1
+ // Pure browser Button (`--surface web`). Same API as Button.tish.
2
+ export fn Button(props) {
3
+ let title = props.title === null ? "Button" : props.title
4
+ let el = document.createElement("button")
5
+ el.textContent = title
6
+ el.className = "btn btn-web"
7
+ if (props.onPress) {
8
+ el.onclick = () => props.onPress()
9
+ }
10
+ return el
11
+ }
@@ -0,0 +1,11 @@
1
+ // Webview surface Button. Omit this file to reuse Button.web.tish via cascade.
2
+ export fn Button(props) {
3
+ let title = props.title === null ? "Button" : props.title
4
+ let el = document.createElement("button")
5
+ el.textContent = title
6
+ el.className = "btn btn-webview"
7
+ if (props.onPress) {
8
+ el.onclick = () => props.onPress()
9
+ }
10
+ return el
11
+ }
@@ -0,0 +1,6 @@
1
+ import { installBridge } from "@tishlang/tish-desktop-api/bridge"
2
+
3
+ installBridge()
4
+ if (import.meta.hot) {
5
+ import.meta.hot.accept(() => installBridge())
6
+ }
@@ -0,0 +1,20 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>__APP_NAME__</title>
7
+ <style>
8
+ html, body, #root { margin: 0; min-height: 100%; font-family: system-ui, sans-serif; }
9
+ #root { padding: 2rem; }
10
+ .muted { color: #666; }
11
+ button { margin: 1rem 0; padding: 0.5rem 1rem; }
12
+ pre { background: #f4f4f5; padding: 1rem; border-radius: 8px; }
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <div id="root"></div>
17
+ <script type="module" src="/bridge-boot.js"></script>
18
+ <script type="module" src="/ui/main.tish"></script>
19
+ </body>
20
+ </html>
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "__APP_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "tish": {
7
+ "source": "./src/main.tish",
8
+ "platform": "macos",
9
+ "surface": "webview",
10
+ "rustDependencies": {
11
+ "tishlang_app": { "path": "__ROOT__/crates/tish_app" }
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build:ui": "vite build",
16
+ "dev:ui": "vite",
17
+ "build:shell": "tish build --target native --native-backend rust --check warn src/main.tish -o __SHELL_OUT__",
18
+ "dev": "mode dev",
19
+ "start": "npm run build:ui && npm run build:shell && ./__SHELL_OUT__"
20
+ },
21
+ "dependencies": {
22
+ "@tishlang/tish-app-api": "file:__ROOT__/packages/app-api",
23
+ "@tishlang/tish-desktop-api": "file:__ROOT__/packages/desktop-api",
24
+ "@tishlang/tish-desktop-shared": "file:__ROOT__/packages/shared"
25
+ },
26
+ "devDependencies": {
27
+ "@tishlang/tish-desktop": "file:__ROOT__/cli",
28
+ "@tishlang/vite-plugin-tish": "file:__ROOT__/../tish/npm/vite-plugin-tish",
29
+ "vite": "^6.0.0"
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "__APP_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "tish": {
7
+ "source": "./src/main.tish",
8
+ "platform": "macos",
9
+ "surface": "webview",
10
+ "rustDependencies": {
11
+ "tishlang_app": "__PKG_VERSION__"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build:ui": "vite build",
16
+ "dev:ui": "vite",
17
+ "build:shell": "tish build --target native --native-backend rust --check warn src/main.tish -o __SHELL_OUT__",
18
+ "dev": "mode dev",
19
+ "start": "npm run build:ui && npm run build:shell && ./__SHELL_OUT__"
20
+ },
21
+ "dependencies": {
22
+ "@tishlang/tish-app-api": "__PKG_VERSION__",
23
+ "@tishlang/tish-desktop-api": "__PKG_VERSION__",
24
+ "@tishlang/tish-desktop-shared": "__PKG_VERSION__"
25
+ },
26
+ "devDependencies": {
27
+ "@tishlang/tish-desktop": "__PKG_VERSION__",
28
+ "@tishlang/vite-plugin-tish": "^2.39.0",
29
+ "vite": "^6.0.0"
30
+ }
31
+ }
File without changes
@@ -0,0 +1,35 @@
1
+ // Minimal BYO CSS — no ui-theme / lattish coupling.
2
+ import { writeFile, mkdir } from "tish:fs"
3
+
4
+ mkdir("public/assets", { recursive: true })
5
+ let css = `
6
+ :root {
7
+ --fg: #1a1a1a;
8
+ --bg: #f6f6f4;
9
+ --muted: #666;
10
+ --accent: #2563eb;
11
+ --border: #ddd;
12
+ }
13
+ * { box-sizing: border-box; }
14
+ body {
15
+ margin: 0;
16
+ font: 15px/1.45 ui-sans-serif, system-ui, sans-serif;
17
+ color: var(--fg);
18
+ background: var(--bg);
19
+ }
20
+ button, .btn {
21
+ font: inherit;
22
+ padding: 0.4rem 0.75rem;
23
+ border: 1px solid var(--border);
24
+ border-radius: 6px;
25
+ background: #fff;
26
+ cursor: pointer;
27
+ }
28
+ button:hover, .btn:hover { border-color: var(--accent); }
29
+ .muted { color: var(--muted); }
30
+ .row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
31
+ .col { display: flex; flex-direction: column; gap: 0.5rem; }
32
+ pre { background: #fff; border: 1px solid var(--border); padding: 0.75rem; border-radius: 6px; }
33
+ `
34
+ writeFile("public/assets/app.css", css)
35
+ console.log("wrote public/assets/app.css (bare BYO)")
@@ -0,0 +1,34 @@
1
+ // Bare template — no lattish. Prefer cargo:tishlang_app.
2
+ import { run, handle, createSurface } from "cargo:tishlang_app"
3
+
4
+ fn greet(from: string): string {
5
+ return "hello from shell Tish, " + from
6
+ }
7
+
8
+ handle("app.hello", (args) => {
9
+ let name: string = "ui"
10
+ if (args !== null && args.from !== null) {
11
+ name = String(args.from)
12
+ }
13
+ return { ok: true, message: greet(name), args: args }
14
+ })
15
+
16
+ createSurface({
17
+ id: "main",
18
+ kind: "webview",
19
+ label: "main",
20
+ url: "http://localhost:__DEV_PORT__/",
21
+ title: "__APP_NAME__",
22
+ width: 900,
23
+ height: 600,
24
+ titleBarStyle: "transparent"
25
+ })
26
+
27
+ run({
28
+ plugins: {
29
+ dialog: true,
30
+ menu: true,
31
+ notification: true,
32
+ singleInstance: false
33
+ }
34
+ })
@@ -0,0 +1,8 @@
1
+ import { mountApp } from "../app/App.tish"
2
+
3
+ fn mount() {
4
+ let root = document.getElementById("root")
5
+ mountApp(root)
6
+ }
7
+
8
+ mount()
@@ -0,0 +1,39 @@
1
+ import { defineConfig } from "vite"
2
+ import path from "node:path"
3
+ import { fileURLToPath } from "node:url"
4
+ import tish from "@tishlang/vite-plugin-tish"
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
7
+ const root = path.resolve(__dirname, "__ROOT__")
8
+
9
+ export default defineConfig({
10
+ plugins: [
11
+ tish({
12
+ platform: process.env.TISH_PLATFORM,
13
+ surface: process.env.TISH_SURFACE || "webview",
14
+ }),
15
+ ],
16
+ resolve: {
17
+ alias: {
18
+ "@tishlang/tish-desktop-api/bridge": path.resolve(
19
+ root,
20
+ "packages/desktop-api/src/bridge.js"
21
+ ),
22
+ "@tishlang/tish-desktop-api": path.resolve(
23
+ root,
24
+ "packages/desktop-api/src/appApi.tish"
25
+ ),
26
+ "@tishlang/tish-app-api": path.resolve(root, "packages/app-api/src/index.tish"),
27
+ "@tishlang/tish-desktop-shared": path.resolve(root, "packages/shared/src/index.tish"),
28
+ },
29
+ },
30
+ server: {
31
+ port: __DEV_PORT__,
32
+ strictPort: true,
33
+ fs: { allow: [root, path.resolve(root, "..")] },
34
+ },
35
+ build: {
36
+ outDir: "dist/ui",
37
+ emptyOutDir: true,
38
+ },
39
+ })
@@ -0,0 +1,19 @@
1
+ import { defineConfig } from "vite"
2
+ import tish from "@tishlang/vite-plugin-tish"
3
+
4
+ export default defineConfig({
5
+ plugins: [
6
+ tish({
7
+ platform: process.env.TISH_PLATFORM,
8
+ surface: process.env.TISH_SURFACE || "webview",
9
+ }),
10
+ ],
11
+ server: {
12
+ port: __DEV_PORT__,
13
+ strictPort: true,
14
+ },
15
+ build: {
16
+ outDir: "dist/ui",
17
+ emptyOutDir: true,
18
+ },
19
+ })