@bud.sh/app 0.5.1 → 0.6.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 (115) hide show
  1. package/README.md +41 -31
  2. package/dist/client/assets/bud/design.js +1 -1
  3. package/dist/client/assets/canvas-Bih9EdKJ.js +1 -0
  4. package/dist/client/assets/difference-worker-Bzg-rizy.js +8 -0
  5. package/dist/client/assets/dist-CdE5wBkg.js +5 -0
  6. package/dist/client/assets/files-1dLuoM2f.js +1 -0
  7. package/dist/client/assets/i18n-CkO6VFI0.js +1 -0
  8. package/dist/client/assets/index-Cn2mxroU.css +2 -0
  9. package/dist/client/assets/{index-Dn2pfmXf.js → index-DtISWZp9.js} +2 -2
  10. package/dist/client/assets/pages-BJ-tNJ4J.js +1 -0
  11. package/dist/client/assets/{project-branches-CMGRmrqr.js → project-branches-Ce3rXrkc.js} +1 -1
  12. package/dist/client/assets/project-comments-CPUONfs8.js +1 -0
  13. package/dist/client/assets/project-thread-links-C-TGkq59.js +1 -0
  14. package/dist/client/assets/{project-threads-ZbKDh78d.js → project-threads-Bv7IDBgi.js} +105 -105
  15. package/dist/client/assets/project-work-DAE9-olg.js +1 -0
  16. package/dist/client/assets/{task-design-BPpc4Gd7.js → task-design-CwySIAOl.js} +3 -3
  17. package/dist/client/assets/tasks-KWsCLi_h.js +3 -0
  18. package/dist/client/assets/wasm-inline-DSUyFn1L.js +1 -0
  19. package/dist/client/assets/workspace-CVdcfaaB.js +2 -0
  20. package/dist/client/index.html +3 -3
  21. package/dist/hosted/assets/{canvas-BYTOp1p7.js → canvas-AII16n9i.js} +97 -6
  22. package/dist/hosted/assets/{comment-data-Cn5y2VxV.js → comment-data-BXfMElfx.js} +1998 -381
  23. package/dist/hosted/assets/dist-BCSTeNf4.js +4785 -0
  24. package/dist/hosted/assets/{files-B1P2_24q.js → files-D_1yeAVO.js} +10 -5
  25. package/dist/hosted/assets/{pages-B0ZlVdci.js → pages-CN_SbKWA.js} +3 -3
  26. package/dist/hosted/assets/{project-branches-DlCWmfRo.js → project-branches-Bxp0DCwg.js} +1 -1
  27. package/dist/hosted/assets/{project-thread-links-BZXQ200n.js → project-thread-links-KqQoKBLE.js} +76 -4
  28. package/dist/{node-host/assets/screen-DapOVrga.js → hosted/assets/screen-DpAcDUKR.js} +25 -1
  29. package/dist/hosted/assets/tasks-D66LlwxM.js +1423 -0
  30. package/dist/hosted/assets/wasm-inline-Dl9tqabx.js +4 -0
  31. package/dist/hosted/hosted.js +7885 -6219
  32. package/dist/node/assets/Stream-CAm1eJ2n.js +16604 -0
  33. package/dist/{server/assets/bridge-B_Blt55E.js → node/assets/bridge-DQSBYHmw.js} +124 -290
  34. package/dist/node/assets/config-9_jWwNBh.js +1067 -0
  35. package/dist/node/assets/load-config.server-CMVtRVmO.js +261 -0
  36. package/dist/node/assets/module-3GgtT4Xs.js +308 -0
  37. package/dist/node/assets/server-DTQFuoX2.js +846 -0
  38. package/dist/node/assets/src-D-kG1GxB.js +2 -0
  39. package/dist/node/assets/{src-CerrKjID.js → src-Dwe9APUx.js} +93 -3
  40. package/dist/node/assets/src-DysjfbM8.js +8592 -0
  41. package/dist/node/bridge.js +1 -845
  42. package/dist/node/cli.js +206 -0
  43. package/dist/node/design.js +811 -8
  44. package/dist/node/index.js +2 -739
  45. package/dist/node/plugins.js +5711 -0
  46. package/dist/node/server.js +1 -6746
  47. package/dist/node/vite.js +121 -0
  48. package/dist/{server/assets/canvas-CkMK4hoN.js → node-host/assets/canvas-BeDoufy1.js} +97 -7
  49. package/dist/node-host/assets/{comment-data-yfWEdDQL.js → comment-data-DE2T9yTj.js} +1974 -355
  50. package/dist/node-host/assets/dist-BCSTeNf4.js +4785 -0
  51. package/dist/node-host/assets/{files-anHi-apm.js → files-Dl-PTS09.js} +11 -6
  52. package/dist/node-host/assets/{pages-CW4aF6dK.js → pages-DL2sk6_U.js} +3 -3
  53. package/dist/node-host/assets/{project-branches-D7rVCxQX.js → project-branches-DGp5ELct.js} +1 -1
  54. package/dist/{server/assets/project-thread-links-lLS_rq7c.js → node-host/assets/project-thread-links-CgBV3Jcm.js} +76 -5
  55. package/dist/{hosted/assets/screen-CfdC3NbR.js → node-host/assets/screen-B55yyVfb.js} +25 -1
  56. package/dist/node-host/assets/tasks-DZRNkoxe.js +1425 -0
  57. package/dist/node-host/assets/wasm-inline-Dl9tqabx.js +4 -0
  58. package/dist/node-host/node-host.js +6127 -4438
  59. package/dist/server/assets/{branch-previews-ClkoJ0lM.js → branch-previews-DedrpnVR.js} +1555 -673
  60. package/dist/{node-host/assets/canvas-DxmcFZCh.js → server/assets/canvas-CJWQ-jjv.js} +98 -6
  61. package/dist/server/assets/{comment-data-NLeHG89b.js → comment-data-Rg42ToTW.js} +1660 -26
  62. package/dist/server/assets/dist-BCSTeNf4.js +4785 -0
  63. package/dist/server/assets/{events-iHpLGr3k.js → events-BH_rAu7O.js} +155 -20
  64. package/dist/server/assets/{files-CRdl489E.js → files-CPJqKeMo.js} +12 -7
  65. package/dist/server/assets/{listener-BAYn9Q-u.js → listener-D61O6PzF.js} +708 -12
  66. package/dist/server/assets/{pages-DXVlJlBC.js → pages-KJY_Ba92.js} +4 -4
  67. package/dist/server/assets/{project-branches-CwTsf6WQ.js → project-branches-qG9ACZvo.js} +2 -2
  68. package/dist/{node-host/assets/project-thread-links-m-OLpsD9.js → server/assets/project-thread-links-CqK0lqCF.js} +77 -4
  69. package/dist/{node-host/assets/tasks-request-B0aeNocI.js → server/assets/project-work-DoIwxWMm.js} +87 -2
  70. package/dist/server/assets/run-BJ8r5jSh.js +572 -0
  71. package/dist/server/assets/{screen-B1zH_1O3.js → screen-CBrHPFug.js} +26 -2
  72. package/dist/server/assets/{server-DxK-UB_Z.js → server-Dkbp5stG.js} +1521 -793
  73. package/dist/server/assets/{services-BRrgXYlT.js → services-BTfig8A8.js} +234 -997
  74. package/dist/server/assets/tasks-Bgu5Lg9Y.js +1427 -0
  75. package/dist/server/assets/wasm-inline-Dl9tqabx.js +4 -0
  76. package/dist/server/capture.js +1 -2
  77. package/dist/server/migration.js +569 -12
  78. package/dist/server/runtime.js +7 -5
  79. package/dist/server/server.js +3 -3
  80. package/dist/types/assets/{config-DIC2cf_S.d.ts → config-CvcYmE2s.d.ts} +188 -50
  81. package/dist/types/assets/{contract-CAT-XFNq.d.ts → contract-B7yuuqSn.d.ts} +44 -2
  82. package/dist/types/assets/{items-CaVkByHk.d.ts → items-BQdaVksf.d.ts} +12 -1
  83. package/dist/types/assets/memory-state-BBW-FAVA.d.ts +236 -0
  84. package/dist/types/assets/picker-Be5Gx4WR.d.ts +9 -0
  85. package/dist/types/assets/{task-design-xJOhRNWh.d.ts → task-design-BDHKFHpp.d.ts} +3 -1
  86. package/dist/types/bridge.d.ts +1 -1
  87. package/dist/types/companion.d.ts +3 -3
  88. package/dist/types/design.d.ts +2 -2
  89. package/dist/types/hosted.d.ts +3 -3
  90. package/dist/types/index.d.ts +2 -2
  91. package/dist/types/node-host.d.ts +2 -2
  92. package/dist/types/plugins.d.ts +445 -0
  93. package/dist/types/screen.d.ts +2 -2
  94. package/dist/types/server.d.ts +2 -228
  95. package/dist/types/vite.d.ts +16 -0
  96. package/package.json +19 -3
  97. package/dist/client/assets/canvas-8GXJIuDK.js +0 -1
  98. package/dist/client/assets/difference-worker-C99ychYw.js +0 -8
  99. package/dist/client/assets/files-DkWt1l9H.js +0 -1
  100. package/dist/client/assets/i18n-hH_Ba5QO.js +0 -1
  101. package/dist/client/assets/index-tpHYVXma.css +0 -2
  102. package/dist/client/assets/pages-BVd6MQmu.js +0 -1
  103. package/dist/client/assets/project-comments-D1IIQwsW.js +0 -1
  104. package/dist/client/assets/project-thread-links-DKwe_SYb.js +0 -1
  105. package/dist/client/assets/project-work-D4DZqBCZ.js +0 -1
  106. package/dist/client/assets/tasks-Cn0VOZ9Z.js +0 -1
  107. package/dist/client/assets/tasks-request-BLyOzokZ.js +0 -1
  108. package/dist/client/assets/workspace-DGErsSg6.js +0 -2
  109. package/dist/hosted/assets/tasks-_yKh2Z6q.js +0 -649
  110. package/dist/hosted/assets/tasks-request-CFPLvLc7.js +0 -113
  111. package/dist/node-host/assets/tasks-BBK_CybR.js +0 -651
  112. package/dist/server/assets/project-work-CSZlCwH-.js +0 -88
  113. package/dist/server/assets/tasks-CGdz-uox.js +0 -652
  114. package/dist/server/assets/tasks-request-D2NBjCTl.js +0 -115
  115. package/dist/types/assets/picker-D1Bw3ndx.d.ts +0 -14
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @bud.sh/app
2
2
 
3
- Bud is a local companion for reviewing a web project: the app itself, its config, screen, design and adapter APIs, and the companion server a host starts. [`@bud.sh/app-vite-plugin`](../app-vite-plugin/README.md) hosts it beside your Vite dev server and provides the `bud` CLI. Bud browses your live pages, shows your routes side by side on a canvas, lets you browse, edit and review files, and keeps discussions on pages, code and tasks through your selected storage adapters. The interface uses Remix 3; your project can use any framework that runs on Vite.
3
+ Bud is a local companion for reviewing a web project: the app itself, its config, screen, design and adapter APIs, and the companion server a host starts. Its Vite plugin, `@bud.sh/app/vite`, hosts it beside your Vite dev server, and the package's `bud` CLI runs it without Vite. Bud browses your live pages, shows your routes side by side on a canvas, lets you browse, edit and review files, and keeps discussions on pages, code and tasks through your selected storage adapters. The interface uses Remix 3; your project can use any framework that runs on Vite.
4
4
 
5
5
  ## Features
6
6
 
@@ -16,14 +16,19 @@ Bud is a local companion for reviewing a web project: the app itself, its config
16
16
 
17
17
  ## Installation
18
18
 
19
- The packages are private and not published yet. Build and pack the app and its Vite host from this repository:
19
+ One package holds the app, its Vite plugin and the `bud` CLI:
20
20
 
21
21
  ```sh
22
- pnpm --filter @bud.sh/app --filter @bud.sh/app-vite-plugin build
22
+ npm install -D @bud.sh/app
23
+ ```
24
+
25
+ To try this repository's version instead, build and pack it:
26
+
27
+ ```sh
28
+ pnpm --filter @bud.sh/app build
23
29
  pnpm --filter @bud.sh/app pack --out /tmp/bud-app.tgz
24
- pnpm --filter @bud.sh/app-vite-plugin pack --out /tmp/bud-vite.tgz
25
30
  # In your project
26
- npm install -D /tmp/bud-app.tgz /tmp/bud-vite.tgz
31
+ npm install -D /tmp/bud-app.tgz
27
32
  ```
28
33
 
29
34
  Node 26.12 or newer is required.
@@ -34,7 +39,7 @@ Add the Vite plugin:
34
39
 
35
40
  ```ts
36
41
  // vite.config.ts
37
- import { bud } from '@bud.sh/app-vite-plugin'
42
+ import { bud } from '@bud.sh/app/vite'
38
43
 
39
44
  export default {
40
45
  plugins: [bud()],
@@ -53,38 +58,44 @@ export default defineConfig({
53
58
  // port: 4000, // Bud's own port; omit to pick a free one
54
59
  // target: { port: 3000 }, // detected from Vite by default
55
60
  // comments: { remote: 'origin' },
56
- // picker: 'bud:react-grab', // or './picker.ts'; bud:dom by default
61
+ // plugins: [reactGrab()], // from @bud.sh/app/plugins; Bud's DOM picker by default
57
62
  })
58
63
  ```
59
64
 
60
- Run your usual Vite dev command and open the printed **Bud** URL. The plugin only runs in development, and config changes restart it.
65
+ Run your usual Vite dev command and open the printed **Bud** URL. The plugin only runs in development, and config changes restart it. It starts Bud's companion when Vite starts listening, finds your dev server's address, refreshes previews on hot updates and adds the small dev bridge Pages uses to follow your live pages; the bridge does nothing outside Bud's frames.
61
66
 
62
- ### Storage and designs
67
+ ### Plugins, storage and designs
63
68
 
64
- `storage.work` and `storage.threads` select independent stores. Both default to `bud:beads`;
65
- set either to `false` to disable it. `bud:git-comments` supports threads only, and
66
- `bud:memory` provides temporary storage for tests and examples. `designs.tasks` selects the
67
- browser presentation separately and defaults to `bud:beads`. `designs.pages` sets how the Pages
68
- sidebar names pages: by `path` (the default) or by `title` with the path beside it.
69
+ Stores, the picker, the task design, extra screens and the factory's sandboxes come from
70
+ plugins, which `@bud.sh/app/plugins` exports: `beads()`, `gitComments()`, `memory()`,
71
+ `reactGrab()`, `react()`, `picker()`, `taskDesign()`, `local()`, `boat()` and `definePlugin`
72
+ for your own. Tasks and discussions are Beads' unless a plugin provides one;
73
+ `storage: { work: false }` or `{ threads: false }` turns one off. `designs.pages` sets how the
74
+ Pages sidebar names pages: by `path` (the default) or by `title` with the path beside it.
69
75
 
70
76
  ```ts
77
+ import { defineConfig } from '@bud.sh/app'
78
+ import { definePlugin, gitComments, taskDesign } from '@bud.sh/app/plugins'
79
+ import { tracker } from './bud/tracker.server.ts'
80
+
71
81
  export default defineConfig({
72
82
  routes: ['/'],
73
- storage: { work: './bud/store.server.ts', threads: 'bud:git-comments' },
74
- designs: { tasks: 'bud:beads' },
83
+ plugins: [
84
+ definePlugin({ name: 'tracker', label: 'Tracker', work: tracker }),
85
+ gitComments(),
86
+ taskDesign('./bud/tasks.tsx'),
87
+ ],
75
88
  })
76
89
  ```
77
90
 
78
- Custom server modules default-export `defineAdapter({ id, label, work?, threads? })` from
79
- `@bud.sh/app/server`. Each slot is a fully provided Effect layer using the exported
80
- `WorkAdapter` or `ThreadAdapter` service. `memoryAdapterLayer({ schema })` supplies both for
81
- fixtures. A shared layer is acquired once, and its resources close with the companion.
82
-
83
- Adapter modules must end in `.server.ts`; custom designs use browser modules ending in
84
- `.ts`, `.tsx`, `.js` or `.jsx`. Both stay inside the project, outside `node_modules`.
85
- Bud validates their paths before listening; browser design exports are validated when opened.
86
- Only each store's public identity and connection state
87
- reach screens through `project.storage`; module paths and server configuration stay private.
91
+ A plugin's store is a fully provided Effect layer using the `WorkAdapter` or `ThreadAdapter`
92
+ service from `@bud.sh/app/server`, or a function making one for `{ project }`;
93
+ `memoryAdapterLayer({ schema })` supplies both for fixtures. A shared layer is acquired once,
94
+ and its resources close with the companion. Task designs are browser modules ending in `.ts`,
95
+ `.tsx`, `.js` or `.jsx` inside the project, outside `node_modules`; Bud checks their paths
96
+ before listening and their exports when opened. Only each store's public identity and
97
+ connection state reach screens through `project.storage`; plugins and server configuration
98
+ stay private.
88
99
 
89
100
  Task designs default-export `defineTaskDesign` from `@bud.sh/app/design`. Its optional
90
101
  `card`, `page`, `properties`, `actions`, `sections` and `column` slots are Remix components.
@@ -164,10 +175,11 @@ Opened screens also stay mounted while hidden. `context.active` tells a screen w
164
175
  ### Without Vite
165
176
 
166
177
  ```sh
167
- bud [project-directory]
178
+ npx bud [project-directory] # standalone, needs target.origin or target.port
179
+ npx bud comments migrate [project-directory] [--to bud:beads] [--dry-run]
168
180
  ```
169
181
 
170
- The standalone `bud` command comes with `@bud.sh/app-vite-plugin` and needs `target.origin` or `target.port` in the config. Previews opened this way can't be commented on; use the Vite plugin for that.
182
+ The `bud` command comes with `@bud.sh/app` and needs `target.origin` or `target.port` in the config to serve. Previews opened this way can't be commented on; use the Vite plugin for that. `bud capture` is what a hosted Bud's builder runs.
171
183
 
172
184
  ### Task links
173
185
 
@@ -185,8 +197,7 @@ Writes use the discussion revision you last read. Conflicts retain the draft for
185
197
  uncertain writes require checking the stored discussion before retrying. **Sync** is explicit
186
198
  and uses the selected adapter's existing remote configuration.
187
199
 
188
- With `storage.threads: 'bud:git-comments'`, discussions use the compatible `bud/comments`
189
- branch. Writes preserve your source branch, index and working files. Sync validates and
200
+ With `gitComments()`, discussions use the compatible `bud/comments` branch. Writes preserve your source branch, index and working files. Sync validates and
190
201
  merges fetched records, then pushes the exact validated commit without forcing. No other
191
202
  application storage selection writes this ref.
192
203
 
@@ -249,7 +260,6 @@ See [AGENTS.md](AGENTS.md) for the app's structure.
249
260
 
250
261
  ## Related Packages
251
262
 
252
- - [`@bud.sh/app-vite-plugin`](../app-vite-plugin/README.md) - Hosts the app beside Vite, and the `bud` CLI
253
263
  - [`@bud.sh/project`](../project/README.md) - Config contract and loading
254
264
  - [`@bud.sh/ui`](../ui/README.md) - Components
255
265
  - [`@bud.sh/comments`](../comments/README.md), [`@bud.sh/files`](../files/README.md), [`@bud.sh/beads`](../beads/README.md) - Domain services
@@ -1 +1 @@
1
- export{r as ActionsDefault,i as ColumnDefault,t as PropertiesDefault,a as SectionsDefault,st as TaskCardDefault,it as TaskField,n as TaskPageDefault,tt as defineTaskDesign,Ln as fieldByRole,at as taskFieldRenderers,Fn as valueByRole}from"../task-design-BPpc4Gd7.js";
1
+ export{r as ActionsDefault,i as ColumnDefault,t as PropertiesDefault,a as SectionsDefault,ct as TaskCardDefault,it as TaskField,n as TaskPageDefault,tt as defineTaskDesign,Hn as fieldByRole,at as taskFieldRenderers,Bn as valueByRole}from"../task-design-CwySIAOl.js";
@@ -0,0 +1 @@
1
+ import{r as e}from"./i18n-CkO6VFI0.js";import{t}from"./jsx-B4XNFIzB.js";import{t as n}from"./component-DWct-Tq6.js";import{n as r}from"./on-mixin-iWnqUzq5.js";import{n as i}from"./attrs-mixin-CmlG_FtV.js";import{c as a,l as o,t as s}from"./loader-Q6-HPKft.js";import{t as c}from"./screen-Dfvzj6n2.js";import{At as l,I as u,T as d,_ as f,v as p,w as m}from"./task-design-CwySIAOl.js";import{G as h,Mt as g,Nt as _,W as v,lt as y,q as b,s as x}from"./project-threads-Bv7IDBgi.js";import{i as S,n as C,t as w}from"./project-comments-CPUONfs8.js";import{i as T,n as E,t as D}from"./project-branches-Ce3rXrkc.js";import{n as O,t as k}from"./project-thread-links-C-TGkq59.js";var A=760,j=r(`pointerdown`,e=>e.stopPropagation());function M(e,t,n){let r=e.capture.width*t,i=e.capture.thumbnails.map(e=>e.width),a=e=>{let t=i.findIndex(t=>r<=t*e);return t<0?`slices`:t},o=e=>e===`slices`?i.length:e,s=a(1);return n===void 0||o(s)>=o(n)||o(a(.85))<o(n)?s:n}function N(e,t){return e?.get(t)??{visible:!0,top:0,bottom:1/0,density:1}}function P(e,t){let n=0;return e.capture.tiles.map((r,i)=>{let a={tile:r,index:i,top:n,src:e.srcs[i]};return n+=r.height,{...a,shownTo:Math.min(n,t)}})}function ee(n){let{route:i,previews:c}=n.props,u=i.pageId??i.id,d=()=>T(n.props.theme,n.props.size),f=``,p,m,g=``;function _(e){return n.props.topOnly?e.capture.tiles[0]?.height??e.capture.height:e.capture.height}function v(){let{preview:e,images:t}=c.get(u),r=t[d()]??m,i=r?_(r):e?.captures[0]?.height??(e?.state===`failed`?A:0);if(!e||!i)return;let a=`${i}:${e.path}:${r?.capture.hash??``}`;f!==a&&(f=a,n.props.onLayout({height:i,path:e.path,pins:r?.capture.pins}))}function y(e){let t=N(n.props.viewport,i.id);if(!t.visible||p===void 0)return{thumbnail:void 0,slices:[]};if(p===`slices`&&e.srcs.length){let n=Math.min(t.bottom,_(e));return{thumbnail:e.thumbnails.at(-1),slices:P(e,n).filter(({src:e,top:n,shownTo:r})=>e&&n<r&&r>t.top)}}let r=p===`slices`?e.thumbnails.length-1:p;return{thumbnail:e.thumbnails[r]??e.thumbnails.at(-1),slices:[]}}function b(){let e=c.get(u).images[d()];if(!e||e===m)return;if(!m||m.capture.hash===e.capture.hash){m=e;return}if(p===`slices`&&!e.srcs.length){c.slices(u,n.props.theme,n.props.size);return}let t=`${e.capture.hash}:${p}`;if(g===t)return;g=t;let r=e,{thumbnail:i,slices:a}=y(r);Promise.all([i,...a.map(({src:e})=>e)].flatMap(e=>{if(!e)return[];let t=new Image;return t.src=e,[t.decode().catch(()=>{})]})).then(()=>{g!==t||n.signal.aborted||(g=``,m=c.get(u).images[d()]??r,v(),n.update())})}let x=c.watch(u,()=>{b(),v(),n.update()}),S=n.props.viewport?.watch(i.id,()=>void n.update());return n.signal.addEventListener(`abort`,()=>{x(),S?.()},{once:!0}),()=>{let{mode:d,origin:f,theme:g,viewport:x,size:S}=n.props,{preview:C,images:w,refreshing:E,error:D}=c.get(u);n.queueTask(()=>{c.show(u,g,S),v()});let O=w[T(g,S)]??w[T(g===`dark`?`light`:`dark`,S)];O&&(!m||m.capture.theme!==O.capture.theme)?m=O:b();let k=m,A=D||(C?.captures.length?null:C?.error),P=new URL(i.path,f).href;if(k){let a=N(x,i.id);if(p=M(k,a.density,p),a.visible&&p===`slices`&&!k.srcs.length){let{theme:e}=k.capture;n.queueTask(()=>c.slices(u,e,S))}let o=_(k),{width:s}=k.capture,{thumbnail:l,slices:f}=y(k);return t(`div`,{role:`img`,"aria-label":e(`app.client.previewImage.preview`,{title:i.title}),"data-detail":a.visible?f.length?`slices`:l?`thumbnail`:`pending`:`hidden`,class:`relative select-none overflow-hidden ${d===`comment`?`cursor-crosshair`:``}`,style:{height:o},mix:[r(`pointerdown`,e=>{d!==`pan`&&e.stopPropagation()}),r(`click`,e=>{if(d!==`comment`||C?.path!==i.path)return;e.stopPropagation();let t=e.currentTarget.getBoundingClientRect(),r={x:(e.clientX-t.left)*s/t.width,y:(e.clientY-t.top)*o/t.height};n.props.onPick({element:null,path:i.path,...h(r,s),found:c.describe(u,k.capture,r.x,r.y)})})],children:[l?t(`img`,{src:l,alt:``,decoding:`async`,draggable:!1,class:`absolute inset-x-0 top-0 block w-full max-w-none`,style:{height:k.capture.height}}):null,f.map(({tile:e,index:n,top:r,src:i})=>t(`img`,{src:i,alt:``,decoding:`async`,draggable:!1,class:`absolute inset-x-0 block w-full max-w-none`,style:{top:r,height:e.height+ +(n<k.capture.tiles.length-1)}},e.hash))]})}return C?.state===`failed`||A&&!E?t(`div`,{class:`absolute inset-0 flex flex-col items-center justify-center gap-3 p-12 text-center`,role:`status`,children:[t(l,{name:`circle-alert`,size:24,class:`text-muted`}),t(o,{variant:`title`,weight:`semibold`,class:`text-ink`,children:e(`app.client.previewImage.captureFailed`,{title:i.title})}),A?t(o,{variant:`ui`,class:`max-w-md text-muted`,children:A}):null,t(`div`,{class:`mt-2 flex gap-2`,children:[t(a,{variant:`secondary`,disabled:E,mix:[j,r(`click`,()=>void c.refresh(u))],children:t(o,{variant:`ui`,children:e(`app.client.previewImage.tryAgain`)})}),t(`a`,{href:P,target:`_blank`,rel:`noreferrer`,class:`bud-interaction bud-control flex h-control items-center rounded-lg px-3 text-ink`,mix:j,children:t(o,{variant:`ui`,children:e(`app.client.previewImage.openPage`)})})]})]}):t(`div`,{class:`absolute inset-0 flex items-center justify-center`,children:t(s,{label:e(`app.client.previewImage.capturing`,{title:i.title})})})}}function te(i){let{route:a,previews:o}=i.props,s=a.pageId??a.id,c=o.watch(s,()=>void i.update());return i.signal.addEventListener(`abort`,c,{once:!0}),()=>{let{preview:i,refreshing:c}=o.get(s),u=c||!!i?.updating,f=i?.state===`ready`?i.error:null;return t(n,{children:[f?t(d,{label:f,children:t(`span`,{tabIndex:0,role:`img`,"aria-label":f,class:`pointer-events-auto ms-1 inline-flex text-amber-500`,mix:j,children:t(l,{name:`circle-alert`,size:13})})}):null,t(m,{icon:`sync`,label:e(`app.client.previewImage.refresh`,{title:a.title}),tooltip:!0,size:`small`,iconSize:13,disabled:c,"aria-busy":u?`true`:void 0,class:`pointer-events-auto ms-0.5 text-muted hover:text-ink ${u?`[&_svg]:animate-spin`:``}`,mix:[j,r(`click`,()=>void o.refresh(s))]})]})}}var F={width:1200,height:800},I=.82;async function ne(e,t,n){let r=t.anchor;if(!r||`type`in r)return;let i=n.find(e=>e.width===r.viewport)??n[0];if(!i)return;let a=await e.picture(r.pageId,`light`,i);if(!a)return;let{capture:o,images:s}=a,c=o.pins?.find(e=>e.id===t.id&&e.x!==null),l=c&&c.x!==null&&c.y!==null?{x:c.x,y:c.y}:{x:r.offsetX*o.width,y:r.offsetY},[u,d]=await Promise.all([L(o,s,l).catch(()=>void 0),e.describe(r.pageId,o,l.x,l.y).catch(()=>null)]);return{...u?{image:u}:{},element:d,point:l}}async function L(e,t,n){let r=Math.min(F.width,e.width),i=Math.min(F.height,e.height),a=Math.max(0,Math.min(e.width-r,Math.round(n.x-r/2))),o=Math.max(0,Math.min(e.height-i,Math.round(n.y-i/2))),s=new OffscreenCanvas(r,i),c=s.getContext(`2d`);if(!c)throw Error(`No canvas.`);c.fillStyle=`#fff`,c.fillRect(0,0,r,i);let l=0;for(let[n,s]of e.tiles.entries()){let u=l+s.height,d=Math.max(o,l),f=Math.min(o+i,u);if(f>d&&t[n]){let i=await createImageBitmap(t[n]);c.drawImage(i,a*e.scale,(d-l)*e.scale,r*e.scale,(f-d)*e.scale,0,d-o,r,f-d),i.close()}l=u}let u=n.x-a,d=n.y-o;c.lineWidth=6,c.strokeStyle=`#fff`,c.beginPath(),c.arc(u,d,18,0,Math.PI*2),c.stroke(),c.lineWidth=3,c.strokeStyle=`#ef4444`,c.stroke();let f=await s.convertToBlob({type:`image/jpeg`,quality:I}),p=new Uint8Array(await f.arrayBuffer()),m=``;for(let e=0;e<p.length;e+=32768)m+=String.fromCharCode(...p.subarray(e,e+32768));return btoa(m)}var R=new Map;function z(){return new Worker(new URL(`/assets/difference-worker-Bzg-rizy.js`,``+import.meta.url),{type:`module`})}function B(t){let{routes:n,before:r,after:i,theme:a,signal:o}=t,s=new Map,c={get:e=>s.get(e)??{state:`pending`,regions:[]},progress:{compared:0,total:n.length},done:n.length===0},l,u=0,d=new Map;function f(e){l??=z(),l.onmessage=e=>{d.get(e.data.id)?.(e.data),d.delete(e.data.id)};let t=u++;return new Promise(n=>{d.set(t,n),l.postMessage({...e,id:t})})}o.addEventListener(`abort`,()=>l?.terminate(),{once:!0});async function p(e,t){let[n,o]=await Promise.all([r.picture(e,a,t),i.picture(e,a,t)]);if(!n||!o)return{state:`missing`,regions:[],before:n?.capture,after:o?.capture};let s={before:n.capture,after:o.capture};if(n.capture.hash===o.capture.hash)return{state:`same`,regions:[],...s};let c=`${n.capture.hash}\0${o.capture.hash}`,l=R.get(c);if(!l){let e=e=>({images:e.images,heights:e.capture.tiles.map(e=>e.height),scale:e.capture.scale}),t=await f({width:n.capture.width,before:e(n),after:e(o)});if(`error`in t)return{state:`failed`,regions:[],error:t.error,...s};l=t.regions,R.set(c,l)}return{state:l.length?`different`:`same`,regions:l,...s}}return(async()=>{for(let r of n){if(o.aborted)return;let i=await p(r.page,r.size).catch(t=>({state:`failed`,regions:[],error:t instanceof Error?t.message:e(`app.client.projectDifferences.comparisonFailed`)}));if(o.aborted)return;s.set(r.id,i),c.progress={compared:c.progress.compared+1,total:n.length},t.onChange(r.id)}c.done=!0,l?.terminate(),l=void 0,t.onChange(null)})(),c}var V=40,H=48;function U(e){let t=0;return{slots:e.map(e=>{let n={top:t,height:V+Math.max(e.before.height,e.after.height,1)};return t+=n.height+H,n}),height:Math.max(1,t-H)}}function W(t){return e(t===`changed`?`app.client.differenceView.changed`:t===`added`?`app.client.differenceView.added`:`app.client.differenceView.removed`)}function G(e){let t=new Map;return e.addEventListener(`abort`,()=>{for(let e of t.values())URL.revokeObjectURL(e)},{once:!0}),e=>{let n=t.get(e);return n||t.set(e,n=URL.createObjectURL(e)),n}}function re(n){let r=G(n.signal),i=0;return()=>{let{route:a,side:s,label:c,regions:l,viewport:u}=n.props,{slots:d,height:f}=U(l);i!==f&&(i=f,n.queueTask(()=>n.props.onLayout({height:f,path:a.path})));let p=u?.get(a.id)?.visible??!0;return t(`div`,{role:`img`,"aria-label":e(`app.client.differenceView.artboardLabel`,{title:a.title,label:c}),"data-difference":s,"data-changes":l.length,class:`relative select-none bg-[var(--bud-main)]`,style:{height:`${f}px`},children:l.map((n,i)=>{let a=n[s],l=n.crops[s],u=d[i];return t(`div`,{"data-kind":n.kind,"data-span":`${a.y} ${a.height}`,class:`absolute inset-x-0`,style:{top:`${u.top}px`,height:`${u.height}px`},children:[t(`div`,{class:`flex items-center gap-2 px-1`,style:{height:`${V}px`},children:[t(o,{variant:`ui`,weight:`medium`,children:e(`app.client.differenceView.changeNumber`,{count:i+1})}),t(o,{variant:`ui`,tone:`muted`,children:W(n.kind)})]}),l&&a.height>0?t(`div`,{class:`relative overflow-hidden`,style:{height:`${a.height}px`},children:[p?t(`img`,{alt:``,src:r(l),draggable:!1,class:`block h-full w-full`}):null,n.kind===`changed`?t(`div`,{"aria-hidden":`true`,class:`pointer-events-none absolute inset-y-0 rounded-sm outline-2 outline-red-500/70`,style:{left:`${n.x}px`,width:`${Math.max(2,n.width)}px`}}):null]}):t(`div`,{class:`grid h-24 place-items-center rounded-lg border border-dashed border-line`,children:t(o,{variant:`ui`,tone:`muted`,children:e(`app.client.differenceView.notIn`,{label:c})})})]},i)})})}}function ie(n){let a=G(n.signal),s=e=>{let{slides:t,index:r}=n.props;t.length&&n.props.onIndex((r+e+t.length)%t.length)};return()=>{let{slides:c,index:l,beforeLabel:u,afterLabel:d}=n.props,f=c[Math.min(l,c.length-1)],p=(n,r)=>{let i=f?.region.crops[n];return t(`figure`,{class:`m-0 flex min-w-0 flex-col gap-2`,children:[t(`figcaption`,{children:t(o,{variant:`ui`,tone:`muted`,children:r})}),i&&f.region[n].height>0?t(`div`,{class:`relative`,children:[t(`img`,{alt:e(`app.client.differenceView.artboardLabel`,{title:f.route.title,label:r}),src:a(i),class:`block w-full rounded-lg ring-1 ring-line`}),f.region.kind===`changed`?t(`div`,{"aria-hidden":`true`,class:`pointer-events-none absolute inset-y-0 rounded-sm outline-2 outline-red-500/70`,style:{left:`${f.region.x/f.width*100}%`,width:`max(2px, ${f.region.width/f.width*100}%)`}}):null]}):t(`div`,{class:`grid h-32 place-items-center rounded-lg border border-dashed border-line`,children:t(o,{variant:`ui`,tone:`muted`,children:e(`app.client.differenceView.notIn`,{label:r})})})]})};return t(`section`,{role:`dialog`,"aria-label":e(`app.client.differenceView.slideshowLabel`),class:`bud-surface absolute inset-0 z-40 flex flex-col bg-[var(--bud-main)]`,mix:i((e,t)=>{e.focus(),e.ownerDocument.addEventListener(`keydown`,e=>{if(e.key===`ArrowRight`)s(1);else if(e.key===`ArrowLeft`)s(-1);else if(e.key===`Escape`)n.props.onClose();else return;e.preventDefault()},{signal:t})}),tabindex:-1,children:[t(`header`,{class:`flex h-12 shrink-0 items-center gap-2 border-b border-line ps-4 pe-2`,children:[t(`div`,{class:`flex min-w-0 flex-1 items-baseline gap-2`,children:[t(o,{variant:`ui`,weight:`medium`,class:`truncate`,children:f?.route.title??e(`app.client.differenceView.noDifferences`)}),f?t(o,{variant:`ui`,tone:`muted`,class:`shrink-0 tabular-nums`,role:`status`,children:e(`app.client.differenceView.slideStatus`,{kind:W(f.region.kind),change:f.index+1,count:f.count,index:l+1,total:c.length})}):null]}),t(m,{tooltip:!0,icon:`chevron-left`,label:e(`app.client.differenceView.previousChange`),disabled:c.length<2,mix:r(`click`,()=>s(-1))}),t(m,{tooltip:!0,icon:`chevron-right`,label:e(`app.client.differenceView.nextChange`),disabled:c.length<2,mix:r(`click`,()=>s(1))}),t(m,{tooltip:!0,icon:`close`,label:e(`app.client.differenceView.closeSlideshow`),shortcut:`escape`,mix:r(`click`,()=>n.props.onClose())})]}),t(`div`,{class:`min-h-0 flex-1 overflow-auto p-4`,children:f?t(`div`,{class:`grid gap-4 md:grid-cols-2`,children:[p(`before`,u),p(`after`,d)]}):null})]})}}function K(e){return!(!e.anchor||`type`in e.anchor)}function ae(e,t){let{themes:n}=e.previews,r=g(t),i=document.documentElement.dataset.theme;return n.find(e=>e===r)??n.find(e=>e===i)??n[0]}function q(i){let a=i.props.project,o,c=w({store:x(a),token:a.token,signal:i.signal,initial:i.props.comments,onChange:()=>{i.update()}});i.props.comments.stored&&c.load();let l=a.workingTree?null:a.main??`main`,d=`bud:canvas-branch:${a.id}`,h=g(d),C=typeof h==`string`?h:l,T=!0,A=!1,j=D({project:a,signal:i.signal,onChange:()=>{C&&C!==l&&j.loaded&&!j.list.branches.some(e=>e.name===C&&e.active)?P(l):i.update()}}),M=new AbortController;i.signal.addEventListener(`abort`,()=>M.abort(),{once:!0});let N=E({project:a,signal:M.signal,branch:C});function P(e){if(A=!1,e===C)return void i.update();C=e,_(d,e),M.abort(),M=new AbortController,N=E({project:a,signal:M.signal,branch:e}),i.update()}let F=`bud:preview-theme:${a.id}`,I=ae(a,F),L=`bud:preview-top-only:${a.id}`,R=g(L)===!0,z=a.previews.viewports,V=z.length>1,H=`bud:canvas-viewport:${a.id}`,U=g(H),W=V&&typeof U==`string`&&(U===`all`||z.some(e=>e.id===U))?U:V?`all`:z[0].id;function G(e){e!==W&&(W=e,_(H,e),i.update())}function q(){let e=W===`all`?z:z.filter(e=>e.id===W);return a.routes.flatMap(t=>e.map(e=>({route:t,size:e,artboard:V?{...t,id:`${t.id}@${e.id}`,pageId:t.id,width:e.width,caption:String(e.width)}:t})))}let J=`bud:canvas-compare:${a.id}`,Y=null,X,Z;function Q(){let t=a.workingTree?[{value:``,label:e(`app.client.projectCanvas.workingTree`)}]:[];for(let e of j.list.branches)e.active&&e.captured&&t.push({value:e.name,label:e.name});return t.filter(e=>e.value!==(C??``))}function oe(t){return t||e(`app.client.projectCanvas.workingTree`)}function se(){let e=Q(),t=g(J);Y=e.find(e=>e.value===t)?.value??e.find(e=>e.value===(j.list.main??`main`))?.value??e[0]?.value??null,Z=void 0,i.update()}function ce(){Y=null,Z=void 0,X?.controller.abort(),X=void 0,i.update()}function le(e){if(Y===null||(Q().some(e=>e.value===Y)||(Y=Q()[0]?.value??null),Y===null))return;let t=`${Y}\0${C??``}\0${I}\0${W}`;if(X?.key===t)return X.result;X?.controller.abort();let n=new AbortController;i.signal.addEventListener(`abort`,()=>n.abort(),{once:!0});let r=E({project:a,signal:n.signal,branch:Y||null}),o=B({routes:q().map(({route:e,size:t,artboard:n})=>({id:n.id,page:e.id,size:t})),before:r,after:e,theme:I,signal:n.signal,onChange:()=>{i.update()}});return X={key:t,controller:n,result:o},o}function $(e){return!V||W===`all`||(z.find(t=>t.width===e.anchor.viewport)??z[0]).id===W}function ue(e){return e.filter(K).filter(e=>(e.anchor.branch??l)===C).filter($)}return()=>{if(o!==i.props.threadId){o=i.props.threadId;let e=o;e&&i.queueTask(()=>{c.loadThread(e)})}if(!j.loaded&&!j.error)return t(s,{label:e(`app.client.projectCanvas.loadingBranches`)});let l=`${a.id}:${a.targetOrigin}:${a.routes.map(e=>e.path).join(`|`)}`,d={...c.snapshot,threads:ue(c.snapshot.threads)},h=q(),g=new Map(h.map(({artboard:e,size:t})=>[e.id,t])),x=le(N),w=oe(Y),E=oe(C),D=x?h.map(({artboard:e})=>e).filter(e=>x.get(e.id).state===`different`):[],M=new Map,B=D.flatMap(e=>[`before`,`after`].map(t=>{let n=`${e.id}#${t}`;return M.set(n,{route:e,side:t}),{id:n,path:e.path,title:e.title,width:e.width,caption:e.caption,compare:{groupId:e.id,groupTitle:e.title,versionLabel:t===`before`?w:E}}})),H=D.flatMap(e=>{let{regions:t,after:n}=x.get(e.id),r=n?.width??e.width??z[0].width;return t.map((n,i)=>({route:e,region:n,index:i,count:t.length,width:r}))}),U=``;if(x){let{compared:t,total:n}=x.progress,r=h.filter(({artboard:e})=>x.get(e.id).state===`missing`).length;U=x.done?D.length?r?e(`app.client.projectCanvas.differentPagesWithMissing`,{changed:D.length,count:n,name:w,missing:r}):e(`app.client.projectCanvas.differentPages`,{changed:D.length,count:n,name:w}):r?e(`app.client.projectCanvas.noDifferencesWithMissing`,{name:w,count:r}):e(`app.client.projectCanvas.noDifferences`,{name:w}):e(`app.client.projectCanvas.comparingPages`,{name:w,done:t,count:n})}let K=Q(),ae=e=>e.mobile||e.width<600?`mobile`:e.width<1100?`tablet`:`desktop`,$=t(n,{children:[V?t(n,{children:[z.map(n=>t(m,{tooltip:!0,icon:ae(n),label:e(`app.client.projectCanvas.showViewport`,{name:n.name,width:n.width}),active:W===n.id,mix:r(`click`,()=>G(n.id))})),t(m,{tooltip:!0,icon:`columns`,label:e(`app.client.projectCanvas.showEveryViewport`),active:W===`all`,mix:r(`click`,()=>G(`all`))}),t(f,{})]}):null,t(m,{tooltip:!0,icon:`compare`,label:e(x?`app.client.projectCanvas.stopComparing`:`app.client.projectCanvas.showDifferences`),active:!!x,disabled:!x&&!K.length,mix:r(`click`,()=>x?ce():se())}),x?t(n,{children:[t(u,{label:e(`app.client.projectCanvas.compareWith`),value:Y??``,options:K,class:`max-w-48`,onChange:e=>{Y=e,Z=void 0,_(J,e),i.update()}}),t(m,{tooltip:!0,icon:`play`,label:e(`app.client.projectCanvas.stepThroughDifferences`),disabled:!H.length,mix:r(`click`,()=>{Z=0,i.update()})})]}):null]});return t(p,{class:`h-full min-h-0`,sidebarLabel:e(`app.client.projectCanvas.branches`),mainLabel:e(`app.client.projectCanvas.canvas`),drawerOpen:A,onDrawerOpenChange:e=>{A=e,i.update()},onWideChange:e=>{T!==e&&(T=e,i.update())},sidebar:t(b,{working:j.list.working,workingTree:a.workingTree,branches:j.list.branches,selected:C,busy:j.busy||!j.loaded,loaded:j.loaded,error:j.error,mobile:!T,onSelect:P,onActivate:(e,t)=>{j.activate(e,t)},onCapture:e=>{j.capture(e)},onClose:()=>{A=!1,i.update()}}),children:t(v,{artboards:x?B:h.map(({artboard:e})=>e),width:z[0].width,storageKey:x?`bud:camera:${l}:differences:${W}`:`bud:camera:${l}:${V?W:z[0].width}`,tools:$,overlay:x&&Z!==void 0?t(ie,{slides:H,index:Z,beforeLabel:w,afterLabel:E,onIndex:e=>{Z=e,i.update()},onClose:()=>{Z=void 0,i.update()}}):null,snapshot:d,capabilities:c.snapshot.capabilities,commentsUnavailable:x?U:(c.loaded?!c.ready:a.storage.threads?.state!==`ready`)?S:void 0,onLoadThread:c.loadThread,renderThreadLinks:e=>t(O,{part:`links`,project:a,thread:e,canLink:c.snapshot.capabilities.link,busy:c.busy,onChange:async()=>{await c.load(),await c.loadThread(e.id,!0)}}),renderThreadActions:e=>t(n,{children:[t(k,{thread:e,canMake:c.snapshot.capabilities.link&&a.storage.work?.state===`ready`,busy:c.busy,onMake:async t=>c.makeTask(t,await ne(N,e,z).catch(()=>void 0))}),t(O,{part:`action`,project:a,thread:e,canLink:c.snapshot.capabilities.link,busy:c.busy,onChange:async()=>{await c.load(),await c.loadThread(e.id,!0)}})]}),initialThreadId:o,loaded:c.loaded,busy:c.busy,error:c.error,now:c.now,onWrite:async e=>{let t=await c.write(e);return{...t,threads:ue(t.threads)}},onSync:()=>c.sync().catch(()=>{}),onReload:c.load,viewerId:c.viewer?.id,onDeleteComment:(e,t)=>c.remove(e,t),onCopyThreadLink:e=>navigator.clipboard.writeText(new URL(y(e.id),window.location.origin).href),interactive:!1,branch:C,theme:I,onThemeChange:a.previews.themes.length>1?e=>{I=e,_(F,e),i.update()}:void 0,topOnly:R,onTopOnlyChange:x?void 0:e=>{R=e,_(L,e),i.update()},onShowSidebar:T?void 0:()=>{A=!0,i.update()},sidebarLabel:e(`app.client.projectCanvas.branches`),renderArtboard:(e,n)=>{let r=M.get(e.id);return r?t(re,{route:e,side:r.side,label:r.side===`before`?w:E,regions:x.get(r.route.id).regions,...n},`${X?.key??``}\0${e.id}`):t(ee,{route:e,origin:a.targetOrigin,theme:I,size:g.get(e.id)??z[0],topOnly:R,previews:N,...n},`${C??``}\0${e.id}`)},renderArtboardActions:e=>C||x?null:t(te,{route:e,previews:N})},`${x?`${l}:differences`:l}:${W}`)})}}var J=c({load:({project:e,signal:t})=>C(e,t),render:(e,{project:n,conversation:r})=>t(q,{project:n,comments:e,threadId:r?.id})});export{J as default};