@ashley-shrok/viewmodel-shell 0.3.2 → 0.3.4

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ashley-shrok/viewmodel-shell",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "A server-driven UI framework where the wire format is structured enough that agents can build full-stack apps without ever opening a browser and all UI tests are pure unit tests with no browser runtime. Server returns a JSON tree of typed nodes; a thin TypeScript adapter renders it to DOM. Backend-agnostic — a .NET reference backend ships with the repo, but any language can produce the JSON contract.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -190,11 +190,15 @@ export interface ShellOptions {
190
190
  onLoading?: (loading: boolean) => void;
191
191
  /** Called before each dispatch — merge the returned headers into every POST request. */
192
192
  getRequestHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
193
+ /** Called when the server responds with a redirect URL. Defaults to window.location.href = url. */
194
+ onRedirect?: (url: string) => void;
193
195
  }
194
196
 
195
197
  export interface ShellResponse {
196
198
  vm: ViewNode;
197
199
  state: unknown;
200
+ /** When set, the shell navigates to this URL instead of re-rendering. */
201
+ redirect?: string;
198
202
  }
199
203
 
200
204
  export class ViewModelShell {
@@ -254,6 +258,14 @@ export class ViewModelShell {
254
258
  });
255
259
  if (!res.ok) throw new Error(`Action '${action.name}' failed: ${res.status}`);
256
260
  const body = (await res.json()) as ShellResponse;
261
+ if (body.redirect) {
262
+ if (this.options.onRedirect) {
263
+ this.options.onRedirect(body.redirect);
264
+ } else {
265
+ window.location.href = body.redirect;
266
+ }
267
+ return;
268
+ }
257
269
  this.currentVm = body.vm;
258
270
  this.currentState = body.state;
259
271
  adapter.render(body.vm, (a) => this.dispatch(a));
@@ -34,8 +34,9 @@
34
34
  --vms-info: #4a9eff;
35
35
  --vms-radius: 10px;
36
36
  --vms-radius-sm: 6px;
37
- --vms-font-body: ui-monospace, 'DM Mono', 'Fira Mono', Menlo, monospace;
38
- --vms-font-head: 'DM Serif Display', Georgia, serif;
37
+ --vms-font-body: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
38
+ --vms-font-head: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
39
+ --vms-font-mono: ui-monospace, 'Cascadia Code', 'Fira Code', Menlo, Consolas, 'Liberation Mono', monospace;
39
40
  --vms-t: 0.15s ease;
40
41
  --vms-color-scheme: dark;
41
42
  }
@@ -56,7 +57,7 @@ body {
56
57
  .vms-page__title {
57
58
  font-family: var(--vms-font-head);
58
59
  font-size: 2.25rem;
59
- font-weight: 400;
60
+ font-weight: 600;
60
61
  letter-spacing: -0.02em;
61
62
  padding-bottom: 0.75rem;
62
63
  border-bottom: 1px solid var(--vms-border);
@@ -114,7 +115,7 @@ select.vms-field__input { cursor: pointer; padding-right: 2.25rem; }
114
115
  /* Code editor field — monospaced, tab-aware, no spell-check chrome.
115
116
  Apps add syntax highlighting via .vms-field--code-{language} hooks. */
116
117
  .vms-field__input--code {
117
- font-family: var(--vms-font-body);
118
+ font-family: var(--vms-font-mono);
118
119
  font-size: 13px;
119
120
  line-height: 1.5;
120
121
  tab-size: 2;
@@ -279,7 +280,7 @@ select.vms-field__input { cursor: pointer; padding-right: 2.25rem; }
279
280
  .vms-text--muted { color: var(--vms-text-muted); font-size: 12px; }
280
281
  .vms-text--strikethrough { color: var(--vms-done-text); text-decoration: line-through; }
281
282
  .vms-text--error { color: var(--vms-error); font-size: 13px; }
282
- .vms-text--pre { font-family: var(--vms-font-body); white-space: pre; }
283
+ .vms-text--pre { font-family: var(--vms-font-mono); white-space: pre; }
283
284
 
284
285
  /* ── Link ── */
285
286
  .vms-link {