@slotted/react 0.1.0-beta.3 → 0.1.0-beta.5

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 (245) hide show
  1. package/README.md +16 -1
  2. package/dist/{accordion-D-YuMJzk.js → accordion-lCqrmQ3w.js} +43 -43
  3. package/dist/accordion.js +1 -1
  4. package/dist/{action-bar-OACchRZw.js → action-bar-ti3e6FK1.js} +1 -1
  5. package/dist/action-bar.js +1 -1
  6. package/dist/{app-shell-CmYvnu_7.js → app-shell-nnSP44OO.js} +271 -267
  7. package/dist/app-shell.js +1 -1
  8. package/dist/bin/slotted-agent-docs.mjs +297 -0
  9. package/dist/calendar-BZ6PP7Ke.js +436 -0
  10. package/dist/calendar.js +1 -1
  11. package/dist/{cascader-D1AhTyBL.js → cascader-Cn2Acpcv.js} +227 -210
  12. package/dist/cascader.js +1 -1
  13. package/dist/chart-04i6NZQA.js +968 -0
  14. package/dist/chart.js +1 -1
  15. package/dist/{checkbox-DfxFHZaU.js → checkbox-B4Sb1eXj.js} +3 -3
  16. package/dist/{checkbox-group-9sDgrV5Z.js → checkbox-group-LpGMuq9w.js} +2 -2
  17. package/dist/checkbox-group.js +1 -1
  18. package/dist/checkbox.js +1 -1
  19. package/dist/{code-block-CFHf8uTm.js → code-block-CTNiyt0U.js} +1 -1
  20. package/dist/code-block.js +1 -1
  21. package/dist/{collapsible-CGo49NNW.js → collapsible-F-K36XbF.js} +17 -17
  22. package/dist/collapsible.js +1 -1
  23. package/dist/{color-picker-CwbWzCKg.js → color-picker-BcRCeISx.js} +4 -4
  24. package/dist/color-picker.js +1 -1
  25. package/dist/{column-manager-CTtizVhm.js → column-manager-BtkYLs5G.js} +4 -4
  26. package/dist/column-manager.js +1 -1
  27. package/dist/{combobox-BVMI9lg8.js → combobox-C1D5doWM.js} +227 -198
  28. package/dist/combobox.js +1 -1
  29. package/dist/{context-menu-BuST6W94.js → context-menu-B00UIBVC.js} +1 -1
  30. package/dist/context-menu.js +1 -1
  31. package/dist/{currency-field-DD9A5U3D.js → currency-field-Dti9JFu0.js} +1 -1
  32. package/dist/currency-field.js +1 -1
  33. package/dist/{dashboard-grid-CBMP_-JV.js → dashboard-grid-CoLKLvYL.js} +1 -1
  34. package/dist/dashboard-grid.js +1 -1
  35. package/dist/{data-grid-BKaGMqIm.js → data-grid-DX95Y7mY.js} +18 -18
  36. package/dist/data-grid.js +1 -1
  37. package/dist/{data-list-oICmxGkA.js → data-list-CWYTPNm-.js} +2 -2
  38. package/dist/data-list.js +1 -1
  39. package/dist/date-field-BxEpqAPg.js +290 -0
  40. package/dist/date-field.js +1 -1
  41. package/dist/date-picker-DRk9SZp1.js +308 -0
  42. package/dist/date-picker.js +1 -1
  43. package/dist/date-range-picker-6Yz7avTS.js +483 -0
  44. package/dist/date-range-picker.js +1 -1
  45. package/dist/{datetime-field-B8TrmsDK.js → datetime-field-D2f9u6im.js} +1 -1
  46. package/dist/datetime-field.js +1 -1
  47. package/dist/datetime-picker-STqSWMkH.js +645 -0
  48. package/dist/datetime-picker.js +1 -1
  49. package/dist/datetime-range-picker-DQNQwr3K.js +1000 -0
  50. package/dist/datetime-range-picker.js +1 -1
  51. package/dist/{detail-panel-qOJiNuzr.js → detail-panel-z6WGleP4.js} +3 -3
  52. package/dist/detail-panel.js +1 -1
  53. package/dist/docs/AGENTS.snippet.md +2 -0
  54. package/dist/docs/app-shell.examples.md +1 -1
  55. package/dist/docs/app-shell.json +4 -4
  56. package/dist/docs/app-shell.md +2 -2
  57. package/dist/docs/calendar.json +7 -0
  58. package/dist/docs/calendar.md +1 -0
  59. package/dist/docs/collapsible.json +1 -1
  60. package/dist/docs/collapsible.md +1 -1
  61. package/dist/docs/date-field.json +8 -1
  62. package/dist/docs/date-field.md +2 -1
  63. package/dist/docs/date-picker.examples.md +29 -0
  64. package/dist/docs/date-picker.json +16 -1
  65. package/dist/docs/date-picker.md +2 -1
  66. package/dist/docs/guidelines/README.md +2 -2
  67. package/dist/docs/guidelines/composition.md +10 -0
  68. package/dist/docs/guidelines/index.md +3 -1
  69. package/dist/docs/guidelines/list-pages.md +12 -1
  70. package/dist/docs/guidelines/own-elements.md +1 -1
  71. package/dist/docs/page-header.json +1 -0
  72. package/dist/docs/page-header.md +1 -1
  73. package/dist/docs/page.json +1 -0
  74. package/dist/docs/page.md +1 -0
  75. package/dist/docs/select.json +1 -1
  76. package/dist/docs/select.md +1 -1
  77. package/dist/docs/skills/build-own-element/SKILL.md +6 -6
  78. package/dist/docs/skills/compose-screen/SKILL.md +13 -6
  79. package/dist/docs/skills/review-screen/SKILL.md +6 -6
  80. package/dist/docs/skills/theme-app/SKILL.md +1 -1
  81. package/dist/docs/skills/waiting-states/SKILL.md +2 -2
  82. package/dist/docs/table.json +13 -0
  83. package/dist/docs/table.md +3 -1
  84. package/dist/docs/tabs.json +22 -4
  85. package/dist/docs/tabs.md +6 -3
  86. package/dist/docs/text-field.json +1 -1
  87. package/dist/docs/text-field.md +1 -1
  88. package/dist/{entity-picker-CPDd73JR.js → entity-picker-BdySwW8F.js} +274 -256
  89. package/dist/entity-picker.js +1 -1
  90. package/dist/{event-calendar-CnF3iIZD.js → event-calendar-CiphPXdV.js} +4 -4
  91. package/dist/event-calendar.js +1 -1
  92. package/dist/{field-NJaCxl2h.js → field-BxQFpOXS.js} +1 -1
  93. package/dist/{field-group-hAzVa2O9.js → field-group-DcN_hiZN.js} +1 -1
  94. package/dist/field-group.js +1 -1
  95. package/dist/field.js +1 -1
  96. package/dist/{filter-bar-D_xDcAp2.js → filter-bar-C_dXljI_.js} +10 -10
  97. package/dist/filter-bar.js +1 -1
  98. package/dist/{hover-card-BJE5dtaQ.js → hover-card-DpVzwvDJ.js} +1 -1
  99. package/dist/hover-card.js +1 -1
  100. package/dist/{import-export-center-DpY2DGBZ.js → import-export-center-BQnMJz4g.js} +3 -3
  101. package/dist/import-export-center.js +1 -1
  102. package/dist/index.js +68 -68
  103. package/dist/{listbox-Dv856z9I.js → listbox-D0MJcAMm.js} +1 -1
  104. package/dist/listbox.js +1 -1
  105. package/dist/{markdown-CeG8mUbI.js → markdown-IiVoh6yi.js} +2 -2
  106. package/dist/markdown.js +1 -1
  107. package/dist/menu-parts-D6v_mz6O.js +809 -0
  108. package/dist/menu.js +1 -1
  109. package/dist/{menubar-b2CruimJ.js → menubar-DApIg1eR.js} +1 -1
  110. package/dist/menubar.js +1 -1
  111. package/dist/{multi-select-DQ5ds0fX.js → multi-select-B8z6ApgW.js} +286 -257
  112. package/dist/multi-select.js +1 -1
  113. package/dist/{notification-center-Sz54IziY.js → notification-center-CGEEHcRA.js} +2 -2
  114. package/dist/notification-center.js +1 -1
  115. package/dist/{number-field-BFIAmv-z.js → number-field-DXk1TAXA.js} +1 -1
  116. package/dist/number-field.js +1 -1
  117. package/dist/{otp-input-BNQhuKaT.js → otp-input-CI-kdNgx.js} +1 -1
  118. package/dist/otp-input.js +1 -1
  119. package/dist/{page-kQgLctsA.js → page-IiYXk1sz.js} +32 -32
  120. package/dist/{page-header-CWEBfMGq.js → page-header-Bn4nIGfF.js} +1 -1
  121. package/dist/page-header.js +1 -1
  122. package/dist/page.js +1 -1
  123. package/dist/{popover-Be7JWbGJ.js → popover-DEp8Bf3e.js} +186 -166
  124. package/dist/popover.js +1 -1
  125. package/dist/{prompt-composer-BxpdkTpZ.js → prompt-composer-DdcU3S3L.js} +1 -1
  126. package/dist/prompt-composer.js +1 -1
  127. package/dist/{radio-group-BaVIP9UH.js → radio-group-D8csBZ8Z.js} +2 -2
  128. package/dist/radio-group.js +1 -1
  129. package/dist/{rating-DYBQBzwB.js → rating-rI3b5zII.js} +1 -1
  130. package/dist/rating.js +1 -1
  131. package/dist/{saved-views-DlE_--Z9.js → saved-views-B3brBTD9.js} +4 -4
  132. package/dist/saved-views.js +1 -1
  133. package/dist/scroll-area-DQ_ansLu.js +112 -0
  134. package/dist/scroll-area.js +1 -1
  135. package/dist/{segmented-control-DmuOGiu6.js → segmented-control-C-PzkTtg.js} +2 -2
  136. package/dist/segmented-control.js +1 -1
  137. package/dist/{select-DOFqPy26.js → select-BUylPwpb.js} +309 -258
  138. package/dist/select.js +1 -1
  139. package/dist/{side-navigation-CBLtCzuJ.js → side-navigation-Bm-BZma1.js} +156 -140
  140. package/dist/side-navigation.js +1 -1
  141. package/dist/{slider-DTes4HLF.js → slider-fp7kyg-6.js} +1 -1
  142. package/dist/slider.js +1 -1
  143. package/dist/{split-button-CPgHiy9G.js → split-button-DKRm0j5c.js} +1 -1
  144. package/dist/split-button.js +1 -1
  145. package/dist/styles.css +1 -1
  146. package/dist/{switch-DQzuIhPX.js → switch-aVoc4C2F.js} +1 -1
  147. package/dist/switch.js +1 -1
  148. package/dist/{table-Cipi2c5X.js → table-BYEvFr4P.js} +206 -203
  149. package/dist/table.js +1 -1
  150. package/dist/tabs-HWmvOKM4.js +355 -0
  151. package/dist/tabs.js +1 -1
  152. package/dist/{tags-input-CcOkm0AW.js → tags-input-pbv6x1Pi.js} +1 -1
  153. package/dist/tags-input.js +1 -1
  154. package/dist/{text-field-DLfIZ0fk.js → text-field-CbQ6UCAP.js} +1 -1
  155. package/dist/text-field.js +1 -1
  156. package/dist/{textarea-CBJBJBi6.js → textarea-DJSfhrXH.js} +1 -1
  157. package/dist/textarea.js +1 -1
  158. package/dist/{time-field-DrhiCtUl.js → time-field-BI9n607q.js} +1 -1
  159. package/dist/time-field.js +1 -1
  160. package/dist/time-picker-D6SlQWNF.js +402 -0
  161. package/dist/time-picker.js +1 -1
  162. package/dist/time-range-picker-CcV3_45h.js +751 -0
  163. package/dist/time-range-picker.js +1 -1
  164. package/dist/{toggle-group-7iBR9Rn1.js → toggle-group-i7JPO8BM.js} +1 -1
  165. package/dist/toggle-group.js +1 -1
  166. package/dist/{toolbar-DDZpEftQ.js → toolbar-B9knmgHA.js} +1 -1
  167. package/dist/toolbar.js +1 -1
  168. package/dist/tooltip-CgjIROUy.js +410 -0
  169. package/dist/tooltip.js +1 -1
  170. package/dist/{top-navigation-e-tWMGNr.js → top-navigation-DiG2PF5W.js} +2 -2
  171. package/dist/top-navigation.js +1 -1
  172. package/dist/{transfer-CqZOTLMP.js → transfer--UOQVeKE.js} +5 -5
  173. package/dist/transfer.js +1 -1
  174. package/dist/types/accordion/accordion.d.ts.map +1 -1
  175. package/dist/types/app-shell/app-shell-parts.d.ts +6 -4
  176. package/dist/types/app-shell/app-shell-parts.d.ts.map +1 -1
  177. package/dist/types/app-shell/app-shell.d.ts.map +1 -1
  178. package/dist/types/calendar/calendar.d.ts +1 -1
  179. package/dist/types/calendar/calendar.d.ts.map +1 -1
  180. package/dist/types/calendar/calendar.types.d.ts +9 -0
  181. package/dist/types/calendar/calendar.types.d.ts.map +1 -1
  182. package/dist/types/calendar/index.d.ts +1 -1
  183. package/dist/types/calendar/index.d.ts.map +1 -1
  184. package/dist/types/cascader/cascader.d.ts.map +1 -1
  185. package/dist/types/chart/chart.d.ts.map +1 -1
  186. package/dist/types/collapsible/collapsible-parts.d.ts.map +1 -1
  187. package/dist/types/combobox/combobox-parts.d.ts.map +1 -1
  188. package/dist/types/date-field/date-field.d.ts +1 -1
  189. package/dist/types/date-field/date-field.d.ts.map +1 -1
  190. package/dist/types/date-field/date-field.types.d.ts +7 -0
  191. package/dist/types/date-field/date-field.types.d.ts.map +1 -1
  192. package/dist/types/date-picker/date-picker.d.ts +5 -1
  193. package/dist/types/date-picker/date-picker.d.ts.map +1 -1
  194. package/dist/types/date-picker/date-picker.types.d.ts +20 -2
  195. package/dist/types/date-picker/date-picker.types.d.ts.map +1 -1
  196. package/dist/types/date-picker/index.d.ts +1 -1
  197. package/dist/types/date-picker/index.d.ts.map +1 -1
  198. package/dist/types/date-range-picker/date-range-picker.d.ts.map +1 -1
  199. package/dist/types/datetime-picker/datetime-picker.d.ts.map +1 -1
  200. package/dist/types/datetime-range-picker/datetime-range-picker.d.ts.map +1 -1
  201. package/dist/types/entity-picker/entity-picker-popup.d.ts.map +1 -1
  202. package/dist/types/menu/menu-parts.d.ts.map +1 -1
  203. package/dist/types/multi-select/multi-select-parts.d.ts.map +1 -1
  204. package/dist/types/page/page.d.ts.map +1 -1
  205. package/dist/types/popover/popover-parts.d.ts.map +1 -1
  206. package/dist/types/scroll-area/scroll-area.d.ts.map +1 -1
  207. package/dist/types/select/select-items.d.ts.map +1 -1
  208. package/dist/types/select/select-parts.d.ts.map +1 -1
  209. package/dist/types/select/select.d.ts.map +1 -1
  210. package/dist/types/side-navigation/side-navigation-parts.d.ts.map +1 -1
  211. package/dist/types/stat-card/stat-card.types.d.ts +2 -2
  212. package/dist/types/stat-card/stat-card.types.d.ts.map +1 -1
  213. package/dist/types/table/index.d.ts +1 -1
  214. package/dist/types/table/index.d.ts.map +1 -1
  215. package/dist/types/table/table-content.d.ts.map +1 -1
  216. package/dist/types/table/table-defaults.d.ts.map +1 -1
  217. package/dist/types/table/table.d.ts +1 -1
  218. package/dist/types/table/table.d.ts.map +1 -1
  219. package/dist/types/table/table.types.d.ts +15 -0
  220. package/dist/types/table/table.types.d.ts.map +1 -1
  221. package/dist/types/tabs/tabs-parts.d.ts +2 -4
  222. package/dist/types/tabs/tabs-parts.d.ts.map +1 -1
  223. package/dist/types/tabs/tabs.d.ts +1 -1
  224. package/dist/types/tabs/tabs.d.ts.map +1 -1
  225. package/dist/types/tabs/tabs.types.d.ts +18 -0
  226. package/dist/types/tabs/tabs.types.d.ts.map +1 -1
  227. package/dist/types/time-picker/time-picker.d.ts.map +1 -1
  228. package/dist/types/time-range-picker/time-range-picker.d.ts.map +1 -1
  229. package/dist/types/tooltip/tooltip-parts.d.ts.map +1 -1
  230. package/dist/{upload-DjnlVR8y.js → upload-CLX5cURk.js} +1 -1
  231. package/dist/upload.js +1 -1
  232. package/package.json +10 -7
  233. package/dist/calendar-B3mio8iQ.js +0 -387
  234. package/dist/chart-O0ZhkzJe.js +0 -966
  235. package/dist/date-field-CYcN6diW.js +0 -279
  236. package/dist/date-picker-4X-_2ltN.js +0 -264
  237. package/dist/date-range-picker-CNOAtHwU.js +0 -471
  238. package/dist/datetime-picker-HDVlUhzy.js +0 -629
  239. package/dist/datetime-range-picker-IqOFJtdW.js +0 -994
  240. package/dist/menu-parts-W58pVNUt.js +0 -786
  241. package/dist/scroll-area-BriwmvYY.js +0 -111
  242. package/dist/tabs-DQ36APY-.js +0 -343
  243. package/dist/time-picker-CRQsMJbQ.js +0 -396
  244. package/dist/time-range-picker-DlZJsj1e.js +0 -745
  245. package/dist/tooltip-DbKTPe_i.js +0 -392
package/dist/app-shell.js CHANGED
@@ -1,2 +1,2 @@
1
- import { C as e, S as t, T as n, _ as r, a as i, b as a, c as o, d as s, f as c, g as l, h as u, i as d, l as f, m as p, n as m, o as h, p as g, r as _, s as v, t as y, u as b, v as x, w as S, x as C, y as w } from "./app-shell-CmYvnu_7.js";
1
+ import { C as e, S as t, T as n, _ as r, a as i, b as a, c as o, d as s, f as c, g as l, h as u, i as d, l as f, m as p, n as m, o as h, p as g, r as _, s as v, t as y, u as b, v as x, w as S, x as C, y as w } from "./app-shell-nnSP44OO.js";
2
2
  export { y as APP_SHELL_OVERLAY_AT, m as AppShell, i as AppShellActions, h as AppShellAside, v as AppShellAsideBody, o as AppShellAsideFooter, f as AppShellAsideHeader, b as AppShellAsideResizer, s as AppShellAsideToggle, c as AppShellBanner, g as AppShellBrand, p as AppShellCentre, S as AppShellDefaultsProvider, u as AppShellFooter, l as AppShellMain, r as AppShellNav, x as AppShellNavBody, w as AppShellNavFooter, a as AppShellNavHeader, C as AppShellNavRail, t as AppShellNavToggle, e as AppShellProgress, _ as useAppShell, n as useAppShellDefaults, d as useAppShellIfPresent };
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Keeps an application's agent material in step with the installed package.
4
+ *
5
+ * slotted-agent-docs instructions write --file <path> [--app-root <dir>] [--theme <name>] [--theme-css <specifier>]
6
+ * slotted-agent-docs instructions check --file <path> [same flags]
7
+ * slotted-agent-docs skills link --dir <path> [--mode link|copy]
8
+ * slotted-agent-docs skills check --dir <path>
9
+ *
10
+ * `instructions` writes the package's `AGENTS.snippet.md` into a block of the
11
+ * named file, between `<!-- slotted:begin version=… -->` and
12
+ * `<!-- slotted:end -->`; text outside the markers is never touched. `skills`
13
+ * makes `<dir>/<skill>` for each skill the package ships, as a relative link
14
+ * or as a copy. Both `check` subcommands exit 1 when the file or the directory
15
+ * differs from what the matching write would produce.
16
+ *
17
+ * The file and the directory are arguments: the command names no agent.
18
+ */
19
+ import {
20
+ cpSync,
21
+ existsSync,
22
+ lstatSync,
23
+ mkdirSync,
24
+ readFileSync,
25
+ readdirSync,
26
+ readlinkSync,
27
+ realpathSync,
28
+ rmSync,
29
+ statSync,
30
+ symlinkSync,
31
+ writeFileSync,
32
+ } from 'node:fs';
33
+ import { dirname, join, relative, resolve, sep } from 'node:path';
34
+ import { fileURLToPath } from 'node:url';
35
+ import { parseArgs } from 'node:util';
36
+
37
+ const BEGIN = /<!-- slotted:begin version=\S* -->/;
38
+ const END = '<!-- slotted:end -->';
39
+ const BASE_SENTENCE = 'Paths below are relative to the directory that holds node_modules.';
40
+
41
+ /** The package that ships this file: the nearest `package.json` named `@slotted/…` above it. */
42
+ function ownPackage() {
43
+ let dir = dirname(realpathSync(fileURLToPath(import.meta.url)));
44
+ for (;;) {
45
+ const manifest = join(dir, 'package.json');
46
+ if (existsSync(manifest)) {
47
+ const { name, version } = JSON.parse(readFileSync(manifest, 'utf8'));
48
+ if (typeof name === 'string' && name.startsWith('@slotted/')) {
49
+ const docs = ['dist/docs', 'docs'].map((path) => join(dir, path)).find(existsSync);
50
+ if (docs === undefined) fail(`${name} has no docs directory`);
51
+ return { name, version, root: dir, docs };
52
+ }
53
+ }
54
+ const parent = dirname(dir);
55
+ if (parent === dir) fail('no @slotted package above this command');
56
+ dir = parent;
57
+ }
58
+ }
59
+
60
+ function fail(message) {
61
+ process.stderr.write(`slotted-agent-docs: ${message}\n`);
62
+ process.exit(2);
63
+ }
64
+
65
+ /* ── instructions ───────────────────────────────────────────────────────── */
66
+
67
+ function renderBlock(pkg, { appRoot, theme, themeCss }) {
68
+ let snippet = readFileSync(join(pkg.docs, 'AGENTS.snippet.md'), 'utf8');
69
+ if (appRoot !== undefined) {
70
+ const prefix = appRoot.replaceAll('\\', '/').replace(/\/+$/, '') || '.';
71
+ snippet = snippet
72
+ .replace(BASE_SENTENCE, 'Paths below are relative to the directory of this file.')
73
+ .replaceAll('`node_modules/', `\`${prefix}/node_modules/`);
74
+ }
75
+ if (theme !== undefined) {
76
+ snippet = snippet.replaceAll('data-slotted-theme="default"', `data-slotted-theme="${theme}"`);
77
+ }
78
+ if (themeCss !== undefined) {
79
+ snippet = snippet.replaceAll('`@slotted/themes/default.css`', `\`${themeCss}\``);
80
+ }
81
+ if (!snippet.endsWith('\n')) snippet += '\n';
82
+ return `<!-- slotted:begin version=${pkg.version} -->\n${snippet}${END}`;
83
+ }
84
+
85
+ /** The file with the block in place: replaced where it stands, or appended. */
86
+ function withBlock(current, block) {
87
+ const begin = BEGIN.exec(current);
88
+ if (begin !== null) {
89
+ const end = current.indexOf(END, begin.index);
90
+ if (end === -1) fail('a begin marker without an end marker');
91
+ return current.slice(0, begin.index) + block + current.slice(end + END.length);
92
+ }
93
+ if (current === '') return `${block}\n`;
94
+ return `${current}${current.endsWith('\n') ? '' : '\n'}\n${block}\n`;
95
+ }
96
+
97
+ /** A unified diff of two texts, by lines, with three lines of context. */
98
+ function unifiedDiff(a, b, from, to) {
99
+ const x = a.split('\n');
100
+ const y = b.split('\n');
101
+ const lcs = Array.from({ length: x.length + 1 }, () => new Array(y.length + 1).fill(0));
102
+ for (let i = x.length - 1; i >= 0; i--)
103
+ for (let j = y.length - 1; j >= 0; j--)
104
+ lcs[i][j] = x[i] === y[j] ? lcs[i + 1][j + 1] + 1 : Math.max(lcs[i + 1][j], lcs[i][j + 1]);
105
+ const ops = [];
106
+ let i = 0;
107
+ let j = 0;
108
+ while (i < x.length || j < y.length) {
109
+ if (i < x.length && j < y.length && x[i] === y[j]) ops.push([' ', x[i++], j++]);
110
+ else if (j < y.length && (i === x.length || lcs[i][j + 1] >= lcs[i + 1][j]))
111
+ ops.push(['+', y[j++], i]);
112
+ else ops.push(['-', x[i++], j]);
113
+ }
114
+ const lines = [`--- ${from}`, `+++ ${to}`];
115
+ let k = 0;
116
+ while (k < ops.length) {
117
+ if (ops[k][0] === ' ') {
118
+ k++;
119
+ continue;
120
+ }
121
+ let start = Math.max(0, k - 3);
122
+ let stop = k;
123
+ while (stop < ops.length) {
124
+ let next = stop;
125
+ while (next < ops.length && ops[next][0] === ' ') next++;
126
+ if (next === ops.length || next - stop > 6) break;
127
+ while (next < ops.length && ops[next][0] !== ' ') next++;
128
+ stop = next;
129
+ }
130
+ stop = Math.min(ops.length, stop + 3);
131
+ const hunk = ops.slice(start, stop);
132
+ const oldStart = ops.slice(0, start).filter(([op]) => op !== '+').length + 1;
133
+ const newStart = ops.slice(0, start).filter(([op]) => op !== '-').length + 1;
134
+ const oldCount = hunk.filter(([op]) => op !== '+').length;
135
+ const newCount = hunk.filter(([op]) => op !== '-').length;
136
+ lines.push(`@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`);
137
+ for (const [op, text] of hunk) lines.push(`${op}${text}`);
138
+ k = stop;
139
+ }
140
+ return `${lines.join('\n')}\n`;
141
+ }
142
+
143
+ function instructions(action, values) {
144
+ if (values.file === undefined) fail('--file is required');
145
+ const pkg = ownPackage();
146
+ const block = renderBlock(pkg, {
147
+ appRoot: values['app-root'],
148
+ theme: values.theme,
149
+ themeCss: values['theme-css'],
150
+ });
151
+ const current = existsSync(values.file) ? readFileSync(values.file, 'utf8') : '';
152
+ const next = withBlock(current, block);
153
+ if (action === 'write') {
154
+ if (next !== current) {
155
+ mkdirSync(dirname(resolve(values.file)), { recursive: true });
156
+ writeFileSync(values.file, next);
157
+ }
158
+ return 0;
159
+ }
160
+ if (next === current) return 0;
161
+ process.stdout.write(unifiedDiff(current, next, values.file, `${values.file} (expected)`));
162
+ return 1;
163
+ }
164
+
165
+ /* ── skills ─────────────────────────────────────────────────────────────── */
166
+
167
+ /**
168
+ * The skill directories as the application sees them: through its own
169
+ * `node_modules/<package>`, whose path survives an upgrade, rather than the
170
+ * store path a package manager may resolve this file to.
171
+ */
172
+ function installedSkills(pkg) {
173
+ const docsInPackage = relative(pkg.root, pkg.docs);
174
+ let base = join(pkg.docs, 'skills');
175
+ for (let dir = process.cwd(); ; dir = dirname(dir)) {
176
+ const candidate = join(dir, 'node_modules', ...pkg.name.split('/'), docsInPackage, 'skills');
177
+ if (existsSync(candidate)) {
178
+ base = candidate;
179
+ break;
180
+ }
181
+ if (dirname(dir) === dir) break;
182
+ }
183
+ const skills = new Map();
184
+ if (!existsSync(base)) return skills;
185
+ for (const entry of readdirSync(base, { withFileTypes: true })) {
186
+ if (entry.isDirectory() && existsSync(join(base, entry.name, 'SKILL.md')))
187
+ skills.set(entry.name, join(base, entry.name));
188
+ }
189
+ return skills;
190
+ }
191
+
192
+ /** A link this command wrote: one that names the package's skills directory. */
193
+ function isOwnLink(path, pkg) {
194
+ return readlinkSync(path).split(/[\\/]/).join('/').includes(`${pkg.name}/`);
195
+ }
196
+
197
+ function sameTree(a, b) {
198
+ const list = (dir) => readdirSync(dir, { recursive: true, encoding: 'utf8' }).sort();
199
+ const left = list(a);
200
+ const right = list(b);
201
+ if (left.join('\n') !== right.join('\n')) return false;
202
+ return left.every((file) => {
203
+ const x = join(a, file);
204
+ const y = join(b, file);
205
+ if (statSync(x).isDirectory() || statSync(y).isDirectory())
206
+ return statSync(x).isDirectory() === statSync(y).isDirectory();
207
+ return readFileSync(x).equals(readFileSync(y));
208
+ });
209
+ }
210
+
211
+ function skillsLink(written, mode, pkg) {
212
+ const dir = resolve(written);
213
+ const skills = installedSkills(pkg);
214
+ if (skills.size === 0) fail(`${pkg.name} ships no skills`);
215
+ mkdirSync(dir, { recursive: true });
216
+ for (const [name, source] of skills) {
217
+ const entry = join(dir, name);
218
+ const target = relative(dir, source);
219
+ const stat = existsSync(entry) || isLink(entry) ? lstatSync(entry) : null;
220
+ if (stat !== null) {
221
+ if (mode === 'link' && stat.isSymbolicLink() && readlinkSync(entry) === target) continue;
222
+ if (mode === 'copy' && stat.isDirectory() && sameTree(entry, source)) continue;
223
+ rmSync(entry, { recursive: true, force: true });
224
+ }
225
+ if (mode === 'link') symlinkSync(target, entry, 'dir');
226
+ else cpSync(source, entry, { recursive: true });
227
+ }
228
+ /* A link to a skill the package no longer ships. */
229
+ for (const entry of readdirSync(dir)) {
230
+ const path = join(dir, entry);
231
+ if (!skills.has(entry) && isLink(path) && isOwnLink(path, pkg)) rmSync(path);
232
+ }
233
+ return 0;
234
+ }
235
+
236
+ function isLink(path) {
237
+ try {
238
+ return lstatSync(path).isSymbolicLink();
239
+ } catch {
240
+ return false;
241
+ }
242
+ }
243
+
244
+ function skillsCheck(dir, pkg) {
245
+ const skills = installedSkills(pkg);
246
+ const problems = [];
247
+ for (const [name, source] of skills) {
248
+ const entry = join(dir, name);
249
+ if (isLink(entry)) {
250
+ if (!existsSync(join(entry, 'SKILL.md'))) problems.push(`${entry}: dangling link`);
251
+ else if (realpathSync(entry) !== realpathSync(source))
252
+ problems.push(`${entry}: links to ${readlinkSync(entry)}, not the installed version`);
253
+ } else if (!existsSync(entry)) problems.push(`${entry}: missing`);
254
+ else if (!sameTree(entry, source))
255
+ problems.push(`${entry}: differs from the installed version`);
256
+ }
257
+ if (existsSync(dir)) {
258
+ for (const entry of readdirSync(dir)) {
259
+ const path = join(dir, entry);
260
+ if (!skills.has(entry) && isLink(path) && isOwnLink(path, pkg) && !existsSync(path))
261
+ problems.push(`${path}: dangling link`);
262
+ }
263
+ }
264
+ if (skills.size === 0) problems.push(`${pkg.name}: no installed skills`);
265
+ for (const problem of problems) process.stdout.write(`${problem.split(sep).join('/')}\n`);
266
+ return problems.length === 0 ? 0 : 1;
267
+ }
268
+
269
+ /* ── entry ──────────────────────────────────────────────────────────────── */
270
+
271
+ const [group, action, ...rest] = process.argv.slice(2);
272
+ const { values } = parseArgs({
273
+ args: rest,
274
+ options: {
275
+ file: { type: 'string' },
276
+ 'app-root': { type: 'string' },
277
+ theme: { type: 'string' },
278
+ 'theme-css': { type: 'string' },
279
+ dir: { type: 'string' },
280
+ mode: { type: 'string', default: 'link' },
281
+ },
282
+ });
283
+
284
+ if (group === 'instructions' && (action === 'write' || action === 'check')) {
285
+ process.exit(instructions(action, values));
286
+ } else if (group === 'skills' && (action === 'link' || action === 'check')) {
287
+ if (values.dir === undefined) fail('--dir is required');
288
+ if (values.mode !== 'link' && values.mode !== 'copy') fail('--mode is link or copy');
289
+ const pkg = ownPackage();
290
+ process.exit(
291
+ action === 'link' ? skillsLink(values.dir, values.mode, pkg) : skillsCheck(values.dir, pkg),
292
+ );
293
+ } else {
294
+ fail(
295
+ 'usage: slotted-agent-docs instructions write|check --file <path> | skills link|check --dir <path>',
296
+ );
297
+ }