@flanksource/clicky-ui 0.3.41 → 0.3.42

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 (472) hide show
  1. package/dist/ai.cjs +4 -0
  2. package/dist/ai.cjs.map +1 -1
  3. package/dist/ai.js +4 -0
  4. package/dist/ai.js.map +1 -1
  5. package/dist/comments/CommentCard.cjs +3 -1
  6. package/dist/comments/CommentCard.cjs.map +1 -1
  7. package/dist/comments/CommentCard.d.ts.map +1 -1
  8. package/dist/comments/CommentCard.js +4 -2
  9. package/dist/comments/CommentCard.js.map +1 -1
  10. package/dist/comments/CommentCardParts.cjs +16 -0
  11. package/dist/comments/CommentCardParts.cjs.map +1 -1
  12. package/dist/comments/CommentCardParts.d.ts +4 -1
  13. package/dist/comments/CommentCardParts.d.ts.map +1 -1
  14. package/dist/comments/CommentCardParts.js +16 -0
  15. package/dist/comments/CommentCardParts.js.map +1 -1
  16. package/dist/comments/comment-types.cjs.map +1 -1
  17. package/dist/comments/comment-types.d.ts +4 -0
  18. package/dist/comments/comment-types.d.ts.map +1 -1
  19. package/dist/comments/comment-types.js.map +1 -1
  20. package/dist/components/Combobox.cjs +54 -8
  21. package/dist/components/Combobox.cjs.map +1 -1
  22. package/dist/components/Combobox.d.ts.map +1 -1
  23. package/dist/components/Combobox.js +56 -10
  24. package/dist/components/Combobox.js.map +1 -1
  25. package/dist/components/ComboboxMenu.cjs +139 -113
  26. package/dist/components/ComboboxMenu.cjs.map +1 -1
  27. package/dist/components/ComboboxMenu.d.ts +3 -1
  28. package/dist/components/ComboboxMenu.d.ts.map +1 -1
  29. package/dist/components/ComboboxMenu.js +139 -113
  30. package/dist/components/ComboboxMenu.js.map +1 -1
  31. package/dist/components/ComboboxMenuTrigger.cjs +87 -0
  32. package/dist/components/ComboboxMenuTrigger.cjs.map +1 -0
  33. package/dist/components/ComboboxMenuTrigger.d.ts +23 -0
  34. package/dist/components/ComboboxMenuTrigger.d.ts.map +1 -0
  35. package/dist/components/ComboboxMenuTrigger.js +87 -0
  36. package/dist/components/ComboboxMenuTrigger.js.map +1 -0
  37. package/dist/components/JsonSchemaForm.cjs +30 -7
  38. package/dist/components/JsonSchemaForm.cjs.map +1 -1
  39. package/dist/components/JsonSchemaForm.d.ts.map +1 -1
  40. package/dist/components/JsonSchemaForm.js +30 -7
  41. package/dist/components/JsonSchemaForm.js.map +1 -1
  42. package/dist/components/SegmentedControl.cjs +20 -3
  43. package/dist/components/SegmentedControl.cjs.map +1 -1
  44. package/dist/components/SegmentedControl.d.ts +11 -0
  45. package/dist/components/SegmentedControl.d.ts.map +1 -1
  46. package/dist/components/SegmentedControl.js +21 -4
  47. package/dist/components/SegmentedControl.js.map +1 -1
  48. package/dist/components/combobox-types.d.ts +8 -0
  49. package/dist/components/combobox-types.d.ts.map +1 -1
  50. package/dist/components/json-schema-form-debug-badge.cjs +108 -0
  51. package/dist/components/json-schema-form-debug-badge.cjs.map +1 -0
  52. package/dist/components/json-schema-form-debug-badge.d.ts +10 -0
  53. package/dist/components/json-schema-form-debug-badge.d.ts.map +1 -0
  54. package/dist/components/json-schema-form-debug-badge.js +108 -0
  55. package/dist/components/json-schema-form-debug-badge.js.map +1 -0
  56. package/dist/components/json-schema-form-debug-glyph-map.cjs +129 -0
  57. package/dist/components/json-schema-form-debug-glyph-map.cjs.map +1 -0
  58. package/dist/components/json-schema-form-debug-glyph-map.d.ts +20 -0
  59. package/dist/components/json-schema-form-debug-glyph-map.d.ts.map +1 -0
  60. package/dist/components/json-schema-form-debug-glyph-map.js +129 -0
  61. package/dist/components/json-schema-form-debug-glyph-map.js.map +1 -0
  62. package/dist/components/json-schema-form-debug-glyph.cjs +13 -0
  63. package/dist/components/json-schema-form-debug-glyph.cjs.map +1 -0
  64. package/dist/components/json-schema-form-debug-glyph.d.ts +6 -0
  65. package/dist/components/json-schema-form-debug-glyph.d.ts.map +1 -0
  66. package/dist/components/json-schema-form-debug-glyph.js +13 -0
  67. package/dist/components/json-schema-form-debug-glyph.js.map +1 -0
  68. package/dist/components/json-schema-form-debug-groups.cjs +56 -0
  69. package/dist/components/json-schema-form-debug-groups.cjs.map +1 -0
  70. package/dist/components/json-schema-form-debug-groups.d.ts +8 -0
  71. package/dist/components/json-schema-form-debug-groups.d.ts.map +1 -0
  72. package/dist/components/json-schema-form-debug-groups.js +56 -0
  73. package/dist/components/json-schema-form-debug-groups.js.map +1 -0
  74. package/dist/components/json-schema-form-debug-keywords.cjs +159 -0
  75. package/dist/components/json-schema-form-debug-keywords.cjs.map +1 -0
  76. package/dist/components/json-schema-form-debug-keywords.d.ts +6 -0
  77. package/dist/components/json-schema-form-debug-keywords.d.ts.map +1 -0
  78. package/dist/components/json-schema-form-debug-keywords.js +159 -0
  79. package/dist/components/json-schema-form-debug-keywords.js.map +1 -0
  80. package/dist/components/json-schema-form-debug-listeners.cjs +102 -0
  81. package/dist/components/json-schema-form-debug-listeners.cjs.map +1 -0
  82. package/dist/components/json-schema-form-debug-listeners.d.ts +6 -0
  83. package/dist/components/json-schema-form-debug-listeners.d.ts.map +1 -0
  84. package/dist/components/json-schema-form-debug-listeners.js +102 -0
  85. package/dist/components/json-schema-form-debug-listeners.js.map +1 -0
  86. package/dist/components/json-schema-form-debug.cjs +31 -0
  87. package/dist/components/json-schema-form-debug.cjs.map +1 -0
  88. package/dist/components/json-schema-form-debug.d.ts +11 -0
  89. package/dist/components/json-schema-form-debug.d.ts.map +1 -0
  90. package/dist/components/json-schema-form-debug.js +31 -0
  91. package/dist/components/json-schema-form-debug.js.map +1 -0
  92. package/dist/components/json-schema-form-enum-choice.cjs +114 -0
  93. package/dist/components/json-schema-form-enum-choice.cjs.map +1 -0
  94. package/dist/components/json-schema-form-enum-choice.d.ts +14 -0
  95. package/dist/components/json-schema-form-enum-choice.d.ts.map +1 -0
  96. package/dist/components/json-schema-form-enum-choice.js +114 -0
  97. package/dist/components/json-schema-form-enum-choice.js.map +1 -0
  98. package/dist/components/json-schema-form-fields.cjs +3 -93
  99. package/dist/components/json-schema-form-fields.cjs.map +1 -1
  100. package/dist/components/json-schema-form-fields.d.ts.map +1 -1
  101. package/dist/components/json-schema-form-fields.js +1 -91
  102. package/dist/components/json-schema-form-fields.js.map +1 -1
  103. package/dist/components/json-schema-form-listeners.cjs +7 -1
  104. package/dist/components/json-schema-form-listeners.cjs.map +1 -1
  105. package/dist/components/json-schema-form-listeners.d.ts.map +1 -1
  106. package/dist/components/json-schema-form-listeners.js +7 -1
  107. package/dist/components/json-schema-form-listeners.js.map +1 -1
  108. package/dist/components/json-schema-form-preferences.cjs +1 -0
  109. package/dist/components/json-schema-form-preferences.cjs.map +1 -1
  110. package/dist/components/json-schema-form-preferences.d.ts +1 -0
  111. package/dist/components/json-schema-form-preferences.d.ts.map +1 -1
  112. package/dist/components/json-schema-form-preferences.js +1 -0
  113. package/dist/components/json-schema-form-preferences.js.map +1 -1
  114. package/dist/components/json-schema-form-render.cjs +21 -5
  115. package/dist/components/json-schema-form-render.cjs.map +1 -1
  116. package/dist/components/json-schema-form-render.d.ts.map +1 -1
  117. package/dist/components/json-schema-form-render.js +21 -5
  118. package/dist/components/json-schema-form-render.js.map +1 -1
  119. package/dist/components/json-schema-form-runtime-types.d.ts +1 -0
  120. package/dist/components/json-schema-form-runtime-types.d.ts.map +1 -1
  121. package/dist/components/json-schema-form-tone.cjs +12 -0
  122. package/dist/components/json-schema-form-tone.cjs.map +1 -1
  123. package/dist/components/json-schema-form-tone.js +12 -0
  124. package/dist/components/json-schema-form-tone.js.map +1 -1
  125. package/dist/components/json-schema-form-types.d.ts +1 -0
  126. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  127. package/dist/data/GraphDiagram.cjs +125 -138
  128. package/dist/data/GraphDiagram.cjs.map +1 -1
  129. package/dist/data/GraphDiagram.d.ts +30 -23
  130. package/dist/data/GraphDiagram.d.ts.map +1 -1
  131. package/dist/data/GraphDiagram.js +128 -141
  132. package/dist/data/GraphDiagram.js.map +1 -1
  133. package/dist/data/GraphDiagramEdges.cjs +208 -0
  134. package/dist/data/GraphDiagramEdges.cjs.map +1 -0
  135. package/dist/data/GraphDiagramEdges.d.ts +40 -0
  136. package/dist/data/GraphDiagramEdges.d.ts.map +1 -0
  137. package/dist/data/GraphDiagramEdges.js +208 -0
  138. package/dist/data/GraphDiagramEdges.js.map +1 -0
  139. package/dist/data/GraphDiagramNodes.cjs +142 -0
  140. package/dist/data/GraphDiagramNodes.cjs.map +1 -0
  141. package/dist/data/GraphDiagramNodes.d.ts +22 -0
  142. package/dist/data/GraphDiagramNodes.d.ts.map +1 -0
  143. package/dist/data/GraphDiagramNodes.js +142 -0
  144. package/dist/data/GraphDiagramNodes.js.map +1 -0
  145. package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs +8 -3
  146. package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs.map +1 -1
  147. package/dist/data/ai/PromptRunEditor/RuntimeRows.d.ts.map +1 -1
  148. package/dist/data/ai/PromptRunEditor/RuntimeRows.js +8 -3
  149. package/dist/data/ai/PromptRunEditor/RuntimeRows.js.map +1 -1
  150. package/dist/data/ai/PromptRunEditor/index.cjs +37 -43
  151. package/dist/data/ai/PromptRunEditor/index.cjs.map +1 -1
  152. package/dist/data/ai/PromptRunEditor/index.d.ts +3 -1
  153. package/dist/data/ai/PromptRunEditor/index.d.ts.map +1 -1
  154. package/dist/data/ai/PromptRunEditor/index.js +38 -44
  155. package/dist/data/ai/PromptRunEditor/index.js.map +1 -1
  156. package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +16 -5
  157. package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
  158. package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts +4 -1
  159. package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
  160. package/dist/data/ai/PromptRunEditor/runtimeActions.js +17 -6
  161. package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
  162. package/dist/data/ai/SessionInspector.approvals-model.cjs +12 -0
  163. package/dist/data/ai/SessionInspector.approvals-model.cjs.map +1 -1
  164. package/dist/data/ai/SessionInspector.approvals-model.d.ts +11 -2
  165. package/dist/data/ai/SessionInspector.approvals-model.d.ts.map +1 -1
  166. package/dist/data/ai/SessionInspector.approvals-model.js +12 -0
  167. package/dist/data/ai/SessionInspector.approvals-model.js.map +1 -1
  168. package/dist/data/ai/SessionInspector.approvals.cjs +25 -1
  169. package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
  170. package/dist/data/ai/SessionInspector.approvals.d.ts.map +1 -1
  171. package/dist/data/ai/SessionInspector.approvals.js +26 -2
  172. package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
  173. package/dist/data/ai/SessionInspector.summary.cjs +9 -3
  174. package/dist/data/ai/SessionInspector.summary.cjs.map +1 -1
  175. package/dist/data/ai/SessionInspector.summary.d.ts.map +1 -1
  176. package/dist/data/ai/SessionInspector.summary.js +9 -3
  177. package/dist/data/ai/SessionInspector.summary.js.map +1 -1
  178. package/dist/data/ai/SessionInspector.transcript.cjs +4 -0
  179. package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
  180. package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
  181. package/dist/data/ai/SessionInspector.transcript.js +4 -0
  182. package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
  183. package/dist/data/ai/SessionViewer.approval-body.cjs +146 -0
  184. package/dist/data/ai/SessionViewer.approval-body.cjs.map +1 -0
  185. package/dist/data/ai/SessionViewer.approval-body.d.ts +11 -0
  186. package/dist/data/ai/SessionViewer.approval-body.d.ts.map +1 -0
  187. package/dist/data/ai/SessionViewer.approval-body.js +146 -0
  188. package/dist/data/ai/SessionViewer.approval-body.js.map +1 -0
  189. package/dist/data/ai/SessionViewer.approval-forms.cjs +150 -0
  190. package/dist/data/ai/SessionViewer.approval-forms.cjs.map +1 -0
  191. package/dist/data/ai/SessionViewer.approval-forms.d.ts +23 -0
  192. package/dist/data/ai/SessionViewer.approval-forms.d.ts.map +1 -0
  193. package/dist/data/ai/SessionViewer.approval-forms.js +150 -0
  194. package/dist/data/ai/SessionViewer.approval-forms.js.map +1 -0
  195. package/dist/data/ai/SessionViewer.cjs +57 -20
  196. package/dist/data/ai/SessionViewer.cjs.map +1 -1
  197. package/dist/data/ai/SessionViewer.d.ts +13 -3
  198. package/dist/data/ai/SessionViewer.d.ts.map +1 -1
  199. package/dist/data/ai/SessionViewer.decision-controls.cjs +313 -0
  200. package/dist/data/ai/SessionViewer.decision-controls.cjs.map +1 -0
  201. package/dist/data/ai/SessionViewer.decision-controls.d.ts +43 -0
  202. package/dist/data/ai/SessionViewer.decision-controls.d.ts.map +1 -0
  203. package/dist/data/ai/SessionViewer.decision-controls.js +313 -0
  204. package/dist/data/ai/SessionViewer.decision-controls.js.map +1 -0
  205. package/dist/data/ai/SessionViewer.decision.cjs +21 -0
  206. package/dist/data/ai/SessionViewer.decision.cjs.map +1 -0
  207. package/dist/data/ai/SessionViewer.decision.d.ts +12 -0
  208. package/dist/data/ai/SessionViewer.decision.d.ts.map +1 -0
  209. package/dist/data/ai/SessionViewer.decision.js +21 -0
  210. package/dist/data/ai/SessionViewer.decision.js.map +1 -0
  211. package/dist/data/ai/SessionViewer.input.cjs +14 -0
  212. package/dist/data/ai/SessionViewer.input.cjs.map +1 -1
  213. package/dist/data/ai/SessionViewer.input.d.ts +5 -0
  214. package/dist/data/ai/SessionViewer.input.d.ts.map +1 -1
  215. package/dist/data/ai/SessionViewer.input.js +14 -0
  216. package/dist/data/ai/SessionViewer.input.js.map +1 -1
  217. package/dist/data/ai/SessionViewer.js +58 -21
  218. package/dist/data/ai/SessionViewer.js.map +1 -1
  219. package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
  220. package/dist/data/ai/SessionViewer.model.d.ts +4 -0
  221. package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
  222. package/dist/data/ai/SessionViewer.model.js.map +1 -1
  223. package/dist/data/ai/SessionViewer.rows.cjs +6 -3
  224. package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
  225. package/dist/data/ai/SessionViewer.rows.d.ts +2 -1
  226. package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
  227. package/dist/data/ai/SessionViewer.rows.js +6 -3
  228. package/dist/data/ai/SessionViewer.rows.js.map +1 -1
  229. package/dist/data/ai/SessionViewer.tool-row.cjs +29 -237
  230. package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
  231. package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
  232. package/dist/data/ai/SessionViewer.tool-row.js +27 -235
  233. package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
  234. package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
  235. package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
  236. package/dist/data/ai/SessionViewerMenu.cjs +8 -2
  237. package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
  238. package/dist/data/ai/SessionViewerMenu.d.ts +4 -1
  239. package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
  240. package/dist/data/ai/SessionViewerMenu.js +8 -2
  241. package/dist/data/ai/SessionViewerMenu.js.map +1 -1
  242. package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs +28 -17
  243. package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs.map +1 -1
  244. package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts +10 -2
  245. package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts.map +1 -1
  246. package/dist/data/ai/SpecRuntimeEditor/CommitSection.js +29 -18
  247. package/dist/data/ai/SpecRuntimeEditor/CommitSection.js.map +1 -1
  248. package/dist/data/ai/SpecRuntimeEditor/index.cjs +9 -1
  249. package/dist/data/ai/SpecRuntimeEditor/index.cjs.map +1 -1
  250. package/dist/data/ai/SpecRuntimeEditor/index.d.ts +9 -2
  251. package/dist/data/ai/SpecRuntimeEditor/index.d.ts.map +1 -1
  252. package/dist/data/ai/SpecRuntimeEditor/index.js +9 -1
  253. package/dist/data/ai/SpecRuntimeEditor/index.js.map +1 -1
  254. package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.cjs +1 -1
  255. package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.js +1 -1
  256. package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
  257. package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts +8 -2
  258. package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
  259. package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
  260. package/dist/data/ai/SpecRuntimeEditor/update.cjs +14 -6
  261. package/dist/data/ai/SpecRuntimeEditor/update.cjs.map +1 -1
  262. package/dist/data/ai/SpecRuntimeEditor/update.d.ts +1 -0
  263. package/dist/data/ai/SpecRuntimeEditor/update.d.ts.map +1 -1
  264. package/dist/data/ai/SpecRuntimeEditor/update.js +14 -6
  265. package/dist/data/ai/SpecRuntimeEditor/update.js.map +1 -1
  266. package/dist/data/ai/approval-request.cjs +75 -0
  267. package/dist/data/ai/approval-request.cjs.map +1 -0
  268. package/dist/data/ai/approval-request.d.ts +155 -0
  269. package/dist/data/ai/approval-request.d.ts.map +1 -0
  270. package/dist/data/ai/approval-request.js +75 -0
  271. package/dist/data/ai/approval-request.js.map +1 -0
  272. package/dist/data/ai/index.d.ts +3 -0
  273. package/dist/data/ai/index.d.ts.map +1 -1
  274. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs +125 -0
  275. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs.map +1 -0
  276. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts +11 -0
  277. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts.map +1 -0
  278. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js +125 -0
  279. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js.map +1 -0
  280. package/dist/data/ai/runtime-preset-menu/index.d.ts +3 -0
  281. package/dist/data/ai/runtime-preset-menu/index.d.ts.map +1 -0
  282. package/dist/data/ai/runtime-preset-menu/model.cjs +73 -0
  283. package/dist/data/ai/runtime-preset-menu/model.cjs.map +1 -0
  284. package/dist/data/ai/runtime-preset-menu/model.d.ts +13 -0
  285. package/dist/data/ai/runtime-preset-menu/model.d.ts.map +1 -0
  286. package/dist/data/ai/runtime-preset-menu/model.js +73 -0
  287. package/dist/data/ai/runtime-preset-menu/model.js.map +1 -0
  288. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs +149 -0
  289. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs.map +1 -0
  290. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts +15 -0
  291. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts.map +1 -0
  292. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js +149 -0
  293. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js.map +1 -0
  294. package/dist/data/ai/runtime-spec-fields.cjs +166 -0
  295. package/dist/data/ai/runtime-spec-fields.cjs.map +1 -0
  296. package/dist/data/ai/runtime-spec-fields.d.ts +13 -0
  297. package/dist/data/ai/runtime-spec-fields.d.ts.map +1 -0
  298. package/dist/data/ai/runtime-spec-fields.js +166 -0
  299. package/dist/data/ai/runtime-spec-fields.js.map +1 -0
  300. package/dist/data/ai/session-categories.cjs +4 -0
  301. package/dist/data/ai/session-categories.cjs.map +1 -1
  302. package/dist/data/ai/session-categories.d.ts +1 -0
  303. package/dist/data/ai/session-categories.d.ts.map +1 -1
  304. package/dist/data/ai/session-categories.js +4 -0
  305. package/dist/data/ai/session-categories.js.map +1 -1
  306. package/dist/data/ai/use-session-scroll.cjs +49 -21
  307. package/dist/data/ai/use-session-scroll.cjs.map +1 -1
  308. package/dist/data/ai/use-session-scroll.d.ts +2 -0
  309. package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
  310. package/dist/data/ai/use-session-scroll.js +49 -21
  311. package/dist/data/ai/use-session-scroll.js.map +1 -1
  312. package/dist/data/chat/Chat.runtime.cjs +1 -1
  313. package/dist/data/chat/Chat.runtime.cjs.map +1 -1
  314. package/dist/data/chat/Chat.runtime.d.ts.map +1 -1
  315. package/dist/data/chat/Chat.runtime.js +1 -1
  316. package/dist/data/chat/Chat.runtime.js.map +1 -1
  317. package/dist/data/graph-columns-layout.cjs +216 -0
  318. package/dist/data/graph-columns-layout.cjs.map +1 -0
  319. package/dist/data/graph-columns-layout.d.ts +56 -0
  320. package/dist/data/graph-columns-layout.d.ts.map +1 -0
  321. package/dist/data/graph-columns-layout.js +216 -0
  322. package/dist/data/graph-columns-layout.js.map +1 -0
  323. package/dist/data/graph-diagram-model.cjs +73 -0
  324. package/dist/data/graph-diagram-model.cjs.map +1 -0
  325. package/dist/data/graph-diagram-model.d.ts +90 -0
  326. package/dist/data/graph-diagram-model.d.ts.map +1 -0
  327. package/dist/data/graph-diagram-model.js +73 -0
  328. package/dist/data/graph-diagram-model.js.map +1 -0
  329. package/dist/data/graph-edge-routing.cjs +235 -0
  330. package/dist/data/graph-edge-routing.cjs.map +1 -0
  331. package/dist/data/graph-edge-routing.d.ts +73 -0
  332. package/dist/data/graph-edge-routing.d.ts.map +1 -0
  333. package/dist/data/graph-edge-routing.js +235 -0
  334. package/dist/data/graph-edge-routing.js.map +1 -0
  335. package/dist/data/graph-layout.cjs +0 -82
  336. package/dist/data/graph-layout.cjs.map +1 -1
  337. package/dist/data/graph-layout.d.ts +1 -28
  338. package/dist/data/graph-layout.d.ts.map +1 -1
  339. package/dist/data/graph-layout.js +1 -83
  340. package/dist/data/graph-layout.js.map +1 -1
  341. package/dist/data/har/HarPanel.cjs +129 -33
  342. package/dist/data/har/HarPanel.cjs.map +1 -1
  343. package/dist/data/har/HarPanel.d.ts +13 -1
  344. package/dist/data/har/HarPanel.d.ts.map +1 -1
  345. package/dist/data/har/HarPanel.js +130 -34
  346. package/dist/data/har/HarPanel.js.map +1 -1
  347. package/dist/data/har/fixtures.d.ts +12 -0
  348. package/dist/data/har/fixtures.d.ts.map +1 -1
  349. package/dist/data/har/types.d.ts +12 -0
  350. package/dist/data/har/types.d.ts.map +1 -1
  351. package/dist/data/runtime/RuntimeBar.cjs +67 -84
  352. package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
  353. package/dist/data/runtime/RuntimeBar.d.ts +4 -5
  354. package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
  355. package/dist/data/runtime/RuntimeBar.fields.cjs +170 -0
  356. package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -0
  357. package/dist/data/runtime/RuntimeBar.fields.d.ts +16 -0
  358. package/dist/data/runtime/RuntimeBar.fields.d.ts.map +1 -0
  359. package/dist/data/runtime/RuntimeBar.fields.js +170 -0
  360. package/dist/data/runtime/RuntimeBar.fields.js.map +1 -0
  361. package/dist/data/runtime/RuntimeBar.js +70 -87
  362. package/dist/data/runtime/RuntimeBar.js.map +1 -1
  363. package/dist/data/runtime/RuntimeBar.selection.cjs +56 -0
  364. package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -0
  365. package/dist/data/runtime/RuntimeBar.selection.d.ts +20 -0
  366. package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -0
  367. package/dist/data/runtime/RuntimeBar.selection.js +56 -0
  368. package/dist/data/runtime/RuntimeBar.selection.js.map +1 -0
  369. package/dist/data/runtime/RuntimeBarActions.cjs +10 -6
  370. package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
  371. package/dist/data/runtime/RuntimeBarActions.d.ts +8 -1
  372. package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
  373. package/dist/data/runtime/RuntimeBarActions.js +10 -6
  374. package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
  375. package/dist/data/runtime/RuntimeBarIdentity.cjs +166 -0
  376. package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -0
  377. package/dist/data/runtime/RuntimeBarIdentity.d.ts +25 -0
  378. package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -0
  379. package/dist/data/runtime/RuntimeBarIdentity.js +166 -0
  380. package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -0
  381. package/dist/data/runtime/RuntimeBarLayout.cjs +95 -0
  382. package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -0
  383. package/dist/data/runtime/RuntimeBarLayout.d.ts +9 -0
  384. package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -0
  385. package/dist/data/runtime/RuntimeBarLayout.js +95 -0
  386. package/dist/data/runtime/RuntimeBarLayout.js.map +1 -0
  387. package/dist/data/runtime/RuntimeBarSegment.cjs +25 -14
  388. package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
  389. package/dist/data/runtime/RuntimeBarSegment.d.ts +4 -0
  390. package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
  391. package/dist/data/runtime/RuntimeBarSegment.js +25 -14
  392. package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
  393. package/dist/data/runtime/RuntimeLimitInput.cjs +41 -0
  394. package/dist/data/runtime/RuntimeLimitInput.cjs.map +1 -0
  395. package/dist/data/runtime/RuntimeLimitInput.d.ts +9 -0
  396. package/dist/data/runtime/RuntimeLimitInput.d.ts.map +1 -0
  397. package/dist/data/runtime/RuntimeLimitInput.js +41 -0
  398. package/dist/data/runtime/RuntimeLimitInput.js.map +1 -0
  399. package/dist/data/runtime/use-runtime-bar-overflow.cjs +70 -0
  400. package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -0
  401. package/dist/data/runtime/use-runtime-bar-overflow.d.ts +13 -0
  402. package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -0
  403. package/dist/data/runtime/use-runtime-bar-overflow.js +70 -0
  404. package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -0
  405. package/dist/data/use-edge-focus.cjs +20 -0
  406. package/dist/data/use-edge-focus.cjs.map +1 -0
  407. package/dist/data/use-edge-focus.d.ts +23 -0
  408. package/dist/data/use-edge-focus.d.ts.map +1 -0
  409. package/dist/data/use-edge-focus.js +20 -0
  410. package/dist/data/use-edge-focus.js.map +1 -0
  411. package/dist/data/use-pan-zoom.cjs +159 -0
  412. package/dist/data/use-pan-zoom.cjs.map +1 -0
  413. package/dist/data/use-pan-zoom.d.ts +79 -0
  414. package/dist/data/use-pan-zoom.d.ts.map +1 -0
  415. package/dist/data/use-pan-zoom.js +159 -0
  416. package/dist/data/use-pan-zoom.js.map +1 -0
  417. package/dist/data/version-info.cjs +3 -3
  418. package/dist/data/version-info.js +3 -3
  419. package/dist/data.cjs +5 -1
  420. package/dist/data.cjs.map +1 -1
  421. package/dist/data.d.ts +4 -3
  422. package/dist/data.d.ts.map +1 -1
  423. package/dist/data.js +6 -2
  424. package/dist/data.js.map +1 -1
  425. package/dist/index.cjs +5 -1
  426. package/dist/index.cjs.map +1 -1
  427. package/dist/index.js +6 -2
  428. package/dist/index.js.map +1 -1
  429. package/dist/overlay/DropdownMenu.cjs +1 -0
  430. package/dist/overlay/DropdownMenu.cjs.map +1 -1
  431. package/dist/overlay/DropdownMenu.d.ts +4 -0
  432. package/dist/overlay/DropdownMenu.d.ts.map +1 -1
  433. package/dist/overlay/DropdownMenu.js +1 -0
  434. package/dist/overlay/DropdownMenu.js.map +1 -1
  435. package/dist/overlay/DropdownMenuSubmenu.cjs +31 -15
  436. package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
  437. package/dist/overlay/DropdownMenuSubmenu.d.ts.map +1 -1
  438. package/dist/overlay/DropdownMenuSubmenu.js +31 -15
  439. package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
  440. package/dist/rpc/OperationCatalog.cjs +3 -1
  441. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  442. package/dist/rpc/OperationCatalog.d.ts +3 -1
  443. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  444. package/dist/rpc/OperationCatalog.js +3 -1
  445. package/dist/rpc/OperationCatalog.js.map +1 -1
  446. package/dist/rpc/useOperationPages.cjs +6 -1
  447. package/dist/rpc/useOperationPages.cjs.map +1 -1
  448. package/dist/rpc/useOperationPages.d.ts +3 -1
  449. package/dist/rpc/useOperationPages.d.ts.map +1 -1
  450. package/dist/rpc/useOperationPages.js +6 -1
  451. package/dist/rpc/useOperationPages.js.map +1 -1
  452. package/dist/styles.css +1 -1
  453. package/package.json +1 -1
  454. package/schemas/json-schema-form.schema.json +5 -0
  455. package/dist/data/runtime/RuntimeBarCombo.cjs +0 -423
  456. package/dist/data/runtime/RuntimeBarCombo.cjs.map +0 -1
  457. package/dist/data/runtime/RuntimeBarCombo.d.ts +0 -33
  458. package/dist/data/runtime/RuntimeBarCombo.d.ts.map +0 -1
  459. package/dist/data/runtime/RuntimeBarCombo.js +0 -423
  460. package/dist/data/runtime/RuntimeBarCombo.js.map +0 -1
  461. package/dist/data/runtime/RuntimeBarLimits.cjs +0 -262
  462. package/dist/data/runtime/RuntimeBarLimits.cjs.map +0 -1
  463. package/dist/data/runtime/RuntimeBarLimits.d.ts +0 -17
  464. package/dist/data/runtime/RuntimeBarLimits.d.ts.map +0 -1
  465. package/dist/data/runtime/RuntimeBarLimits.js +0 -262
  466. package/dist/data/runtime/RuntimeBarLimits.js.map +0 -1
  467. package/dist/data/runtime/RuntimeBarSegments.cjs +0 -346
  468. package/dist/data/runtime/RuntimeBarSegments.cjs.map +0 -1
  469. package/dist/data/runtime/RuntimeBarSegments.d.ts +0 -37
  470. package/dist/data/runtime/RuntimeBarSegments.d.ts.map +0 -1
  471. package/dist/data/runtime/RuntimeBarSegments.js +0 -346
  472. package/dist/data/runtime/RuntimeBarSegments.js.map +0 -1
@@ -121,7 +121,8 @@ function JsonSchemaForm({
121
121
  render: jsonSchemaFormRender.renderApi,
122
122
  ...expressionEvaluator ? { expressionEvaluator } : {},
123
123
  ...idPrefix ? { idPrefix } : {},
124
- ...fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}
124
+ ...fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {},
125
+ ...prefs.debug ? { debug: true } : {}
125
126
  };
126
127
  const discKey = typeof resolvedSchema["x-discriminator"] === "string" ? resolvedSchema["x-discriminator"] : void 0;
127
128
  const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === "");
@@ -139,7 +140,9 @@ function JsonSchemaForm({
139
140
  onFilterChange: setFieldFilter,
140
141
  onSelectSize: (next) => applyPrefs({ ...prefs, size: next }),
141
142
  onSelectLayout: (next) => applyPrefs({ ...prefs, layoutMode: next }),
142
- onSelectSort: (next) => applyPrefs({ ...prefs, sortMode: next })
143
+ onSelectSort: (next) => applyPrefs({ ...prefs, sortMode: next }),
144
+ debug: prefs.debug === true,
145
+ onToggleDebug: () => applyPrefs({ ...prefs, debug: !prefs.debug })
143
146
  }
144
147
  ),
145
148
  title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: utils.cn("font-semibold", jsonSchemaFormSize.labelSizeClass[effectiveSize]), children: title }),
@@ -199,9 +202,11 @@ function PreferencesMenu({
199
202
  onFilterChange,
200
203
  onSelectSize,
201
204
  onSelectLayout,
202
- onSelectSort
205
+ onSelectSort,
206
+ debug,
207
+ onToggleDebug
203
208
  }) {
204
- const filterActive = fieldFilter.trim() !== "";
209
+ const filterActive = fieldFilter.trim() !== "" || debug;
205
210
  return /* @__PURE__ */ jsxRuntime.jsx(
206
211
  DropdownMenu.DropdownMenu,
207
212
  {
@@ -261,7 +266,20 @@ function PreferencesMenu({
261
266
  }
262
267
  },
263
268
  opt.value
264
- ))
269
+ )),
270
+ /* @__PURE__ */ jsxRuntime.jsx(PreferenceSection, { title: "Debug" }),
271
+ /* @__PURE__ */ jsxRuntime.jsx(
272
+ PreferenceItem,
273
+ {
274
+ role: "menuitemcheckbox",
275
+ label: "Show hidden fields & sources",
276
+ selected: debug,
277
+ onSelect: () => {
278
+ onToggleDebug();
279
+ closeMenu();
280
+ }
281
+ }
282
+ )
265
283
  ] })
266
284
  }
267
285
  );
@@ -269,12 +287,17 @@ function PreferencesMenu({
269
287
  function PreferenceSection({ title }) {
270
288
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: title });
271
289
  }
272
- function PreferenceItem({ label, selected, onSelect }) {
290
+ function PreferenceItem({
291
+ label,
292
+ selected,
293
+ onSelect,
294
+ role = "menuitemradio"
295
+ }) {
273
296
  return /* @__PURE__ */ jsxRuntime.jsxs(
274
297
  "button",
275
298
  {
276
299
  type: "button",
277
- role: "menuitemradio",
300
+ role,
278
301
  "aria-checked": selected,
279
302
  className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground",
280
303
  onClick: onSelect,
@@ -1 +1 @@
1
- {"version":3,"file":"JsonSchemaForm.cjs","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiEllipsisBold } from \"../icons\";\nimport { FormFieldFilter } from \"./json-schema-form-filter-input\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { FieldsGrid } from \"./json-schema-form-layout\";\nimport { FormErrorSummary } from \"./json-schema-form-error-display\";\nimport { unmatchedFormErrors } from \"./json-schema-form-errors\";\nimport { FormLookupProvider } from \"./FormLookupProvider\";\nimport { DiscriminatedForm } from \"./json-schema-form-discriminator\";\nimport { rehydrateRefs } from \"./json-schema-form-refs\";\nimport { renderApi, renderObjectFields } from \"./json-schema-form-render\";\nimport { applySchemaDefaults } from \"./json-schema-form-defaults\";\nimport {\n cssLength,\n DEFAULT_COLUMN_MIN_WIDTH,\n normalizeColumns,\n} from \"./json-schema-form-utils\";\nimport { DEFAULT_FORM_SIZE, fieldInnerGapClass, labelSizeClass, type FormSize } from \"./json-schema-form-size\";\nimport {\n DEFAULT_PREFERENCES_STORAGE_KEY,\n readPreferences,\n writePreferences,\n type FormPreferences,\n type LayoutMode,\n type SortMode,\n} from \"./json-schema-form-preferences\";\nimport type { FormLayout, JsonSchemaFormProps, RenderContext } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"600px\";\n\n// resolveFormLayout maps the `layout`/`inline` props plus an optional menu-driven\n// `modeOverride` to a single resolved FormLayout. An explicit `layout` sets the\n// base; `inline` is the shorthand for it; `modeOverride` (from the preferences\n// menu) wins over both but only flips the mode — width caps from `layout` are\n// preserved. Both modes fill valueMaxWidth (inline value column / stacked\n// label+value stack); the label cap only applies inline.\nfunction resolveFormLayout(\n layout: FormLayout | undefined,\n inline: boolean,\n modeOverride: LayoutMode | undefined,\n): FormLayout {\n const baseMode = layout?.mode ?? (inline ? \"inline\" : \"stacked\");\n const mode = modeOverride ?? baseMode;\n const valueMaxWidth = layout?.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH;\n // `help` is orthogonal to mode, so it survives a menu-driven mode flip.\n const help = layout?.help ? { help: layout.help } : {};\n if (mode === \"properties\") return { ...layout, mode, ...help };\n if (mode !== \"inline\") return { mode: \"stacked\", valueMaxWidth, ...help };\n return {\n mode: \"inline\",\n labelMaxWidth: layout?.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth,\n ...help,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n rootValue,\n onRootChange,\n instancePath = \"\",\n errors = [],\n readOnly = false,\n inline = false,\n layout,\n size = DEFAULT_FORM_SIZE,\n idPrefix,\n hideReadOnlyFields = false,\n hideEmpty = false,\n autoSave = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n showPreferencesMenu = true,\n showFilter,\n persistPreferences = true,\n preferencesStorageKey = DEFAULT_PREFERENCES_STORAGE_KEY,\n lookupFetcher,\n expressionEvaluator,\n applyDefaults = true,\n}: JsonSchemaFormProps) {\n // When the menu is hidden, never touch localStorage and start from an empty\n // override so behaviour is identical to before this feature existed.\n const [prefs, setPrefs] = useState<FormPreferences>(() =>\n showPreferencesMenu && persistPreferences ? readPreferences(preferencesStorageKey) : {},\n );\n // The field filter is transient view state (a \"find\" over the fields), never\n // persisted — reopening the form should never start with fields hidden.\n const [fieldFilter, setFieldFilter] = useState(\"\");\n\n const effectiveSize = prefs.size ?? size;\n const resolvedLayout = resolveFormLayout(layout, inline, prefs.layoutMode);\n const filterVisible = showFilter ?? (showPreferencesMenu && resolvedLayout.mode === \"properties\");\n // The `requiredFirst` prop sets the base sort; a menu selection overrides it.\n const effectiveSortMode = prefs.sortMode ?? (requiredFirst ? \"required-first\" : \"schema\");\n\n const applyPrefs = (next: FormPreferences) => {\n setPrefs(next);\n if (persistPreferences) writePreferences(preferencesStorageKey, next);\n };\n\n // A bundled schema (components under `$defs`, referenced by local `#/$defs`\n // pointers) is resolved once into a self-contained tree the renderer walks\n // directly; a non-bundled schema passes through untouched.\n const resolvedSchema = useMemo(() => rehydrateRefs(schema), [schema]);\n // Suppressing at the value (not only at the commit effect below) is deliberate:\n // renderObjectFields spreads `effectiveValue` when a single field changes, so a\n // render-only application would still leak the defaults on the first edit.\n const effectiveValue = useMemo(\n () => (applyDefaults ? applySchemaDefaults(resolvedSchema, value) : value),\n [applyDefaults, resolvedSchema, value],\n );\n const preExtensions = pre ?? [];\n const unmatchedErrors = useMemo(\n () =>\n unmatchedFormErrors({\n schema: resolvedSchema,\n value: effectiveValue,\n errors,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n pre: preExtensions,\n rootValue: rootValue ?? effectiveValue,\n instancePath,\n ...(hiddenKeys ? { hiddenKeys } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n }),\n [effectiveValue, errors, expressionEvaluator, fieldFilter, hiddenKeys, hideEmpty, hideReadOnlyFields, instancePath, preExtensions, readOnly, resolvedSchema, rootValue],\n );\n // Defaults are part of the submitted form value, not only presentation. This\n // is especially important for required discriminator fields whose default\n // selects an if/then branch.\n useEffect(() => {\n if (!readOnly && effectiveValue !== value) onChange(effectiveValue);\n }, [effectiveValue, onChange, readOnly, value]);\n\n const ctx: RenderContext = {\n readOnly,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n autoSave,\n layout: resolvedLayout,\n size: effectiveSize,\n sortMode: effectiveSortMode,\n pre: preExtensions,\n post: post ?? [],\n rootValue: rootValue ?? effectiveValue,\n onRootChange: onRootChange ?? onChange,\n instancePath,\n errors,\n depth: 0,\n render: renderApi,\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n ...(idPrefix ? { idPrefix } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n };\n // A schema may name a discriminator property whose value selects a \"kind\"; the\n // form then runs a two-phase pick-then-fill flow (see DiscriminatedForm).\n const discKey = typeof resolvedSchema[\"x-discriminator\"] === \"string\" ? resolvedSchema[\"x-discriminator\"] : undefined;\n const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === \"\");\n\n const objectRows = discKey\n ? null\n : renderObjectFields(resolvedSchema, effectiveValue, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n const noMatches = objectRows != null && objectRows.length === 0 && fieldFilter.trim() !== \"\";\n\n return (\n <FormLookupProvider {...(lookupFetcher ? { fetcher: lookupFetcher } : {})}>\n <div data-json-schema-form className={cn(\"relative flex flex-col\", fieldInnerGapClass[effectiveSize])}>\n {showPreferencesMenu && !inPickerPhase && (\n <PreferencesMenu\n size={effectiveSize}\n layoutMode={resolvedLayout.mode}\n sortMode={effectiveSortMode}\n fieldFilter={fieldFilter}\n filterInMenu={!filterVisible}\n onFilterChange={setFieldFilter}\n onSelectSize={(next) => applyPrefs({ ...prefs, size: next })}\n onSelectLayout={(next) => applyPrefs({ ...prefs, layoutMode: next })}\n onSelectSort={(next) => applyPrefs({ ...prefs, sortMode: next })}\n />\n )}\n {title && <h3 className={cn(\"font-semibold\", labelSizeClass[effectiveSize])}>{title}</h3>}\n {filterVisible && !inPickerPhase && (\n <div className=\"max-w-md pr-9\">\n <FormFieldFilter value={fieldFilter} onChange={setFieldFilter} />\n </div>\n )}\n <FormErrorSummary errors={unmatchedErrors} />\n <FieldsGrid\n layout={resolvedLayout}\n size={effectiveSize}\n columns={normalizeColumns(resolvedSchema[\"x-columns\"])}\n columnMinWidth={cssLength(resolvedSchema[\"x-column-min-width\"], DEFAULT_COLUMN_MIN_WIDTH)}\n {...(typeof resolvedSchema[\"x-columns-max-width\"] === \"string\"\n ? { columnsMaxWidth: resolvedSchema[\"x-columns-max-width\"] }\n : {})}\n {...(typeof resolvedSchema[\"x-classes\"] === \"string\" ? { className: resolvedSchema[\"x-classes\"] } : {})}\n >\n {discKey ? (\n <DiscriminatedForm\n schema={resolvedSchema}\n value={effectiveValue}\n onChange={onChange}\n ctx={ctx}\n discKey={discKey}\n />\n ) : (\n objectRows\n )}\n </FieldsGrid>\n {noMatches && (\n <p className={cn(\"text-muted-foreground\", labelSizeClass[effectiveSize])}>\n No fields match “{fieldFilter.trim()}”.\n </p>\n )}\n </div>\n </FormLookupProvider>\n );\n}\n\nconst SIZE_OPTIONS: { value: FormSize; label: string }[] = [\n { value: \"xs\", label: \"Extra small\" },\n { value: \"sm\", label: \"Small\" },\n { value: \"md\", label: \"Medium\" },\n { value: \"lg\", label: \"Large\" },\n { value: \"xl\", label: \"Extra large\" },\n];\n\nconst LAYOUT_OPTIONS: { value: LayoutMode; label: string }[] = [\n { value: \"stacked\", label: \"Stacked\" },\n { value: \"inline\", label: \"Inline\" },\n { value: \"properties\", label: \"Properties\" },\n];\n\nconst SORT_OPTIONS: { value: SortMode; label: string }[] = [\n { value: \"schema\", label: \"Schema order\" },\n { value: \"required-first\", label: \"Required first\" },\n { value: \"priority\", label: \"Required & filled first\" },\n];\n\n// PreferencesMenu is the compact top-right ellipsis menu controlling this form's\n// size, layout, sort, and a live field filter. Selecting an option fires the\n// matching callback and closes the menu; typing in the filter updates fields\n// live without closing. The parent decides whether to persist.\nfunction PreferencesMenu({\n size,\n layoutMode,\n sortMode,\n fieldFilter,\n filterInMenu,\n onFilterChange,\n onSelectSize,\n onSelectLayout,\n onSelectSort,\n}: {\n size: FormSize;\n layoutMode: LayoutMode;\n sortMode: SortMode;\n fieldFilter: string;\n filterInMenu: boolean;\n onFilterChange: (value: string) => void;\n onSelectSize: (size: FormSize) => void;\n onSelectLayout: (mode: LayoutMode) => void;\n onSelectSort: (mode: SortMode) => void;\n}) {\n const filterActive = fieldFilter.trim() !== \"\";\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Form display options\"\n className=\"absolute right-0 top-0 z-10\"\n trigger={\n <button\n type=\"button\"\n aria-label=\"Form display options\"\n aria-haspopup=\"menu\"\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n filterActive ? \"text-primary\" : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon icon={UiEllipsisBold} className=\"text-lg\" />\n </button>\n }\n >\n {(closeMenu) => (\n <>\n {filterInMenu && <div className=\"px-2 pb-1.5 pt-1\">\n <FormFieldFilter value={fieldFilter} onChange={onFilterChange} />\n </div>}\n <PreferenceSection title=\"Size\" />\n {SIZE_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === size}\n onSelect={() => {\n onSelectSize(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Layout\" />\n {LAYOUT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === layoutMode}\n onSelect={() => {\n onSelectLayout(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Sort\" />\n {SORT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === sortMode}\n onSelect={() => {\n onSelectSort(opt.value);\n closeMenu();\n }}\n />\n ))}\n </>\n )}\n </DropdownMenu>\n );\n}\n\nfunction PreferenceSection({ title }: { title: string }) {\n return (\n <div className=\"px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {title}\n </div>\n );\n}\n\nfunction PreferenceItem({ label, selected, onSelect }: { label: string; selected: boolean; onSelect: () => void }) {\n return (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={selected}\n className=\"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground\"\n onClick={onSelect}\n >\n <span className=\"flex w-3.5 shrink-0 justify-center\">\n {selected && <Icon icon={UiCheck} className=\"text-xs\" />}\n </span>\n {label}\n </button>\n );\n}\n"],"names":["DEFAULT_FORM_SIZE","DEFAULT_PREFERENCES_STORAGE_KEY","useState","readPreferences","writePreferences","useMemo","rehydrateRefs","applySchemaDefaults","unmatchedFormErrors","useEffect","renderApi","renderObjectFields","jsx","FormLookupProvider","cn","fieldInnerGapClass","labelSizeClass","FormFieldFilter","FormErrorSummary","FieldsGrid","normalizeColumns","cssLength","DEFAULT_COLUMN_MIN_WIDTH","DiscriminatedForm","DropdownMenu","Icon","UiEllipsisBold","jsxs","Fragment","UiCheck"],"mappings":"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"}
1
+ {"version":3,"file":"JsonSchemaForm.cjs","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiEllipsisBold } from \"../icons\";\nimport { FormFieldFilter } from \"./json-schema-form-filter-input\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { FieldsGrid } from \"./json-schema-form-layout\";\nimport { FormErrorSummary } from \"./json-schema-form-error-display\";\nimport { unmatchedFormErrors } from \"./json-schema-form-errors\";\nimport { FormLookupProvider } from \"./FormLookupProvider\";\nimport { DiscriminatedForm } from \"./json-schema-form-discriminator\";\nimport { rehydrateRefs } from \"./json-schema-form-refs\";\nimport { renderApi, renderObjectFields } from \"./json-schema-form-render\";\nimport { applySchemaDefaults } from \"./json-schema-form-defaults\";\nimport {\n cssLength,\n DEFAULT_COLUMN_MIN_WIDTH,\n normalizeColumns,\n} from \"./json-schema-form-utils\";\nimport { DEFAULT_FORM_SIZE, fieldInnerGapClass, labelSizeClass, type FormSize } from \"./json-schema-form-size\";\nimport {\n DEFAULT_PREFERENCES_STORAGE_KEY,\n readPreferences,\n writePreferences,\n type FormPreferences,\n type LayoutMode,\n type SortMode,\n} from \"./json-schema-form-preferences\";\nimport type { FormLayout, JsonSchemaFormProps, RenderContext } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"600px\";\n\n// resolveFormLayout maps the `layout`/`inline` props plus an optional menu-driven\n// `modeOverride` to a single resolved FormLayout. An explicit `layout` sets the\n// base; `inline` is the shorthand for it; `modeOverride` (from the preferences\n// menu) wins over both but only flips the mode — width caps from `layout` are\n// preserved. Both modes fill valueMaxWidth (inline value column / stacked\n// label+value stack); the label cap only applies inline.\nfunction resolveFormLayout(\n layout: FormLayout | undefined,\n inline: boolean,\n modeOverride: LayoutMode | undefined,\n): FormLayout {\n const baseMode = layout?.mode ?? (inline ? \"inline\" : \"stacked\");\n const mode = modeOverride ?? baseMode;\n const valueMaxWidth = layout?.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH;\n // `help` is orthogonal to mode, so it survives a menu-driven mode flip.\n const help = layout?.help ? { help: layout.help } : {};\n if (mode === \"properties\") return { ...layout, mode, ...help };\n if (mode !== \"inline\") return { mode: \"stacked\", valueMaxWidth, ...help };\n return {\n mode: \"inline\",\n labelMaxWidth: layout?.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth,\n ...help,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n rootValue,\n onRootChange,\n instancePath = \"\",\n errors = [],\n readOnly = false,\n inline = false,\n layout,\n size = DEFAULT_FORM_SIZE,\n idPrefix,\n hideReadOnlyFields = false,\n hideEmpty = false,\n autoSave = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n showPreferencesMenu = true,\n showFilter,\n persistPreferences = true,\n preferencesStorageKey = DEFAULT_PREFERENCES_STORAGE_KEY,\n lookupFetcher,\n expressionEvaluator,\n applyDefaults = true,\n}: JsonSchemaFormProps) {\n // When the menu is hidden, never touch localStorage and start from an empty\n // override so behaviour is identical to before this feature existed.\n const [prefs, setPrefs] = useState<FormPreferences>(() =>\n showPreferencesMenu && persistPreferences ? readPreferences(preferencesStorageKey) : {},\n );\n // The field filter is transient view state (a \"find\" over the fields), never\n // persisted — reopening the form should never start with fields hidden.\n const [fieldFilter, setFieldFilter] = useState(\"\");\n\n const effectiveSize = prefs.size ?? size;\n const resolvedLayout = resolveFormLayout(layout, inline, prefs.layoutMode);\n const filterVisible = showFilter ?? (showPreferencesMenu && resolvedLayout.mode === \"properties\");\n // The `requiredFirst` prop sets the base sort; a menu selection overrides it.\n const effectiveSortMode = prefs.sortMode ?? (requiredFirst ? \"required-first\" : \"schema\");\n\n const applyPrefs = (next: FormPreferences) => {\n setPrefs(next);\n if (persistPreferences) writePreferences(preferencesStorageKey, next);\n };\n\n // A bundled schema (components under `$defs`, referenced by local `#/$defs`\n // pointers) is resolved once into a self-contained tree the renderer walks\n // directly; a non-bundled schema passes through untouched.\n const resolvedSchema = useMemo(() => rehydrateRefs(schema), [schema]);\n // Suppressing at the value (not only at the commit effect below) is deliberate:\n // renderObjectFields spreads `effectiveValue` when a single field changes, so a\n // render-only application would still leak the defaults on the first edit.\n const effectiveValue = useMemo(\n () => (applyDefaults ? applySchemaDefaults(resolvedSchema, value) : value),\n [applyDefaults, resolvedSchema, value],\n );\n const preExtensions = pre ?? [];\n const unmatchedErrors = useMemo(\n () =>\n unmatchedFormErrors({\n schema: resolvedSchema,\n value: effectiveValue,\n errors,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n pre: preExtensions,\n rootValue: rootValue ?? effectiveValue,\n instancePath,\n ...(hiddenKeys ? { hiddenKeys } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n }),\n [effectiveValue, errors, expressionEvaluator, fieldFilter, hiddenKeys, hideEmpty, hideReadOnlyFields, instancePath, preExtensions, readOnly, resolvedSchema, rootValue],\n );\n // Defaults are part of the submitted form value, not only presentation. This\n // is especially important for required discriminator fields whose default\n // selects an if/then branch.\n useEffect(() => {\n if (!readOnly && effectiveValue !== value) onChange(effectiveValue);\n }, [effectiveValue, onChange, readOnly, value]);\n\n const ctx: RenderContext = {\n readOnly,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n autoSave,\n layout: resolvedLayout,\n size: effectiveSize,\n sortMode: effectiveSortMode,\n pre: preExtensions,\n post: post ?? [],\n rootValue: rootValue ?? effectiveValue,\n onRootChange: onRootChange ?? onChange,\n instancePath,\n errors,\n depth: 0,\n render: renderApi,\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n ...(idPrefix ? { idPrefix } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(prefs.debug ? { debug: true } : {}),\n };\n // A schema may name a discriminator property whose value selects a \"kind\"; the\n // form then runs a two-phase pick-then-fill flow (see DiscriminatedForm).\n const discKey = typeof resolvedSchema[\"x-discriminator\"] === \"string\" ? resolvedSchema[\"x-discriminator\"] : undefined;\n const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === \"\");\n\n const objectRows = discKey\n ? null\n : renderObjectFields(resolvedSchema, effectiveValue, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n const noMatches = objectRows != null && objectRows.length === 0 && fieldFilter.trim() !== \"\";\n\n return (\n <FormLookupProvider {...(lookupFetcher ? { fetcher: lookupFetcher } : {})}>\n <div data-json-schema-form className={cn(\"relative flex flex-col\", fieldInnerGapClass[effectiveSize])}>\n {showPreferencesMenu && !inPickerPhase && (\n <PreferencesMenu\n size={effectiveSize}\n layoutMode={resolvedLayout.mode}\n sortMode={effectiveSortMode}\n fieldFilter={fieldFilter}\n filterInMenu={!filterVisible}\n onFilterChange={setFieldFilter}\n onSelectSize={(next) => applyPrefs({ ...prefs, size: next })}\n onSelectLayout={(next) => applyPrefs({ ...prefs, layoutMode: next })}\n onSelectSort={(next) => applyPrefs({ ...prefs, sortMode: next })}\n debug={prefs.debug === true}\n onToggleDebug={() => applyPrefs({ ...prefs, debug: !prefs.debug })}\n />\n )}\n {title && <h3 className={cn(\"font-semibold\", labelSizeClass[effectiveSize])}>{title}</h3>}\n {filterVisible && !inPickerPhase && (\n <div className=\"max-w-md pr-9\">\n <FormFieldFilter value={fieldFilter} onChange={setFieldFilter} />\n </div>\n )}\n <FormErrorSummary errors={unmatchedErrors} />\n <FieldsGrid\n layout={resolvedLayout}\n size={effectiveSize}\n columns={normalizeColumns(resolvedSchema[\"x-columns\"])}\n columnMinWidth={cssLength(resolvedSchema[\"x-column-min-width\"], DEFAULT_COLUMN_MIN_WIDTH)}\n {...(typeof resolvedSchema[\"x-columns-max-width\"] === \"string\"\n ? { columnsMaxWidth: resolvedSchema[\"x-columns-max-width\"] }\n : {})}\n {...(typeof resolvedSchema[\"x-classes\"] === \"string\" ? { className: resolvedSchema[\"x-classes\"] } : {})}\n >\n {discKey ? (\n <DiscriminatedForm\n schema={resolvedSchema}\n value={effectiveValue}\n onChange={onChange}\n ctx={ctx}\n discKey={discKey}\n />\n ) : (\n objectRows\n )}\n </FieldsGrid>\n {noMatches && (\n <p className={cn(\"text-muted-foreground\", labelSizeClass[effectiveSize])}>\n No fields match “{fieldFilter.trim()}”.\n </p>\n )}\n </div>\n </FormLookupProvider>\n );\n}\n\nconst SIZE_OPTIONS: { value: FormSize; label: string }[] = [\n { value: \"xs\", label: \"Extra small\" },\n { value: \"sm\", label: \"Small\" },\n { value: \"md\", label: \"Medium\" },\n { value: \"lg\", label: \"Large\" },\n { value: \"xl\", label: \"Extra large\" },\n];\n\nconst LAYOUT_OPTIONS: { value: LayoutMode; label: string }[] = [\n { value: \"stacked\", label: \"Stacked\" },\n { value: \"inline\", label: \"Inline\" },\n { value: \"properties\", label: \"Properties\" },\n];\n\nconst SORT_OPTIONS: { value: SortMode; label: string }[] = [\n { value: \"schema\", label: \"Schema order\" },\n { value: \"required-first\", label: \"Required first\" },\n { value: \"priority\", label: \"Required & filled first\" },\n];\n\n// PreferencesMenu is the compact top-right ellipsis menu controlling this form's\n// size, layout, sort, and a live field filter. Selecting an option fires the\n// matching callback and closes the menu; typing in the filter updates fields\n// live without closing. The parent decides whether to persist.\nfunction PreferencesMenu({\n size,\n layoutMode,\n sortMode,\n fieldFilter,\n filterInMenu,\n onFilterChange,\n onSelectSize,\n onSelectLayout,\n onSelectSort,\n debug,\n onToggleDebug,\n}: {\n size: FormSize;\n layoutMode: LayoutMode;\n sortMode: SortMode;\n fieldFilter: string;\n filterInMenu: boolean;\n onFilterChange: (value: string) => void;\n onSelectSize: (size: FormSize) => void;\n onSelectLayout: (mode: LayoutMode) => void;\n onSelectSort: (mode: SortMode) => void;\n debug: boolean;\n onToggleDebug: () => void;\n}) {\n const filterActive = fieldFilter.trim() !== \"\" || debug;\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Form display options\"\n className=\"absolute right-0 top-0 z-10\"\n trigger={\n <button\n type=\"button\"\n aria-label=\"Form display options\"\n aria-haspopup=\"menu\"\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n filterActive ? \"text-primary\" : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon icon={UiEllipsisBold} className=\"text-lg\" />\n </button>\n }\n >\n {(closeMenu) => (\n <>\n {filterInMenu && <div className=\"px-2 pb-1.5 pt-1\">\n <FormFieldFilter value={fieldFilter} onChange={onFilterChange} />\n </div>}\n <PreferenceSection title=\"Size\" />\n {SIZE_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === size}\n onSelect={() => {\n onSelectSize(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Layout\" />\n {LAYOUT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === layoutMode}\n onSelect={() => {\n onSelectLayout(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Sort\" />\n {SORT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === sortMode}\n onSelect={() => {\n onSelectSort(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Debug\" />\n <PreferenceItem\n role=\"menuitemcheckbox\"\n label=\"Show hidden fields & sources\"\n selected={debug}\n onSelect={() => {\n onToggleDebug();\n closeMenu();\n }}\n />\n </>\n )}\n </DropdownMenu>\n );\n}\n\nfunction PreferenceSection({ title }: { title: string }) {\n return (\n <div className=\"px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {title}\n </div>\n );\n}\n\nfunction PreferenceItem({\n label,\n selected,\n onSelect,\n role = \"menuitemradio\",\n}: {\n label: string;\n selected: boolean;\n onSelect: () => void;\n role?: \"menuitemradio\" | \"menuitemcheckbox\";\n}) {\n return (\n <button\n type=\"button\"\n role={role}\n aria-checked={selected}\n className=\"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground\"\n onClick={onSelect}\n >\n <span className=\"flex w-3.5 shrink-0 justify-center\">\n {selected && <Icon icon={UiCheck} className=\"text-xs\" />}\n </span>\n {label}\n </button>\n );\n}\n"],"names":["DEFAULT_FORM_SIZE","DEFAULT_PREFERENCES_STORAGE_KEY","useState","readPreferences","writePreferences","useMemo","rehydrateRefs","applySchemaDefaults","unmatchedFormErrors","useEffect","renderApi","renderObjectFields","jsx","FormLookupProvider","cn","fieldInnerGapClass","labelSizeClass","FormFieldFilter","FormErrorSummary","FieldsGrid","normalizeColumns","cssLength","DEFAULT_COLUMN_MIN_WIDTH","DiscriminatedForm","DropdownMenu","Icon","UiEllipsisBold","jsxs","Fragment","UiCheck"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"JsonSchemaForm.d.ts","sourceRoot":"","sources":["../../src/components/JsonSchemaForm.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAc,mBAAmB,EAAiB,MAAM,0BAA0B,CAAC;AAoC/F,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,YAAiB,EACjB,MAAW,EACX,QAAgB,EAChB,MAAc,EACd,MAAM,EACN,IAAwB,EACxB,QAAQ,EACR,kBAA0B,EAC1B,SAAiB,EACjB,QAAgB,EAChB,UAAU,EACV,aAAqB,EACrB,KAAK,EACL,GAAG,EACH,IAAI,EACJ,mBAA0B,EAC1B,UAAU,EACV,kBAAyB,EACzB,qBAAuD,EACvD,aAAa,EACb,mBAAmB,EACnB,aAAoB,GACrB,EAAE,mBAAmB,+BA8IrB"}
1
+ {"version":3,"file":"JsonSchemaForm.d.ts","sourceRoot":"","sources":["../../src/components/JsonSchemaForm.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAc,mBAAmB,EAAiB,MAAM,0BAA0B,CAAC;AAoC/F,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,YAAiB,EACjB,MAAW,EACX,QAAgB,EAChB,MAAc,EACd,MAAM,EACN,IAAwB,EACxB,QAAQ,EACR,kBAA0B,EAC1B,SAAiB,EACjB,QAAgB,EAChB,UAAU,EACV,aAAqB,EACrB,KAAK,EACL,GAAG,EACH,IAAI,EACJ,mBAA0B,EAC1B,UAAU,EACV,kBAAyB,EACzB,qBAAuD,EACvD,aAAa,EACb,mBAAmB,EACnB,aAAoB,GACrB,EAAE,mBAAmB,+BAiJrB"}
@@ -119,7 +119,8 @@ function JsonSchemaForm({
119
119
  render: renderApi,
120
120
  ...expressionEvaluator ? { expressionEvaluator } : {},
121
121
  ...idPrefix ? { idPrefix } : {},
122
- ...fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}
122
+ ...fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {},
123
+ ...prefs.debug ? { debug: true } : {}
123
124
  };
124
125
  const discKey = typeof resolvedSchema["x-discriminator"] === "string" ? resolvedSchema["x-discriminator"] : void 0;
125
126
  const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === "");
@@ -137,7 +138,9 @@ function JsonSchemaForm({
137
138
  onFilterChange: setFieldFilter,
138
139
  onSelectSize: (next) => applyPrefs({ ...prefs, size: next }),
139
140
  onSelectLayout: (next) => applyPrefs({ ...prefs, layoutMode: next }),
140
- onSelectSort: (next) => applyPrefs({ ...prefs, sortMode: next })
141
+ onSelectSort: (next) => applyPrefs({ ...prefs, sortMode: next }),
142
+ debug: prefs.debug === true,
143
+ onToggleDebug: () => applyPrefs({ ...prefs, debug: !prefs.debug })
141
144
  }
142
145
  ),
143
146
  title && /* @__PURE__ */ jsx("h3", { className: cn("font-semibold", labelSizeClass[effectiveSize]), children: title }),
@@ -197,9 +200,11 @@ function PreferencesMenu({
197
200
  onFilterChange,
198
201
  onSelectSize,
199
202
  onSelectLayout,
200
- onSelectSort
203
+ onSelectSort,
204
+ debug,
205
+ onToggleDebug
201
206
  }) {
202
- const filterActive = fieldFilter.trim() !== "";
207
+ const filterActive = fieldFilter.trim() !== "" || debug;
203
208
  return /* @__PURE__ */ jsx(
204
209
  DropdownMenu,
205
210
  {
@@ -259,7 +264,20 @@ function PreferencesMenu({
259
264
  }
260
265
  },
261
266
  opt.value
262
- ))
267
+ )),
268
+ /* @__PURE__ */ jsx(PreferenceSection, { title: "Debug" }),
269
+ /* @__PURE__ */ jsx(
270
+ PreferenceItem,
271
+ {
272
+ role: "menuitemcheckbox",
273
+ label: "Show hidden fields & sources",
274
+ selected: debug,
275
+ onSelect: () => {
276
+ onToggleDebug();
277
+ closeMenu();
278
+ }
279
+ }
280
+ )
263
281
  ] })
264
282
  }
265
283
  );
@@ -267,12 +285,17 @@ function PreferencesMenu({
267
285
  function PreferenceSection({ title }) {
268
286
  return /* @__PURE__ */ jsx("div", { className: "px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: title });
269
287
  }
270
- function PreferenceItem({ label, selected, onSelect }) {
288
+ function PreferenceItem({
289
+ label,
290
+ selected,
291
+ onSelect,
292
+ role = "menuitemradio"
293
+ }) {
271
294
  return /* @__PURE__ */ jsxs(
272
295
  "button",
273
296
  {
274
297
  type: "button",
275
- role: "menuitemradio",
298
+ role,
276
299
  "aria-checked": selected,
277
300
  className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground",
278
301
  onClick: onSelect,
@@ -1 +1 @@
1
- {"version":3,"file":"JsonSchemaForm.js","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiEllipsisBold } from \"../icons\";\nimport { FormFieldFilter } from \"./json-schema-form-filter-input\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { FieldsGrid } from \"./json-schema-form-layout\";\nimport { FormErrorSummary } from \"./json-schema-form-error-display\";\nimport { unmatchedFormErrors } from \"./json-schema-form-errors\";\nimport { FormLookupProvider } from \"./FormLookupProvider\";\nimport { DiscriminatedForm } from \"./json-schema-form-discriminator\";\nimport { rehydrateRefs } from \"./json-schema-form-refs\";\nimport { renderApi, renderObjectFields } from \"./json-schema-form-render\";\nimport { applySchemaDefaults } from \"./json-schema-form-defaults\";\nimport {\n cssLength,\n DEFAULT_COLUMN_MIN_WIDTH,\n normalizeColumns,\n} from \"./json-schema-form-utils\";\nimport { DEFAULT_FORM_SIZE, fieldInnerGapClass, labelSizeClass, type FormSize } from \"./json-schema-form-size\";\nimport {\n DEFAULT_PREFERENCES_STORAGE_KEY,\n readPreferences,\n writePreferences,\n type FormPreferences,\n type LayoutMode,\n type SortMode,\n} from \"./json-schema-form-preferences\";\nimport type { FormLayout, JsonSchemaFormProps, RenderContext } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"600px\";\n\n// resolveFormLayout maps the `layout`/`inline` props plus an optional menu-driven\n// `modeOverride` to a single resolved FormLayout. An explicit `layout` sets the\n// base; `inline` is the shorthand for it; `modeOverride` (from the preferences\n// menu) wins over both but only flips the mode — width caps from `layout` are\n// preserved. Both modes fill valueMaxWidth (inline value column / stacked\n// label+value stack); the label cap only applies inline.\nfunction resolveFormLayout(\n layout: FormLayout | undefined,\n inline: boolean,\n modeOverride: LayoutMode | undefined,\n): FormLayout {\n const baseMode = layout?.mode ?? (inline ? \"inline\" : \"stacked\");\n const mode = modeOverride ?? baseMode;\n const valueMaxWidth = layout?.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH;\n // `help` is orthogonal to mode, so it survives a menu-driven mode flip.\n const help = layout?.help ? { help: layout.help } : {};\n if (mode === \"properties\") return { ...layout, mode, ...help };\n if (mode !== \"inline\") return { mode: \"stacked\", valueMaxWidth, ...help };\n return {\n mode: \"inline\",\n labelMaxWidth: layout?.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth,\n ...help,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n rootValue,\n onRootChange,\n instancePath = \"\",\n errors = [],\n readOnly = false,\n inline = false,\n layout,\n size = DEFAULT_FORM_SIZE,\n idPrefix,\n hideReadOnlyFields = false,\n hideEmpty = false,\n autoSave = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n showPreferencesMenu = true,\n showFilter,\n persistPreferences = true,\n preferencesStorageKey = DEFAULT_PREFERENCES_STORAGE_KEY,\n lookupFetcher,\n expressionEvaluator,\n applyDefaults = true,\n}: JsonSchemaFormProps) {\n // When the menu is hidden, never touch localStorage and start from an empty\n // override so behaviour is identical to before this feature existed.\n const [prefs, setPrefs] = useState<FormPreferences>(() =>\n showPreferencesMenu && persistPreferences ? readPreferences(preferencesStorageKey) : {},\n );\n // The field filter is transient view state (a \"find\" over the fields), never\n // persisted — reopening the form should never start with fields hidden.\n const [fieldFilter, setFieldFilter] = useState(\"\");\n\n const effectiveSize = prefs.size ?? size;\n const resolvedLayout = resolveFormLayout(layout, inline, prefs.layoutMode);\n const filterVisible = showFilter ?? (showPreferencesMenu && resolvedLayout.mode === \"properties\");\n // The `requiredFirst` prop sets the base sort; a menu selection overrides it.\n const effectiveSortMode = prefs.sortMode ?? (requiredFirst ? \"required-first\" : \"schema\");\n\n const applyPrefs = (next: FormPreferences) => {\n setPrefs(next);\n if (persistPreferences) writePreferences(preferencesStorageKey, next);\n };\n\n // A bundled schema (components under `$defs`, referenced by local `#/$defs`\n // pointers) is resolved once into a self-contained tree the renderer walks\n // directly; a non-bundled schema passes through untouched.\n const resolvedSchema = useMemo(() => rehydrateRefs(schema), [schema]);\n // Suppressing at the value (not only at the commit effect below) is deliberate:\n // renderObjectFields spreads `effectiveValue` when a single field changes, so a\n // render-only application would still leak the defaults on the first edit.\n const effectiveValue = useMemo(\n () => (applyDefaults ? applySchemaDefaults(resolvedSchema, value) : value),\n [applyDefaults, resolvedSchema, value],\n );\n const preExtensions = pre ?? [];\n const unmatchedErrors = useMemo(\n () =>\n unmatchedFormErrors({\n schema: resolvedSchema,\n value: effectiveValue,\n errors,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n pre: preExtensions,\n rootValue: rootValue ?? effectiveValue,\n instancePath,\n ...(hiddenKeys ? { hiddenKeys } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n }),\n [effectiveValue, errors, expressionEvaluator, fieldFilter, hiddenKeys, hideEmpty, hideReadOnlyFields, instancePath, preExtensions, readOnly, resolvedSchema, rootValue],\n );\n // Defaults are part of the submitted form value, not only presentation. This\n // is especially important for required discriminator fields whose default\n // selects an if/then branch.\n useEffect(() => {\n if (!readOnly && effectiveValue !== value) onChange(effectiveValue);\n }, [effectiveValue, onChange, readOnly, value]);\n\n const ctx: RenderContext = {\n readOnly,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n autoSave,\n layout: resolvedLayout,\n size: effectiveSize,\n sortMode: effectiveSortMode,\n pre: preExtensions,\n post: post ?? [],\n rootValue: rootValue ?? effectiveValue,\n onRootChange: onRootChange ?? onChange,\n instancePath,\n errors,\n depth: 0,\n render: renderApi,\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n ...(idPrefix ? { idPrefix } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n };\n // A schema may name a discriminator property whose value selects a \"kind\"; the\n // form then runs a two-phase pick-then-fill flow (see DiscriminatedForm).\n const discKey = typeof resolvedSchema[\"x-discriminator\"] === \"string\" ? resolvedSchema[\"x-discriminator\"] : undefined;\n const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === \"\");\n\n const objectRows = discKey\n ? null\n : renderObjectFields(resolvedSchema, effectiveValue, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n const noMatches = objectRows != null && objectRows.length === 0 && fieldFilter.trim() !== \"\";\n\n return (\n <FormLookupProvider {...(lookupFetcher ? { fetcher: lookupFetcher } : {})}>\n <div data-json-schema-form className={cn(\"relative flex flex-col\", fieldInnerGapClass[effectiveSize])}>\n {showPreferencesMenu && !inPickerPhase && (\n <PreferencesMenu\n size={effectiveSize}\n layoutMode={resolvedLayout.mode}\n sortMode={effectiveSortMode}\n fieldFilter={fieldFilter}\n filterInMenu={!filterVisible}\n onFilterChange={setFieldFilter}\n onSelectSize={(next) => applyPrefs({ ...prefs, size: next })}\n onSelectLayout={(next) => applyPrefs({ ...prefs, layoutMode: next })}\n onSelectSort={(next) => applyPrefs({ ...prefs, sortMode: next })}\n />\n )}\n {title && <h3 className={cn(\"font-semibold\", labelSizeClass[effectiveSize])}>{title}</h3>}\n {filterVisible && !inPickerPhase && (\n <div className=\"max-w-md pr-9\">\n <FormFieldFilter value={fieldFilter} onChange={setFieldFilter} />\n </div>\n )}\n <FormErrorSummary errors={unmatchedErrors} />\n <FieldsGrid\n layout={resolvedLayout}\n size={effectiveSize}\n columns={normalizeColumns(resolvedSchema[\"x-columns\"])}\n columnMinWidth={cssLength(resolvedSchema[\"x-column-min-width\"], DEFAULT_COLUMN_MIN_WIDTH)}\n {...(typeof resolvedSchema[\"x-columns-max-width\"] === \"string\"\n ? { columnsMaxWidth: resolvedSchema[\"x-columns-max-width\"] }\n : {})}\n {...(typeof resolvedSchema[\"x-classes\"] === \"string\" ? { className: resolvedSchema[\"x-classes\"] } : {})}\n >\n {discKey ? (\n <DiscriminatedForm\n schema={resolvedSchema}\n value={effectiveValue}\n onChange={onChange}\n ctx={ctx}\n discKey={discKey}\n />\n ) : (\n objectRows\n )}\n </FieldsGrid>\n {noMatches && (\n <p className={cn(\"text-muted-foreground\", labelSizeClass[effectiveSize])}>\n No fields match “{fieldFilter.trim()}”.\n </p>\n )}\n </div>\n </FormLookupProvider>\n );\n}\n\nconst SIZE_OPTIONS: { value: FormSize; label: string }[] = [\n { value: \"xs\", label: \"Extra small\" },\n { value: \"sm\", label: \"Small\" },\n { value: \"md\", label: \"Medium\" },\n { value: \"lg\", label: \"Large\" },\n { value: \"xl\", label: \"Extra large\" },\n];\n\nconst LAYOUT_OPTIONS: { value: LayoutMode; label: string }[] = [\n { value: \"stacked\", label: \"Stacked\" },\n { value: \"inline\", label: \"Inline\" },\n { value: \"properties\", label: \"Properties\" },\n];\n\nconst SORT_OPTIONS: { value: SortMode; label: string }[] = [\n { value: \"schema\", label: \"Schema order\" },\n { value: \"required-first\", label: \"Required first\" },\n { value: \"priority\", label: \"Required & filled first\" },\n];\n\n// PreferencesMenu is the compact top-right ellipsis menu controlling this form's\n// size, layout, sort, and a live field filter. Selecting an option fires the\n// matching callback and closes the menu; typing in the filter updates fields\n// live without closing. The parent decides whether to persist.\nfunction PreferencesMenu({\n size,\n layoutMode,\n sortMode,\n fieldFilter,\n filterInMenu,\n onFilterChange,\n onSelectSize,\n onSelectLayout,\n onSelectSort,\n}: {\n size: FormSize;\n layoutMode: LayoutMode;\n sortMode: SortMode;\n fieldFilter: string;\n filterInMenu: boolean;\n onFilterChange: (value: string) => void;\n onSelectSize: (size: FormSize) => void;\n onSelectLayout: (mode: LayoutMode) => void;\n onSelectSort: (mode: SortMode) => void;\n}) {\n const filterActive = fieldFilter.trim() !== \"\";\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Form display options\"\n className=\"absolute right-0 top-0 z-10\"\n trigger={\n <button\n type=\"button\"\n aria-label=\"Form display options\"\n aria-haspopup=\"menu\"\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n filterActive ? \"text-primary\" : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon icon={UiEllipsisBold} className=\"text-lg\" />\n </button>\n }\n >\n {(closeMenu) => (\n <>\n {filterInMenu && <div className=\"px-2 pb-1.5 pt-1\">\n <FormFieldFilter value={fieldFilter} onChange={onFilterChange} />\n </div>}\n <PreferenceSection title=\"Size\" />\n {SIZE_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === size}\n onSelect={() => {\n onSelectSize(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Layout\" />\n {LAYOUT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === layoutMode}\n onSelect={() => {\n onSelectLayout(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Sort\" />\n {SORT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === sortMode}\n onSelect={() => {\n onSelectSort(opt.value);\n closeMenu();\n }}\n />\n ))}\n </>\n )}\n </DropdownMenu>\n );\n}\n\nfunction PreferenceSection({ title }: { title: string }) {\n return (\n <div className=\"px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {title}\n </div>\n );\n}\n\nfunction PreferenceItem({ label, selected, onSelect }: { label: string; selected: boolean; onSelect: () => void }) {\n return (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={selected}\n className=\"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground\"\n onClick={onSelect}\n >\n <span className=\"flex w-3.5 shrink-0 justify-center\">\n {selected && <Icon icon={UiCheck} className=\"text-xs\" />}\n </span>\n {label}\n </button>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"JsonSchemaForm.js","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiEllipsisBold } from \"../icons\";\nimport { FormFieldFilter } from \"./json-schema-form-filter-input\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { FieldsGrid } from \"./json-schema-form-layout\";\nimport { FormErrorSummary } from \"./json-schema-form-error-display\";\nimport { unmatchedFormErrors } from \"./json-schema-form-errors\";\nimport { FormLookupProvider } from \"./FormLookupProvider\";\nimport { DiscriminatedForm } from \"./json-schema-form-discriminator\";\nimport { rehydrateRefs } from \"./json-schema-form-refs\";\nimport { renderApi, renderObjectFields } from \"./json-schema-form-render\";\nimport { applySchemaDefaults } from \"./json-schema-form-defaults\";\nimport {\n cssLength,\n DEFAULT_COLUMN_MIN_WIDTH,\n normalizeColumns,\n} from \"./json-schema-form-utils\";\nimport { DEFAULT_FORM_SIZE, fieldInnerGapClass, labelSizeClass, type FormSize } from \"./json-schema-form-size\";\nimport {\n DEFAULT_PREFERENCES_STORAGE_KEY,\n readPreferences,\n writePreferences,\n type FormPreferences,\n type LayoutMode,\n type SortMode,\n} from \"./json-schema-form-preferences\";\nimport type { FormLayout, JsonSchemaFormProps, RenderContext } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"600px\";\n\n// resolveFormLayout maps the `layout`/`inline` props plus an optional menu-driven\n// `modeOverride` to a single resolved FormLayout. An explicit `layout` sets the\n// base; `inline` is the shorthand for it; `modeOverride` (from the preferences\n// menu) wins over both but only flips the mode — width caps from `layout` are\n// preserved. Both modes fill valueMaxWidth (inline value column / stacked\n// label+value stack); the label cap only applies inline.\nfunction resolveFormLayout(\n layout: FormLayout | undefined,\n inline: boolean,\n modeOverride: LayoutMode | undefined,\n): FormLayout {\n const baseMode = layout?.mode ?? (inline ? \"inline\" : \"stacked\");\n const mode = modeOverride ?? baseMode;\n const valueMaxWidth = layout?.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH;\n // `help` is orthogonal to mode, so it survives a menu-driven mode flip.\n const help = layout?.help ? { help: layout.help } : {};\n if (mode === \"properties\") return { ...layout, mode, ...help };\n if (mode !== \"inline\") return { mode: \"stacked\", valueMaxWidth, ...help };\n return {\n mode: \"inline\",\n labelMaxWidth: layout?.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth,\n ...help,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n rootValue,\n onRootChange,\n instancePath = \"\",\n errors = [],\n readOnly = false,\n inline = false,\n layout,\n size = DEFAULT_FORM_SIZE,\n idPrefix,\n hideReadOnlyFields = false,\n hideEmpty = false,\n autoSave = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n showPreferencesMenu = true,\n showFilter,\n persistPreferences = true,\n preferencesStorageKey = DEFAULT_PREFERENCES_STORAGE_KEY,\n lookupFetcher,\n expressionEvaluator,\n applyDefaults = true,\n}: JsonSchemaFormProps) {\n // When the menu is hidden, never touch localStorage and start from an empty\n // override so behaviour is identical to before this feature existed.\n const [prefs, setPrefs] = useState<FormPreferences>(() =>\n showPreferencesMenu && persistPreferences ? readPreferences(preferencesStorageKey) : {},\n );\n // The field filter is transient view state (a \"find\" over the fields), never\n // persisted — reopening the form should never start with fields hidden.\n const [fieldFilter, setFieldFilter] = useState(\"\");\n\n const effectiveSize = prefs.size ?? size;\n const resolvedLayout = resolveFormLayout(layout, inline, prefs.layoutMode);\n const filterVisible = showFilter ?? (showPreferencesMenu && resolvedLayout.mode === \"properties\");\n // The `requiredFirst` prop sets the base sort; a menu selection overrides it.\n const effectiveSortMode = prefs.sortMode ?? (requiredFirst ? \"required-first\" : \"schema\");\n\n const applyPrefs = (next: FormPreferences) => {\n setPrefs(next);\n if (persistPreferences) writePreferences(preferencesStorageKey, next);\n };\n\n // A bundled schema (components under `$defs`, referenced by local `#/$defs`\n // pointers) is resolved once into a self-contained tree the renderer walks\n // directly; a non-bundled schema passes through untouched.\n const resolvedSchema = useMemo(() => rehydrateRefs(schema), [schema]);\n // Suppressing at the value (not only at the commit effect below) is deliberate:\n // renderObjectFields spreads `effectiveValue` when a single field changes, so a\n // render-only application would still leak the defaults on the first edit.\n const effectiveValue = useMemo(\n () => (applyDefaults ? applySchemaDefaults(resolvedSchema, value) : value),\n [applyDefaults, resolvedSchema, value],\n );\n const preExtensions = pre ?? [];\n const unmatchedErrors = useMemo(\n () =>\n unmatchedFormErrors({\n schema: resolvedSchema,\n value: effectiveValue,\n errors,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n pre: preExtensions,\n rootValue: rootValue ?? effectiveValue,\n instancePath,\n ...(hiddenKeys ? { hiddenKeys } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n }),\n [effectiveValue, errors, expressionEvaluator, fieldFilter, hiddenKeys, hideEmpty, hideReadOnlyFields, instancePath, preExtensions, readOnly, resolvedSchema, rootValue],\n );\n // Defaults are part of the submitted form value, not only presentation. This\n // is especially important for required discriminator fields whose default\n // selects an if/then branch.\n useEffect(() => {\n if (!readOnly && effectiveValue !== value) onChange(effectiveValue);\n }, [effectiveValue, onChange, readOnly, value]);\n\n const ctx: RenderContext = {\n readOnly,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n autoSave,\n layout: resolvedLayout,\n size: effectiveSize,\n sortMode: effectiveSortMode,\n pre: preExtensions,\n post: post ?? [],\n rootValue: rootValue ?? effectiveValue,\n onRootChange: onRootChange ?? onChange,\n instancePath,\n errors,\n depth: 0,\n render: renderApi,\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n ...(idPrefix ? { idPrefix } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(prefs.debug ? { debug: true } : {}),\n };\n // A schema may name a discriminator property whose value selects a \"kind\"; the\n // form then runs a two-phase pick-then-fill flow (see DiscriminatedForm).\n const discKey = typeof resolvedSchema[\"x-discriminator\"] === \"string\" ? resolvedSchema[\"x-discriminator\"] : undefined;\n const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === \"\");\n\n const objectRows = discKey\n ? null\n : renderObjectFields(resolvedSchema, effectiveValue, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n const noMatches = objectRows != null && objectRows.length === 0 && fieldFilter.trim() !== \"\";\n\n return (\n <FormLookupProvider {...(lookupFetcher ? { fetcher: lookupFetcher } : {})}>\n <div data-json-schema-form className={cn(\"relative flex flex-col\", fieldInnerGapClass[effectiveSize])}>\n {showPreferencesMenu && !inPickerPhase && (\n <PreferencesMenu\n size={effectiveSize}\n layoutMode={resolvedLayout.mode}\n sortMode={effectiveSortMode}\n fieldFilter={fieldFilter}\n filterInMenu={!filterVisible}\n onFilterChange={setFieldFilter}\n onSelectSize={(next) => applyPrefs({ ...prefs, size: next })}\n onSelectLayout={(next) => applyPrefs({ ...prefs, layoutMode: next })}\n onSelectSort={(next) => applyPrefs({ ...prefs, sortMode: next })}\n debug={prefs.debug === true}\n onToggleDebug={() => applyPrefs({ ...prefs, debug: !prefs.debug })}\n />\n )}\n {title && <h3 className={cn(\"font-semibold\", labelSizeClass[effectiveSize])}>{title}</h3>}\n {filterVisible && !inPickerPhase && (\n <div className=\"max-w-md pr-9\">\n <FormFieldFilter value={fieldFilter} onChange={setFieldFilter} />\n </div>\n )}\n <FormErrorSummary errors={unmatchedErrors} />\n <FieldsGrid\n layout={resolvedLayout}\n size={effectiveSize}\n columns={normalizeColumns(resolvedSchema[\"x-columns\"])}\n columnMinWidth={cssLength(resolvedSchema[\"x-column-min-width\"], DEFAULT_COLUMN_MIN_WIDTH)}\n {...(typeof resolvedSchema[\"x-columns-max-width\"] === \"string\"\n ? { columnsMaxWidth: resolvedSchema[\"x-columns-max-width\"] }\n : {})}\n {...(typeof resolvedSchema[\"x-classes\"] === \"string\" ? { className: resolvedSchema[\"x-classes\"] } : {})}\n >\n {discKey ? (\n <DiscriminatedForm\n schema={resolvedSchema}\n value={effectiveValue}\n onChange={onChange}\n ctx={ctx}\n discKey={discKey}\n />\n ) : (\n objectRows\n )}\n </FieldsGrid>\n {noMatches && (\n <p className={cn(\"text-muted-foreground\", labelSizeClass[effectiveSize])}>\n No fields match “{fieldFilter.trim()}”.\n </p>\n )}\n </div>\n </FormLookupProvider>\n );\n}\n\nconst SIZE_OPTIONS: { value: FormSize; label: string }[] = [\n { value: \"xs\", label: \"Extra small\" },\n { value: \"sm\", label: \"Small\" },\n { value: \"md\", label: \"Medium\" },\n { value: \"lg\", label: \"Large\" },\n { value: \"xl\", label: \"Extra large\" },\n];\n\nconst LAYOUT_OPTIONS: { value: LayoutMode; label: string }[] = [\n { value: \"stacked\", label: \"Stacked\" },\n { value: \"inline\", label: \"Inline\" },\n { value: \"properties\", label: \"Properties\" },\n];\n\nconst SORT_OPTIONS: { value: SortMode; label: string }[] = [\n { value: \"schema\", label: \"Schema order\" },\n { value: \"required-first\", label: \"Required first\" },\n { value: \"priority\", label: \"Required & filled first\" },\n];\n\n// PreferencesMenu is the compact top-right ellipsis menu controlling this form's\n// size, layout, sort, and a live field filter. Selecting an option fires the\n// matching callback and closes the menu; typing in the filter updates fields\n// live without closing. The parent decides whether to persist.\nfunction PreferencesMenu({\n size,\n layoutMode,\n sortMode,\n fieldFilter,\n filterInMenu,\n onFilterChange,\n onSelectSize,\n onSelectLayout,\n onSelectSort,\n debug,\n onToggleDebug,\n}: {\n size: FormSize;\n layoutMode: LayoutMode;\n sortMode: SortMode;\n fieldFilter: string;\n filterInMenu: boolean;\n onFilterChange: (value: string) => void;\n onSelectSize: (size: FormSize) => void;\n onSelectLayout: (mode: LayoutMode) => void;\n onSelectSort: (mode: SortMode) => void;\n debug: boolean;\n onToggleDebug: () => void;\n}) {\n const filterActive = fieldFilter.trim() !== \"\" || debug;\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Form display options\"\n className=\"absolute right-0 top-0 z-10\"\n trigger={\n <button\n type=\"button\"\n aria-label=\"Form display options\"\n aria-haspopup=\"menu\"\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n filterActive ? \"text-primary\" : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon icon={UiEllipsisBold} className=\"text-lg\" />\n </button>\n }\n >\n {(closeMenu) => (\n <>\n {filterInMenu && <div className=\"px-2 pb-1.5 pt-1\">\n <FormFieldFilter value={fieldFilter} onChange={onFilterChange} />\n </div>}\n <PreferenceSection title=\"Size\" />\n {SIZE_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === size}\n onSelect={() => {\n onSelectSize(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Layout\" />\n {LAYOUT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === layoutMode}\n onSelect={() => {\n onSelectLayout(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Sort\" />\n {SORT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === sortMode}\n onSelect={() => {\n onSelectSort(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Debug\" />\n <PreferenceItem\n role=\"menuitemcheckbox\"\n label=\"Show hidden fields & sources\"\n selected={debug}\n onSelect={() => {\n onToggleDebug();\n closeMenu();\n }}\n />\n </>\n )}\n </DropdownMenu>\n );\n}\n\nfunction PreferenceSection({ title }: { title: string }) {\n return (\n <div className=\"px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {title}\n </div>\n );\n}\n\nfunction PreferenceItem({\n label,\n selected,\n onSelect,\n role = \"menuitemradio\",\n}: {\n label: string;\n selected: boolean;\n onSelect: () => void;\n role?: \"menuitemradio\" | \"menuitemcheckbox\";\n}) {\n return (\n <button\n type=\"button\"\n role={role}\n aria-checked={selected}\n className=\"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground\"\n onClick={onSelect}\n >\n <span className=\"flex w-3.5 shrink-0 justify-center\">\n {selected && <Icon icon={UiCheck} className=\"text-xs\" />}\n </span>\n {label}\n </button>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -19,6 +19,8 @@ function SegmentedControl({
19
19
  "aria-label": ariaLabel
20
20
  }) {
21
21
  const btnRefs = react.useRef([]);
22
+ const markerIdBase = react.useId();
23
+ const hasSelection = options.some((option) => option.id === value);
22
24
  const move = (from, dir) => {
23
25
  var _a;
24
26
  const n = options.length;
@@ -47,6 +49,8 @@ function SegmentedControl({
47
49
  ),
48
50
  children: options.map((option, index) => {
49
51
  const active = option.id === value;
52
+ const implied = !hasSelection && option.implied === true;
53
+ const markerId = option.marker ? `${markerIdBase}-marker-${index}` : void 0;
50
54
  return /* @__PURE__ */ jsxRuntime.jsxs(
51
55
  "button",
52
56
  {
@@ -56,9 +60,11 @@ function SegmentedControl({
56
60
  type: "button",
57
61
  role: "radio",
58
62
  "aria-checked": active,
63
+ "aria-describedby": markerId,
64
+ "data-implied": implied ? "true" : void 0,
59
65
  title: option.title,
60
66
  disabled: option.disabled,
61
- tabIndex: active ? 0 : -1,
67
+ tabIndex: active || implied ? 0 : -1,
62
68
  onClick: () => !option.disabled && onChange(option.id),
63
69
  onKeyDown: (e) => {
64
70
  if (e.key === "ArrowRight" || e.key === "ArrowDown") {
@@ -76,7 +82,7 @@ function SegmentedControl({
76
82
  size === "lg" && "rounded-lg text-left",
77
83
  option.description ? "whitespace-normal" : "whitespace-nowrap",
78
84
  SIZE_CLASSES[size],
79
- active ? size === "lg" ? "border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25" : "border-border bg-card text-foreground shadow-sm" : size === "lg" ? "border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm" : "text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground",
85
+ active ? size === "lg" ? "border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25" : "border-border bg-card text-foreground shadow-sm" : implied ? size === "lg" ? "border-dashed border-primary/60 bg-card text-foreground hover:shadow-sm" : "border-dashed border-primary/60 text-foreground hover:bg-background/60" : size === "lg" ? "border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm" : "text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground",
80
86
  active && option.activeClassName
81
87
  ),
82
88
  children: [
@@ -99,7 +105,18 @@ function SegmentedControl({
99
105
  size === "lg" && "flex flex-col items-start text-left leading-tight"
100
106
  ),
101
107
  children: [
102
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: option.label }),
108
+ option.marker ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
109
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: option.label }),
110
+ /* @__PURE__ */ jsxRuntime.jsx(
111
+ "span",
112
+ {
113
+ id: markerId,
114
+ "aria-hidden": "true",
115
+ className: "shrink-0 text-[11px] font-normal opacity-70",
116
+ children: option.marker
117
+ }
118
+ )
119
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: option.label }),
103
120
  option.description && /* @__PURE__ */ jsxRuntime.jsx(
104
121
  "span",
105
122
  {
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControl.cjs","sources":["../../src/components/SegmentedControl.tsx"],"sourcesContent":["import { useRef, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../data/Icon\";\n\nexport type SegmentedSize = \"sm\" | \"md\" | \"lg\";\n\nexport type SegmentedOption<T extends string = string> = {\n /** Stable value emitted on selection. */\n id: T;\n /** Visible label. */\n label: ReactNode;\n /** Optional leading icon (imported `Ui*` component or runtime name). */\n icon?: string | StaticIconComponent;\n /** Classes applied to the leading icon. */\n iconClassName?: string;\n /** Classes applied to this segment only while selected. */\n activeClassName?: string;\n /** Optional secondary line, used by larger card-like segmented controls. */\n description?: ReactNode;\n /** Native title attribute. */\n title?: string;\n /** Disable this segment. */\n disabled?: boolean;\n};\n\nexport type SegmentedControlProps<T extends string = string> = {\n /** Currently selected option id. */\n value: T;\n /** Mutually-exclusive options rendered left to right. */\n options: SegmentedOption<T>[];\n /** Called with the newly selected id. */\n onChange: (id: T) => void;\n /** Control size. `md` (default) matches form controls; `sm` is denser and `lg` is card-like. */\n size?: SegmentedSize;\n /** Allows segments to wrap instead of overflowing horizontally. */\n wrap?: boolean;\n /** Accessible group label. */\n \"aria-label\"?: string;\n /** Classes applied to the track. */\n className?: string;\n};\n\nconst SIZE_CLASSES: Record<SegmentedSize, string> = {\n sm: \"text-xs px-density-2 py-density-1 gap-1\",\n md: \"h-full px-control-px text-sm gap-1.5\",\n lg: \"min-h-[4.25rem] min-w-44 flex-1 px-density-3 py-density-3 gap-density-2 text-sm\",\n};\n\n/**\n * Single-select toggle group (the Gavel `Segmented` \"Mine / All / Bots\"\n * pattern). A muted track holds mutually-exclusive segments; the active\n * segment lifts onto the card surface. Built on clicky tokens so it inherits\n * dark-mode and density. Use for small, flat choice sets — reach for `Select`\n * when the option count grows.\n */\nexport function SegmentedControl<T extends string = string>({\n value,\n options,\n onChange,\n size = \"md\",\n wrap = false,\n className,\n \"aria-label\": ariaLabel,\n}: SegmentedControlProps<T>) {\n const btnRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const move = (from: number, dir: 1 | -1) => {\n const n = options.length;\n let i = from;\n for (let step = 0; step < n; step++) {\n i = (i + dir + n) % n;\n const opt = options[i];\n if (opt && !opt.disabled) {\n onChange(opt.id);\n btnRefs.current[i]?.focus();\n return;\n }\n }\n };\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n className={cn(\n \"inline-flex items-center rounded-md bg-muted p-0.5\",\n size === \"md\" && \"h-control-h\",\n size === \"lg\" && \"gap-density-2 bg-transparent p-0\",\n wrap && \"flex-wrap\",\n className,\n )}\n >\n {options.map((option, index) => {\n const active = option.id === value;\n return (\n <button\n key={option.id}\n ref={(el) => {\n btnRefs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n title={option.title}\n disabled={option.disabled}\n tabIndex={active ? 0 : -1}\n onClick={() => !option.disabled && onChange(option.id)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n move(index, 1);\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n move(index, -1);\n }\n }}\n className={cn(\n \"inline-flex items-center rounded-[5px] border border-transparent font-medium transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n size === \"lg\" && \"rounded-lg text-left\",\n option.description ? \"whitespace-normal\" : \"whitespace-nowrap\",\n SIZE_CLASSES[size],\n active\n ? size === \"lg\"\n ? \"border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25\"\n : \"border-border bg-card text-foreground shadow-sm\"\n : size === \"lg\"\n ? \"border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm\"\n : \"text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground\",\n active && option.activeClassName,\n )}\n >\n {option.icon && (\n <Icon\n {...(typeof option.icon === \"string\"\n ? { name: option.icon }\n : { icon: option.icon })}\n className={cn(\n size === \"lg\" ? \"size-4 shrink-0\" : \"size-3.5 shrink-0\",\n size === \"lg\" &&\n (active ? \"text-primary\" : \"text-muted-foreground\"),\n option.iconClassName,\n )}\n />\n )}\n <span\n className={cn(\n \"min-w-0\",\n size === \"lg\" &&\n \"flex flex-col items-start text-left leading-tight\",\n )}\n >\n <span className=\"min-w-0 truncate\">{option.label}</span>\n {option.description && (\n <span\n className={cn(\n \"mt-0.5 max-w-56 whitespace-normal break-words text-[11px] font-normal leading-snug\",\n active\n ? \"text-muted-foreground\"\n : \"text-muted-foreground/80\",\n )}\n >\n {option.description}\n </span>\n )}\n </span>\n </button>\n );\n })}\n </div>\n );\n}\n"],"names":["useRef","jsx","cn","jsxs","Icon"],"mappings":"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"}
1
+ {"version":3,"file":"SegmentedControl.cjs","sources":["../../src/components/SegmentedControl.tsx"],"sourcesContent":["import { useId, useRef, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../data/Icon\";\n\nexport type SegmentedSize = \"sm\" | \"md\" | \"lg\";\n\nexport type SegmentedOption<T extends string = string> = {\n /** Stable value emitted on selection. */\n id: T;\n /** Visible label. */\n label: ReactNode;\n /** Optional leading icon (imported `Ui*` component or runtime name). */\n icon?: string | StaticIconComponent;\n /** Classes applied to the leading icon. */\n iconClassName?: string;\n /** Classes applied to this segment only while selected. */\n activeClassName?: string;\n /** Optional secondary line, used by larger card-like segmented controls. */\n description?: ReactNode;\n /** Native title attribute. */\n title?: string;\n /**\n * Short muted tag rendered after the label (e.g. \"default\"). It is exposed to\n * assistive tech as the segment's accessible description, not its name.\n */\n marker?: string;\n /**\n * Render this segment as the implied choice while no option is selected (e.g.\n * a schema default the value has not been set to). It is outlined, not\n * filled, and stays `aria-checked=false` because nothing is selected.\n */\n implied?: boolean;\n /** Disable this segment. */\n disabled?: boolean;\n};\n\nexport type SegmentedControlProps<T extends string = string> = {\n /** Currently selected option id. */\n value: T;\n /** Mutually-exclusive options rendered left to right. */\n options: SegmentedOption<T>[];\n /** Called with the newly selected id. */\n onChange: (id: T) => void;\n /** Control size. `md` (default) matches form controls; `sm` is denser and `lg` is card-like. */\n size?: SegmentedSize;\n /** Allows segments to wrap instead of overflowing horizontally. */\n wrap?: boolean;\n /** Accessible group label. */\n \"aria-label\"?: string;\n /** Classes applied to the track. */\n className?: string;\n};\n\nconst SIZE_CLASSES: Record<SegmentedSize, string> = {\n sm: \"text-xs px-density-2 py-density-1 gap-1\",\n md: \"h-full px-control-px text-sm gap-1.5\",\n lg: \"min-h-[4.25rem] min-w-44 flex-1 px-density-3 py-density-3 gap-density-2 text-sm\",\n};\n\n/**\n * Single-select toggle group (the Gavel `Segmented` \"Mine / All / Bots\"\n * pattern). A muted track holds mutually-exclusive segments; the active\n * segment lifts onto the card surface. Built on clicky tokens so it inherits\n * dark-mode and density. Use for small, flat choice sets — reach for `Select`\n * when the option count grows.\n */\nexport function SegmentedControl<T extends string = string>({\n value,\n options,\n onChange,\n size = \"md\",\n wrap = false,\n className,\n \"aria-label\": ariaLabel,\n}: SegmentedControlProps<T>) {\n const btnRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const markerIdBase = useId();\n const hasSelection = options.some((option) => option.id === value);\n\n const move = (from: number, dir: 1 | -1) => {\n const n = options.length;\n let i = from;\n for (let step = 0; step < n; step++) {\n i = (i + dir + n) % n;\n const opt = options[i];\n if (opt && !opt.disabled) {\n onChange(opt.id);\n btnRefs.current[i]?.focus();\n return;\n }\n }\n };\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n className={cn(\n \"inline-flex items-center rounded-md bg-muted p-0.5\",\n size === \"md\" && \"h-control-h\",\n size === \"lg\" && \"gap-density-2 bg-transparent p-0\",\n wrap && \"flex-wrap\",\n className,\n )}\n >\n {options.map((option, index) => {\n const active = option.id === value;\n const implied = !hasSelection && option.implied === true;\n const markerId = option.marker ? `${markerIdBase}-marker-${index}` : undefined;\n return (\n <button\n key={option.id}\n ref={(el) => {\n btnRefs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-describedby={markerId}\n data-implied={implied ? \"true\" : undefined}\n title={option.title}\n disabled={option.disabled}\n tabIndex={active || implied ? 0 : -1}\n onClick={() => !option.disabled && onChange(option.id)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n move(index, 1);\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n move(index, -1);\n }\n }}\n className={cn(\n \"inline-flex items-center rounded-[5px] border border-transparent font-medium transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n size === \"lg\" && \"rounded-lg text-left\",\n option.description ? \"whitespace-normal\" : \"whitespace-nowrap\",\n SIZE_CLASSES[size],\n active\n ? size === \"lg\"\n ? \"border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25\"\n : \"border-border bg-card text-foreground shadow-sm\"\n : implied\n ? size === \"lg\"\n ? \"border-dashed border-primary/60 bg-card text-foreground hover:shadow-sm\"\n : \"border-dashed border-primary/60 text-foreground hover:bg-background/60\"\n : size === \"lg\"\n ? \"border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm\"\n : \"text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground\",\n active && option.activeClassName,\n )}\n >\n {option.icon && (\n <Icon\n {...(typeof option.icon === \"string\"\n ? { name: option.icon }\n : { icon: option.icon })}\n className={cn(\n size === \"lg\" ? \"size-4 shrink-0\" : \"size-3.5 shrink-0\",\n size === \"lg\" &&\n (active ? \"text-primary\" : \"text-muted-foreground\"),\n option.iconClassName,\n )}\n />\n )}\n <span\n className={cn(\n \"min-w-0\",\n size === \"lg\" &&\n \"flex flex-col items-start text-left leading-tight\",\n )}\n >\n {option.marker ? (\n <span className=\"inline-flex min-w-0 max-w-full items-baseline gap-1\">\n <span className=\"min-w-0 truncate\">{option.label}</span>\n <span\n id={markerId}\n aria-hidden=\"true\"\n className=\"shrink-0 text-[11px] font-normal opacity-70\"\n >\n {option.marker}\n </span>\n </span>\n ) : (\n <span className=\"min-w-0 truncate\">{option.label}</span>\n )}\n {option.description && (\n <span\n className={cn(\n \"mt-0.5 max-w-56 whitespace-normal break-words text-[11px] font-normal leading-snug\",\n active\n ? \"text-muted-foreground\"\n : \"text-muted-foreground/80\",\n )}\n >\n {option.description}\n </span>\n )}\n </span>\n </button>\n );\n })}\n </div>\n );\n}\n"],"names":["useRef","useId","jsx","cn","jsxs","Icon"],"mappings":"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"}
@@ -16,6 +16,17 @@ export type SegmentedOption<T extends string = string> = {
16
16
  description?: ReactNode;
17
17
  /** Native title attribute. */
18
18
  title?: string;
19
+ /**
20
+ * Short muted tag rendered after the label (e.g. "default"). It is exposed to
21
+ * assistive tech as the segment's accessible description, not its name.
22
+ */
23
+ marker?: string;
24
+ /**
25
+ * Render this segment as the implied choice while no option is selected (e.g.
26
+ * a schema default the value has not been set to). It is outlined, not
27
+ * filled, and stays `aria-checked=false` because nothing is selected.
28
+ */
29
+ implied?: boolean;
19
30
  /** Disable this segment. */
20
31
  disabled?: boolean;
21
32
  };
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControl.d.ts","sourceRoot":"","sources":["../../src/components/SegmentedControl.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE9D,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/C,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACvD,yCAAyC;IACzC,EAAE,EAAE,CAAC,CAAC;IACN,qBAAqB;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAC7D,oCAAoC;IACpC,KAAK,EAAE,CAAC,CAAC;IACT,yDAAyD;IACzD,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,yCAAyC;IACzC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC;IAC1B,gGAAgG;IAChG,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAC1D,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAAW,EACX,IAAY,EACZ,SAAS,EACT,YAAY,EAAE,SAAS,GACxB,EAAE,qBAAqB,CAAC,CAAC,CAAC,+BA6G1B"}
1
+ {"version":3,"file":"SegmentedControl.d.ts","sourceRoot":"","sources":["../../src/components/SegmentedControl.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE9D,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/C,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACvD,yCAAyC;IACzC,EAAE,EAAE,CAAC,CAAC;IACN,qBAAqB;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAC7D,oCAAoC;IACpC,KAAK,EAAE,CAAC,CAAC;IACT,yDAAyD;IACzD,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,yCAAyC;IACzC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC;IAC1B,gGAAgG;IAChG,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAC1D,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAAW,EACX,IAAY,EACZ,SAAS,EACT,YAAY,EAAE,SAAS,GACxB,EAAE,qBAAqB,CAAC,CAAC,CAAC,+BAoI1B"}
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useRef } from "react";
2
+ import { useRef, useId } from "react";
3
3
  import { cn } from "../lib/utils.js";
4
4
  import { Icon } from "../data/Icon.js";
5
5
  const SIZE_CLASSES = {
@@ -17,6 +17,8 @@ function SegmentedControl({
17
17
  "aria-label": ariaLabel
18
18
  }) {
19
19
  const btnRefs = useRef([]);
20
+ const markerIdBase = useId();
21
+ const hasSelection = options.some((option) => option.id === value);
20
22
  const move = (from, dir) => {
21
23
  var _a;
22
24
  const n = options.length;
@@ -45,6 +47,8 @@ function SegmentedControl({
45
47
  ),
46
48
  children: options.map((option, index) => {
47
49
  const active = option.id === value;
50
+ const implied = !hasSelection && option.implied === true;
51
+ const markerId = option.marker ? `${markerIdBase}-marker-${index}` : void 0;
48
52
  return /* @__PURE__ */ jsxs(
49
53
  "button",
50
54
  {
@@ -54,9 +58,11 @@ function SegmentedControl({
54
58
  type: "button",
55
59
  role: "radio",
56
60
  "aria-checked": active,
61
+ "aria-describedby": markerId,
62
+ "data-implied": implied ? "true" : void 0,
57
63
  title: option.title,
58
64
  disabled: option.disabled,
59
- tabIndex: active ? 0 : -1,
65
+ tabIndex: active || implied ? 0 : -1,
60
66
  onClick: () => !option.disabled && onChange(option.id),
61
67
  onKeyDown: (e) => {
62
68
  if (e.key === "ArrowRight" || e.key === "ArrowDown") {
@@ -74,7 +80,7 @@ function SegmentedControl({
74
80
  size === "lg" && "rounded-lg text-left",
75
81
  option.description ? "whitespace-normal" : "whitespace-nowrap",
76
82
  SIZE_CLASSES[size],
77
- active ? size === "lg" ? "border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25" : "border-border bg-card text-foreground shadow-sm" : size === "lg" ? "border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm" : "text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground",
83
+ active ? size === "lg" ? "border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25" : "border-border bg-card text-foreground shadow-sm" : implied ? size === "lg" ? "border-dashed border-primary/60 bg-card text-foreground hover:shadow-sm" : "border-dashed border-primary/60 text-foreground hover:bg-background/60" : size === "lg" ? "border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm" : "text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground",
78
84
  active && option.activeClassName
79
85
  ),
80
86
  children: [
@@ -97,7 +103,18 @@ function SegmentedControl({
97
103
  size === "lg" && "flex flex-col items-start text-left leading-tight"
98
104
  ),
99
105
  children: [
100
- /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label }),
106
+ option.marker ? /* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
107
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label }),
108
+ /* @__PURE__ */ jsx(
109
+ "span",
110
+ {
111
+ id: markerId,
112
+ "aria-hidden": "true",
113
+ className: "shrink-0 text-[11px] font-normal opacity-70",
114
+ children: option.marker
115
+ }
116
+ )
117
+ ] }) : /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label }),
101
118
  option.description && /* @__PURE__ */ jsx(
102
119
  "span",
103
120
  {