@imfusion/web-ui 0.5.1-dev.3.g8e0a047a → 0.5.1-dev.30.gf9b152db

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 (57) hide show
  1. package/README.md +148 -55
  2. package/bin/install.js +374 -0
  3. package/bin/install.test.ts +243 -0
  4. package/dist/build/vite-css-module-names/index.d.ts +20 -0
  5. package/dist/build/vite-css-module-names.js +17 -0
  6. package/dist/components/field/field.d.ts +104 -0
  7. package/dist/components/field/field.meta.d.ts +2 -0
  8. package/dist/components/field/index.d.ts +2 -0
  9. package/dist/components/fieldset/fieldset.d.ts +29 -0
  10. package/dist/components/fieldset/fieldset.meta.d.ts +2 -0
  11. package/dist/components/fieldset/index.d.ts +2 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +4956 -4317
  14. package/dist/integrations/image-display-options.js +1 -1
  15. package/dist/style.css +1 -1
  16. package/dist/{tabs-DqBFSqq6.js → tabs-CVp_SgBl.js} +1 -1
  17. package/package.json +35 -24
  18. package/src/docgen/doc.gen.json +327 -0
  19. package/src/llms/llms.gen.txt +12 -0
  20. package/src/llms/skills/imf-web-ui/SKILL.md +15 -11
  21. package/src/llms/skills/imf-web-ui-agent-setup/SKILL.md +82 -0
  22. package/src/llms/skills/imf-web-ui-agent-setup/templates/hooks/baseline-staleness.sh +17 -0
  23. package/src/llms/skills/imf-web-ui-agent-setup/templates/hooks/post-tool-use.sh +33 -0
  24. package/src/llms/skills/imf-web-ui-agent-setup/templates/hooks/session-start.sh +4 -0
  25. package/src/llms/skills/imf-web-ui-agent-setup/templates/hooks/user-prompt-submit.sh +4 -0
  26. package/src/llms/skills/imf-web-ui-agent-setup/templates/settings.json +37 -0
  27. package/src/llms/skills/imf-web-ui-components/SKILL.md +2 -1
  28. package/src/llms/skills/imf-web-ui-frontend-conventions/SKILL.md +46 -0
  29. package/src/llms/skills/imf-web-ui-frontend-conventions/references/assets.md +23 -0
  30. package/src/llms/skills/imf-web-ui-frontend-conventions/references/class-names.md +42 -0
  31. package/src/llms/skills/imf-web-ui-frontend-conventions/references/components.md +63 -0
  32. package/src/llms/skills/imf-web-ui-frontend-conventions/references/data.md +201 -0
  33. package/src/llms/skills/imf-web-ui-frontend-conventions/references/docs-structure.md +44 -0
  34. package/src/llms/skills/imf-web-ui-frontend-conventions/references/git.md +33 -0
  35. package/src/llms/skills/imf-web-ui-frontend-conventions/references/library-boundary.md +37 -0
  36. package/src/llms/skills/imf-web-ui-frontend-conventions/references/npm-project.md +57 -0
  37. package/src/llms/skills/imf-web-ui-frontend-conventions/references/project-structure.md +21 -0
  38. package/src/llms/skills/{imf-web-ui-frontend-patterns/references/react-patterns.md → imf-web-ui-frontend-conventions/references/react.md} +28 -12
  39. package/src/llms/skills/imf-web-ui-frontend-conventions/references/stack.md +39 -0
  40. package/src/llms/skills/imf-web-ui-frontend-conventions/references/styling.md +91 -0
  41. package/src/llms/skills/imf-web-ui-frontend-conventions/references/testing.md +18 -0
  42. package/src/llms/skills/imf-web-ui-frontend-conventions/references/tooling.md +76 -0
  43. package/src/llms/skills/imf-web-ui-frontend-conventions/references/typescript.md +46 -0
  44. package/src/llms/skills/imf-web-ui-frontend-conventions/references/validation.md +88 -0
  45. package/src/llms/skills/imf-web-ui-frontend-setup/SKILL.md +66 -0
  46. package/src/llms/skills/imf-web-ui-frontend-setup/templates/AGENTS.md +34 -0
  47. package/src/llms/skills/imf-web-ui-frontend-setup/templates/FRONTEND_SETUP_REPORT.md +45 -0
  48. package/src/llms/skills/imf-web-ui-frontend-setup/templates/README.md +27 -0
  49. package/src/llms/skills/imf-web-ui-library-setup/SKILL.md +36 -0
  50. package/src/llms/skills/imf-web-ui-update/SKILL.md +166 -0
  51. package/src/llms/skills/imf-web-ui-ux/SKILL.md +4 -4
  52. package/src/llms/skills/imf-web-ui-ux/references/forms.md +1 -1
  53. package/bin/install-skill.js +0 -180
  54. package/src/llms/skills/imf-web-ui-frontend-patterns/SKILL.md +0 -93
  55. package/src/llms/skills/imf-web-ui-frontend-patterns/references/code-conventions.md +0 -133
  56. package/src/llms/skills/imf-web-ui-imfusion-frontend-setup/SKILL.md +0 -201
  57. package/src/llms/skills/imf-web-ui-setup/SKILL.md +0 -57
@@ -3786,4 +3786,4 @@ function Mo({ className: e, ...t }) {
3786
3786
  }
3787
3787
  Mo.displayName = "Tabs.Panel";
3788
3788
  //#endregion
3789
- export { Hn as $, M as $n, Vt as $t, Kr as A, Ue as An, xn as At, Tr as B, J as Bn, pn as Bt, ha as C, st as Cn, Tn as Ct, gi as D, Je as Dn, kn as Dt, hi as E, $e as En, wn as Et, Fr as F, X as Fn, vn as Ft, mr as G, F as Gn, en as Gt, Sr as H, V as Hn, fn as Ht, Nr as I, ke as In, yn as It, fr as J, T as Jn, Jt, pr as K, N as Kn, $t as Kt, Mr as L, Ee as Ln, hn as Lt, zr as M, Pe as Mn, Cn as Mt, Ir as N, Ae as Nn, bn as Nt, mi as O, Ke as On, Dn as Ot, Pr as P, je as Pn, _n as Pt, Kn as Q, k as Qn, Kt as Qt, kr as R, be as Rn, mn as Rt, _a as S, ct as Sn, jn as St, ra as T, rt as Tn, En as Tt, br as U, B as Un, sn as Ut, Cr as V, U as Vn, ln as Vt, hr as W, L as Wn, tn as Wt, Gn as X, ee as Xn, qt as Xt, gr as Y, f as Yn, Zt as Yt, Un as Z, u as Zn, Gt as Zt, Ta as _, _t as _n, In as _t, Do as a, jt as an, D as ar, Yn as at, fa as b, ft as bn, Fn as bt, to as c, Pt as cn, g as cr, ur as ct, Xa as d, Ot as dn, E as dr, Bn as dt, zt as en, A as er, Jn as et, Ua as f, gt as fn, zn as ft, ka as g, vt as gn, Ln as gt, Oa as h, yt as hn, Rn as ht, jo as i, Dt as in, h as ir, er as it, Wr as j, Z as jn, Sn as jt, ai as k, qe as kn, An as kt, $a as l, xt as ln, v as lr, qn as lt, Na as m, Ft as mn, Vn as mt, Oo as n, At as nn, w as nr, $n as nt, ko as o, Et as on, p as or, sr as ot, Ra as p, bt as pn, dr as pt, vr as q, O as qn, Qt as qt, Mo as r, St as rn, m as rr, Xn as rt, bo as s, Tt as sn, _ as sr, cr as st, Ao as t, Lt as tn, d as tr, Qn as tt, Za as u, Ct as un, y as ur, Zn as ut, ma as v, It as vn, Nn as vt, pa as w, it as wn, On as wt, da as x, ut as xn, Mn as xt, ga as y, pt as yn, Pn as yt, Or as z, _e as zn, dn as zt };
3789
+ export { Hn as $, ee as $n, Vt as $t, Kr as A, Je as An, xn as At, Tr as B, Ee as Bn, pn as Bt, ha as C, ct as Cn, Tn as Ct, gi as D, rt as Dn, kn as Dt, hi as E, it as En, wn as Et, Fr as F, Pe as Fn, vn as Ft, mr as G, V as Gn, en as Gt, Sr as H, _e as Hn, fn as Ht, Nr as I, Ae as In, yn as It, fr as J, F as Jn, Jt, pr as K, B as Kn, $t as Kt, Mr as L, je as Ln, hn as Lt, zr as M, qe as Mn, Cn as Mt, Ir as N, Ue as Nn, bn as Nt, mi as O, Xe as On, Dn as Ot, Pr as P, Z as Pn, _n as Pt, Kn as Q, f as Qn, Kt as Qt, kr as R, X as Rn, mn as Rt, _a as S, ut as Sn, jn as St, ra as T, st as Tn, En as Tt, br as U, J as Un, sn as Ut, Cr as V, be as Vn, ln as Vt, hr as W, U as Wn, tn as Wt, Gn as X, O as Xn, qt as Xt, gr as Y, N as Yn, Zt as Yt, Un as Z, T as Zn, Gt as Zt, Ta as _, _t as _n, In as _t, Do as a, jt as an, w as ar, Yn as at, fa as b, dt as bn, Fn as bt, to as c, Pt as cn, D as cr, ur as ct, Xa as d, Ot as dn, g as dr, Bn as dt, zt as en, u as er, Jn as et, Ua as f, gt as fn, v as fr, zn as ft, ka as g, vt as gn, Ln as gt, Oa as h, yt as hn, Rn as ht, jo as i, Dt as in, d as ir, er as it, Wr as j, Ke as jn, Sn as jt, ai as k, $e as kn, An as kt, $a as l, xt as ln, p as lr, qn as lt, Na as m, Ft as mn, E as mr, Vn as mt, Oo as n, At as nn, M as nr, $n as nt, ko as o, Et as on, m as or, sr as ot, Ra as p, bt as pn, y as pr, dr as pt, vr as q, L as qn, Qt as qt, Mo as r, St as rn, A as rr, Xn as rt, bo as s, Tt as sn, h as sr, cr as st, Ao as t, Lt as tn, k as tr, Qn as tt, Za as u, Ct as un, _ as ur, Zn as ut, ma as v, It as vn, Nn as vt, pa as w, ot as wn, On as wt, da as x, ft as xn, Mn as xt, ga as y, pt as yn, Pn as yt, Or as z, ke as zn, dn as zt };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imfusion/web-ui",
3
- "version": "0.5.1-dev.3.g8e0a047a",
3
+ "version": "0.5.1-dev.30.gf9b152db",
4
4
  "description": "The official Web UI component library for ImFusion web apps",
5
5
  "author": "ImFusion GmbH",
6
6
  "license": "UNLICENSED",
@@ -9,10 +9,17 @@
9
9
  "access": "restricted"
10
10
  },
11
11
  "type": "module",
12
+ "engines": {
13
+ "node": ">=24"
14
+ },
15
+ "imports": {
16
+ "#/*": "./src/*",
17
+ "#/storybook/*": "./.storybook/*"
18
+ },
12
19
  "module": "./dist/index.js",
13
20
  "types": "./dist/index.d.ts",
14
21
  "bin": {
15
- "web-ui-install-skills": "./bin/install-skill.js"
22
+ "web-ui-install": "bin/install.js"
16
23
  },
17
24
  "exports": {
18
25
  ".": {
@@ -23,6 +30,10 @@
23
30
  "types": "./dist/integrations/*/index.d.ts",
24
31
  "import": "./dist/integrations/*.js"
25
32
  },
33
+ "./build/*": {
34
+ "types": "./dist/build/*/index.d.ts",
35
+ "import": "./dist/build/*.js"
36
+ },
26
37
  "./styles.css": "./dist/style.css",
27
38
  "./docgen.json": "./src/docgen/doc.gen.json",
28
39
  "./llms.txt": "./src/llms/llms.gen.txt",
@@ -36,37 +47,36 @@
36
47
  "bin"
37
48
  ],
38
49
  "scripts": {
39
- "codegen:docgen": "tsx src/docgen/gen-docgen.ts",
40
- "codegen:llms": "tsx src/llms/gen-llms.ts",
41
- "codegen:watch": "tsx watch src/codegen/run.ts",
42
- "codegen:storybook": "tsx src/codegen/run.ts --storybook",
43
- "codegen": "tsx src/codegen/run.ts",
44
- "build": "npm run codegen && rm -rf dist && vite build && npm run codegen:docgen && npm run codegen:llms",
45
50
  "dev": "tsx scripts/dev.ts",
46
51
  "dev:host": "tsx scripts/dev.ts --host",
47
52
  "dev:lib": "concurrently -n codegen,lib -c yellow,blue \"npm run codegen:watch\" \"vite build --watch\"",
48
- "typecheck": "npm run codegen && tsc -p tsconfig.lib.json --noEmit && tsc -p .storybook/tsconfig.json --noEmit",
53
+ "build": "npm run codegen && rm -rf dist && vite build && npm run codegen:docgen && npm run codegen:llms",
54
+ "build:storybook": "npm run codegen:storybook && storybook build",
55
+ "storybook": "npm run codegen:storybook && storybook dev -p 6006 --no-open",
56
+ "storybook:free-ports": "tsx scripts/free-storybook-ports.ts",
57
+ "codegen": "tsx src/codegen/run.ts",
58
+ "codegen:watch": "tsx watch src/codegen/run.ts",
59
+ "codegen:storybook": "tsx src/codegen/run.ts --storybook",
60
+ "codegen:docgen": "tsx src/docgen/gen-docgen.ts",
61
+ "codegen:llms": "tsx src/llms/gen-llms.ts",
62
+ "verify:format": "prettier --check .",
63
+ "verify:lint": "eslint . --cache --max-warnings=0",
64
+ "verify:typecheck": "npm run codegen && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.lib.json --noEmit && tsc -p .storybook/tsconfig.json --noEmit",
65
+ "verify:tests": "vitest run",
66
+ "verify:deps": "tsx scripts/check-pinned-dependencies.ts",
67
+ "verify:changelog": "tsx scripts/verify/changelog.ts",
68
+ "verify:staged": "tsx scripts/verify/staged.ts",
69
+ "verify:full": "tsx scripts/verify/full.ts && npm run verify:tests",
49
70
  "format": "prettier --write .",
50
- "format:check": "prettier --check .",
51
- "lint": "eslint . --cache --max-warnings=0",
52
- "lint:fix": "eslint . --cache --fix",
71
+ "lint": "eslint . --cache --fix",
53
72
  "lint:inspect": "npx @eslint/config-inspector@latest",
73
+ "test:unit": "vitest run --project unit",
74
+ "test:stories": "vitest run --project storybook",
75
+ "test:watch": "vitest",
54
76
  "skills:eval": "node src/llms/evals/run.mjs",
55
77
  "skills:eval:dev": "WEB_UI_SKILL_EVAL_ROOT=/private/tmp/web-ui-dev-skill-evals WEB_UI_SKILL_EVAL_RESULTS_DIR=.agents/evals/results WEB_UI_SKILL_EVAL_REPORT_PATH=.agents/evals/REPORT.md WEB_UI_SKILL_EVAL_SKILL_FAMILY=web-ui-dev WEB_UI_SKILL_EVAL_WORKSPACE_LABEL='development repository' node src/llms/evals/run.mjs --scenarios-dir .agents/evals/scenarios --setup .agents/evals/setup-env.sh",
56
78
  "skills:eval:compare": "node src/llms/evals/compare.mjs",
57
79
  "skills:eval:report": "node src/llms/evals/report.mjs",
58
- "storybook": "npm run codegen:storybook && storybook dev -p 6006 --no-open",
59
- "storybook:free-ports": "tsx scripts/free-storybook-ports.ts",
60
- "build:storybook": "npm run codegen:storybook && storybook build",
61
- "test": "vitest run",
62
- "test:unit": "vitest run --project unit",
63
- "test:stories": "vitest run --project storybook",
64
- "test:watch": "vitest",
65
- "verify:preflight": "tsx scripts/verify/full.ts",
66
- "verify:full": "npm run verify:preflight && npm run test",
67
- "worktree:create": "tsx scripts/worktrees.ts create",
68
- "worktree:close": "tsx scripts/worktrees.ts close",
69
- "worktree:discard": "tsx scripts/worktrees.ts discard",
70
80
  "knip": "knip",
71
81
  "git:config": "git config core.hooksPath .githooks && git config pull.rebase true && git config merge.ff only"
72
82
  },
@@ -124,6 +134,7 @@
124
134
  "globals": "15.15.0",
125
135
  "jiti": "2.7.0",
126
136
  "knip": "6.14.2",
137
+ "lightningcss": "1.32.0",
127
138
  "nano-staged": "1.0.2",
128
139
  "playwright": "1.60.0",
129
140
  "prettier": "3.8.3",
@@ -1194,6 +1194,333 @@
1194
1194
  }
1195
1195
  ]
1196
1196
  },
1197
+ "field": {
1198
+ "root": {
1199
+ "name": "Field.Root",
1200
+ "description": "Field.Root — groups a label, control, validation state, and supporting copy.",
1201
+ "props": [
1202
+ {
1203
+ "name": "actionsRef",
1204
+ "required": false,
1205
+ "type": "RefObject<FieldRootActions | null>",
1206
+ "defaultValue": null,
1207
+ "description": ""
1208
+ },
1209
+ {
1210
+ "name": "className",
1211
+ "required": false,
1212
+ "type": "string | ((state: FieldRootState) => string)",
1213
+ "defaultValue": null,
1214
+ "description": ""
1215
+ },
1216
+ {
1217
+ "name": "dirty",
1218
+ "required": false,
1219
+ "type": "boolean",
1220
+ "defaultValue": null,
1221
+ "description": ""
1222
+ },
1223
+ {
1224
+ "name": "disabled",
1225
+ "required": false,
1226
+ "type": "boolean",
1227
+ "defaultValue": "false",
1228
+ "description": ""
1229
+ },
1230
+ {
1231
+ "name": "invalid",
1232
+ "required": false,
1233
+ "type": "boolean",
1234
+ "defaultValue": null,
1235
+ "description": ""
1236
+ },
1237
+ {
1238
+ "name": "name",
1239
+ "required": false,
1240
+ "type": "string",
1241
+ "defaultValue": null,
1242
+ "description": ""
1243
+ },
1244
+ {
1245
+ "name": "render",
1246
+ "required": false,
1247
+ "type": "| ReactElement<\n unknown,\n string | JSXElementConstructor<any>\n >\n| ComponentRenderFn<HTMLProps, FieldRootState>",
1248
+ "defaultValue": null,
1249
+ "description": ""
1250
+ },
1251
+ {
1252
+ "name": "style",
1253
+ "required": false,
1254
+ "type": "| CSSProperties\n| ((state: FieldRootState) => CSSProperties)",
1255
+ "defaultValue": null,
1256
+ "description": ""
1257
+ },
1258
+ {
1259
+ "name": "touched",
1260
+ "required": false,
1261
+ "type": "boolean",
1262
+ "defaultValue": null,
1263
+ "description": ""
1264
+ },
1265
+ {
1266
+ "name": "validate",
1267
+ "required": false,
1268
+ "type": "(\n value: unknown,\n formValues: Record<string, any>\n) =>\n | string\n | string[]\n | Promise<string | string[] | null>\n | null",
1269
+ "defaultValue": null,
1270
+ "description": ""
1271
+ },
1272
+ {
1273
+ "name": "validationDebounceTime",
1274
+ "required": false,
1275
+ "type": "number",
1276
+ "defaultValue": "0",
1277
+ "description": ""
1278
+ },
1279
+ {
1280
+ "name": "validationMode",
1281
+ "required": false,
1282
+ "type": "FormValidationMode",
1283
+ "defaultValue": "onSubmit",
1284
+ "description": ""
1285
+ }
1286
+ ]
1287
+ },
1288
+ "subComponents": [
1289
+ {
1290
+ "name": "Field.Control",
1291
+ "description": "Field.Control — a native input control with Field labeling and validation.",
1292
+ "props": [
1293
+ {
1294
+ "name": "className",
1295
+ "required": false,
1296
+ "type": "string | ((state: FieldControlState) => string)",
1297
+ "defaultValue": null,
1298
+ "description": ""
1299
+ },
1300
+ {
1301
+ "name": "defaultValue",
1302
+ "required": false,
1303
+ "type": "string | number | readonly string[]",
1304
+ "defaultValue": null,
1305
+ "description": ""
1306
+ },
1307
+ {
1308
+ "name": "onValueChange",
1309
+ "required": false,
1310
+ "type": "(\n value: string,\n eventDetails: {\n reason: \"none\";\n event: Event;\n cancel: () => void;\n allowPropagation: () => void;\n isCanceled: boolean;\n isPropagationAllowed: boolean;\n trigger: Element;\n }\n) => void",
1311
+ "defaultValue": null,
1312
+ "description": ""
1313
+ },
1314
+ {
1315
+ "name": "render",
1316
+ "required": false,
1317
+ "type": "| ReactElement<\n unknown,\n string | JSXElementConstructor<any>\n >\n| ComponentRenderFn<HTMLProps, FieldControlState>",
1318
+ "defaultValue": null,
1319
+ "description": ""
1320
+ },
1321
+ {
1322
+ "name": "style",
1323
+ "required": false,
1324
+ "type": "| CSSProperties\n| ((state: FieldControlState) => CSSProperties)",
1325
+ "defaultValue": null,
1326
+ "description": ""
1327
+ }
1328
+ ]
1329
+ },
1330
+ {
1331
+ "name": "Field.Description",
1332
+ "description": "Field.Description — supporting information for a field.",
1333
+ "props": [
1334
+ {
1335
+ "name": "className",
1336
+ "required": false,
1337
+ "type": "| string\n| ((state: FieldDescriptionState) => string)",
1338
+ "defaultValue": null,
1339
+ "description": ""
1340
+ },
1341
+ {
1342
+ "name": "render",
1343
+ "required": false,
1344
+ "type": "| ReactElement<\n unknown,\n string | JSXElementConstructor<any>\n >\n| ComponentRenderFn<HTMLProps, FieldDescriptionState>",
1345
+ "defaultValue": null,
1346
+ "description": ""
1347
+ },
1348
+ {
1349
+ "name": "style",
1350
+ "required": false,
1351
+ "type": "| CSSProperties\n| ((state: FieldDescriptionState) => CSSProperties)",
1352
+ "defaultValue": null,
1353
+ "description": ""
1354
+ }
1355
+ ]
1356
+ },
1357
+ {
1358
+ "name": "Field.Error",
1359
+ "description": "Field.Error — an inline validation message shown when its match condition fails.",
1360
+ "props": [
1361
+ {
1362
+ "name": "className",
1363
+ "required": false,
1364
+ "type": "string | ((state: FieldErrorState) => string)",
1365
+ "defaultValue": null,
1366
+ "description": ""
1367
+ },
1368
+ {
1369
+ "name": "match",
1370
+ "required": false,
1371
+ "type": "boolean | keyof ValidityState",
1372
+ "defaultValue": null,
1373
+ "description": ""
1374
+ },
1375
+ {
1376
+ "name": "render",
1377
+ "required": false,
1378
+ "type": "| ReactElement<\n unknown,\n string | JSXElementConstructor<any>\n >\n| ComponentRenderFn<HTMLProps, FieldErrorState>",
1379
+ "defaultValue": null,
1380
+ "description": ""
1381
+ },
1382
+ {
1383
+ "name": "style",
1384
+ "required": false,
1385
+ "type": "| CSSProperties\n| ((state: FieldErrorState) => CSSProperties)",
1386
+ "defaultValue": null,
1387
+ "description": ""
1388
+ }
1389
+ ]
1390
+ },
1391
+ {
1392
+ "name": "Field.Item",
1393
+ "description": "Field.Item — groups one checkable option with its label and description.",
1394
+ "props": [
1395
+ {
1396
+ "name": "className",
1397
+ "required": false,
1398
+ "type": "string | ((state: FieldItemState) => string)",
1399
+ "defaultValue": null,
1400
+ "description": ""
1401
+ },
1402
+ {
1403
+ "name": "disabled",
1404
+ "required": false,
1405
+ "type": "boolean",
1406
+ "defaultValue": "false",
1407
+ "description": ""
1408
+ },
1409
+ {
1410
+ "name": "render",
1411
+ "required": false,
1412
+ "type": "| ReactElement<\n unknown,\n string | JSXElementConstructor<any>\n >\n| ComponentRenderFn<HTMLProps, FieldItemState>",
1413
+ "defaultValue": null,
1414
+ "description": ""
1415
+ },
1416
+ {
1417
+ "name": "style",
1418
+ "required": false,
1419
+ "type": "| CSSProperties\n| ((state: FieldItemState) => CSSProperties)",
1420
+ "defaultValue": null,
1421
+ "description": ""
1422
+ }
1423
+ ]
1424
+ },
1425
+ {
1426
+ "name": "Field.Label",
1427
+ "description": "Field.Label — an accessible label automatically associated with the control.",
1428
+ "props": [
1429
+ {
1430
+ "name": "className",
1431
+ "required": false,
1432
+ "type": "string | ((state: FieldLabelState) => string)",
1433
+ "defaultValue": null,
1434
+ "description": ""
1435
+ },
1436
+ {
1437
+ "name": "nativeLabel",
1438
+ "required": false,
1439
+ "type": "boolean",
1440
+ "defaultValue": "true",
1441
+ "description": ""
1442
+ },
1443
+ {
1444
+ "name": "render",
1445
+ "required": false,
1446
+ "type": "| ReactElement<\n unknown,\n string | JSXElementConstructor<any>\n >\n| ComponentRenderFn<HTMLProps, FieldLabelState>",
1447
+ "defaultValue": null,
1448
+ "description": ""
1449
+ },
1450
+ {
1451
+ "name": "style",
1452
+ "required": false,
1453
+ "type": "| CSSProperties\n| ((state: FieldLabelState) => CSSProperties)",
1454
+ "defaultValue": null,
1455
+ "description": ""
1456
+ }
1457
+ ]
1458
+ },
1459
+ {
1460
+ "name": "Field.Validity",
1461
+ "description": "Field.Validity — renderless access to the field validity data for custom messages.\nIts function child owns the rendered element and therefore its identity and styling.",
1462
+ "props": []
1463
+ }
1464
+ ]
1465
+ },
1466
+ "fieldset": {
1467
+ "root": {
1468
+ "name": "Fieldset.Root",
1469
+ "description": "Fieldset.Root — semantic grouping for related form controls and a shared legend.",
1470
+ "props": [
1471
+ {
1472
+ "name": "className",
1473
+ "required": false,
1474
+ "type": "string | ((state: FieldsetRootState) => string)",
1475
+ "defaultValue": null,
1476
+ "description": ""
1477
+ },
1478
+ {
1479
+ "name": "render",
1480
+ "required": false,
1481
+ "type": "| ReactElement<\n unknown,\n string | JSXElementConstructor<any>\n >\n| ComponentRenderFn<HTMLProps, FieldsetRootState>",
1482
+ "defaultValue": null,
1483
+ "description": ""
1484
+ },
1485
+ {
1486
+ "name": "style",
1487
+ "required": false,
1488
+ "type": "| CSSProperties\n| ((state: FieldsetRootState) => CSSProperties)",
1489
+ "defaultValue": null,
1490
+ "description": ""
1491
+ }
1492
+ ]
1493
+ },
1494
+ "subComponents": [
1495
+ {
1496
+ "name": "Fieldset.Legend",
1497
+ "description": "Fieldset.Legend — the accessible label for its related controls.",
1498
+ "props": [
1499
+ {
1500
+ "name": "className",
1501
+ "required": false,
1502
+ "type": "string | ((state: FieldsetLegendState) => string)",
1503
+ "defaultValue": null,
1504
+ "description": ""
1505
+ },
1506
+ {
1507
+ "name": "render",
1508
+ "required": false,
1509
+ "type": "| ReactElement<\n unknown,\n string | JSXElementConstructor<any>\n >\n| ComponentRenderFn<HTMLProps, FieldsetLegendState>",
1510
+ "defaultValue": null,
1511
+ "description": ""
1512
+ },
1513
+ {
1514
+ "name": "style",
1515
+ "required": false,
1516
+ "type": "| CSSProperties\n| ((state: FieldsetLegendState) => CSSProperties)",
1517
+ "defaultValue": null,
1518
+ "description": ""
1519
+ }
1520
+ ]
1521
+ }
1522
+ ]
1523
+ },
1197
1524
  "input": {
1198
1525
  "root": {
1199
1526
  "name": "Input",
@@ -73,6 +73,18 @@ Off-canvas panel that slides in from a screen edge. Use for mobile navigation, s
73
73
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .drawer (jq: jq '.drawer' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
74
74
  - further reading (usage/anatomy, not props): https://base-ui.com/react/components/drawer.md
75
75
 
76
+ ## Field
77
+ - category: Inputs, status: stable
78
+ Accessible field composition for a label, form control, supporting description, and inline validation message. Use it to associate a control such as Input, Checkbox, or Select with field state including valid, invalid, dirty, touched, filled, and focused.
79
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .field (jq: jq '.field' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
80
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/field.md
81
+
82
+ ## Fieldset
83
+ - category: Inputs, status: stable
84
+ Semantic grouping for related form controls with a shared legend. Also called a form group; use it to communicate a common topic and propagate disabled state without introducing a decorative container.
85
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .fieldset (jq: jq '.fieldset' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
86
+ - further reading (usage/anatomy, not props): https://base-ui.com/react/components/fieldset.md
87
+
76
88
  ## ImageDisplayOptions
77
89
  - category: Inputs, status: experimental
78
90
  A panel or toolbar of controls bound to an image dataset's display options.
@@ -2,8 +2,8 @@
2
2
  name: imf-web-ui
3
3
  description:
4
4
  "Entry point for UI work in a project that depends on @imfusion/web-ui. Decides whether guidance is needed at all, then
5
- routes to the right companion skill — component reference, UX guidance, or frontend patterns. Load when adding or editing
6
- UI in a consumer repo."
5
+ routes to the right companion skill — component reference, UX guidance, or frontend conventions. Load when adding or
6
+ editing UI in a consumer repo."
7
7
  ---
8
8
 
9
9
  # imf-web-ui
@@ -24,16 +24,17 @@ Guidance skills exist to fill gaps, not to add ceremony to clear tasks.
24
24
 
25
25
  ## Routing
26
26
 
27
- | The task at hand | Open |
28
- | ----------------------------------------------------------------------------------------------------- | ------------------------------------ |
29
- | Using a specific component; checking props, sub-components, or defaults | `imf-web-ui-components` |
30
- | First-time setup, adding a library dependency, or components rendering unstyled/broken | `imf-web-ui-setup` |
31
- | Building/reshaping a screen or flow; choosing between components; layout, density, hierarchy, states | `imf-web-ui-ux` |
32
- | Writing wrappers or custom UI; styling beyond defaults; adding files; TypeScript, naming, testing | `imf-web-ui-frontend-patterns` |
33
- | Setting up or auditing an **ImFusion** repo's tooling: formatting, linting, hooks, scripts, structure | `imf-web-ui-imfusion-frontend-setup` |
27
+ | The task at hand | Open |
28
+ | --------------------------------------------------------------------------------------------------------- | --------------------------------- |
29
+ | Using a specific component; checking props, sub-components, or defaults | `imf-web-ui-components` |
30
+ | First-time setup, adding a library dependency, or components rendering unstyled/broken | `imf-web-ui-library-setup` |
31
+ | Building/reshaping a screen or flow; choosing between components; layout, density, hierarchy, states | `imf-web-ui-ux` |
32
+ | Writing wrappers or custom UI; styling beyond defaults; adding files; TypeScript, naming, testing | `imf-web-ui-frontend-conventions` |
33
+ | Setting up or auditing an **ImFusion** repo's tooling: formatting, linting, hooks, scripts, structure | `imf-web-ui-frontend-setup` |
34
+ | Setting up or refreshing agent tooling: vendored skills, lifecycle hooks, dependency-shipped Agent Skills | `imf-web-ui-agent-setup` |
34
35
 
35
- The last row is narrow on purpose. It's for "what is this project missing?" — a question about the repo as a whole. Being
36
- asked to add one config file is just that edit; make it, and don't open a skill to do so.
36
+ The two setup rows are narrow on purpose. They're for "what is this project missing?" — a question about the repo as a whole.
37
+ Being asked to add one config file is just that edit; make it, and don't open a skill to do so.
37
38
 
38
39
  Tasks routinely span two: building a screen usually means `imf-web-ui-ux` for the shape and `imf-web-ui-components` for the
39
40
  APIs. That's normal — open both, in that order.
@@ -43,6 +44,9 @@ APIs. That's normal — open both, in that order.
43
44
  TanStack is the recommended tooling library — routing, server state, forms, tables. When a task needs one of those and the
44
45
  project has no incumbent, propose it, and read the library's own docs (`npx @tanstack/cli`) rather than working from memory.
45
46
 
47
+ Much of the suite also ships Agent Skills inside the package, reachable via TanStack Intent. Wiring that up is
48
+ `imf-web-ui-agent-setup`.
49
+
46
50
  ## When to interview the human
47
51
 
48
52
  `imf-web-ui-ux` contains a short per-feature interview. Run it **only** when both hold:
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: imf-web-ui-agent-setup
3
+ description:
4
+ "Install or update the LLM/agent tooling @imfusion/web-ui ships in a consumer repo: the vendored imf-web-ui-* skills, the
5
+ AGENTS.md fence, the agent lifecycle hooks, and the staleness wiring. Also covers reaching the Agent Skills a dependency
6
+ ships — TanStack Intent (@tanstack/intent) and its allowlist. Wraps npx web-ui-install and adds the judgment the binary
7
+ can't have — reading what the repo already registers before adding anything. Load when setting up agent tooling in a
8
+ consumer app, when skills are stale, when hooks should be installed or adapted, or when asked to set up TanStack Intent or
9
+ dependency-shipped Agent Skills. Not for project tooling (imf-web-ui-frontend-setup) or library wiring
10
+ (imf-web-ui-library-setup)."
11
+ allowed-tools: Read Bash
12
+ ---
13
+
14
+ # imf-web-ui-agent-setup
15
+
16
+ Sets up or updates the agent side of a consumer repo. The binary does the mechanics; this skill does the judgment.
17
+
18
+ ## Skills
19
+
20
+ `npx web-ui-install` installs or refreshes the vendored `imf-web-ui-*` skills (interactive target choice on first run,
21
+ remembered after; `--reconfigure` re-opens it). It also refreshes the `<!-- imf-web-ui:begin/end -->` fence in an existing
22
+ `AGENTS.md`. Stale check: `.imf-web-ui-skill-version.json` in each installed skill vs. the installed package version — older
23
+ marker means re-run the binary, never hand-diff skill contents.
24
+
25
+ ## Hooks
26
+
27
+ Three agent lifecycle hooks ship as templates in [`templates/hooks/`](templates/hooks/), registration in
28
+ [`templates/settings.json`](templates/settings.json):
29
+
30
+ - **SessionStart** — once per session: the conventions baseline is vendored, load it before writing.
31
+ - **UserPromptSubmit** — a one-line conventions reminder per prompt. Per-prompt, not per-tool-call: a PreToolUse reminder
32
+ would re-inject the same text on every edit.
33
+ - **PostToolUse** (advisory) — file-scope checks on the touched file after every Edit/Write, failures fed straight back. It
34
+ resolves the nearest package from the edited file, so a frontend nested below a monorepo root uses its own config and
35
+ dependencies. Never exits non-zero.
36
+ - **`baseline-staleness.sh`** — not registered as an agent hook; the repo's pre-commit calls it
37
+ ([`git.md`](../imf-web-ui-frontend-conventions/references/git.md), Staleness at commit time).
38
+
39
+ **Read `.claude/settings.json` before installing.** Then pick per event:
40
+
41
+ - **Nothing registered** → install as shipped: `npx web-ui-install --hooks` copies the scripts to `.agents/hooks/imf-web-ui/`
42
+ (installer-owned, refreshed wholesale) and merges the registrations without touching existing entries.
43
+ - **The repo already covers an event** (its own session reminder, its own post-edit verify) → don't stack a second hook on
44
+ it. Use the template as a starting point instead: fold the missing behaviour into the repo's existing script, or adapt the
45
+ template and register that. Surface the situation and let the human pick.
46
+
47
+ ## Assessment reference
48
+
49
+ A static frontend setup assessment checks that the complete consumer skill bundle and version markers match the declared
50
+ `@imfusion/web-ui` version; the AGENTS fence exists; SessionStart, UserPromptSubmit, and PostToolUse behavior is installed
51
+ and registered or consciously adapted; PostToolUse resolves the edited file's package and its tools in monorepos; and the
52
+ tracked pre-commit path calls `baseline-staleness.sh`. Read files and settings as text—do not run installers, hooks, or local
53
+ config queries during assessment.
54
+
55
+ ## Dependency-shipped skills
56
+
57
+ Some libraries ship Agent Skills inside their npm package; TanStack does across much of the suite.
58
+ [TanStack Intent](https://github.com/TanStack/intent) (`@tanstack/intent`) is the CLI that surfaces them — an agent holding a
59
+ dependency but not its guidance writes plausible code against a half-remembered API.
60
+
61
+ Setting it up is the project's own call, not something web-ui does on its behalf. Point it out:
62
+
63
+ > This project has TanStack dependencies that ship their own Agent Skills. `@tanstack/intent` can make them reachable — worth
64
+ > a look if you want your agent working from the library's own guidance.
65
+
66
+ Intent offers two things: a fenced instructions block in `AGENTS.md`, and a `PreToolUse` hook that blocks an edit until a
67
+ matching skill has been read. The house preference is both — the block alone is advice an agent can walk past. The hook
68
+ refuses every edit while no matching skill is loadable, so a project adopting it wants the current docs open; that sequencing
69
+ belongs to whoever runs it.
70
+
71
+ **Allowlist the whole scope.** `intent.skills` takes `@tanstack/*`. Per-package entries like `@tanstack/react-query` look
72
+ more precise and silently reach almost nothing, because the skills ship from packages the app never names directly. Exclude
73
+ `@tanstack/devtools-event-client` — it publishes skills that are noise in an app repo.
74
+
75
+ Read Intent's own docs before wiring it; it is young and moves. Whatever the project decides, guidance you didn't read is not
76
+ guidance you have: use `npx @tanstack/cli` for TanStack docs, and never guess at a skill name.
77
+
78
+ ## Not this skill
79
+
80
+ - Project tooling, docs structure, the audit checklist → `imf-web-ui-frontend-setup` (which reads this skill as its
81
+ agent-tooling assessment contract)
82
+ - Library wiring (styles import, provider) → `imf-web-ui-library-setup`
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env sh
2
+ # Advisory baseline-staleness check, meant to be called from the repo's pre-commit hook.
3
+ # Compares the installed imf-web-ui skill markers against the installed package version
4
+ # and warns on drift. Always exits 0 — staleness never blocks a commit.
5
+ PKG=node_modules/@imfusion/web-ui/package.json
6
+ [ -f "$PKG" ] || exit 0
7
+ CURRENT=$(node -p "require('./$PKG').version" 2>/dev/null) || exit 0
8
+
9
+ for marker in .agents/skills/imf-web-ui-*/.imf-web-ui-skill-version.json; do
10
+ [ -f "$marker" ] || continue
11
+ INSTALLED=$(node -p "require('./$marker').version" 2>/dev/null) || continue
12
+ if [ "$INSTALLED" != "$CURRENT" ]; then
13
+ echo "imf-web-ui skills are stale ($INSTALLED installed, package is $CURRENT) — run: npx web-ui-install"
14
+ break
15
+ fi
16
+ done
17
+ exit 0
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env sh
2
+ # PostToolUse (Edit|Write): advisory file-scope checks on the touched file. Never exits
3
+ # non-zero, so a mid-flight refactor can't trap the agent. Resolve the package from the
4
+ # edited file, not cwd or the Git root, which may belong to a parent monorepo.
5
+ FILE=$(sed -n 's/.*"file_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1)
6
+ [ -f "$FILE" ] || exit 0
7
+
8
+ FILE_DIR=$(cd "$(dirname "$FILE")" && pwd) || exit 0
9
+ FILE="$FILE_DIR/$(basename "$FILE")"
10
+ PACKAGE_ROOT=$FILE_DIR
11
+ while [ "$PACKAGE_ROOT" != "/" ] && [ ! -f "$PACKAGE_ROOT/package.json" ]; do
12
+ PACKAGE_ROOT=$(dirname "$PACKAGE_ROOT")
13
+ done
14
+ [ -f "$PACKAGE_ROOT/package.json" ] || exit 0
15
+
16
+ TOOL_ROOT=$PACKAGE_ROOT
17
+ while [ "$TOOL_ROOT" != "/" ] && [ ! -d "$TOOL_ROOT/node_modules/.bin" ]; do
18
+ TOOL_ROOT=$(dirname "$TOOL_ROOT")
19
+ done
20
+ [ -d "$TOOL_ROOT/node_modules/.bin" ] || exit 0
21
+ cd "$PACKAGE_ROOT" || exit 0
22
+
23
+ case "$FILE" in
24
+ *.ts | *.tsx | *.js | *.jsx)
25
+ [ -x "$TOOL_ROOT/node_modules/.bin/eslint" ] && "$TOOL_ROOT/node_modules/.bin/eslint" --cache "$FILE" 2>&1
26
+ ;;
27
+ esac
28
+ case "$FILE" in
29
+ *.ts | *.tsx | *.js | *.jsx | *.css | *.json | *.md)
30
+ [ -x "$TOOL_ROOT/node_modules/.bin/prettier" ] && "$TOOL_ROOT/node_modules/.bin/prettier" --check "$FILE" 2>&1
31
+ ;;
32
+ esac
33
+ exit 0