@health-samurai/react-components 0.0.0-alpha.3 → 0.0.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/dist/bundle.css +687 -446
  2. package/dist/src/components/code-editor/http/grammar/http.d.ts +3 -0
  3. package/dist/src/components/code-editor/http/grammar/http.d.ts.map +1 -0
  4. package/dist/src/components/code-editor/http/grammar/http.grammar +74 -0
  5. package/dist/src/components/code-editor/http/grammar/http.js +38 -0
  6. package/dist/src/components/code-editor/http/grammar/http.js.map +1 -0
  7. package/dist/src/components/code-editor/http/grammar/http.terms.d.ts +2 -0
  8. package/dist/src/components/code-editor/http/grammar/http.terms.d.ts.map +1 -0
  9. package/dist/src/components/code-editor/http/grammar/http.terms.js +4 -0
  10. package/dist/src/components/code-editor/http/grammar/http.terms.js.map +1 -0
  11. package/dist/src/components/code-editor/http/grammar/http.test.d.ts +2 -0
  12. package/dist/src/components/code-editor/http/grammar/http.test.d.ts.map +1 -0
  13. package/dist/src/components/code-editor/http/grammar/http.test.js +80 -0
  14. package/dist/src/components/code-editor/http/grammar/http.test.js.map +1 -0
  15. package/dist/src/components/code-editor/http/index.d.ts +4 -0
  16. package/dist/src/components/code-editor/http/index.d.ts.map +1 -0
  17. package/dist/src/components/code-editor/http/index.js +66 -0
  18. package/dist/src/components/code-editor/http/index.js.map +1 -0
  19. package/dist/src/components/code-editor/index.d.ts +13 -2
  20. package/dist/src/components/code-editor/index.d.ts.map +1 -1
  21. package/dist/src/components/code-editor/index.js +161 -20
  22. package/dist/src/components/code-editor/index.js.map +1 -1
  23. package/dist/src/components/code-editor.stories.js +3 -1
  24. package/dist/src/components/code-editor.stories.js.map +1 -1
  25. package/dist/src/components/request-line-editor.d.ts +11 -35
  26. package/dist/src/components/request-line-editor.d.ts.map +1 -1
  27. package/dist/src/components/request-line-editor.js +51 -49
  28. package/dist/src/components/request-line-editor.js.map +1 -1
  29. package/dist/src/components/request-line-editor.stories.d.ts.map +1 -1
  30. package/dist/src/components/request-line-editor.stories.js +17 -53
  31. package/dist/src/components/request-line-editor.stories.js.map +1 -1
  32. package/dist/src/components/tree-view.d.ts +16 -0
  33. package/dist/src/components/tree-view.d.ts.map +1 -0
  34. package/dist/src/components/tree-view.js +67 -0
  35. package/dist/src/components/tree-view.js.map +1 -0
  36. package/dist/src/components/tree-view.stories.d.ts +13 -0
  37. package/dist/src/components/tree-view.stories.d.ts.map +1 -0
  38. package/dist/src/components/tree-view.stories.js +274 -0
  39. package/dist/src/components/tree-view.stories.js.map +1 -0
  40. package/dist/src/icons.d.ts +3 -0
  41. package/dist/src/icons.d.ts.map +1 -0
  42. package/dist/src/icons.js +47 -0
  43. package/dist/src/icons.js.map +1 -0
  44. package/dist/src/index.css +42 -3
  45. package/dist/src/index.d.ts +1 -1
  46. package/dist/src/index.d.ts.map +1 -1
  47. package/dist/src/index.js +1 -1
  48. package/dist/src/index.js.map +1 -1
  49. package/dist/src/shadcn/components/ui/accordion.d.ts.map +1 -1
  50. package/dist/src/shadcn/components/ui/accordion.js +23 -5
  51. package/dist/src/shadcn/components/ui/accordion.js.map +1 -1
  52. package/dist/src/shadcn/components/ui/alert.d.ts.map +1 -1
  53. package/dist/src/shadcn/components/ui/alert.js +12 -5
  54. package/dist/src/shadcn/components/ui/alert.js.map +1 -1
  55. package/dist/src/shadcn/components/ui/avatar.d.ts.map +1 -1
  56. package/dist/src/shadcn/components/ui/avatar.js +4 -3
  57. package/dist/src/shadcn/components/ui/avatar.js.map +1 -1
  58. package/dist/src/shadcn/components/ui/badge.d.ts.map +1 -1
  59. package/dist/src/shadcn/components/ui/badge.js +16 -5
  60. package/dist/src/shadcn/components/ui/badge.js.map +1 -1
  61. package/dist/src/shadcn/components/ui/breadcrumb.d.ts.map +1 -1
  62. package/dist/src/shadcn/components/ui/breadcrumb.js +6 -6
  63. package/dist/src/shadcn/components/ui/breadcrumb.js.map +1 -1
  64. package/dist/src/shadcn/components/ui/button.d.ts.map +1 -1
  65. package/dist/src/shadcn/components/ui/button.js +19 -11
  66. package/dist/src/shadcn/components/ui/button.js.map +1 -1
  67. package/dist/src/shadcn/components/ui/card.d.ts.map +1 -1
  68. package/dist/src/shadcn/components/ui/card.js +14 -6
  69. package/dist/src/shadcn/components/ui/card.js.map +1 -1
  70. package/dist/src/shadcn/components/ui/carousel.d.ts.map +1 -1
  71. package/dist/src/shadcn/components/ui/carousel.js +1 -0
  72. package/dist/src/shadcn/components/ui/carousel.js.map +1 -1
  73. package/dist/src/shadcn/components/ui/checkbox.d.ts.map +1 -1
  74. package/dist/src/shadcn/components/ui/checkbox.js +20 -5
  75. package/dist/src/shadcn/components/ui/checkbox.js.map +1 -1
  76. package/dist/src/shadcn/components/ui/checkbox.stories.d.ts.map +1 -1
  77. package/dist/src/shadcn/components/ui/checkbox.stories.js +44 -35
  78. package/dist/src/shadcn/components/ui/checkbox.stories.js.map +1 -1
  79. package/dist/src/shadcn/components/ui/combobox.d.ts +18 -0
  80. package/dist/src/shadcn/components/ui/combobox.d.ts.map +1 -0
  81. package/dist/src/shadcn/components/ui/combobox.js +121 -0
  82. package/dist/src/shadcn/components/ui/combobox.js.map +1 -0
  83. package/dist/src/shadcn/components/ui/combobox.stories.d.ts +11 -0
  84. package/dist/src/shadcn/components/ui/combobox.stories.d.ts.map +1 -0
  85. package/dist/src/shadcn/components/ui/combobox.stories.js +16 -0
  86. package/dist/src/shadcn/components/ui/combobox.stories.js.map +1 -0
  87. package/dist/src/shadcn/components/ui/command.d.ts.map +1 -1
  88. package/dist/src/shadcn/components/ui/command.js +73 -12
  89. package/dist/src/shadcn/components/ui/command.js.map +1 -1
  90. package/dist/src/shadcn/components/ui/command.stories.js +0 -1
  91. package/dist/src/shadcn/components/ui/command.stories.js.map +1 -1
  92. package/dist/src/shadcn/components/ui/dialog.d.ts.map +1 -1
  93. package/dist/src/shadcn/components/ui/dialog.js +35 -7
  94. package/dist/src/shadcn/components/ui/dialog.js.map +1 -1
  95. package/dist/src/shadcn/components/ui/drawer.d.ts.map +1 -1
  96. package/dist/src/shadcn/components/ui/drawer.js +26 -5
  97. package/dist/src/shadcn/components/ui/drawer.js.map +1 -1
  98. package/dist/src/shadcn/components/ui/dropdown-menu.d.ts.map +1 -1
  99. package/dist/src/shadcn/components/ui/dropdown-menu.js +12 -1
  100. package/dist/src/shadcn/components/ui/dropdown-menu.js.map +1 -1
  101. package/dist/src/shadcn/components/ui/form.d.ts.map +1 -1
  102. package/dist/src/shadcn/components/ui/form.js +12 -4
  103. package/dist/src/shadcn/components/ui/form.js.map +1 -1
  104. package/dist/src/shadcn/components/ui/input-otp.d.ts.map +1 -1
  105. package/dist/src/shadcn/components/ui/input-otp.js +1 -0
  106. package/dist/src/shadcn/components/ui/input-otp.js.map +1 -1
  107. package/dist/src/shadcn/components/ui/input.d.ts.map +1 -1
  108. package/dist/src/shadcn/components/ui/input.js +87 -16
  109. package/dist/src/shadcn/components/ui/input.js.map +1 -1
  110. package/dist/src/shadcn/components/ui/label.d.ts.map +1 -1
  111. package/dist/src/shadcn/components/ui/label.js +8 -1
  112. package/dist/src/shadcn/components/ui/label.js.map +1 -1
  113. package/dist/src/shadcn/components/ui/menubar.d.ts.map +1 -1
  114. package/dist/src/shadcn/components/ui/menubar.js +35 -13
  115. package/dist/src/shadcn/components/ui/menubar.js.map +1 -1
  116. package/dist/src/shadcn/components/ui/pagination.d.ts.map +1 -1
  117. package/dist/src/shadcn/components/ui/pagination.js +6 -6
  118. package/dist/src/shadcn/components/ui/pagination.js.map +1 -1
  119. package/dist/src/shadcn/components/ui/popover.d.ts.map +1 -1
  120. package/dist/src/shadcn/components/ui/popover.js +12 -1
  121. package/dist/src/shadcn/components/ui/popover.js.map +1 -1
  122. package/dist/src/shadcn/components/ui/progress.d.ts.map +1 -1
  123. package/dist/src/shadcn/components/ui/progress.js +6 -2
  124. package/dist/src/shadcn/components/ui/progress.js.map +1 -1
  125. package/dist/src/shadcn/components/ui/radio-group.d.ts.map +1 -1
  126. package/dist/src/shadcn/components/ui/radio-group.js +11 -6
  127. package/dist/src/shadcn/components/ui/radio-group.js.map +1 -1
  128. package/dist/src/shadcn/components/ui/radio-group.stories.d.ts.map +1 -1
  129. package/dist/src/shadcn/components/ui/radio-group.stories.js +57 -34
  130. package/dist/src/shadcn/components/ui/radio-group.stories.js.map +1 -1
  131. package/dist/src/shadcn/components/ui/resizable.d.ts.map +1 -1
  132. package/dist/src/shadcn/components/ui/resizable.js +1 -0
  133. package/dist/src/shadcn/components/ui/resizable.js.map +1 -1
  134. package/dist/src/shadcn/components/ui/scroll-area.d.ts.map +1 -1
  135. package/dist/src/shadcn/components/ui/scroll-area.js +9 -3
  136. package/dist/src/shadcn/components/ui/scroll-area.js.map +1 -1
  137. package/dist/src/shadcn/components/ui/select.d.ts.map +1 -1
  138. package/dist/src/shadcn/components/ui/select.js +49 -14
  139. package/dist/src/shadcn/components/ui/select.js.map +1 -1
  140. package/dist/src/shadcn/components/ui/select.stories.d.ts.map +1 -1
  141. package/dist/src/shadcn/components/ui/select.stories.js +1 -4
  142. package/dist/src/shadcn/components/ui/select.stories.js.map +1 -1
  143. package/dist/src/shadcn/components/ui/separator.d.ts.map +1 -1
  144. package/dist/src/shadcn/components/ui/separator.js +7 -1
  145. package/dist/src/shadcn/components/ui/separator.js.map +1 -1
  146. package/dist/src/shadcn/components/ui/sidebar.d.ts.map +1 -1
  147. package/dist/src/shadcn/components/ui/sidebar.js +20 -6
  148. package/dist/src/shadcn/components/ui/sidebar.js.map +1 -1
  149. package/dist/src/shadcn/components/ui/skeleton.d.ts.map +1 -1
  150. package/dist/src/shadcn/components/ui/skeleton.js +3 -1
  151. package/dist/src/shadcn/components/ui/skeleton.js.map +1 -1
  152. package/dist/src/shadcn/components/ui/slider.d.ts.map +1 -1
  153. package/dist/src/shadcn/components/ui/slider.js +34 -4
  154. package/dist/src/shadcn/components/ui/slider.js.map +1 -1
  155. package/dist/src/shadcn/components/ui/sonner.d.ts +16 -1
  156. package/dist/src/shadcn/components/ui/sonner.d.ts.map +1 -1
  157. package/dist/src/shadcn/components/ui/sonner.js +23 -3
  158. package/dist/src/shadcn/components/ui/sonner.js.map +1 -1
  159. package/dist/src/shadcn/components/ui/sonner.stories.d.ts.map +1 -1
  160. package/dist/src/shadcn/components/ui/sonner.stories.js +19 -11
  161. package/dist/src/shadcn/components/ui/sonner.stories.js.map +1 -1
  162. package/dist/src/shadcn/components/ui/switch.d.ts.map +1 -1
  163. package/dist/src/shadcn/components/ui/switch.js +18 -2
  164. package/dist/src/shadcn/components/ui/switch.js.map +1 -1
  165. package/dist/src/shadcn/components/ui/table.d.ts.map +1 -1
  166. package/dist/src/shadcn/components/ui/table.js +12 -8
  167. package/dist/src/shadcn/components/ui/table.js.map +1 -1
  168. package/dist/src/shadcn/components/ui/tabs.d.ts +21 -3
  169. package/dist/src/shadcn/components/ui/tabs.d.ts.map +1 -1
  170. package/dist/src/shadcn/components/ui/tabs.js +314 -9
  171. package/dist/src/shadcn/components/ui/tabs.js.map +1 -1
  172. package/dist/src/shadcn/components/ui/tabs.stories.d.ts.map +1 -1
  173. package/dist/src/shadcn/components/ui/tabs.stories.js +50 -1
  174. package/dist/src/shadcn/components/ui/tabs.stories.js.map +1 -1
  175. package/dist/src/shadcn/components/ui/textarea.d.ts.map +1 -1
  176. package/dist/src/shadcn/components/ui/textarea.js +15 -1
  177. package/dist/src/shadcn/components/ui/textarea.js.map +1 -1
  178. package/dist/src/shadcn/components/ui/toggle-group.d.ts.map +1 -1
  179. package/dist/src/shadcn/components/ui/toggle-group.js +7 -2
  180. package/dist/src/shadcn/components/ui/toggle-group.js.map +1 -1
  181. package/dist/src/shadcn/components/ui/toggle.d.ts.map +1 -1
  182. package/dist/src/shadcn/components/ui/toggle.js +18 -6
  183. package/dist/src/shadcn/components/ui/toggle.js.map +1 -1
  184. package/dist/src/shadcn/components/ui/tooltip.d.ts.map +1 -1
  185. package/dist/src/shadcn/components/ui/tooltip.js +11 -1
  186. package/dist/src/shadcn/components/ui/tooltip.js.map +1 -1
  187. package/dist/src/shadcn/components/ui/tree.d.ts +20 -0
  188. package/dist/src/shadcn/components/ui/tree.d.ts.map +1 -0
  189. package/dist/src/shadcn/components/ui/tree.js +111 -0
  190. package/dist/src/shadcn/components/ui/tree.js.map +1 -0
  191. package/package.json +9 -2
  192. package/src/components/code-editor/http/grammar/http.grammar +74 -0
  193. package/src/components/code-editor/http/grammar/http.terms.ts +9 -0
  194. package/src/components/code-editor/http/grammar/http.test.ts +110 -0
  195. package/src/components/code-editor/http/grammar/http.ts +21 -0
  196. package/src/components/code-editor/http/index.ts +87 -0
  197. package/src/components/code-editor/index.tsx +182 -21
  198. package/src/components/code-editor.stories.tsx +1 -1
  199. package/src/components/request-line-editor.stories.tsx +17 -27
  200. package/src/components/request-line-editor.tsx +72 -61
  201. package/src/components/tree-view.stories.tsx +260 -0
  202. package/src/components/tree-view.tsx +101 -0
  203. package/src/icons.tsx +45 -0
  204. package/src/index.css +42 -3
  205. package/src/index.tsx +1 -1
  206. package/src/shadcn/components/ui/accordion.tsx +66 -8
  207. package/src/shadcn/components/ui/alert.tsx +53 -15
  208. package/src/shadcn/components/ui/avatar.tsx +17 -6
  209. package/src/shadcn/components/ui/badge.tsx +67 -18
  210. package/src/shadcn/components/ui/breadcrumb.tsx +35 -7
  211. package/src/shadcn/components/ui/button.tsx +118 -57
  212. package/src/shadcn/components/ui/card.tsx +44 -13
  213. package/src/shadcn/components/ui/carousel.tsx +1 -0
  214. package/src/shadcn/components/ui/checkbox.stories.tsx +20 -24
  215. package/src/shadcn/components/ui/checkbox.tsx +45 -4
  216. package/src/shadcn/components/ui/combobox.stories.tsx +19 -0
  217. package/src/shadcn/components/ui/combobox.tsx +142 -0
  218. package/src/shadcn/components/ui/command.stories.tsx +1 -1
  219. package/src/shadcn/components/ui/command.tsx +192 -36
  220. package/src/shadcn/components/ui/dialog.tsx +101 -13
  221. package/src/shadcn/components/ui/drawer.tsx +93 -18
  222. package/src/shadcn/components/ui/dropdown-menu.tsx +38 -9
  223. package/src/shadcn/components/ui/form.tsx +16 -4
  224. package/src/shadcn/components/ui/input-otp.tsx +1 -0
  225. package/src/shadcn/components/ui/input.tsx +281 -29
  226. package/src/shadcn/components/ui/label.tsx +21 -4
  227. package/src/shadcn/components/ui/menubar.tsx +188 -43
  228. package/src/shadcn/components/ui/pagination.tsx +12 -6
  229. package/src/shadcn/components/ui/popover.tsx +35 -4
  230. package/src/shadcn/components/ui/progress.tsx +21 -5
  231. package/src/shadcn/components/ui/radio-group.stories.tsx +22 -14
  232. package/src/shadcn/components/ui/radio-group.tsx +42 -5
  233. package/src/shadcn/components/ui/resizable.tsx +1 -0
  234. package/src/shadcn/components/ui/scroll-area.tsx +33 -5
  235. package/src/shadcn/components/ui/select.stories.tsx +0 -2
  236. package/src/shadcn/components/ui/select.tsx +184 -33
  237. package/src/shadcn/components/ui/separator.tsx +15 -5
  238. package/src/shadcn/components/ui/sidebar.tsx +68 -26
  239. package/src/shadcn/components/ui/skeleton.tsx +4 -1
  240. package/src/shadcn/components/ui/slider.tsx +82 -11
  241. package/src/shadcn/components/ui/sonner.stories.tsx +19 -15
  242. package/src/shadcn/components/ui/sonner.tsx +53 -3
  243. package/src/shadcn/components/ui/switch.tsx +53 -7
  244. package/src/shadcn/components/ui/table.tsx +38 -11
  245. package/src/shadcn/components/ui/tabs.stories.tsx +32 -0
  246. package/src/shadcn/components/ui/tabs.tsx +455 -17
  247. package/src/shadcn/components/ui/textarea.tsx +42 -4
  248. package/src/shadcn/components/ui/toggle-group.tsx +28 -5
  249. package/src/shadcn/components/ui/toggle.tsx +59 -18
  250. package/src/shadcn/components/ui/tooltip.tsx +33 -8
  251. package/src/shadcn/components/ui/tree.tsx +200 -0
@@ -0,0 +1,74 @@
1
+ @top Http {
2
+ httpRequest
3
+ }
4
+
5
+ @tokens {
6
+ eof { @eof }
7
+
8
+ lf { $[\n] }
9
+ notLf { ![\n] }
10
+
11
+ cr { $[\r] }
12
+ notCr { ![\r] }
13
+
14
+ colon { $[:] }
15
+ notColon { ![:] }
16
+
17
+ space { $[ \t] }
18
+ notSpace { ![ \t] }
19
+
20
+ headerNameChar { ![\n\r \t:] }
21
+ headerNameText { headerNameChar+ }
22
+
23
+ headerValueFirstChar { ![\n\r \t] }
24
+ headerValueChar { ![\n\r] }
25
+ headerValueLastChar { headerValueFirstChar }
26
+ headerValueText { headerValueFirstChar headerValueChar* headerValueLastChar | headerValueFirstChar }
27
+
28
+ methodChar { ![\n\r \t] }
29
+ methodText { methodChar+ }
30
+
31
+ pathChar { ![\n\r] }
32
+ firstPathChar { ![\n\r \t] }
33
+ pathText { firstPathChar pathChar* }
34
+
35
+ crlf { (cr lf) | cr | lf }
36
+
37
+ bodyChar { _ }
38
+ }
39
+
40
+ HttpRequestMethod[group="Method"] {
41
+ methodText
42
+ }
43
+
44
+ HttpRequestPath {
45
+ pathText
46
+ }
47
+
48
+ httpRequestLine {
49
+ space* HttpRequestMethod space+ HttpRequestPath crlf
50
+ }
51
+
52
+ HttpHeaderName {
53
+ headerNameText
54
+ }
55
+
56
+ HttpHeaderValue {
57
+ headerValueText
58
+ }
59
+
60
+ HttpHeader {
61
+ space* HttpHeaderName space* colon space* HttpHeaderValue space* crlf
62
+ }
63
+
64
+ HttpHeaders {
65
+ HttpHeader+
66
+ }
67
+
68
+ HttpBody {
69
+ bodyChar*
70
+ }
71
+
72
+ httpRequest {
73
+ httpRequestLine HttpHeaders? crlf HttpBody
74
+ }
@@ -0,0 +1,9 @@
1
+ // This file was generated by lezer-generator. You probably shouldn't edit it.
2
+ export const Http = 1,
3
+ HttpRequestMethod = 2,
4
+ HttpRequestPath = 3,
5
+ HttpHeaders = 4,
6
+ HttpHeader = 5,
7
+ HttpHeaderName = 6,
8
+ HttpHeaderValue = 7,
9
+ HttpBody = 8;
@@ -0,0 +1,110 @@
1
+ // Tests for lezer Http grammar
2
+
3
+ import { testTree } from "@lezer/generator/test";
4
+ import { parser } from "./http";
5
+
6
+ type StackEntry = {
7
+ name: string;
8
+ from: number;
9
+ to: number;
10
+ value: string;
11
+ children: StackEntry[];
12
+ textNode?: boolean;
13
+ };
14
+
15
+ function parseHttp(input: string): StackEntry {
16
+ const stack: StackEntry[] = [];
17
+ parser.parse(input).iterate({
18
+ enter: (node) => {
19
+ const nodeName = node.type.name;
20
+ const nodeFrom = node.from;
21
+ const nodeTo = node.to;
22
+ const value = input.slice(nodeFrom, nodeTo);
23
+
24
+ stack.push({
25
+ name: nodeName,
26
+ from: nodeFrom,
27
+ to: nodeTo,
28
+ value: value,
29
+ children: [],
30
+ });
31
+ },
32
+
33
+ leave: () => {
34
+ const current = stack.pop();
35
+ if (current === undefined) {
36
+ throw "Stack underflow";
37
+ }
38
+
39
+ if (stack.length === 0) {
40
+ // Re-push root
41
+ stack.push(current);
42
+ return;
43
+ }
44
+
45
+ const parent = stack[stack.length - 1];
46
+ if (parent === undefined) {
47
+ throw "Impossible";
48
+ }
49
+
50
+ parent.children.push(current);
51
+ },
52
+ });
53
+
54
+ const res = stack.pop();
55
+ if (res === undefined) {
56
+ throw "Stack underflow";
57
+ }
58
+ return res;
59
+ }
60
+
61
+ type Tree = TreeNode | string;
62
+ type TreeNode = {
63
+ name: string;
64
+ children: Tree[];
65
+ };
66
+
67
+ function transform(root: StackEntry): Tree {
68
+ const tree: Tree = {
69
+ name: root.name,
70
+ children: [],
71
+ };
72
+
73
+ let pos = root.from;
74
+ for (const child of root.children) {
75
+ if (pos < child.from) {
76
+ const prefix = root.value.slice(pos - root.from, child.from - root.from);
77
+ tree.children.push(prefix);
78
+ }
79
+
80
+ tree.children.push(transform(child));
81
+ pos = child.to;
82
+ }
83
+
84
+ if (pos < root.to) {
85
+ tree.children.push(root.value.slice(pos - root.from));
86
+ }
87
+
88
+ return tree;
89
+ }
90
+
91
+ const tree = parser.parse("GET /\nAccept: text/yaml\n\nhello: world");
92
+ console.dir(parseHttp("GET /\nAccept: text/yaml\n\nhello: world\n\nagain"), {
93
+ depth: null,
94
+ });
95
+ console.dir(
96
+ transform(parseHttp("GET /\nAccept: text/yaml\n\nhello: world\n\nagain")),
97
+ {
98
+ depth: null,
99
+ },
100
+ );
101
+ console.log(tree);
102
+ tree.iterate({
103
+ enter: (node) => {
104
+ console.log(`ENTER ${node.type.name}[${node.from}:${node.to}]`);
105
+ },
106
+ leave: (node) => {
107
+ console.log(`LEAVE ${node.type.name}[${node.from}:${node.to}]`);
108
+ },
109
+ });
110
+ testTree(tree, `Http`);
@@ -0,0 +1,21 @@
1
+ // This file was generated by lezer-generator. You probably shouldn't edit it.
2
+ import { LRParser } from "@lezer/lr";
3
+ export const parser = LRParser.deserialize({
4
+ version: 14,
5
+ states:
6
+ "'zOQOPOOOOOO'#Ce'#CeOQOPO'#CjOOOO'#C^'#C^OYOPO'#CjO_OQO'#CiQOOOOOOOOO-E6c-E6cOYOPO,59UOjOSO,59UOrOQO'#CaOOOO'#Cb'#CbOzOQO'#CaOOOO'#Cf'#CfO!SOQO'#C`O!_OWO,59TO!gOPO,59TOjOSO1G.pOOOO'#C_'#C_O!lOPO1G.pO!qOQO,58{O!qOQO,58{O!yO`O,58{OOOO-E6d-E6dOOOO'#Cg'#CgO#ROWO'#CdOOOO1G.o1G.oO!_OWO1G.oO#ZOPO7+$[OOOO7+$[7+$[O#`OQO1G.gO!yO`O1G.gO!yO`O1G.gOOOO'#Cc'#CcO#hOPO1G.gOOOO-E6e-E6eOOOO7+$Z7+$ZOOOO<<Gv<<GvO!yO`O7+$RO!yO`O7+$RO#pOPO7+$RO#pOPO7+$ROOOO7+$R7+$RO!yO`O<<GmO#xOPO<<GmO#xOPO<<GmOOOO<<Gm<<GmO$QOPOAN=XO$QOPOAN=XOOOOAN=XAN=XO$YOPOG22sOOOOG22sG22sOOOOLD(_LD(_",
7
+ stateData:
8
+ "$b~O_PO`RO~O_PO~O_POb_OcZO~O_POabO~O_POcZO~O_POdfO~O_POcZObSX~OfhO[WP~ObkO~ObmO~O_POdoO~O_POeqO~OfhO[WX~ObuO~O_POdvO~O_PObzO~O_POb!OO~O_POb!RO~O_POb!TO~O_POb!UO~O",
9
+ goto: "#|_PP`flosz!Y!`#i#oP#v#yQSORWQQcXRlaR`TT]T^S[T^RdYQrfSxopS|vwR!P{Qj_RtkQQOjVQXYaenpwy{}!Q!SQXSSYT^QaWQe[QndQpfQwoQyrQ{vQ}xQ!Q|R!S!PQ^TRg^Si_kRsiRUORTO",
10
+ nodeNames:
11
+ "⚠ Http HttpRequestMethod HttpRequestPath HttpHeaders HttpHeader HttpHeaderName HttpHeaderValue HttpBody",
12
+ maxTerm: 22,
13
+ nodeProps: [["group", 2, "Method"]],
14
+ skippedNodes: [0],
15
+ repeatNodeCount: 3,
16
+ tokenData:
17
+ "'xoR]OXzXY&VYZ&^Z]z]^&e^pzpq&Vq![z![!]&t!];'Sz;'S;=`'k;=`<%l's<%lOzo!XYfWcQe``PaSOX!wXY#rZ]!w^p!wpq#rq![!w![!]%W!];'S!w;'S;=`&P<%lO!wg#SYcQe``PaSOX!wXY#rZ]!w^p!wpq#rq![!w![!]%W!];'S!w;'S;=`&P<%lO!wd#wWaSOX$aXY#rZ]$a^p$apq#rq;'S$a;'S;=`%Q<%lO$ad$hWe`aSOX$aXY#rZ]$a^p$apq#rq;'S$a;'S;=`%Q<%lO$ad%TP;=`<%l$ae%aWe``PaSOX%WXY#rZ]%W^p%Wpq#rq;'S%W;'S;=`%y<%lO%We%|P;=`<%l%Wg&SP;=`<%l!wo&^OfW_gZ&eOfWbRZ&lPfWbRYZ&oR&tObRo'RWfWdQe``PaSOX%WXY#rZ]%W^p%Wpq#rq;'S%W;'S;=`%y<%lO%Wo'pPfW;=`<%lzW'xOfW",
18
+ tokenizers: [0, 1, 2, 3, 4],
19
+ topRules: { Http: [0, 1] },
20
+ tokenPrec: 0,
21
+ });
@@ -0,0 +1,87 @@
1
+ import {
2
+ foldInside,
3
+ foldNodeProp,
4
+ type Language,
5
+ LanguageSupport,
6
+ LRLanguage,
7
+ } from "@codemirror/language";
8
+ import { parseMixed } from "@lezer/common";
9
+ import { styleTags, tags } from "@lezer/highlight";
10
+ import type { LRParser } from "@lezer/lr";
11
+ import { parser } from "./grammar/http";
12
+
13
+ function makeParser(
14
+ bodyLanguages: (contentType: string) => Language | null,
15
+ ): LRParser {
16
+ return parser.configure({
17
+ props: [
18
+ styleTags({
19
+ HttpHeaderName: tags.variableName,
20
+ HttpHeaderValue: tags.attributeValue,
21
+ }),
22
+
23
+ foldNodeProp.add({
24
+ HttpHeaders: foldInside,
25
+ }),
26
+ ],
27
+ wrap: parseMixed((node, input) => {
28
+ if (node.name !== "HttpBody") {
29
+ return null;
30
+ }
31
+
32
+ const headers = node.node.prevSibling;
33
+ if (headers?.name !== "HttpHeaders") {
34
+ return null;
35
+ }
36
+
37
+ let contentType: string | null = null;
38
+
39
+ for (
40
+ let child = headers.firstChild;
41
+ child !== null;
42
+ child = child.nextSibling
43
+ ) {
44
+ const headerNameNode = child.getChild("HttpHeaderName");
45
+ if (headerNameNode === null) {
46
+ continue;
47
+ }
48
+
49
+ const headerName = input.read(headerNameNode.from, headerNameNode.to);
50
+ if (headerName.toLowerCase() !== "content-type") {
51
+ continue;
52
+ }
53
+
54
+ if (contentType !== null) {
55
+ // Disallow multiple content types
56
+ return null;
57
+ }
58
+
59
+ const headerValueNode = child.getChild("HttpHeaderValue");
60
+ if (headerValueNode === null) {
61
+ continue;
62
+ }
63
+
64
+ contentType = input.read(headerValueNode.from, headerValueNode.to);
65
+ }
66
+
67
+ if (contentType === null) {
68
+ return null;
69
+ }
70
+
71
+ const language = bodyLanguages(contentType);
72
+ if (language === null) {
73
+ return null;
74
+ }
75
+
76
+ return { parser: language.parser };
77
+ }),
78
+ });
79
+ }
80
+
81
+ function http(bodyLanguages: (contentType: string) => Language | null) {
82
+ const parser = makeParser(bodyLanguages);
83
+ const language = LRLanguage.define({ parser: parser });
84
+ return new LanguageSupport(language, []);
85
+ }
86
+
87
+ export { http };
@@ -16,7 +16,7 @@ import {
16
16
  } from "@codemirror/language";
17
17
  import { linter, lintGutter, lintKeymap } from "@codemirror/lint";
18
18
  import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
19
- import { EditorState } from "@codemirror/state";
19
+ import { Compartment, EditorState } from "@codemirror/state";
20
20
  import {
21
21
  crosshairCursor,
22
22
  drawSelection,
@@ -28,10 +28,13 @@ import {
28
28
  keymap,
29
29
  lineNumbers,
30
30
  rectangularSelection,
31
+ type ViewUpdate,
31
32
  } from "@codemirror/view";
32
33
  import { tags } from "@lezer/highlight";
33
34
  import * as React from "react";
34
35
 
36
+ import { http } from "./http";
37
+
35
38
  const baseTheme = EditorView.baseTheme({
36
39
  "&": {
37
40
  backgroundColor: "var(--color-bg-primary)",
@@ -70,6 +73,44 @@ const baseTheme = EditorView.baseTheme({
70
73
  },
71
74
  });
72
75
 
76
+ const readOnlyTheme = EditorView.theme({
77
+ "&": {
78
+ backgroundColor: "var(--color-bg-secondary)",
79
+ height: "100%",
80
+ width: "100%",
81
+ fontSize: "14px",
82
+ paddingTop: "8px",
83
+ paddingBottom: "8px",
84
+ },
85
+ ".cm-scroller": {
86
+ overflow: "auto",
87
+ },
88
+ ".cm-content": {
89
+ fontFamily: "var(--font-family-mono)",
90
+ padding: "0",
91
+ },
92
+ "&.cm-focused": {
93
+ outline: "none",
94
+ },
95
+ ".cm-gutter": {
96
+ fontFamily: "var(--font-family-mono)",
97
+ },
98
+ ".cm-gutters": {
99
+ backgroundColor: "var(--color-bg-secondary)",
100
+ border: "none",
101
+ },
102
+ ".cm-lineNumbers": {
103
+ paddingLeft: "16px",
104
+ },
105
+ ".cm-activeLineGutter": {
106
+ backgroundColor: "var(--color-bg-secondary)",
107
+ color: "var(--color-text-primary)",
108
+ },
109
+ ".cm-activeLine": {
110
+ backgroundColor: "rgba(255, 255, 255, 0)",
111
+ },
112
+ });
113
+
73
114
  const customHighlightStyle = HighlightStyle.define([
74
115
  { tag: tags.propertyName, color: "#EA4A35" },
75
116
  { tag: tags.string, color: "#405CBF" },
@@ -78,25 +119,70 @@ const customHighlightStyle = HighlightStyle.define([
78
119
  { tag: tags.null, color: "#569cd6" },
79
120
  ]);
80
121
 
122
+ type LanguageMode = "json" | "http";
123
+
124
+ function languageExtensions(mode: LanguageMode) {
125
+ if (mode === "http") {
126
+ const jsonLang = json();
127
+ return [
128
+ http((ct) => (ct === "application/json" ? jsonLang.language : null)),
129
+ syntaxHighlighting(customHighlightStyle),
130
+ ];
131
+ } else {
132
+ return [
133
+ json(),
134
+ linter(jsonParseLinter(), { delay: 300 }),
135
+ syntaxHighlighting(customHighlightStyle),
136
+ ];
137
+ }
138
+ }
139
+
140
+ type CodeEditorProps = {
141
+ readOnly?: boolean;
142
+ defaultValue?: string;
143
+ currentValue?: string;
144
+ onChange?: (value: string) => void;
145
+ onUpdate?: (update: ViewUpdate) => void;
146
+ id?: string;
147
+ mode?: LanguageMode;
148
+ viewCallback?: (view: EditorView) => void;
149
+ };
150
+
151
+ export type CodeEditorView = EditorView;
152
+
81
153
  export function CodeEditor({
82
154
  defaultValue,
155
+ currentValue,
83
156
  onChange,
84
- }: {
85
- defaultValue?: string;
86
- onChange?: (value: string) => void;
87
- }) {
88
- const editorRef = React.useRef(null);
157
+ onUpdate,
158
+ viewCallback,
159
+ readOnly = false,
160
+ id,
161
+ mode = "json",
162
+ }: CodeEditorProps) {
163
+ const domRef = React.useRef(null);
164
+ const [view, setView] = React.useState<EditorView | null>(null);
165
+
166
+ const initialValue = React.useRef(defaultValue ?? "");
167
+
168
+ const onChangeComparment = React.useRef(new Compartment());
169
+ const onUpdateComparment = React.useRef(new Compartment());
170
+ const languageCompartment = React.useRef(new Compartment());
171
+ const readOnlyCompartment = React.useRef(new Compartment());
172
+ const themeCompartment = React.useRef(new Compartment());
89
173
 
90
174
  React.useEffect(() => {
91
- if (!editorRef.current) {
175
+ if (!domRef.current) {
92
176
  return;
93
177
  }
94
178
 
95
179
  const view = new EditorView({
96
- parent: editorRef.current,
180
+ parent: domRef.current,
97
181
  state: EditorState.create({
98
- doc: defaultValue ?? "",
182
+ doc: initialValue.current,
99
183
  extensions: [
184
+ EditorView.contentAttributes.of({ "data-gramm": "false" }),
185
+ readOnlyCompartment.current.of(EditorState.readOnly.of(false)),
100
186
  lineNumbers(),
101
187
  foldGutter(),
102
188
  highlightSpecialChars(),
@@ -105,8 +191,7 @@ export function CodeEditor({
105
191
  dropCursor(),
106
192
  EditorState.allowMultipleSelections.of(true),
107
193
  indentOnInput(),
108
- json(),
109
- syntaxHighlighting(customHighlightStyle),
194
+ languageCompartment.current.of([]),
110
195
  bracketMatching(),
111
196
  closeBrackets(),
112
197
  autocompletion(),
@@ -115,7 +200,7 @@ export function CodeEditor({
115
200
  highlightActiveLine(),
116
201
  highlightActiveLineGutter(),
117
202
  highlightSelectionMatches(),
118
- baseTheme,
203
+ themeCompartment.current.of(baseTheme),
119
204
  keymap.of([
120
205
  ...closeBracketsKeymap,
121
206
  ...defaultKeymap,
@@ -125,19 +210,95 @@ export function CodeEditor({
125
210
  ...completionKeymap,
126
211
  ...lintKeymap,
127
212
  ]),
128
- linter(jsonParseLinter(), { delay: 300 }),
129
213
  lintGutter(),
130
- EditorView.updateListener.of((update) => {
131
- if (update.docChanged && onChange) {
132
- onChange(update.view.state.doc.toString());
133
- }
134
- }),
214
+ onChangeComparment.current.of([]),
215
+ onUpdateComparment.current.of([]),
135
216
  ],
136
217
  }),
137
218
  });
138
219
 
139
- return () => view.destroy();
140
- }, [defaultValue, onChange]);
220
+ setView(() => view);
221
+
222
+ return () => {
223
+ view.destroy();
224
+ setView(() => null);
225
+ };
226
+ }, []);
227
+
228
+ React.useEffect(() => {
229
+ if (viewCallback && view) {
230
+ viewCallback(view);
231
+ }
232
+ }, [view, viewCallback]);
233
+
234
+ React.useEffect(() => {
235
+ view?.dispatch({
236
+ effects: onChangeComparment.current.reconfigure([
237
+ EditorView.updateListener.of((update) => {
238
+ if (update.docChanged && onChange) {
239
+ onChange(update.view.state.doc.toString());
240
+ }
241
+ }),
242
+ ]),
243
+ });
244
+ }, [view, onChange]);
245
+
246
+ React.useEffect(() => {
247
+ view?.dispatch({
248
+ effects: onUpdateComparment.current.reconfigure([
249
+ EditorView.updateListener.of((update) => {
250
+ if (onUpdate) {
251
+ onUpdate(update);
252
+ }
253
+ }),
254
+ ]),
255
+ });
256
+ }, [view, onUpdate]);
257
+
258
+ // FIXME: it is probably better to have CM manage its state.
259
+ React.useEffect(() => {
260
+ if (!view || currentValue === undefined) {
261
+ return;
262
+ }
263
+
264
+ const currentDoc = view.state.doc.toString();
265
+ if (currentDoc !== currentValue) {
266
+ view.dispatch({
267
+ changes: {
268
+ from: 0,
269
+ to: currentDoc.length,
270
+ insert: currentValue,
271
+ },
272
+ });
273
+ }
274
+ }, [currentValue, view]);
275
+
276
+ React.useEffect(() => {
277
+ if (view === null) {
278
+ return;
279
+ }
280
+ view.dispatch({
281
+ effects: languageCompartment.current.reconfigure(
282
+ languageExtensions(mode),
283
+ ),
284
+ });
285
+ }, [mode, view]);
286
+
287
+ React.useEffect(() => {
288
+ if (view === null) {
289
+ return;
290
+ }
291
+ view.dispatch({
292
+ effects: [
293
+ readOnlyCompartment.current.reconfigure(
294
+ EditorState.readOnly.of(readOnly),
295
+ ),
296
+ themeCompartment.current.reconfigure(
297
+ readOnly ? readOnlyTheme : baseTheme,
298
+ ),
299
+ ],
300
+ });
301
+ }, [readOnly, view]);
141
302
 
142
- return <div className="h-full w-full" ref={editorRef} />;
303
+ return <div className="h-full w-full" ref={domRef} id={id} />;
143
304
  }
@@ -28,7 +28,7 @@ export const Default: Story = {
28
28
  },
29
29
  render: () => (
30
30
  <div className="h-[500px] w-[500px]">
31
- <CodeEditor />
31
+ <CodeEditor mode="http" />
32
32
  </div>
33
33
  ),
34
34
  };
@@ -18,13 +18,9 @@ const meta: Meta<typeof RequestLineEditor> = {
18
18
  export default meta;
19
19
  type Story = StoryObj<typeof RequestLineEditor>;
20
20
 
21
- function RequestLineEditorWrapper({
22
- selectedMethod,
23
- methods,
24
- inputValue,
25
- }: RequestLineEditorProps) {
26
- const [currentSelectedMethod, setMethod] = React.useState(selectedMethod);
27
- const [currentInputValue, setInputValue] = React.useState(inputValue);
21
+ function RequestLineEditorWrapper({ method, path }: RequestLineEditorProps) {
22
+ const [currentSelectedMethod, setMethod] = React.useState(method);
23
+ const [currentInputValue, setInputValue] = React.useState(path);
28
24
  const actionSetMethod = (method: string) => {
29
25
  action("setMethod")(method);
30
26
  setMethod(method);
@@ -35,56 +31,50 @@ function RequestLineEditorWrapper({
35
31
  };
36
32
  return (
37
33
  <RequestLineEditor
38
- methods={methods}
39
- selectedMethod={currentSelectedMethod}
40
- setMethod={actionSetMethod}
41
- inputValue={currentInputValue}
42
- onInputChange={actionSetInputValue}
34
+ method={currentSelectedMethod}
35
+ onMethodChange={actionSetMethod}
36
+ path={currentInputValue}
37
+ onPathChange={actionSetInputValue}
43
38
  />
44
39
  );
45
40
  }
46
41
 
47
42
  export const GET: Story = {
48
43
  args: {
49
- selectedMethod: "GET",
50
- methods: ["GET", "POST", "PUT", "PATCH", "DELETE"],
51
- inputValue: "/fhir/Patient",
44
+ method: "GET",
45
+ path: "/fhir/Patient",
52
46
  },
53
47
  render: (args) => <RequestLineEditorWrapper {...args} />,
54
48
  };
55
49
 
56
50
  export const POST: Story = {
57
51
  args: {
58
- selectedMethod: "POST",
59
- methods: ["GET", "POST", "PUT", "PATCH", "DELETE"],
60
- inputValue: "/fhir/Patient",
52
+ method: "POST",
53
+ path: "/fhir/Patient",
61
54
  },
62
55
  render: (args) => <RequestLineEditorWrapper {...args} />,
63
56
  };
64
57
 
65
58
  export const PUT: Story = {
66
59
  args: {
67
- selectedMethod: "PUT",
68
- methods: ["GET", "POST", "PUT", "PATCH", "DELETE"],
69
- inputValue: "/fhir/Patient",
60
+ method: "PUT",
61
+ path: "/fhir/Patient",
70
62
  },
71
63
  render: (args) => <RequestLineEditorWrapper {...args} />,
72
64
  };
73
65
 
74
66
  export const PATCH: Story = {
75
67
  args: {
76
- selectedMethod: "PATCH",
77
- methods: ["GET", "POST", "PUT", "PATCH", "DELETE"],
78
- inputValue: "/fhir/Patient",
68
+ method: "PATCH",
69
+ path: "/fhir/Patient",
79
70
  },
80
71
  render: (args) => <RequestLineEditorWrapper {...args} />,
81
72
  };
82
73
 
83
74
  export const DELETE: Story = {
84
75
  args: {
85
- selectedMethod: "DELETE",
86
- methods: ["GET", "POST", "PUT", "PATCH", "DELETE"],
87
- inputValue: "/fhir/Patient",
76
+ method: "DELETE",
77
+ path: "/fhir/Patient",
88
78
  },
89
79
  render: (args) => <RequestLineEditorWrapper {...args} />,
90
80
  };