@homepages/template-kit 0.9.0-dev-20260719205406 → 0.9.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 (146) hide show
  1. package/CHANGELOG.md +60 -59
  2. package/README.md +14 -4
  3. package/dist/contracts/fill-treatments.d.ts +23 -0
  4. package/dist/fixtures/sample-property.d.ts +4 -7
  5. package/dist/fixtures/sample-property.js +41 -97
  6. package/dist/fixtures/scenario.d.ts +1 -1
  7. package/dist/fixtures/scenarios/for-rent-condo.js +24 -44
  8. package/dist/fixtures/scenarios/luxury-multi-unit.js +1 -1
  9. package/dist/fixtures/scenarios/sparse-single-family.js +14 -26
  10. package/dist/fixtures.d.ts +2 -2
  11. package/dist/fixtures.js +1 -2
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +2 -2
  14. package/dist/islands/discover.js +1 -1
  15. package/dist/islands/esbuild-plugin.js +1 -1
  16. package/dist/islands/wrap.d.ts +9 -1
  17. package/dist/manifest.json +940 -0
  18. package/dist/media/pack.d.ts +49 -0
  19. package/dist/media/pack.js +69 -0
  20. package/dist/media/resolve-fixture-media.d.ts +22 -0
  21. package/dist/media/resolve-fixture-media.js +73 -0
  22. package/dist/media/resolve-media.js +195 -0
  23. package/dist/package.js +1 -1
  24. package/dist/schema/property-facts.d.ts +2 -2
  25. package/dist/schema/resolve-section-ref.d.ts +4 -0
  26. package/dist/schema/rows.d.ts +9 -0
  27. package/dist/schema/section-nav.d.ts +5 -1
  28. package/dist/schema/slot-types.d.ts +1 -1
  29. package/dist/ssr.d.ts +19 -2
  30. package/dist/ssr.js +32 -13
  31. package/guide/INDEX.md +5 -0
  32. package/guide/check.md +1 -0
  33. package/guide/dev.md +1 -0
  34. package/guide/llms.txt +11 -3
  35. package/guide/recipes/image-slot-crop.md +6 -6
  36. package/guide/recipes/pick-a-scenario.md +13 -5
  37. package/guide/schema-system.md +36 -12
  38. package/guide/upgrading.md +12 -8
  39. package/package.json +4 -16
  40. package/dist/canvas-core/chrome-css.d.ts +0 -24
  41. package/dist/canvas-core/chrome-css.js +0 -403
  42. package/dist/canvas-core/chrome.d.ts +0 -49
  43. package/dist/canvas-core/chrome.js +0 -147
  44. package/dist/canvas-core/frame.d.ts +0 -20
  45. package/dist/canvas-core/frame.js +0 -23
  46. package/dist/canvas-core/hidden-tabs.d.ts +0 -16
  47. package/dist/canvas-core/hidden-tabs.js +0 -84
  48. package/dist/canvas-core/resolve-target.js +0 -55
  49. package/dist/canvas-core/scroll.d.ts +0 -10
  50. package/dist/canvas-core/scroll.js +0 -15
  51. package/dist/canvas-core/section-dom.d.ts +0 -6
  52. package/dist/canvas-core/section-dom.js +0 -43
  53. package/dist/canvas-core/srcdoc.d.ts +0 -8
  54. package/dist/canvas-core/srcdoc.js +0 -77
  55. package/dist/canvas-core/types.d.ts +0 -76
  56. package/dist/canvas-core.d.ts +0 -9
  57. package/dist/canvas-core.js +0 -9
  58. package/dist/cli/check/config.js +0 -41
  59. package/dist/cli/check/css.js +0 -131
  60. package/dist/cli/check/diagnostics.js +0 -37
  61. package/dist/cli/check/index.js +0 -94
  62. package/dist/cli/check/loader.js +0 -149
  63. package/dist/cli/check/paths.js +0 -15
  64. package/dist/cli/check/relativize.js +0 -18
  65. package/dist/cli/check/render-invariants.js +0 -24
  66. package/dist/cli/check/resolve-tool.js +0 -38
  67. package/dist/cli/check/section-assets.js +0 -58
  68. package/dist/cli/check/stages/deps.js +0 -337
  69. package/dist/cli/check/stages/lint.js +0 -46
  70. package/dist/cli/check/stages/render.js +0 -97
  71. package/dist/cli/check/stages/size.js +0 -274
  72. package/dist/cli/check/stages/tree.js +0 -206
  73. package/dist/cli/check/stages/typecheck.js +0 -46
  74. package/dist/cli/check/stages/validate/catalog-exhaustiveness.js +0 -18
  75. package/dist/cli/check/stages/validate/facts.js +0 -19
  76. package/dist/cli/check/stages/validate/formatter-contract.js +0 -14
  77. package/dist/cli/check/stages/validate/group-contract.js +0 -21
  78. package/dist/cli/check/stages/validate/index.js +0 -66
  79. package/dist/cli/check/stages/validate/list-scalar-contract.js +0 -22
  80. package/dist/cli/check/stages/validate/nav-contract.js +0 -92
  81. package/dist/cli/check/stages/validate/nested-slot-contract.js +0 -12
  82. package/dist/cli/check/stages/validate/object-list-contract.js +0 -31
  83. package/dist/cli/check/stages/validate/orchestrator.js +0 -241
  84. package/dist/cli/check/stages/validate/produced-by-contract.js +0 -18
  85. package/dist/cli/check/stages/validate/row-contract.js +0 -31
  86. package/dist/cli/check/stages/validate/select-contract.js +0 -13
  87. package/dist/cli/check/stages/validate/source-contract.js +0 -21
  88. package/dist/cli/check/stages/validate/variant-contract.js +0 -15
  89. package/dist/cli/check/workspace.js +0 -99
  90. package/dist/cli/dev/build-css.js +0 -97
  91. package/dist/cli/dev/catalog.js +0 -35
  92. package/dist/cli/dev/compose-template.js +0 -39
  93. package/dist/cli/dev/content-override.js +0 -58
  94. package/dist/cli/dev/diagnostics.js +0 -68
  95. package/dist/cli/dev/discover.js +0 -35
  96. package/dist/cli/dev/fill-state.js +0 -77
  97. package/dist/cli/dev/index.js +0 -42
  98. package/dist/cli/dev/inspect.js +0 -38
  99. package/dist/cli/dev/island-bootstrap.js +0 -38
  100. package/dist/cli/dev/island-canvas-bootstrap.js +0 -204
  101. package/dist/cli/dev/island-map.js +0 -35
  102. package/dist/cli/dev/island-transform.js +0 -31
  103. package/dist/cli/dev/manifest-instances.js +0 -31
  104. package/dist/cli/dev/render-section.js +0 -24
  105. package/dist/cli/dev/screenshot-target.js +0 -24
  106. package/dist/cli/dev/section-page.js +0 -91
  107. package/dist/cli/dev/server.js +0 -510
  108. package/dist/cli/dev/slot-schema.js +0 -12
  109. package/dist/cli/dev/structure-summary.js +0 -119
  110. package/dist/cli/dev/tailwind.js +0 -32
  111. package/dist/cli/dev/tsconfig-paths-plugin.js +0 -90
  112. package/dist/cli/dev/vite-server.js +0 -39
  113. package/dist/cli/dev/workspace.js +0 -63
  114. package/dist/cli/link/index.js +0 -74
  115. package/dist/cli/link/overlay.js +0 -59
  116. package/dist/cli/link/watch.js +0 -25
  117. package/dist/cli/new/emit.js +0 -48
  118. package/dist/cli/new/index.js +0 -69
  119. package/dist/cli/new/scaffold/section/_Renderer.tsx +0 -20
  120. package/dist/cli/new/scaffold/section/_fill-spec.ts +0 -18
  121. package/dist/cli/new/scaffold/section/_fixtures.ts +0 -13
  122. package/dist/cli/new/scaffold/section/_schema.ts +0 -24
  123. package/dist/cli/new/scaffold/template/_manifest.json +0 -9
  124. package/dist/cli/new/scaffold/template/sections/hero/ExpandableText.tsx +0 -45
  125. package/dist/cli/new/scaffold/template/sections/hero/Renderer.tsx +0 -40
  126. package/dist/cli/new/scaffold/template/sections/hero/components/Feature.tsx +0 -14
  127. package/dist/cli/new/scaffold/template/sections/hero/fill-spec.ts +0 -29
  128. package/dist/cli/new/scaffold/template/sections/hero/fixtures.ts +0 -41
  129. package/dist/cli/new/scaffold/template/sections/hero/schema.ts +0 -60
  130. package/dist/cli/new/scaffold/template/theme.css +0 -24
  131. package/dist/cli/new/scaffold/template/theme.ts +0 -27
  132. package/dist/cli/new/scaffold-assets.js +0 -20
  133. package/dist/cli/pack/collect.js +0 -44
  134. package/dist/cli/pack/guards.js +0 -57
  135. package/dist/cli/pack/index.js +0 -66
  136. package/dist/cli/pack/manifest.js +0 -15
  137. package/dist/cli/pack/zip.js +0 -86
  138. package/dist/cli/theme/generate.js +0 -43
  139. package/dist/cli/theme/index.js +0 -33
  140. package/dist/cli/theme/load-theme.js +0 -69
  141. package/dist/cli.d.ts +0 -1
  142. package/dist/cli.js +0 -138
  143. package/dist/dev-client/assets/index-CJa9G1Na.css +0 -1
  144. package/dist/dev-client/assets/index-C_1atZs4.js +0 -450
  145. package/dist/dev-client/index.html +0 -13
  146. package/dist/tokens.css +0 -21
@@ -2,7 +2,7 @@
2
2
  purpose: Add an image slot the editor crops to a fixed ratio.
3
3
  status: living
4
4
  related: [../schema-system.md, ../primitives.md, ../rules/image-bare-needs-reason.md, pick-a-scenario.md]
5
- updated: 2026-07-16
5
+ updated: 2026-07-19
6
6
  ---
7
7
  # Image slot with a locked crop
8
8
 
@@ -51,20 +51,20 @@ interior_image: {
51
51
  ```
52
52
 
53
53
  ```ts
54
- // fixtures.ts — a photo + a matching mkResponsive() height
55
- import { mkResponsive, scenarios } from "@homepages/template-kit/fixtures";
54
+ // fixtures.ts — the photo's asset id, exactly as a saved page states it
55
+ import { scenarios } from "@homepages/template-kit/fixtures";
56
56
 
57
57
  const interiorImage = scenarios.luxuryMultiUnit.photos[3]!;
58
58
  // ...
59
59
  interior_image: {
60
60
  photo_id: interiorImage.id,
61
- url: interiorImage.url,
62
61
  alt: interiorImage.alt,
63
- // Height set to a 4:3 ratio to match the slot's locked crop.
64
- responsive: mkResponsive(interiorImage.url, 1600, 1200),
65
62
  },
66
63
  ```
67
64
 
65
+ The `url` and the responsive ladder the Renderer reads are attached when the fixture
66
+ loads — see [Media is stated by id](../schema-system.md#media-is-stated-by-id-never-by-url).
67
+
68
68
  An image slot supports two independent geometry configs — use one, not both, per
69
69
  slot:
70
70
 
@@ -2,7 +2,7 @@
2
2
  purpose: Source a fixture's slots from real property data, by the fill-by-source rule.
3
3
  status: living
4
4
  related: [../schema-system.md, fixture-states.md, ../vocabulary.md]
5
- updated: 2026-07-16
5
+ updated: 2026-07-19
6
6
  ---
7
7
  # Pick a scenario for a fixture
8
8
 
@@ -59,7 +59,6 @@ nothing about the layout it's supposed to preview.
59
59
  ```ts
60
60
  import {
61
61
  contactCards,
62
- mkResponsive,
63
62
  poisByCategory,
64
63
  primaryContact,
65
64
  propertyMetrics,
@@ -75,7 +74,6 @@ const s = scenarios.luxuryMultiUnit;
75
74
  | `contactCards(s)` | Every attached contact, in order (`ContactFixture[]`) |
76
75
  | `poisByCategory(s)` | The scenario's POIs bucketed by category (`Record<PoiFixture["category"], PoiFixture[]>`) |
77
76
  | `propertyMetrics(s)` | `beds`/`baths`/`sqft`/`price` off the lowest-position unit, `bedsMin`/`bedsMax`/`bathsMin`/`bathsMax`/`sqftMax`/`priceStart` across all units, and `addressLine1`/`addressLine2` |
78
- | `mkResponsive(url, width, height)` | A deterministic `ResponsiveImage` descriptor so `<Image responsive>` can be previewed and snapshotted |
79
77
 
80
78
  `propertyMetrics` returns kit fact vocabulary — `addressLine1`/`addressLine2`, not a
81
79
  template's own slot names, so the kit never learns what a section calls its slots. Map
@@ -90,10 +88,20 @@ address_locality: m.addressLine2,
90
88
 
91
89
  Fields the helpers don't cover are readable straight off the scenario: `s.photos`,
92
90
  `s.pois`, `s.amenities`, `s.contacts`, `s.media`, and `s.facts` (the raw
93
- `PropertyFacts`). A contact's org name and logos (`logo_light`/`logo_dark`) live on
94
- `ContactFixture["fields"]`, not on a sibling "brand" object — read them off
91
+ `PropertyFacts`). A contact's org name and logos (`logo_light_id`/`logo_dark_id`) live
92
+ on `ContactFixture["fields"]`, not on a sibling "brand" object — read them off
95
93
  `primaryContact(s).fields` or `s.contacts`.
96
94
 
95
+ ### Media comes off the scenario as an id
96
+
97
+ Every media reference in a scenario is an **asset id**, the same thing a saved page
98
+ holds — `s.photos[n].id`, `primaryContact(s).fields.headshot_id` / `.logo_light_id` /
99
+ `.logo_dark_id`, `s.media.video_id`, and a floor plan ref's `id`. Put the id in the
100
+ fixture and stop there: the url, the `alt` fallback, and the responsive ladder are
101
+ attached for you when the fixture loads. Never state a url in a fixture.
102
+ (`s.media.tour_3d_url` is the one exception — a 3D tour is a third-party embed with no
103
+ asset behind it.)
104
+
97
105
  ### Add a scenario-driven state
98
106
 
99
107
  A `states` entry designed to look different against a sparser property sources from a
@@ -2,7 +2,7 @@
2
2
  purpose: The section authoring contract — schema.ts, fill-spec.ts, fixtures.ts, and the closed source/transform vocabulary.
3
3
  status: living
4
4
  related: [primitives.md, theme-and-css.md, vocabulary.md, recipes/pick-a-scenario.md]
5
- updated: 2026-07-17
5
+ updated: 2026-07-19
6
6
  ---
7
7
  # The schema system
8
8
 
@@ -229,12 +229,16 @@ headline, an empty list).
229
229
 
230
230
  ```ts
231
231
  import type { FixtureModule } from "@homepages/template-kit";
232
+ import { scenarios } from "@homepages/template-kit/fixtures";
232
233
 
233
234
  const fixtures: FixtureModule = {
234
235
  base: {
235
236
  slots: {
236
237
  headline: "101 Queensway, Jamaica Plain, MA 02130",
237
- hero_image: { photo_id: "p1", url: "https://example.com/a.jpg", alt: "Front elevation" },
238
+ // An image slot states the asset id a real page holds — never a URL. The
239
+ // preview server resolves it to a url, an alt fallback, and a responsive
240
+ // ladder, exactly as the platform does when the page is published.
241
+ hero_image: { photo_id: scenarios.luxuryMultiUnit.photos[19]!.id, alt: "Front elevation" },
238
242
  blurb: "A bright corner home moments from the Emerald Necklace.",
239
243
  },
240
244
  options: { align: "center" },
@@ -255,7 +259,7 @@ contacts, the cases that actually break a layout. Pick the one whose breadth mat
255
259
  state you're exercising:
256
260
 
257
261
  ```ts
258
- import { scenarios, primaryContact, poisByCategory, propertyMetrics, contactCards, mkResponsive }
262
+ import { scenarios, primaryContact, poisByCategory, propertyMetrics, contactCards }
259
263
  from "@homepages/template-kit/fixtures";
260
264
 
261
265
  const s = scenarios.luxuryMultiUnit; // or sparseSingleFamily / forRentCondo
@@ -298,7 +302,6 @@ wants, without re-typing the scenario's data:
298
302
  | `contactCards(s)` | Every attached contact, in order (`ContactFixture[]`) |
299
303
  | `poisByCategory(s)` | The scenario's POIs bucketed by category (`Record<PoiFixture["category"], PoiFixture[]>`) |
300
304
  | `propertyMetrics(s)` | Beds/baths/sqft/price off the lowest-position unit, `*Min`/`*Max`/`priceStart` across all units, and `addressLine1`/`addressLine2` |
301
- | `mkResponsive(url, width, height)` | Synthesizes a deterministic `ResponsiveImage` descriptor so `<Image responsive>` can be previewed and snapshotted |
302
305
 
303
306
  `propertyMetrics` returns kit fact vocabulary — `addressLine1`/`addressLine2`, never a
304
307
  template's own slot names, so the kit never learns what a section calls its slots. Map it
@@ -307,8 +310,29 @@ to your slots at the call site: `address_street: m.addressLine1`.
307
310
  `s.photos`, `s.pois`, `s.amenities`, `s.contacts`, `s.media`, and `s.facts`
308
311
  (the raw `PropertyFacts`) are also readable straight off the scenario for slots that don't
309
312
  need a helper's projection — a gallery slot can bind directly to `s.photos`. A contact's
310
- org name and logos (`logo_light`/`logo_dark`) live on `ContactFixture["fields"]`, not on
311
- a sibling "brand" object — read them off `primaryContact(s).fields` or `s.contacts`.
313
+ org name and logos (`logo_light_id`/`logo_dark_id`) live on `ContactFixture["fields"]`,
314
+ not on a sibling "brand" object — read them off `primaryContact(s).fields` or
315
+ `s.contacts`.
316
+
317
+ ### Media is stated by id, never by URL
318
+
319
+ A fixture's job is to state what a **saved page** holds, and a saved page holds an
320
+ asset id — the platform turns that id into a served URL at render time. So a fixture
321
+ does the same: give an image slot a `photo_id` (a video slot a `video_id`), and the
322
+ url, the `alt` fallback, and the responsive ladder are attached for you when the
323
+ fixture loads, in the preview server and in `check` alike. A fixture that states a
324
+ URL is exercising a path real content never takes.
325
+
326
+ The ids to use are the scenario's own: `s.photos[n].id` for a photo,
327
+ `primaryContact(s).fields.headshot_id` / `.logo_light_id` / `.logo_dark_id` for a
328
+ contact's images, `s.media.video_id` for the hosted video. `s.media.tour_3d_url`
329
+ stays a URL on purpose — a 3D tour is a third-party embed the platform does not host,
330
+ so there is no asset to name. Floor plan refs
331
+ (`s.facts.units[*].floor_plans`) likewise carry only `id`/`floor_label`/`position`;
332
+ their `url`, `alt`, and `responsive` are optional and appear only after resolution.
333
+
334
+ An id that names nothing resolves to an empty image, which previews as an empty slot
335
+ rather than an error — so take the ids off the scenario rather than typing them.
312
336
 
313
337
  See [Pick a scenario](recipes/pick-a-scenario.md) for the full picker and helper
314
338
  cheat-sheet.
@@ -318,14 +342,14 @@ cheat-sheet.
318
342
  A scenario is the **fixture view** of a property, not the fact bundle the AI-fill pipeline
319
343
  reads. The difference matters when you write a `fill-spec.ts`:
320
344
 
321
- - Scenarios carry values that only exist *after* fill and render — `UnitRow.description`
322
- and `features` are AI-written copy; a floor plan's `url` and `alt` are attached when the
323
- image is served. Nothing upstream produces these; they are here so your renderer has
324
- something real to draw.
345
+ - Scenarios carry values that only exist *after* fill — `UnitRow.description` and
346
+ `features` are AI-written copy. Nothing upstream produces these; they are here so your
347
+ renderer has something real to draw.
325
348
  - Scenarios hoist some facts **out** of `facts` and onto the scenario itself, in the shapes
326
349
  a renderer wants: `photos` → `s.photos` (`PhotoFixture[]`), `pois` → `s.pois`
327
- (`PoiFixture[]`), and the fact bundle's `tours` → `s.media` — a single `MediaFixture`
328
- **object** (`video_url`, `tour_3d_url`), not an array. Floor plans hoist too, but onto
350
+ (`PoiFixture[]`), and the fact bundle's hosted videos and `tours` → `s.media` — a
351
+ single `MediaFixture` **object**, not an array: `video_id` names one hosted video
352
+ asset, `tour_3d_url` the third-party embed link. Floor plans hoist too, but onto
329
353
  each unit: `s.facts.units[*].floor_plans` (`FloorplanAssignment[]`).
330
354
  - `contacts` is **duplicated, not hoisted**. `s.contacts` holds the render-shaped
331
355
  `ContactFixture[]` your renderer draws, and `facts.contacts` still exists as well — so a
@@ -43,19 +43,21 @@ npm run check
43
43
  CHANGELOG in the package (`node_modules/@homepages/template-kit/CHANGELOG.md`) for
44
44
  what changed and why.
45
45
 
46
- ## The lint preset upgrades separately
46
+ ## The CLI and the lint preset upgrade separately
47
47
 
48
- `@homepages/eslint-plugin-template` is its own package with its own version line,
49
- so the kit's number tells you nothing about it and `npm update
50
- @homepages/template-kit` never moves it. Update it the same way, on its own:
48
+ `@homepages/template-cli` (which provides the `template-kit` command) and
49
+ `@homepages/eslint-plugin-template` (the lint preset) are each their own package on
50
+ their own version line, so the kit's number tells you nothing about them and `npm
51
+ update @homepages/template-kit` never moves them. Update each on its own:
51
52
 
52
53
  ```bash
54
+ npm update @homepages/template-cli
53
55
  npm update @homepages/eslint-plugin-template
54
56
  ```
55
57
 
56
- It declares the kit as a **peer dependency**, so its range says which kit line it
57
- supports. If `npm install` reports a peer conflict after a kit minor, the preset is
58
- the package to bump — not the kit to hold back.
58
+ Both declare the kit as a **peer dependency**, so each one's range says which kit
59
+ line it supports. If `npm install` reports a peer conflict after a kit minor, the
60
+ package to bump is the one reporting it — not the kit to hold back.
59
61
 
60
62
  ## How long you have
61
63
 
@@ -74,4 +76,6 @@ npm ls @homepages/template-kit # what you have installed
74
76
  npm view @homepages/template-kit version # the current release
75
77
  ```
76
78
 
77
- The same two commands work for `@homepages/eslint-plugin-template`.
79
+ The same two commands work for `@homepages/template-cli` and
80
+ `@homepages/eslint-plugin-template`. `template-kit --version` prints the pair the
81
+ command is actually running as `<cli> (kit <kit>)`.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@homepages/template-kit",
3
- "version": "0.9.0-dev-20260719205406",
4
- "description": "Authoring kit for HomePages marketing-section templates: schema system, contract primitives, theme tokens, and the template-kit CLI.",
3
+ "version": "0.9.0",
4
+ "description": "Authoring kit for HomePages marketing-section templates: schema system, contract primitives, theme tokens, and the design-system CSS layer.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
7
7
  "engines": {
@@ -22,9 +22,6 @@
22
22
  "tsconfig.base.json",
23
23
  "CHANGELOG.md"
24
24
  ],
25
- "bin": {
26
- "template-kit": "dist/cli.js"
27
- },
28
25
  "exports": {
29
26
  ".": {
30
27
  "types": "./dist/index.d.ts",
@@ -50,10 +47,6 @@
50
47
  "types": "./dist/rules.d.ts",
51
48
  "default": "./dist/rules.js"
52
49
  },
53
- "./canvas-core": {
54
- "types": "./dist/canvas-core.d.ts",
55
- "default": "./dist/canvas-core.js"
56
- },
57
50
  "./styles.css": "./dist/styles.css",
58
51
  "./base.css": "./dist/base.css",
59
52
  "./tsconfig": "./tsconfig.base.json",
@@ -64,10 +57,9 @@
64
57
  ],
65
58
  "scripts": {
66
59
  "prepack": "npm run build",
67
- "build": "tsdown && node scripts/build-dev-client.mjs && node scripts/build-cli-assets.mjs",
60
+ "build": "tsdown",
68
61
  "typecheck": "tsc --noEmit",
69
62
  "lint": "eslint .",
70
- "pretest": "node test/link-fixture-workspace.mjs",
71
63
  "test": "node --import tsx --test 'src/**/*.test.ts' 'src/**/*.test.tsx'",
72
64
  "lint:pkg": "publint --strict && attw --pack . --profile esm-only --exclude-entrypoints styles.css base.css",
73
65
  "verify:consumer": "node scripts/verify-consumer.mjs",
@@ -81,15 +73,12 @@
81
73
  "devDependencies": {
82
74
  "@arethetypeswrong/cli": "^0.18.5",
83
75
  "@eslint/js": "^9.39.4",
84
- "@playwright/test": "^1.60.0",
85
76
  "@tailwindcss/cli": "^4.3.0",
86
77
  "@types/jsdom": "^21.1.7",
87
78
  "@types/node": "^20.17.10",
88
79
  "@types/react": "^19.0.0",
89
80
  "@types/react-dom": "^19.0.0",
90
81
  "@typescript-eslint/parser": "^8.60.1",
91
- "@vitejs/plugin-react": "^4.3.4",
92
- "chokidar": "^4.0.1",
93
82
  "esbuild": "^0.28.1",
94
83
  "eslint": "^9.39.4",
95
84
  "jsdom": "^26.1.0",
@@ -100,8 +89,7 @@
100
89
  "tsdown": "0.22.7",
101
90
  "tsx": "^4.19.2",
102
91
  "typescript": "^5.7.2",
103
- "typescript-eslint": "^8.60.1",
104
- "vite": "^6.0.5"
92
+ "typescript-eslint": "^8.60.1"
105
93
  },
106
94
  "dependencies": {
107
95
  "magic-string": "^0.30.21",
@@ -1,24 +0,0 @@
1
- import { MarkerAttrs } from "./types.js";
2
- //#region src/canvas-core/chrome-css.d.ts
3
- /**
4
- * Custom properties the chrome CSS reads but deliberately does not declare —
5
- * the host must set them on the iframe document's root element. This is the
6
- * host's obligation, not a suggestion: an adapter that skips one leaves the
7
- * declared inline fallback in force, which renders plausibly and silently
8
- * wrong rather than failing.
9
- *
10
- * - `--we-panel-w`: the floating panel's measured width, mirrored onto the
11
- * iframe root so the page card's right padding clears it. Unset, the card
12
- * lays out against the 436px base-width fallback and drifts out of alignment
13
- * whenever the real panel is any other width.
14
- * - `--we-content`: the host's interior scaling unit, mirrored in so hidden-tab
15
- * chrome scales with the rest of the UI. Unset, it pins to the 1px fallback
16
- * and the tabs stay laptop-sized while every surrounding surface scales.
17
- *
18
- * Anything added here must actually be read by the kernel; the token test
19
- * fails on a stale entry.
20
- */
21
- declare const HOST_INJECTED_PROPERTIES: readonly ["--we-panel-w", "--we-content"];
22
- declare function buildChromeCss(markers: MarkerAttrs): string;
23
- //#endregion
24
- export { HOST_INJECTED_PROPERTIES, buildChromeCss };