@box-kite/react 2.0.1 → 2.2.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 (145) hide show
  1. package/.claude/rules/box-kite-rules.md +24 -2
  2. package/.claude/skills/box-kite/SKILL.md +27 -5
  3. package/.claude/skills/box-kite/references/components.md +8 -3
  4. package/.claude/skills/box-kite/references/patterns.md +24 -1
  5. package/.claude/skills/box-kite/references/styling.md +23 -0
  6. package/.cursor/rules/box-kite.mdc +25 -3
  7. package/AGENTS.md +28 -3
  8. package/BOX_AI_CONTEXT.md +732 -12
  9. package/BOX_KITE_AI_CONTEXT.md +732 -12
  10. package/README.md +41 -9
  11. package/box.cjs +1 -1
  12. package/box.d.ts +13 -2
  13. package/box.mjs +25 -18
  14. package/catalog.cjs +1 -0
  15. package/catalog.d.ts +8 -0
  16. package/catalog.mjs +2347 -0
  17. package/client.cjs +1 -1
  18. package/client.mjs +59 -53
  19. package/components/agent.cjs +1 -0
  20. package/components/agent.d.ts +215 -0
  21. package/components/agent.mjs +405 -0
  22. package/components/button.cjs +1 -1
  23. package/components/button.mjs +10 -14
  24. package/components/chart.d.ts +1 -0
  25. package/components/dashboard.cjs +1 -0
  26. package/components/dashboard.d.ts +121 -0
  27. package/components/dashboard.mjs +690 -0
  28. package/components/dataGrid/components/dataGridBody.d.ts +2 -1
  29. package/components/dataGrid/components/dataGridDetailRow.d.ts +13 -2
  30. package/components/dataGrid/components/dataGridGroupRow.d.ts +13 -2
  31. package/components/dataGrid/components/dataGridRow.d.ts +13 -2
  32. package/components/dataGrid/contracts/dataGridContract.d.ts +66 -2
  33. package/components/dataGrid/models/cellModel.d.ts +3 -0
  34. package/components/dataGrid/models/editModel.d.ts +27 -0
  35. package/components/dataGrid/models/exportModel.d.ts +2 -1
  36. package/components/dataGrid/models/gridModel.d.ts +3 -0
  37. package/components/dataGrid/models/rangeModel.d.ts +119 -0
  38. package/components/dataGrid/models/viewportModel.d.ts +23 -2
  39. package/components/dataGrid/useGridNavigation.d.ts +10 -2
  40. package/components/dataGrid.cjs +4 -1
  41. package/components/dataGrid.d.ts +3 -0
  42. package/components/dataGrid.mjs +1056 -765
  43. package/components/flex.cjs +1 -1
  44. package/components/flex.mjs +10 -13
  45. package/components/form.cjs +1 -1
  46. package/components/form.mjs +7 -7
  47. package/components/grid.cjs +1 -1
  48. package/components/grid.mjs +10 -13
  49. package/components/markdown.cjs +1 -0
  50. package/components/markdown.d.ts +55 -0
  51. package/components/markdown.mjs +179 -0
  52. package/components/menu.cjs +1 -1
  53. package/components/menu.mjs +16 -16
  54. package/components/overlay.cjs +1 -1
  55. package/components/overlay.mjs +35 -34
  56. package/components/popover.cjs +1 -1
  57. package/components/popover.mjs +4 -4
  58. package/components/semantics.cjs +1 -1
  59. package/components/semantics.d.ts +29 -29
  60. package/components/semantics.mjs +9 -13
  61. package/components/skeleton.cjs +1 -0
  62. package/components/skeleton.d.ts +34 -0
  63. package/components/skeleton.mjs +25 -0
  64. package/components/svg.cjs +1 -1
  65. package/components/svg.mjs +38 -44
  66. package/components/textarea.cjs +1 -1
  67. package/components/textarea.mjs +12 -16
  68. package/components/textbox.cjs +1 -1
  69. package/components/textbox.mjs +12 -16
  70. package/components/toaster.cjs +1 -1
  71. package/components/toaster.mjs +42 -43
  72. package/components/visuallyHidden.cjs +1 -1
  73. package/components/visuallyHidden.mjs +10 -13
  74. package/dashboardSchema.cjs +1 -0
  75. package/dashboardSchema.mjs +78 -0
  76. package/docs/a11y.md +2 -3
  77. package/docs/catalog.md +451 -0
  78. package/docs/components.md +4 -0
  79. package/docs/index.md +3 -0
  80. package/docs/interop.md +237 -0
  81. package/docs/mcp.md +70 -0
  82. package/docs/props.md +135 -23
  83. package/interop.cjs +1 -0
  84. package/interop.d.ts +51 -0
  85. package/interop.mjs +454 -0
  86. package/layer.cjs +1 -1
  87. package/layer.mjs +61 -59
  88. package/mcp/src/data.d.ts +88 -0
  89. package/mcp/src/data.test.d.ts +1 -0
  90. package/mcp/src/engine.d.ts +23 -0
  91. package/mcp/src/index.d.ts +1 -0
  92. package/mcp/src/search.d.ts +26 -0
  93. package/mcp/src/search.test.d.ts +1 -0
  94. package/mcp/src/server.d.ts +18 -0
  95. package/mcp/src/server.test.d.ts +1 -0
  96. package/mcp/src/styles.d.ts +27 -0
  97. package/mcp/src/styles.test.d.ts +1 -0
  98. package/mcp/src/tools.d.ts +18 -0
  99. package/mcp/src/vocabulary.d.ts +41 -0
  100. package/package.json +170 -37
  101. package/react/boxComponent.d.ts +10 -0
  102. package/react/popover/useTopLayer.d.ts +17 -0
  103. package/react/spec/renderSpec.d.ts +51 -0
  104. package/react/spec/specBoundary.d.ts +25 -0
  105. package/react/spec/specRegistry.d.ts +42 -0
  106. package/react/spec/specRenderer.d.ts +10 -0
  107. package/react/theme/theme.d.ts +10 -0
  108. package/react/useStyles.d.ts +2 -0
  109. package/react-shared.cjs +1 -1
  110. package/react-shared.mjs +44 -37
  111. package/registry/blocks/dashboard-shell/dashboard-shell.d.ts +22 -0
  112. package/registry/blocks/dashboard-shell/dashboard-stats.d.ts +13 -0
  113. package/registry/blocks/data-grid/invoice-rows.d.ts +15 -0
  114. package/registry/blocks/data-grid/invoices-grid.d.ts +1 -0
  115. package/registry/blocks/settings-form/settings-form.d.ts +17 -0
  116. package/rsc.cjs +1 -1
  117. package/rsc.d.ts +11 -1
  118. package/rsc.mjs +15 -12
  119. package/spec.cjs +2 -0
  120. package/spec.d.ts +12 -0
  121. package/spec.mjs +382 -0
  122. package/specData.cjs +1 -0
  123. package/specData.mjs +69 -0
  124. package/specDefs.cjs +1 -0
  125. package/specDefs.mjs +33 -0
  126. package/specSchema.cjs +1 -0
  127. package/specSchema.mjs +88 -0
  128. package/ssg.cjs +1 -1
  129. package/ssg.d.ts +8 -2
  130. package/ssg.mjs +13 -9
  131. package/utils/agent/agentUtils.d.ts +81 -0
  132. package/utils/catalog/catalogContracts.d.ts +19 -0
  133. package/utils/catalog/catalogManifest.d.ts +8 -0
  134. package/utils/dashboard/dashboardSchema.d.ts +18 -0
  135. package/utils/dashboard/dashboardUtils.d.ts +97 -0
  136. package/utils/environment/environmentUtils.d.ts +5 -0
  137. package/utils/interop/a2uiInterop.d.ts +82 -0
  138. package/utils/interop/assistantUiInterop.d.ts +34 -0
  139. package/utils/interop/toolInterop.d.ts +30 -0
  140. package/utils/spec/specData.d.ts +19 -0
  141. package/utils/spec/specDefs.d.ts +11 -0
  142. package/utils/spec/specProps.d.ts +15 -0
  143. package/utils/spec/specSchema.d.ts +23 -0
  144. package/utils/spec/specTypes.d.ts +71 -0
  145. package/utils/spec/specValidate.d.ts +10 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@box-kite/react",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "pages/**"
@@ -34,6 +34,21 @@
34
34
  "import": "./anchor.mjs",
35
35
  "require": "./anchor.cjs"
36
36
  },
37
+ "./catalog": {
38
+ "types": "./catalog.d.ts",
39
+ "import": "./catalog.mjs",
40
+ "require": "./catalog.cjs"
41
+ },
42
+ "./interop": {
43
+ "types": "./interop.d.ts",
44
+ "import": "./interop.mjs",
45
+ "require": "./interop.cjs"
46
+ },
47
+ "./spec": {
48
+ "types": "./spec.d.ts",
49
+ "import": "./spec.mjs",
50
+ "require": "./spec.cjs"
51
+ },
37
52
  "./ssg": {
38
53
  "types": "./ssg.d.ts",
39
54
  "import": "./ssg.mjs",
@@ -59,6 +74,7 @@
59
74
  "preview": "vite preview ./pages --config ./pages.vite.config.ts --outDir ../dist-pages",
60
75
  "build": "npm run build:core && vite build",
61
76
  "build:core": "vite build --config vite.core.config.ts && node scripts/postbuild-core.mjs",
77
+ "build:mcp": "vite build --config vite.mcp.config.ts && node scripts/postbuild-mcp.mjs",
62
78
  "postbuild": "node scripts/postbuild.mjs",
63
79
  "build:bridge": "node scripts/build-bridge.mjs",
64
80
  "build:dev": "npm run build:core && vite build --mode dev",
@@ -75,10 +91,17 @@
75
91
  "docs:props": "node scripts/check-props-api.mjs --fix",
76
92
  "check:components": "node scripts/check-components-api.mjs",
77
93
  "docs:components": "node scripts/check-components-api.mjs --fix",
94
+ "check:catalog": "node scripts/check-catalog-api.mjs",
95
+ "docs:catalog": "node scripts/check-catalog-api.mjs --fix",
78
96
  "check:conventions": "node scripts/check-component-conventions.mjs",
79
97
  "check:agents": "node scripts/check-agent-files.mjs",
80
98
  "docs:agents": "node scripts/check-agent-files.mjs --fix",
81
- "check:package": "publint dist && attw --pack dist --ignore-rules false-esm cjs-resolves-to-esm internal-resolution-error && publint dist-core && attw --pack dist-core --ignore-rules false-esm cjs-resolves-to-esm internal-resolution-error",
99
+ "check:package": "publint dist && attw --pack dist --ignore-rules false-esm cjs-resolves-to-esm internal-resolution-error && publint dist-core && attw --pack dist-core --ignore-rules false-esm cjs-resolves-to-esm internal-resolution-error && publint dist-mcp",
100
+ "bench": "node bench/run.mjs",
101
+ "compare": "node dev/compare/report.mjs",
102
+ "compare:tailwind": "node dev/compare/report.mjs tailwind",
103
+ "compare:radix": "node dev/compare/report.mjs radix",
104
+ "compare:grid": "node dev/compare/report.mjs grid",
82
105
  "size": "size-limit",
83
106
  "size:published": "node dev/published-size.mjs",
84
107
  "release": "node scripts/release.mjs"
@@ -89,27 +112,30 @@
89
112
  "path": "dist/box.mjs",
90
113
  "ignore": [
91
114
  "react",
92
- "react-dom"
115
+ "react-dom",
116
+ "./diagnostics-*"
93
117
  ],
94
118
  "gzip": true,
95
- "limit": "30.40 KB"
119
+ "limit": "36.28 KB"
96
120
  },
97
121
  {
98
122
  "name": "Box in a Server Component (react-server entry)",
99
123
  "path": "dist/rsc.mjs",
100
124
  "ignore": [
101
125
  "react",
102
- "react-dom"
126
+ "react-dom",
127
+ "./diagnostics-*"
103
128
  ],
104
129
  "gzip": true,
105
- "limit": "28.90 KB"
130
+ "limit": "34.69 KB"
106
131
  },
107
132
  {
108
133
  "name": "Behavior primitives (a11y entry)",
109
134
  "path": "dist/a11y.mjs",
110
135
  "ignore": [
111
136
  "react",
112
- "react-dom"
137
+ "react-dom",
138
+ "./diagnostics-*"
113
139
  ],
114
140
  "gzip": true,
115
141
  "limit": "3.2 KB"
@@ -119,123 +145,215 @@
119
145
  "path": "dist/anchor.mjs",
120
146
  "ignore": [
121
147
  "react",
122
- "react-dom"
148
+ "react-dom",
149
+ "./diagnostics-*"
123
150
  ],
124
151
  "gzip": true,
125
152
  "limit": "2.25 KB"
126
153
  },
154
+ {
155
+ "name": "Component catalog (catalog entry)",
156
+ "path": "dist/catalog.mjs",
157
+ "ignore": [
158
+ "react",
159
+ "react-dom",
160
+ "./diagnostics-*"
161
+ ],
162
+ "gzip": true,
163
+ "limit": "54.73 KB"
164
+ },
165
+ {
166
+ "name": "Spec renderer (spec entry)",
167
+ "path": "dist/spec.mjs",
168
+ "ignore": [
169
+ "react",
170
+ "react-dom",
171
+ "./diagnostics-*"
172
+ ],
173
+ "gzip": true,
174
+ "limit": "4.7 KB"
175
+ },
176
+ {
177
+ "name": "Ecosystem interop (interop entry)",
178
+ "path": "dist/interop.mjs",
179
+ "ignore": [
180
+ "react",
181
+ "react-dom",
182
+ "./diagnostics-*"
183
+ ],
184
+ "gzip": true,
185
+ "limit": "4 KB"
186
+ },
127
187
  {
128
188
  "name": "Core engine (@box-kite/core, no React)",
129
189
  "path": "dist-core/core.mjs",
130
190
  "gzip": true,
131
- "limit": "28.17 KB"
191
+ "limit": "35.73 KB",
192
+ "ignore": [
193
+ "./diagnostics-*"
194
+ ]
132
195
  },
133
196
  {
134
197
  "name": "Dialog",
135
198
  "path": "dist/components/dialog.mjs",
136
199
  "ignore": [
137
200
  "react",
138
- "react-dom"
201
+ "react-dom",
202
+ "./diagnostics-*"
139
203
  ],
140
204
  "gzip": true,
141
- "limit": "32.55 KB"
205
+ "limit": "38.35 KB"
142
206
  },
143
207
  {
144
208
  "name": "Popover",
145
209
  "path": "dist/components/popover.mjs",
146
210
  "ignore": [
147
211
  "react",
148
- "react-dom"
212
+ "react-dom",
213
+ "./diagnostics-*"
149
214
  ],
150
215
  "gzip": true,
151
- "limit": "34.02 KB"
216
+ "limit": "39.88 KB"
152
217
  },
153
218
  {
154
219
  "name": "Menu",
155
220
  "path": "dist/components/menu.mjs",
156
221
  "ignore": [
157
222
  "react",
158
- "react-dom"
223
+ "react-dom",
224
+ "./diagnostics-*"
159
225
  ],
160
226
  "gzip": true,
161
- "limit": "36.27 KB"
227
+ "limit": "42.15 KB"
162
228
  },
163
229
  {
164
230
  "name": "Accordion",
165
231
  "path": "dist/components/accordion.mjs",
166
232
  "ignore": [
167
233
  "react",
168
- "react-dom"
234
+ "react-dom",
235
+ "./diagnostics-*"
236
+ ],
237
+ "gzip": true,
238
+ "limit": "37.60 KB"
239
+ },
240
+ {
241
+ "name": "Agent",
242
+ "path": "dist/components/agent.mjs",
243
+ "ignore": [
244
+ "react",
245
+ "react-dom",
246
+ "./diagnostics-*"
247
+ ],
248
+ "gzip": true,
249
+ "limit": "38.34 KB"
250
+ },
251
+ {
252
+ "name": "Markdown",
253
+ "path": "dist/components/markdown.mjs",
254
+ "ignore": [
255
+ "react",
256
+ "react-dom",
257
+ "./diagnostics-*"
169
258
  ],
170
259
  "gzip": true,
171
- "limit": "31.76 KB"
260
+ "limit": "36.84 KB"
261
+ },
262
+ {
263
+ "name": "Skeleton",
264
+ "path": "dist/components/skeleton.mjs",
265
+ "ignore": [
266
+ "react",
267
+ "react-dom",
268
+ "./diagnostics-*"
269
+ ],
270
+ "gzip": true,
271
+ "limit": "36.17 KB"
172
272
  },
173
273
  {
174
274
  "name": "Tabs",
175
275
  "path": "dist/components/tabs.mjs",
176
276
  "ignore": [
177
277
  "react",
178
- "react-dom"
278
+ "react-dom",
279
+ "./diagnostics-*"
179
280
  ],
180
281
  "gzip": true,
181
- "limit": "32.96 KB"
282
+ "limit": "38.80 KB"
182
283
  },
183
284
  {
184
285
  "name": "Slider",
185
286
  "path": "dist/components/slider.mjs",
186
287
  "ignore": [
187
288
  "react",
188
- "react-dom"
289
+ "react-dom",
290
+ "./diagnostics-*"
189
291
  ],
190
292
  "gzip": true,
191
- "limit": "32.12 KB"
293
+ "limit": "37.95 KB"
192
294
  },
193
295
  {
194
296
  "name": "Progress",
195
297
  "path": "dist/components/progress.mjs",
196
298
  "ignore": [
197
299
  "react",
198
- "react-dom"
300
+ "react-dom",
301
+ "./diagnostics-*"
199
302
  ],
200
303
  "gzip": true,
201
- "limit": "30.28 KB"
304
+ "limit": "36.15 KB"
202
305
  },
203
306
  {
204
307
  "name": "Toaster",
205
308
  "path": "dist/components/toaster.mjs",
206
309
  "ignore": [
207
310
  "react",
208
- "react-dom"
311
+ "react-dom",
312
+ "./diagnostics-*"
209
313
  ],
210
314
  "gzip": true,
211
- "limit": "33.77 KB"
315
+ "limit": "39.62 KB"
212
316
  },
213
317
  {
214
318
  "name": "Combobox",
215
319
  "path": "dist/components/combobox.mjs",
216
320
  "ignore": [
217
321
  "react",
218
- "react-dom"
322
+ "react-dom",
323
+ "./diagnostics-*"
324
+ ],
325
+ "gzip": true,
326
+ "limit": "45.41 KB"
327
+ },
328
+ {
329
+ "name": "Dashboard",
330
+ "path": "dist/components/dashboard.mjs",
331
+ "ignore": [
332
+ "react",
333
+ "react-dom",
334
+ "./diagnostics-*"
219
335
  ],
220
336
  "gzip": true,
221
- "limit": "39.54 KB"
337
+ "limit": "41.80 KB"
222
338
  },
223
339
  {
224
340
  "name": "DataGrid",
225
341
  "path": "dist/components/dataGrid.mjs",
226
342
  "ignore": [
227
343
  "react",
228
- "react-dom"
344
+ "react-dom",
345
+ "./diagnostics-*"
229
346
  ],
230
347
  "gzip": true,
231
- "limit": "74.86 KB"
348
+ "limit": "83.18 KB"
232
349
  },
233
350
  {
234
351
  "name": "DataGrid export, the chunk fetched on the first press",
235
352
  "path": "dist/gridExport.mjs",
236
353
  "ignore": [
237
354
  "react",
238
- "react-dom"
355
+ "react-dom",
356
+ "./diagnostics-*"
239
357
  ],
240
358
  "gzip": true,
241
359
  "limit": "3.8 KB"
@@ -245,10 +363,11 @@
245
363
  "path": "dev/size-full.mjs",
246
364
  "ignore": [
247
365
  "react",
248
- "react-dom"
366
+ "react-dom",
367
+ "./diagnostics-*"
249
368
  ],
250
369
  "gzip": true,
251
- "limit": "96.82 KB"
370
+ "limit": "114.74 KB"
252
371
  }
253
372
  ],
254
373
  "repository": {
@@ -276,35 +395,48 @@
276
395
  "url": "https://github.com/box-kite/box-kite/issues"
277
396
  },
278
397
  "homepage": "https://www.box-kite.dev",
279
- "description": "One React component with 221 typed CSS props that generates atomic CSS at runtime — no CSS files, no build step, renders in a Server Component.",
398
+ "description": "One React component with 235 typed CSS props that generates atomic CSS at runtime — no CSS files, no build step, renders in a Server Component.",
280
399
  "peerDependencies": {
281
400
  "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
282
401
  "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
283
402
  },
284
403
  "dependencies": {
285
- "@box-kite/core": "2.0.1",
404
+ "@box-kite/core": "2.2.0",
286
405
  "csstype": "^3.2.3",
287
406
  "use-sync-external-store": "^1.6.0"
288
407
  },
289
408
  "devDependencies": {
290
409
  "@arethetypeswrong/cli": "^0.18.5",
410
+ "@assistant-ui/core": "^0.3.20",
411
+ "@copilotkit/a2ui-renderer": "^1.73.0",
412
+ "@emotion/react": "^11.14.0",
413
+ "@emotion/styled": "^11.14.1",
291
414
  "@eslint/js": "^10.0.1",
292
415
  "@iconify-json/simple-icons": "^1.2.94",
293
416
  "@iconify/react": "^6.0.2",
417
+ "@json-render/core": "^0.20.0",
418
+ "@json-render/react": "^0.20.0",
419
+ "@lezer/javascript": "^1.5.5",
420
+ "@modelcontextprotocol/sdk": "^1.30.0",
421
+ "@mui/material": "^9.4.0",
422
+ "@mui/x-data-grid": "^9.14.0",
294
423
  "@size-limit/preset-small-lib": "^13.0.3",
295
424
  "@svgr/core": "^8.1.0",
296
425
  "@svgr/plugin-jsx": "^8.1.0",
426
+ "@tanstack/react-table": "^9.2.4",
427
+ "@tanstack/react-virtual": "^3.14.13",
297
428
  "@testing-library/dom": "^10.4.1",
298
429
  "@testing-library/jest-dom": "^7.0.0",
299
430
  "@testing-library/react": "^16.3.2",
300
431
  "@testing-library/user-event": "^14.6.6",
301
432
  "@types/node": "^26.1.2",
302
- "@types/prismjs": "^1.26.6",
303
433
  "@types/react": "^19.2.18",
304
434
  "@types/react-dom": "^19.2.4",
305
435
  "@types/use-sync-external-store": "^1.5.0",
306
436
  "@vitejs/plugin-react": "^6.0.5",
307
437
  "@vitest/coverage-v8": "^4.1.11",
438
+ "ag-grid-community": "^36.2.0",
439
+ "ag-grid-react": "^36.2.0",
308
440
  "axe-core": "^4.13.0",
309
441
  "eslint": "^10.8.0",
310
442
  "eslint-config-prettier": "^10.1.8",
@@ -318,18 +450,19 @@
318
450
  "lucide-react": "^1.28.0",
319
451
  "marked": "^18.0.11",
320
452
  "prettier": "^3.9.6",
321
- "prismjs": "^1.30.0",
322
453
  "publint": "^0.3.24",
323
454
  "react": "^19.2.8",
324
455
  "react-dom": "^19.2.8",
325
456
  "react-router-dom": "^7.18.2",
326
457
  "recharts": "^3.10.1",
327
458
  "size-limit": "^13.0.3",
459
+ "sucrase": "^3.35.1",
328
460
  "typescript": "^6.0.3",
329
461
  "typescript-eslint": "^8.66.0",
330
462
  "unplugin-icons": "^23.0.1",
331
463
  "vite": "^8.2.0",
332
464
  "vite-plugin-dts": "^5.0.3",
333
- "vitest": "^4.1.10"
465
+ "vitest": "^4.1.10",
466
+ "zod": "^4.6.5"
334
467
  }
335
468
  }
@@ -0,0 +1,10 @@
1
+ import { default as React, Ref } from 'react';
2
+ type Render = (props: any, ref: any) => React.ReactNode;
3
+ /**
4
+ * A component that is a Box: memoized, which skips a leaf whose props are all primitives, and one fiber on
5
+ * React 19. React 18 needs a `forwardRef` under the `memo`, which makes it two.
6
+ */
7
+ export default function boxComponent(render: Render, displayName: string): React.MemoExoticComponent<((props: {
8
+ ref?: Ref<unknown>;
9
+ }) => React.ReactNode) | React.ForwardRefExoticComponent<Omit<any, "ref"> & React.RefAttributes<unknown>>>;
10
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Whether a floating layer goes in the top layer or in a portal — and, which is the point of reading it
3
+ * through a store, *when* that is decided. Asking the browser directly during a server render answers
4
+ * false (there is no `HTMLElement`), so the portal branch is taken and renders nothing, while the client
5
+ * renders the layer: one React #418 per load for any layer that is open in server-rendered HTML (bug
6
+ * #197). The server snapshot is therefore the top-layer shape.
7
+ *
8
+ * React reads that snapshot only while hydrating, so the two paths — which are different *positions* in
9
+ * the React tree, and so a remount — cost one correction on exactly one path: a browser with no Popover
10
+ * API adopting HTML that already holds the layer, where nothing can have been focused inside it yet. A
11
+ * layer a browser mounts (a dropdown opening) reads the real answer on its first render and never moves,
12
+ * which is what B2 stage 2 fixed and what a `useState(true)` corrected in an effect gives up.
13
+ *
14
+ * The consequence for a caller: while hydrating, this says `true` in a browser that has no `showPopover`
15
+ * to call, so an effect that calls one asks `supportsPopover()` rather than trusting this.
16
+ */
17
+ export default function useTopLayer(): boolean;
@@ -0,0 +1,51 @@
1
+ import { ReactNode } from 'react';
2
+ import { SpecIssue } from '../../utils/spec/specTypes';
3
+ import { SpecRegistry } from './specRegistry';
4
+ /** What a bound event hands the host. Everything about where it came from, and nothing about what to do. */
5
+ export interface SpecActionDetails {
6
+ /** What the spec sent with the action, resolved against the data the way a prop is. */
7
+ payload?: unknown;
8
+ /** The arguments the component called its handler with. */
9
+ args: unknown[];
10
+ /** The event prop that fired. */
11
+ prop: string;
12
+ component: string;
13
+ path: string;
14
+ }
15
+ export type SpecActionHandler = (action: string, details: SpecActionDetails) => void;
16
+ export interface SpecRenderOptions {
17
+ /** What the spec may name, and what each name renders. */
18
+ registry: SpecRegistry;
19
+ /** What `{ $data: … }` reads from. */
20
+ data?: unknown;
21
+ /** Every action the spec binds arrives here. The host decides what any of them mean. */
22
+ onAction?: SpecActionHandler;
23
+ /** What stands in for a node that could not render. Nothing, unless the app says otherwise. */
24
+ fallback?: (issue: SpecIssue) => ReactNode;
25
+ /** A tree bigger than this stops rendering — a generated spec has no author to notice a runaway one. */
26
+ maxNodes?: number;
27
+ maxDepth?: number;
28
+ /** A node that threw renders its fallback until this changes: the next spec is a fresh chance. */
29
+ resetKey?: unknown;
30
+ /** A node that threw during a *commit*, which is after this function has returned. */
31
+ onError?: (issue: SpecIssue) => void;
32
+ /**
33
+ * The last value each node was given for a prop it cannot render without. A stream is not monotone —
34
+ * a column's `align` passes through `"e"` on its way to `"end"`, which fails its own schema and takes
35
+ * the whole `def` with it — so without this a grid on screen is unmounted and rebuilt several times
36
+ * in the last moments of a spec. `<SpecRenderer>` keeps one; a one-shot render needs none.
37
+ */
38
+ memory?: SpecMemory;
39
+ }
40
+ /** Keyed by a node's path and component: a different component at that path remembers nothing. */
41
+ export type SpecMemory = Map<string, Record<string, unknown>>;
42
+ export interface SpecRenderResult {
43
+ element: ReactNode;
44
+ /** Everything that did not render, and why. Advisory — the tree renders around every one of them. */
45
+ issues: SpecIssue[];
46
+ }
47
+ /**
48
+ * The spec as React elements, and everything that did not render. No hook in it, so a static spec
49
+ * renders on a server and a test can assert the issues without mounting anything.
50
+ */
51
+ export declare function renderSpec(spec: unknown, options: SpecRenderOptions): SpecRenderResult;
@@ -0,0 +1,25 @@
1
+ import { Component, ReactNode } from 'react';
2
+ import { SpecIssue } from '../../utils/spec/specTypes';
3
+ export interface SpecBoundaryProps {
4
+ /** Where the node sits in the spec, for the issue this reports. */
5
+ path: string;
6
+ component: string;
7
+ /** A new spec resets the boundary: the next version of a node deserves its own chance to render. */
8
+ resetKey: unknown;
9
+ fallback: (issue: SpecIssue) => ReactNode;
10
+ onError?: (issue: SpecIssue) => void;
11
+ children: ReactNode;
12
+ }
13
+ interface SpecBoundaryState {
14
+ message: string | null;
15
+ resetKey: unknown;
16
+ }
17
+ export default class SpecBoundary extends Component<SpecBoundaryProps, SpecBoundaryState> {
18
+ state: SpecBoundaryState;
19
+ static getDerivedStateFromProps(props: SpecBoundaryProps, state: SpecBoundaryState): Partial<SpecBoundaryState> | null;
20
+ static getDerivedStateFromError(error: unknown): Partial<SpecBoundaryState>;
21
+ componentDidCatch(error: unknown): void;
22
+ private issue;
23
+ render(): ReactNode;
24
+ }
25
+ export {};
@@ -0,0 +1,42 @@
1
+ import { ComponentType } from 'react';
2
+ import { CatalogSchema } from '@box-kite/core';
3
+ import { SpecRules } from '../../utils/spec/specTypes';
4
+ /** A component the catalog does not describe, or one whose rules the app wants to narrow. */
5
+ export interface SpecComponent {
6
+ component: ComponentType<any>;
7
+ /** What its props may be, as JSON Schema. Without one, a spec may set none of them. */
8
+ props?: CatalogSchema;
9
+ /** Where children may go. `['default']` unless the catalog says otherwise. */
10
+ slots?: string[];
11
+ /** The props a spec may bind an action to — the only props that can ever become a function. */
12
+ events?: string[];
13
+ description?: string;
14
+ }
15
+ export interface SpecRegistryEntry extends SpecRules {
16
+ component: ComponentType<any>;
17
+ }
18
+ export interface SpecRegistry {
19
+ /** Every component a spec may name, in the order they were registered. */
20
+ readonly names: string[];
21
+ /** The rules alone, which is what `specSchema()` takes: registry in, the model's constraint out. */
22
+ readonly components: Record<string, SpecRules>;
23
+ get(type: string): SpecRegistryEntry | undefined;
24
+ }
25
+ /** What a `catalog()` result carries per component. Structural, so the catalog entry is not imported. */
26
+ interface CatalogSource {
27
+ components: Record<string, {
28
+ description?: string;
29
+ props?: CatalogSchema;
30
+ slots?: string[];
31
+ events?: string[];
32
+ }>;
33
+ }
34
+ export interface SpecRegistryOptions {
35
+ /** The implementations, by the name a spec writes. A bare component takes its rules from the catalog. */
36
+ components: Record<string, ComponentType<any> | SpecComponent>;
37
+ /** `catalog()`, narrowed however the app narrowed it. Anything it describes needs no rules of its own. */
38
+ catalog?: CatalogSource;
39
+ }
40
+ /** The registry a `<SpecRenderer>` renders against. */
41
+ export declare function createSpecRegistry(options: SpecRegistryOptions): SpecRegistry;
42
+ export default createSpecRegistry;
@@ -0,0 +1,10 @@
1
+ import { SpecIssue } from '../../utils/spec/specTypes';
2
+ import { SpecRenderOptions } from './renderSpec';
3
+ export interface SpecRendererProps extends Omit<SpecRenderOptions, 'onError' | 'resetKey' | 'memory'> {
4
+ /** Whatever arrived. Every field of it is checked, so a partial object from a stream is welcome. */
5
+ spec: unknown;
6
+ /** Called after each render whose issues changed, and again when a node throws during a commit. */
7
+ onIssues?: (issues: SpecIssue[]) => void;
8
+ }
9
+ /** A generated spec, rendered against what the app allows. */
10
+ export default function SpecRenderer({ spec, onIssues, ...options }: SpecRendererProps): import('react').ReactNode;
@@ -12,6 +12,16 @@ interface ThemeProps {
12
12
  * `globalStyles={{ scrollbarColor: ['violet-500', 'transparent'], theme: { dark: { scrollbarColor: [...] } } }}`.
13
13
  */
14
14
  globalStyles?: BoxStyleProps;
15
+ /**
16
+ * Cross-fade the page when the theme changes, where the browser has view transitions. Off by default,
17
+ * because a transition is a decision about the app rather than about theming.
18
+ *
19
+ * It exists as a prop rather than a recipe because the recipe has a trap in it: `startViewTransition`
20
+ * screenshots the page the moment its callback returns, and a `setState` has not rendered by then — so
21
+ * a hand-rolled version captures the old theme twice and nothing appears to change. This flushes the
22
+ * update inside the callback. Reduced motion skips the transition and keeps the theme change.
23
+ */
24
+ viewTransition?: boolean;
15
25
  }
16
26
  /**
17
27
  * The React binding for the theme system. Everything that actually touches the platform — reading
@@ -15,6 +15,8 @@ export declare namespace StylesContext {
15
15
  function clear(): void;
16
16
  /** The CSS emitted so far, as text. Flushes first — see `StyleEngine.getStyles`. */
17
17
  function getStyles(): string;
18
+ /** The CSS as a `<style>` element the browser can adopt — see `StyleEngine.getStyleTag`. */
19
+ function getStyleTag(): string;
18
20
  /** The id of the `<style>` element the default engine writes to. */
19
21
  function styleElementId(): string;
20
22
  /** Apply explicit engine configuration. Call before the first render — cached class names are dropped when the configuration changes. */
package/react-shared.cjs CHANGED
@@ -1 +1 @@
1
- const e=require("./rolldown-runtime.cjs");let t=require("react");t=e.t(t,1);let n=require("@box-kite/core");function r({classNames:e,styleElements:t},r){return{className:(0,n.classNames)(e,r).join(` `),styles:t}}var i={selected:`aria-selected`},a;(function(e){function t(e,t,n){e!==void 0&&e!=null&&(n[i[t]??t]=Array.isArray(e)?e[0]:e)}e.assignBooleanProp=t})(a||={});var o=a;function s(e,t){let r=e,{props:i,className:a,disabled:s,required:c,checked:l,selected:u}=r,d={...i,className:(0,n.classNames)(t,a).join(` `)};return o.assignBooleanProp(s,`disabled`,d),o.assignBooleanProp(c,`required`,d),o.assignBooleanProp(l,`checked`,d),o.assignBooleanProp(u,`selected`,d),`style`in r&&(d.style=r.style),`id`in r&&(d.id=r.id),d}var c=parseInt(t.default.version,10)>=19,l=!1;function u(e){if(e?.length)return!c&&!l&&(l=!0,console.warn(`[box-kite] Box.configure({ sink: 'element' }) needs React 19 to hoist and dedupe its <style> elements; React ${t.default.version} will render them inline. Use the default sink instead.`)),e.map(({href:e,css:n,precedence:r})=>t.default.createElement(`style`,{key:e,href:e,precedence:r,dangerouslySetInnerHTML:{__html:n}}))}function d(e,t){let{classNames:r,signature:i,styleElements:a}=(0,n.getDefaultEngine)().resolveClassNames(e,t);return{classNames:r,signature:i,styleElements:u(a)}}var f=`__boxAttributesInProps`;function p(e){return e[f]=!0,e}function m(e){return typeof e==`function`||typeof e==`object`&&e?e[f]===!0:!1}var h=[`role`,`aria-label`,`aria-labelledby`,`aria-hidden`];function g(e,t){if(e!==void 0)return{role:`img`,"aria-label":e};if(!(t&&h.some(e=>e in t)))return{"aria-hidden":!0}}var _;(function(e){function t(e){return e.charAt(0).toUpperCase()+e.slice(1)}e.capitalize=t})(_||={});var v=_,y;(function(e){function t(e,t,n){let r={...e},i=r.props||{};return t.forEach(e=>{e in r&&(i[e]=r[e],delete r[e])}),n&&Object.entries(n).forEach(([e,t])=>{i[e]=t}),r.props=i,r}e.buildProps=t;function n(e){return!!e&&typeof e==`object`}e.isObject=n;function r(e,t){return e in t}e.isKeyOf=r})(y||={});var b=y,x=[`sky-500`,`emerald-500`,`amber-500`,`violet-500`,`rose-500`,`cyan-500`],S=[`sky-400`,`emerald-400`,`amber-400`,`violet-400`,`rose-400`,`cyan-400`];function C(e){return e.reduce((e,t,n)=>(e[`chart-${n+1}`]=t,e),{})}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return u}});
1
+ const e=require("./rolldown-runtime.cjs");let t=require("react");t=e.t(t,1);let n=require("@box-kite/core");function r({classNames:e,styleElements:t},r){return{className:(0,n.classNames)(e,r).join(` `),styles:t}}var i=parseInt(t.default.version,10)>=19;function a(e,n){let r=i?t=>e(t,t.ref??null):(0,t.forwardRef)(e),a=(0,t.memo)(r);return r.displayName=n,a.displayName=n,a}var o={selected:`aria-selected`},s;(function(e){function t(e,t,n){e!==void 0&&e!=null&&(n[o[t]??t]=Array.isArray(e)?e[0]:e)}e.assignBooleanProp=t})(s||={});var c=s;function l(e,t){let r=e,{props:i,className:a,disabled:o,required:s,checked:l,selected:u}=r,d={...i,className:(0,n.classNames)(t,a).join(` `)};return c.assignBooleanProp(o,`disabled`,d),c.assignBooleanProp(s,`required`,d),c.assignBooleanProp(l,`checked`,d),c.assignBooleanProp(u,`selected`,d),`style`in r&&(d.style=r.style),`id`in r&&(d.id=r.id),d}var u=parseInt(t.default.version,10)>=19,d=!1;function f(e){if(e?.length)return!u&&!d&&(d=!0,console.warn(`[box-kite] Box.configure({ sink: 'element' }) needs React 19 to hoist and dedupe its <style> elements; React ${t.default.version} will render them inline. Use the default sink instead.`)),e.map(({href:e,css:n,precedence:r})=>t.default.createElement(`style`,{key:e,href:e,precedence:r,dangerouslySetInnerHTML:{__html:n}}))}function p(e,t){let{classNames:r,signature:i,styleElements:a}=(0,n.getDefaultEngine)().resolveClassNames(e,t);return{classNames:r,signature:i,styleElements:f(a)}}var m=`__boxAttributesInProps`;function h(e){return e[m]=!0,e}function g(e){return typeof e==`function`||typeof e==`object`&&e?e[m]===!0:!1}var _=[`role`,`aria-label`,`aria-labelledby`,`aria-hidden`];function v(e,t){if(e!==void 0)return{role:`img`,"aria-label":e};if(!(t&&_.some(e=>e in t)))return{"aria-hidden":!0}}var y;(function(e){function t(e){return e.charAt(0).toUpperCase()+e.slice(1)}e.capitalize=t})(y||={});var b=y,x;(function(e){function t(e,t,n){let r={...e},i=r.props||{};return t.forEach(e=>{e in r&&(i[e]=r[e],delete r[e])}),n&&Object.entries(n).forEach(([e,t])=>{i[e]=t}),r.props=i,r}e.buildProps=t;function n(e){return!!e&&typeof e==`object`}e.isObject=n;function r(e,t){return e in t}e.isKeyOf=r})(x||={});var S=x,C=[`sky-500`,`emerald-500`,`amber-500`,`violet-500`,`rose-500`,`cyan-500`],w=[`sky-400`,`emerald-400`,`amber-400`,`violet-400`,`rose-400`,`cyan-400`];function T(e){return e.reduce((e,t,n)=>(e[`chart-${n+1}`]=t,e),{})}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return f}});