@health-samurai/react-components 0.0.0-alpha.13 → 0.0.0-alpha.15

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.
@@ -147,34 +147,50 @@
147
147
  --corner-corner-m: 6px;
148
148
  --corner-corner-l: 8px;
149
149
  --corner-corner-xs: 2px;
150
- --color-elements-readable: var(--color-neutral-900);
151
150
  --color-cta: var(--color-brand-600);
152
151
  --color-critical-default: var(--color-red-600);
153
- --color-elements-disabled: var(--color-neutral-300);
154
- --color-elements-assistive: var(--color-neutral-500);
155
- --color-surface-0: var(--color-neutral-50);
156
- --color-border-default: var(--color-neutral-200);
157
- --color-surface-selected: var(--color-neutral-200);
158
152
  --color-cta-hover: var(--color-brand-700);
159
153
  --color-critical-hover: var(--color-red-700);
160
- --color-surface-1: var(--color-neutral-100);
161
154
  --color-border-XS-critical: var(--color-red-50);
162
155
  --color-border-XS-critical-hover: var(--color-red-100);
163
156
  --color-elements-green: var(--color-green-600);
164
157
  --color-elements-yellow: var(--color-yellow-500);
165
158
  --color-border-XS-regular: var(--color-blue-300);
166
159
  --color-border-XS-regular-hover: var(--color-blue-400);
167
- --color-separator: var(--color-neutral-200);
168
160
  --color-surface-info: var(--color-blue-50);
169
161
  --color-surface-warning: var(--color-yellow-50);
170
162
  --color-surface-alert: var(--color-red-50);
171
163
  --color-elements-warning: var(--color-yellow-700);
172
164
  --color-code-red: var(--color-red-600);
173
165
  --color-code-blue: var(--color-blue-500);
174
- --color-elements-readable-inv: var(--color-neutral-50);
175
166
  --color-logo-readable: var(--color-neutral-800);
176
167
  --color-elements-links: var(--color-brand-600);
177
168
  --color-elements-info: var(--color-brand-600);
178
169
  --color-elements-alert: var(--color-red-600);
179
170
  --color-illustrations-solid: var(--color-brand-600);
180
171
  }
172
+
173
+ /* Semantic tokens that need dark mode overrides — use @theme inline + :root so .dark can override */
174
+ @theme inline {
175
+ --color-elements-readable: var(--hs-elements-readable);
176
+ --color-elements-readable-inv: var(--hs-elements-readable-inv);
177
+ --color-elements-assistive: var(--hs-elements-assistive);
178
+ --color-elements-disabled: var(--hs-elements-disabled);
179
+ --color-surface-0: var(--hs-surface-0);
180
+ --color-surface-1: var(--hs-surface-1);
181
+ --color-surface-selected: var(--hs-surface-selected);
182
+ --color-border-default: var(--hs-border-default);
183
+ --color-separator: var(--hs-separator);
184
+ }
185
+
186
+ :root {
187
+ --hs-elements-readable: var(--color-neutral-900);
188
+ --hs-elements-readable-inv: var(--color-neutral-50);
189
+ --hs-elements-assistive: var(--color-neutral-500);
190
+ --hs-elements-disabled: var(--color-neutral-300);
191
+ --hs-surface-0: var(--color-neutral-50);
192
+ --hs-surface-1: var(--color-neutral-100);
193
+ --hs-surface-selected: var(--color-neutral-200);
194
+ --hs-border-default: var(--color-neutral-200);
195
+ --hs-separator: var(--color-neutral-200);
196
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@health-samurai/react-components",
3
- "version": "0.0.0-alpha.13",
3
+ "version": "0.0.0-alpha.15",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -55,7 +55,7 @@ import {
55
55
  type ViewUpdate,
56
56
  } from "@codemirror/view";
57
57
  import { tags } from "@lezer/highlight";
58
- import { ChevronDown, ChevronUp, X } from "lucide-react";
58
+ import { Braces, ChevronDown, ChevronUp, Terminal, X } from "lucide-react";
59
59
  import * as React from "react";
60
60
  import { flushSync } from "react-dom";
61
61
  import { createRoot } from "react-dom/client";
@@ -200,17 +200,21 @@ const errorTooltipHandler = EditorView.domEventHandlers({
200
200
  },
201
201
  });
202
202
 
203
- const baseTheme = EditorView.baseTheme({
203
+ const baseTheme = EditorView.theme({
204
204
  "&": {
205
205
  backgroundColor: "var(--color-bg-primary)",
206
206
  height: "100%",
207
207
  width: "100%",
208
208
  fontSize: "14px",
209
- paddingTop: "8px",
210
- paddingBottom: "8px",
209
+ },
210
+ "&.cm-editor": {
211
+ paddingTop: "0 !important",
212
+ paddingBottom: "0 !important",
211
213
  },
212
214
  ".cm-scroller": {
213
215
  overflow: "auto",
216
+ paddingTop: "8px",
217
+ paddingBottom: "8px",
214
218
  },
215
219
  ".cm-content": {
216
220
  fontFamily: "var(--font-family-mono)",
@@ -219,6 +223,9 @@ const baseTheme = EditorView.baseTheme({
219
223
  "&.cm-focused": {
220
224
  outline: "none",
221
225
  },
226
+ ".cm-cursor, .cm-dropCursor": {
227
+ borderLeftColor: "var(--color-text-primary)",
228
+ },
222
229
  ".cm-gutter": {
223
230
  fontFamily: "var(--font-family-mono)",
224
231
  },
@@ -247,17 +254,62 @@ const baseTheme = EditorView.baseTheme({
247
254
  },
248
255
  });
249
256
 
257
+ const completionTheme = EditorView.theme({
258
+ ".cm-tooltip.cm-tooltip-autocomplete > ul": {
259
+ maxHeight: "400px",
260
+ },
261
+ ".cm-tooltip.cm-tooltip-autocomplete > ul > li": {
262
+ display: "flex",
263
+ alignItems: "center",
264
+ gap: "8px",
265
+ },
266
+ ".cm-completionLabel": {
267
+ flex: "1",
268
+ minWidth: "0",
269
+ },
270
+ ".cm-completionDetail": {
271
+ color: "var(--color-text-tertiary)",
272
+ fontSize: "12px",
273
+ marginLeft: "auto",
274
+ whiteSpace: "nowrap",
275
+ },
276
+ ".cm-completionInfo": {
277
+ backgroundColor: "var(--color-bg-primary)",
278
+ border: "1px solid var(--color-border-primary)",
279
+ borderRadius: "var(--radius-md)",
280
+ color: "var(--color-text-secondary)",
281
+ fontFamily: "var(--font-family-sans)",
282
+ fontSize: "12px",
283
+ padding: "8px 12px",
284
+ lineHeight: "1.4",
285
+ whiteSpace: "normal",
286
+ maxWidth: "300px",
287
+ },
288
+ ".cm-completion-icon": {
289
+ display: "flex",
290
+ alignItems: "center",
291
+ justifyContent: "center",
292
+ width: "16px",
293
+ height: "16px",
294
+ flexShrink: "0",
295
+ },
296
+ });
297
+
250
298
  const readOnlyTheme = EditorView.theme({
251
299
  "&": {
252
300
  backgroundColor: "var(--color-bg-secondary)",
253
301
  height: "100%",
254
302
  width: "100%",
255
303
  fontSize: "14px",
256
- paddingTop: "8px",
257
- paddingBottom: "8px",
304
+ },
305
+ "&.cm-editor": {
306
+ paddingTop: "0 !important",
307
+ paddingBottom: "0 !important",
258
308
  },
259
309
  ".cm-scroller": {
260
310
  overflow: "auto",
311
+ paddingTop: "8px",
312
+ paddingBottom: "8px",
261
313
  },
262
314
  ".cm-content": {
263
315
  fontFamily: "var(--font-family-mono)",
@@ -534,20 +586,20 @@ const customSearchExtension = [
534
586
  ];
535
587
 
536
588
  const customHighlightStyle = HighlightStyle.define([
537
- { tag: tags.propertyName, color: "#EA4A35" },
538
- { tag: tags.string, color: "#405CBF" },
539
- { tag: tags.number, color: "#00A984" },
540
- { tag: tags.bool, color: "#569cd6" },
541
- { tag: tags.null, color: "#569cd6" },
542
- { tag: tags.keyword, color: "#569cd6" },
543
- { tag: tags.operatorKeyword, color: "#405CBF" },
544
- { tag: tags.controlKeyword, color: "#EA4A35" },
545
- { tag: tags.typeName, color: "#00A984" },
546
- { tag: tags.variableName, color: "#EA4A35" },
547
- { tag: tags.operator, color: "#405CBF" },
548
- { tag: tags.comment, color: "#00A984" },
549
- { tag: tags.lineComment, color: "#00A984" },
550
- { tag: tags.blockComment, color: "#00A984" },
589
+ { tag: tags.propertyName, color: "var(--hs-syntax-property)" },
590
+ { tag: tags.string, color: "var(--hs-syntax-string)" },
591
+ { tag: tags.number, color: "var(--hs-syntax-number)" },
592
+ { tag: tags.bool, color: "var(--hs-syntax-keyword)" },
593
+ { tag: tags.null, color: "var(--hs-syntax-keyword)" },
594
+ { tag: tags.keyword, color: "var(--hs-syntax-keyword)" },
595
+ { tag: tags.operatorKeyword, color: "var(--hs-syntax-string)" },
596
+ { tag: tags.controlKeyword, color: "var(--hs-syntax-property)" },
597
+ { tag: tags.typeName, color: "var(--hs-syntax-number)" },
598
+ { tag: tags.variableName, color: "var(--hs-syntax-property)" },
599
+ { tag: tags.operator, color: "var(--hs-syntax-string)" },
600
+ { tag: tags.comment, color: "var(--hs-syntax-comment)" },
601
+ { tag: tags.lineComment, color: "var(--hs-syntax-comment)" },
602
+ { tag: tags.blockComment, color: "var(--hs-syntax-comment)" },
551
603
  ]);
552
604
 
553
605
  const SQL_KEYWORDS = [
@@ -748,13 +800,27 @@ export function CodeEditor({
748
800
  languageCompartment.current.of([]),
749
801
  bracketMatching(),
750
802
  closeBrackets(),
751
- autocompletion(),
803
+ autocompletion({
804
+ icons: false,
805
+ maxRenderedOptions: 1000,
806
+ addToOptions: [{ render: renderCompletionIcon, position: 20 }],
807
+ optionClass: (_completion) =>
808
+ "!px-2 !py-1 rounded-md aria-selected:!bg-bg-quaternary aria-selected:!text-text-primary hover:!bg-bg-secondary flex items-center gap-2",
809
+ tooltipClass: (_state) =>
810
+ "!bg-bg-primary rounded-md p-2 shadow-md !border-border-primary !typo-body",
811
+ compareCompletions: (a, b) => {
812
+ const aIsProperty = a.type === "property" ? 0 : 1;
813
+ const bIsProperty = b.type === "property" ? 0 : 1;
814
+ return aIsProperty - bIsProperty;
815
+ },
816
+ }),
752
817
  rectangularSelection(),
753
818
  crosshairCursor(),
754
819
  highlightActiveLine(),
755
820
  highlightActiveLineGutter(),
756
821
  highlightSelectionMatches(),
757
822
  themeCompartment.current.of(baseTheme),
823
+ completionTheme,
758
824
  keymap.of([
759
825
  ...closeBracketsKeymap,
760
826
  ...defaultKeymap,
@@ -908,6 +974,9 @@ const editorInputTheme = EditorView.theme({
908
974
  fontSize: "var(--font-size-sm)",
909
975
  color: "var(--color-text-primary)",
910
976
  },
977
+ ".cm-cursor, .cm-dropCursor": {
978
+ borderLeftColor: "var(--color-text-primary)",
979
+ },
911
980
  "&.cm-editor.cm-focused": {
912
981
  outline: "none",
913
982
  },
@@ -942,10 +1011,18 @@ const editorInputTheme = EditorView.theme({
942
1011
  },
943
1012
  });
944
1013
 
1014
+ const KeywordIcon = () => <Terminal size={16} color="#717684" />;
1015
+ const OperatorIcon = () => <Braces size={16} color="#717684" />;
1016
+
945
1017
  function getCompletionIcon(completion: Completion): React.FC | null {
946
1018
  if (completion.type === "function") return SquareFunctionIcon;
1019
+ if (completion.type === "keyword") return KeywordIcon;
1020
+ if (completion.type === "operator") return OperatorIcon;
947
1021
  const detail = completion.detail;
948
- if (!detail) return null;
1022
+ if (!detail) {
1023
+ if (completion.type === "variable") return SquareFunctionIcon;
1024
+ return null;
1025
+ }
949
1026
  const typeName = detail.replace(/\[\]$/, "");
950
1027
  if (!typeName) return null;
951
1028
  const firstChar = typeName[0];
@@ -206,13 +206,13 @@ function FhirStructureView({
206
206
  }, [tree]);
207
207
 
208
208
  return (
209
- <div className="h-fit w-fit min-h-0 min-w-0">
210
- <div className="flex items-center gap-2 font-semibold text-xs text-text-secondary border-b py-2 bg-bg-primary sticky top-0 z-20">
211
- <div className="min-w-[260px] w-[260px] ml-4">Name</div>
209
+ <div className="min-h-0 min-w-0">
210
+ <div className="flex items-center gap-2 font-semibold text-xs text-text-secondary border-b py-2 pl-[34px] bg-bg-primary sticky top-0 z-20">
211
+ <div className="min-w-[260px] w-[260px]">Name</div>
212
212
  <div className="min-w-[60px] w-[60px]">Flags</div>
213
213
  <div className="min-w-[50px] w-[50px]">Card.</div>
214
214
  <div className="min-w-[200px] w-[200px]">Type</div>
215
- <div className="min-w-[200px] w-[200px]">Description</div>
215
+ <div className="flex-1">Description</div>
216
216
  </div>
217
217
  <TreeView
218
218
  focusedItem={null}