@health-samurai/react-components 0.0.0-alpha.5 → 0.0.0-alpha.7
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.
- package/dist/bundle.css +318 -31
- package/dist/src/components/button-dropdown.d.ts +10 -0
- package/dist/src/components/button-dropdown.d.ts.map +1 -0
- package/dist/src/components/button-dropdown.js +70 -0
- package/dist/src/components/button-dropdown.js.map +1 -0
- package/dist/src/components/button-dropdown.stories.d.ts +11 -0
- package/dist/src/components/button-dropdown.stories.d.ts.map +1 -0
- package/dist/src/components/button-dropdown.stories.js +48 -0
- package/dist/src/components/button-dropdown.stories.js.map +1 -0
- package/dist/src/components/code-editor/index.d.ts +3 -2
- package/dist/src/components/code-editor/index.d.ts.map +1 -1
- package/dist/src/components/code-editor/index.js +152 -4
- package/dist/src/components/code-editor/index.js.map +1 -1
- package/dist/src/components/code-editor.stories.d.ts +1 -0
- package/dist/src/components/code-editor.stories.d.ts.map +1 -1
- package/dist/src/components/code-editor.stories.js +252 -1
- package/dist/src/components/code-editor.stories.js.map +1 -1
- package/dist/src/components/copy-icon.d.ts +5 -1
- package/dist/src/components/copy-icon.d.ts.map +1 -1
- package/dist/src/components/copy-icon.js +41 -3
- package/dist/src/components/copy-icon.js.map +1 -1
- package/dist/src/components/data-table.d.ts +9 -0
- package/dist/src/components/data-table.d.ts.map +1 -0
- package/dist/src/components/data-table.js +66 -0
- package/dist/src/components/data-table.js.map +1 -0
- package/dist/src/components/data-table.stories.d.ts +7 -0
- package/dist/src/components/data-table.stories.d.ts.map +1 -0
- package/dist/src/components/data-table.stories.js +240 -0
- package/dist/src/components/data-table.stories.js.map +1 -0
- package/dist/src/components/fhir-structure-view.d.ts +34 -0
- package/dist/src/components/fhir-structure-view.d.ts.map +1 -0
- package/dist/src/components/fhir-structure-view.js +226 -0
- package/dist/src/components/fhir-structure-view.js.map +1 -0
- package/dist/src/components/fhir-structure-view.stories.d.ts +7 -0
- package/dist/src/components/fhir-structure-view.stories.d.ts.map +1 -0
- package/dist/src/components/fhir-structure-view.stories.js +447 -0
- package/dist/src/components/fhir-structure-view.stories.js.map +1 -0
- package/dist/src/components/request-line-editor.d.ts +3 -1
- package/dist/src/components/request-line-editor.d.ts.map +1 -1
- package/dist/src/components/request-line-editor.js +26 -5
- package/dist/src/components/request-line-editor.js.map +1 -1
- package/dist/src/components/segment-control.d.ts +16 -0
- package/dist/src/components/segment-control.d.ts.map +1 -0
- package/dist/src/components/segment-control.js +48 -0
- package/dist/src/components/segment-control.js.map +1 -0
- package/dist/src/components/segment-control.stories.d.ts +15 -0
- package/dist/src/components/segment-control.stories.d.ts.map +1 -0
- package/dist/src/components/segment-control.stories.js +33 -0
- package/dist/src/components/segment-control.stories.js.map +1 -0
- package/dist/src/components/split-button.d.ts +5 -0
- package/dist/src/components/split-button.d.ts.map +1 -0
- package/dist/src/components/split-button.js +12 -0
- package/dist/src/components/split-button.js.map +1 -0
- package/dist/src/components/split-button.stories.d.ts +7 -0
- package/dist/src/components/split-button.stories.d.ts.map +1 -0
- package/dist/src/components/split-button.stories.js +57 -0
- package/dist/src/components/split-button.stories.js.map +1 -0
- package/dist/src/components/tree-view.d.ts +16 -7
- package/dist/src/components/tree-view.d.ts.map +1 -1
- package/dist/src/components/tree-view.js +75 -19
- package/dist/src/components/tree-view.js.map +1 -1
- package/dist/src/components/tree-view.stories.d.ts +3 -3
- package/dist/src/components/tree-view.stories.d.ts.map +1 -1
- package/dist/src/components/tree-view.stories.js +14 -5
- package/dist/src/components/tree-view.stories.js.map +1 -1
- package/dist/src/icons.d.ts +6 -0
- package/dist/src/icons.d.ts.map +1 -1
- package/dist/src/icons.js +235 -3
- package/dist/src/icons.js.map +1 -1
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +10 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/shadcn/components/ui/alert-dialog.d.ts +3 -1
- package/dist/src/shadcn/components/ui/alert-dialog.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/alert-dialog.js +5 -2
- package/dist/src/shadcn/components/ui/alert-dialog.js.map +1 -1
- package/dist/src/shadcn/components/ui/badge.d.ts +1 -1
- package/dist/src/shadcn/components/ui/card.d.ts +5 -1
- package/dist/src/shadcn/components/ui/card.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/card.js +21 -8
- package/dist/src/shadcn/components/ui/card.js.map +1 -1
- package/dist/src/shadcn/components/ui/card.stories.d.ts +302 -1
- package/dist/src/shadcn/components/ui/card.stories.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/card.stories.js +23 -2
- package/dist/src/shadcn/components/ui/card.stories.js.map +1 -1
- package/dist/src/shadcn/components/ui/combobox.d.ts +13 -0
- package/dist/src/shadcn/components/ui/combobox.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/combobox.js +102 -0
- package/dist/src/shadcn/components/ui/combobox.js.map +1 -1
- package/dist/src/shadcn/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/dropdown-menu.js +1 -1
- package/dist/src/shadcn/components/ui/dropdown-menu.js.map +1 -1
- package/dist/src/shadcn/components/ui/input.d.ts +3 -1
- package/dist/src/shadcn/components/ui/input.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/input.js +39 -1
- package/dist/src/shadcn/components/ui/input.js.map +1 -1
- package/dist/src/shadcn/components/ui/pagination.d.ts +8 -1
- package/dist/src/shadcn/components/ui/pagination.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/pagination.js +36 -19
- package/dist/src/shadcn/components/ui/pagination.js.map +1 -1
- package/dist/src/shadcn/components/ui/pagination.stories.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/pagination.stories.js +44 -37
- package/dist/src/shadcn/components/ui/pagination.stories.js.map +1 -1
- package/dist/src/shadcn/components/ui/table.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/table.js +1 -1
- package/dist/src/shadcn/components/ui/table.js.map +1 -1
- package/dist/src/shadcn/components/ui/tabs.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/tabs.js +1 -0
- package/dist/src/shadcn/components/ui/tabs.js.map +1 -1
- package/dist/src/shadcn/components/ui/tree.d.ts +10 -2
- package/dist/src/shadcn/components/ui/tree.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/tree.js +31 -8
- package/dist/src/shadcn/components/ui/tree.js.map +1 -1
- package/dist/src/typography.css +36 -8
- package/package.json +5 -1
- package/src/components/button-dropdown.stories.tsx +41 -0
- package/src/components/button-dropdown.tsx +95 -0
- package/src/components/code-editor/index.tsx +129 -4
- package/src/components/code-editor.stories.tsx +294 -0
- package/src/components/copy-icon.tsx +57 -3
- package/src/components/data-table.stories.tsx +89 -0
- package/src/components/data-table.tsx +120 -0
- package/src/components/fhir-structure-view.stories.tsx +439 -0
- package/src/components/fhir-structure-view.tsx +229 -0
- package/src/components/request-line-editor.tsx +30 -4
- package/src/components/segment-control.stories.tsx +29 -0
- package/src/components/segment-control.tsx +81 -0
- package/src/components/split-button.stories.tsx +49 -0
- package/src/components/split-button.tsx +17 -0
- package/src/components/tree-view.stories.tsx +20 -15
- package/src/components/tree-view.tsx +118 -15
- package/src/icons.tsx +245 -3
- package/src/index.tsx +10 -2
- package/src/shadcn/components/ui/alert-dialog.tsx +6 -2
- package/src/shadcn/components/ui/card.stories.tsx +17 -3
- package/src/shadcn/components/ui/card.tsx +52 -8
- package/src/shadcn/components/ui/combobox.tsx +127 -0
- package/src/shadcn/components/ui/dropdown-menu.tsx +1 -2
- package/src/shadcn/components/ui/input.tsx +119 -0
- package/src/shadcn/components/ui/pagination.stories.tsx +8 -2
- package/src/shadcn/components/ui/pagination.tsx +54 -3
- package/src/shadcn/components/ui/table.tsx +6 -1
- package/src/shadcn/components/ui/tabs.tsx +1 -0
- package/src/shadcn/components/ui/tree.tsx +63 -10
- package/src/typography.css +36 -8
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
} from "@codemirror/autocomplete";
|
|
7
7
|
import { defaultKeymap, history, historyKeymap } from "@codemirror/commands";
|
|
8
8
|
import { json, jsonParseLinter } from "@codemirror/lang-json";
|
|
9
|
+
import { SQLDialect, sql } from "@codemirror/lang-sql";
|
|
10
|
+
import { yaml } from "@codemirror/lang-yaml";
|
|
9
11
|
import {
|
|
10
12
|
bracketMatching,
|
|
11
13
|
foldGutter,
|
|
@@ -117,17 +119,128 @@ const customHighlightStyle = HighlightStyle.define([
|
|
|
117
119
|
{ tag: tags.number, color: "#00A984" },
|
|
118
120
|
{ tag: tags.bool, color: "#569cd6" },
|
|
119
121
|
{ tag: tags.null, color: "#569cd6" },
|
|
122
|
+
{ tag: tags.keyword, color: "#569cd6" },
|
|
123
|
+
{ tag: tags.operatorKeyword, color: "#405CBF" },
|
|
124
|
+
{ tag: tags.controlKeyword, color: "#EA4A35" },
|
|
125
|
+
{ tag: tags.typeName, color: "#00A984" },
|
|
126
|
+
{ tag: tags.variableName, color: "#EA4A35" },
|
|
127
|
+
{ tag: tags.operator, color: "#405CBF" },
|
|
128
|
+
{ tag: tags.comment, color: "#00A984" },
|
|
129
|
+
{ tag: tags.lineComment, color: "#00A984" },
|
|
130
|
+
{ tag: tags.blockComment, color: "#00A984" },
|
|
120
131
|
]);
|
|
121
132
|
|
|
122
|
-
|
|
133
|
+
const SQL_KEYWORDS = [
|
|
134
|
+
"select",
|
|
135
|
+
"from",
|
|
136
|
+
"where",
|
|
137
|
+
"and",
|
|
138
|
+
"or",
|
|
139
|
+
"not",
|
|
140
|
+
"in",
|
|
141
|
+
"between",
|
|
142
|
+
"like",
|
|
143
|
+
"insert",
|
|
144
|
+
"update",
|
|
145
|
+
"delete",
|
|
146
|
+
"create",
|
|
147
|
+
"drop",
|
|
148
|
+
"alter",
|
|
149
|
+
"table",
|
|
150
|
+
"index",
|
|
151
|
+
"join",
|
|
152
|
+
"inner",
|
|
153
|
+
"left",
|
|
154
|
+
"right",
|
|
155
|
+
"outer",
|
|
156
|
+
"on",
|
|
157
|
+
"as",
|
|
158
|
+
"order",
|
|
159
|
+
"by",
|
|
160
|
+
"group",
|
|
161
|
+
"having",
|
|
162
|
+
"limit",
|
|
163
|
+
"offset",
|
|
164
|
+
"union",
|
|
165
|
+
"intersect",
|
|
166
|
+
"except",
|
|
167
|
+
"distinct",
|
|
168
|
+
"all",
|
|
169
|
+
"exists",
|
|
170
|
+
"case",
|
|
171
|
+
"when",
|
|
172
|
+
"then",
|
|
173
|
+
"else",
|
|
174
|
+
"end",
|
|
175
|
+
"null",
|
|
176
|
+
"true",
|
|
177
|
+
"false",
|
|
178
|
+
"is",
|
|
179
|
+
"asc",
|
|
180
|
+
"desc",
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
const SQL_BUILTIN = [
|
|
184
|
+
"varchar",
|
|
185
|
+
"char",
|
|
186
|
+
"text",
|
|
187
|
+
"integer",
|
|
188
|
+
"int",
|
|
189
|
+
"bigint",
|
|
190
|
+
"decimal",
|
|
191
|
+
"numeric",
|
|
192
|
+
"float",
|
|
193
|
+
"real",
|
|
194
|
+
"boolean",
|
|
195
|
+
"date",
|
|
196
|
+
"time",
|
|
197
|
+
"timestamp",
|
|
198
|
+
"uuid",
|
|
199
|
+
"count",
|
|
200
|
+
"sum",
|
|
201
|
+
"avg",
|
|
202
|
+
"min",
|
|
203
|
+
"max",
|
|
204
|
+
"coalesce",
|
|
205
|
+
"concat",
|
|
206
|
+
"substring",
|
|
207
|
+
"upper",
|
|
208
|
+
"lower",
|
|
209
|
+
"trim",
|
|
210
|
+
"length",
|
|
211
|
+
"now",
|
|
212
|
+
"current_date",
|
|
213
|
+
"current_time",
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
const customSQLDialect = SQLDialect.define({
|
|
217
|
+
keywords: SQL_KEYWORDS.join(" "),
|
|
218
|
+
builtin: SQL_BUILTIN.join(" "),
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
type LanguageMode = "json" | "http" | "sql" | "yaml";
|
|
123
222
|
|
|
124
223
|
function languageExtensions(mode: LanguageMode) {
|
|
125
224
|
if (mode === "http") {
|
|
126
225
|
const jsonLang = json();
|
|
226
|
+
const yamlLang = yaml();
|
|
227
|
+
return [
|
|
228
|
+
http((ct) =>
|
|
229
|
+
ct === "application/json"
|
|
230
|
+
? jsonLang.language
|
|
231
|
+
: ct === "text/yaml"
|
|
232
|
+
? yamlLang.language
|
|
233
|
+
: null,
|
|
234
|
+
),
|
|
235
|
+
syntaxHighlighting(customHighlightStyle),
|
|
236
|
+
];
|
|
237
|
+
} else if (mode === "sql") {
|
|
127
238
|
return [
|
|
128
|
-
|
|
239
|
+
sql({ dialect: customSQLDialect }),
|
|
129
240
|
syntaxHighlighting(customHighlightStyle),
|
|
130
241
|
];
|
|
242
|
+
} else if (mode === "yaml") {
|
|
243
|
+
return [yaml(), syntaxHighlighting(customHighlightStyle)];
|
|
131
244
|
} else {
|
|
132
245
|
return [
|
|
133
246
|
json(),
|
|
@@ -139,6 +252,7 @@ function languageExtensions(mode: LanguageMode) {
|
|
|
139
252
|
|
|
140
253
|
type CodeEditorProps = {
|
|
141
254
|
readOnly?: boolean;
|
|
255
|
+
isReadOnlyTheme?: boolean;
|
|
142
256
|
defaultValue?: string;
|
|
143
257
|
currentValue?: string;
|
|
144
258
|
onChange?: (value: string) => void;
|
|
@@ -159,6 +273,7 @@ export function CodeEditor({
|
|
|
159
273
|
readOnly = false,
|
|
160
274
|
id,
|
|
161
275
|
mode = "json",
|
|
276
|
+
isReadOnlyTheme = false,
|
|
162
277
|
}: CodeEditorProps) {
|
|
163
278
|
const domRef = React.useRef(null);
|
|
164
279
|
const [view, setView] = React.useState<EditorView | null>(null);
|
|
@@ -293,12 +408,22 @@ export function CodeEditor({
|
|
|
293
408
|
readOnlyCompartment.current.reconfigure(
|
|
294
409
|
EditorState.readOnly.of(readOnly),
|
|
295
410
|
),
|
|
411
|
+
],
|
|
412
|
+
});
|
|
413
|
+
}, [readOnly, view]);
|
|
414
|
+
|
|
415
|
+
React.useEffect(() => {
|
|
416
|
+
if (view === null) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
view.dispatch({
|
|
420
|
+
effects: [
|
|
296
421
|
themeCompartment.current.reconfigure(
|
|
297
|
-
|
|
422
|
+
isReadOnlyTheme ? readOnlyTheme : baseTheme,
|
|
298
423
|
),
|
|
299
424
|
],
|
|
300
425
|
});
|
|
301
|
-
}, [
|
|
426
|
+
}, [isReadOnlyTheme, view]);
|
|
302
427
|
|
|
303
428
|
return <div className="h-full w-full" ref={domRef} id={id} />;
|
|
304
429
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { EditorView } from "@codemirror/view";
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { Input } from "#shadcn/components/ui/input.js";
|
|
2
5
|
import { CodeEditor } from "./code-editor";
|
|
3
6
|
|
|
4
7
|
const meta: Meta<typeof CodeEditor> = {
|
|
@@ -32,3 +35,294 @@ export const Default: Story = {
|
|
|
32
35
|
</div>
|
|
33
36
|
),
|
|
34
37
|
};
|
|
38
|
+
|
|
39
|
+
type ParsedHeader = {
|
|
40
|
+
name: string;
|
|
41
|
+
nameTrivia: string;
|
|
42
|
+
value: string;
|
|
43
|
+
valueTrivia: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type Parsed = {
|
|
47
|
+
method: string;
|
|
48
|
+
methodTrivia: string;
|
|
49
|
+
path: string;
|
|
50
|
+
pathTrivia: string;
|
|
51
|
+
headers: ParsedHeader[];
|
|
52
|
+
headersTrivia: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function parse(query: string): Parsed {
|
|
56
|
+
let hi = 0;
|
|
57
|
+
let lo = 0;
|
|
58
|
+
const res: Parsed = {
|
|
59
|
+
method: "",
|
|
60
|
+
methodTrivia: "",
|
|
61
|
+
path: "",
|
|
62
|
+
pathTrivia: "",
|
|
63
|
+
headers: [],
|
|
64
|
+
headersTrivia: "",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Note that we iterate by code units, but it doesn't change correctness.
|
|
68
|
+
// method
|
|
69
|
+
for (hi = 0; hi < query.length; ++hi) {
|
|
70
|
+
const c = query[hi];
|
|
71
|
+
if (c === " " || c === "\t" || c === "\n") {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
res.method = query.substring(lo, hi);
|
|
76
|
+
lo = hi;
|
|
77
|
+
if (lo >= query.length) {
|
|
78
|
+
return res;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// method trivia
|
|
82
|
+
for (hi = lo; hi < query.length; ++hi) {
|
|
83
|
+
const c = query[hi];
|
|
84
|
+
if (!(c === " " || c === "\t")) {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
res.methodTrivia = query.substring(lo, hi);
|
|
89
|
+
lo = hi;
|
|
90
|
+
if (lo >= query.length) {
|
|
91
|
+
return res;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// path
|
|
95
|
+
for (hi = lo; hi < query.length; ++hi) {
|
|
96
|
+
const c = query[hi];
|
|
97
|
+
if (c === "\n") {
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
res.path = query.substring(lo, hi);
|
|
102
|
+
lo = hi;
|
|
103
|
+
if (lo >= query.length) {
|
|
104
|
+
return res;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// path trivia
|
|
108
|
+
if (query[hi] === "\n") {
|
|
109
|
+
hi += 1;
|
|
110
|
+
res.pathTrivia = query.substring(lo, hi);
|
|
111
|
+
}
|
|
112
|
+
lo = hi;
|
|
113
|
+
if (lo >= query.length) {
|
|
114
|
+
return res;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// headers
|
|
118
|
+
let header: ParsedHeader = {
|
|
119
|
+
name: "",
|
|
120
|
+
nameTrivia: "",
|
|
121
|
+
value: "",
|
|
122
|
+
valueTrivia: "",
|
|
123
|
+
};
|
|
124
|
+
let headerReady = false;
|
|
125
|
+
// SAFETY: don't decrease hi inside this loop.
|
|
126
|
+
for (hi = lo; hi < query.length; ++hi) {
|
|
127
|
+
if (headerReady) {
|
|
128
|
+
res.headers.push(header);
|
|
129
|
+
}
|
|
130
|
+
header = { name: "", nameTrivia: "", value: "", valueTrivia: "" };
|
|
131
|
+
headerReady = false;
|
|
132
|
+
|
|
133
|
+
if (query[hi] === "\n") {
|
|
134
|
+
// end of headers
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// header name
|
|
139
|
+
for (lo = hi; hi <= query.length; ++hi) {
|
|
140
|
+
const c = query[hi];
|
|
141
|
+
if (c === " " || c === "\t" || c === "\n" || c === ":") {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
headerReady = true;
|
|
146
|
+
header.name = query.substring(lo, hi);
|
|
147
|
+
lo = hi;
|
|
148
|
+
if (lo >= query.length) {
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// header name trivia
|
|
153
|
+
let colonFound = false;
|
|
154
|
+
for (lo = hi; hi <= query.length; ++hi) {
|
|
155
|
+
const c = query[hi];
|
|
156
|
+
if (c === ":" && !colonFound) {
|
|
157
|
+
colonFound = true;
|
|
158
|
+
} else if (!(c === " " || c === "\t")) {
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
header.nameTrivia = query.substring(lo, hi);
|
|
163
|
+
lo = hi;
|
|
164
|
+
if (lo >= query.length) {
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// header value
|
|
169
|
+
for (hi = lo; hi < query.length; ++hi) {
|
|
170
|
+
const c = query[hi];
|
|
171
|
+
if (c === "\n") {
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
header.value = query.substring(lo, hi);
|
|
176
|
+
lo = hi;
|
|
177
|
+
if (lo >= query.length) {
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// header value trivia
|
|
182
|
+
if (query[hi] === "\n") {
|
|
183
|
+
header.valueTrivia = query.substring(lo, hi + 1);
|
|
184
|
+
}
|
|
185
|
+
lo = hi + 1;
|
|
186
|
+
if (lo >= query.length) {
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (headerReady) {
|
|
191
|
+
res.headers.push(header);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (query[hi] === "\n") {
|
|
195
|
+
res.headersTrivia = query.substring(lo, hi + 1);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return res;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const MethodInput = React.memo(function MethodInput({
|
|
202
|
+
method,
|
|
203
|
+
onMethodChange,
|
|
204
|
+
}: {
|
|
205
|
+
method: string;
|
|
206
|
+
onMethodChange: (ev: React.ChangeEvent<HTMLInputElement>) => void;
|
|
207
|
+
}) {
|
|
208
|
+
return (
|
|
209
|
+
<div className="flex justify-center items-baseline">
|
|
210
|
+
Method:
|
|
211
|
+
<Input
|
|
212
|
+
type="text"
|
|
213
|
+
className="inline"
|
|
214
|
+
value={method}
|
|
215
|
+
onChange={onMethodChange}
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const PathInput = React.memo(function PathInput({
|
|
222
|
+
path,
|
|
223
|
+
onPathChange,
|
|
224
|
+
}: {
|
|
225
|
+
path: string;
|
|
226
|
+
onPathChange: (ev: React.ChangeEvent<HTMLInputElement>) => void;
|
|
227
|
+
}) {
|
|
228
|
+
return (
|
|
229
|
+
<div className="flex justify-center items-baseline">
|
|
230
|
+
{"Path: "}
|
|
231
|
+
<Input
|
|
232
|
+
type="text"
|
|
233
|
+
className="inline"
|
|
234
|
+
value={path}
|
|
235
|
+
onChange={onPathChange}
|
|
236
|
+
/>
|
|
237
|
+
</div>
|
|
238
|
+
);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
function ComplexComp() {
|
|
242
|
+
const [rawQuery, setRawQuery] = React.useState("");
|
|
243
|
+
const parsed = React.useMemo(() => parse(rawQuery), [rawQuery]);
|
|
244
|
+
const parsedRef = React.useRef(parsed);
|
|
245
|
+
React.useEffect(() => {
|
|
246
|
+
parsedRef.current = parsed;
|
|
247
|
+
}, [parsed]);
|
|
248
|
+
const method = React.useMemo(() => parsed.method, [parsed.method]);
|
|
249
|
+
const path = React.useMemo(() => parsed.path, [parsed.path]);
|
|
250
|
+
|
|
251
|
+
const viewRef = React.useRef<EditorView | null>(null);
|
|
252
|
+
|
|
253
|
+
const onMethodChange = React.useCallback(
|
|
254
|
+
(ev: React.ChangeEvent<HTMLInputElement>) => {
|
|
255
|
+
let newVal = ev.target.value;
|
|
256
|
+
|
|
257
|
+
if (newVal.indexOf(" ") !== -1) {
|
|
258
|
+
newVal = newVal.replaceAll(" ", "").replaceAll("\t", "");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const view = viewRef.current;
|
|
262
|
+
if (view === null) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const from = 0;
|
|
267
|
+
const to = parsedRef.current.method.length;
|
|
268
|
+
|
|
269
|
+
view.dispatch({
|
|
270
|
+
changes: {
|
|
271
|
+
from: from,
|
|
272
|
+
to: to,
|
|
273
|
+
insert: newVal,
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
},
|
|
277
|
+
[],
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
const onPathChange = React.useCallback(
|
|
281
|
+
(ev: React.ChangeEvent<HTMLInputElement>) => {
|
|
282
|
+
const newVal = ev.target.value;
|
|
283
|
+
|
|
284
|
+
const view = viewRef.current;
|
|
285
|
+
if (view === null) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const from =
|
|
290
|
+
parsedRef.current.method.length + parsedRef.current.methodTrivia.length;
|
|
291
|
+
const to = from + parsedRef.current.path.length;
|
|
292
|
+
console.log(from, to);
|
|
293
|
+
|
|
294
|
+
view.dispatch({
|
|
295
|
+
changes: {
|
|
296
|
+
from: from,
|
|
297
|
+
to: to,
|
|
298
|
+
insert: newVal,
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
},
|
|
302
|
+
[],
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<>
|
|
307
|
+
<MethodInput method={method} onMethodChange={onMethodChange} />
|
|
308
|
+
<PathInput path={path} onPathChange={onPathChange} />
|
|
309
|
+
<div className="h-[500px] w-[500px] border-black border-2">
|
|
310
|
+
<CodeEditor
|
|
311
|
+
mode="http"
|
|
312
|
+
onUpdate={(update) => {
|
|
313
|
+
if (update.docChanged) {
|
|
314
|
+
setRawQuery(update.state.doc.toString());
|
|
315
|
+
}
|
|
316
|
+
}}
|
|
317
|
+
viewCallback={(view) => {
|
|
318
|
+
viewRef.current = view;
|
|
319
|
+
}}
|
|
320
|
+
/>
|
|
321
|
+
</div>
|
|
322
|
+
</>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export const Complex: Story = {
|
|
327
|
+
render: () => ComplexComp(),
|
|
328
|
+
};
|
|
@@ -1,17 +1,53 @@
|
|
|
1
1
|
import { Check, Copy } from "lucide-react";
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import { toast } from "sonner";
|
|
4
|
+
import {
|
|
5
|
+
Tooltip,
|
|
6
|
+
TooltipContent,
|
|
7
|
+
TooltipTrigger,
|
|
8
|
+
} from "#shadcn/components/ui/tooltip";
|
|
3
9
|
|
|
4
10
|
interface CopyIconProps {
|
|
5
11
|
text: string;
|
|
12
|
+
showTooltip?: boolean;
|
|
13
|
+
tooltipText?: string;
|
|
14
|
+
showToast?: boolean;
|
|
15
|
+
onCopy?: (text: string) => void;
|
|
6
16
|
}
|
|
7
17
|
|
|
8
|
-
function CopyIcon({
|
|
18
|
+
function CopyIcon({
|
|
19
|
+
text,
|
|
20
|
+
showTooltip = true,
|
|
21
|
+
tooltipText = "Copy",
|
|
22
|
+
showToast = true,
|
|
23
|
+
onCopy,
|
|
24
|
+
...props
|
|
25
|
+
}: CopyIconProps) {
|
|
9
26
|
const [isActive, setIsActive] = React.useState(false);
|
|
10
27
|
|
|
11
28
|
async function handleClick() {
|
|
12
29
|
try {
|
|
13
30
|
await navigator.clipboard.writeText(text);
|
|
14
31
|
setIsActive(true);
|
|
32
|
+
|
|
33
|
+
if (showToast) {
|
|
34
|
+
const truncatedText =
|
|
35
|
+
text.length > 30 ? `${text.slice(0, 30)}...` : text;
|
|
36
|
+
toast(
|
|
37
|
+
<div className="flex flex-col gap-1">
|
|
38
|
+
<span className="typo-body">Successfully copied</span>
|
|
39
|
+
<span className="typo-code text-text-secondary">
|
|
40
|
+
{truncatedText}
|
|
41
|
+
</span>
|
|
42
|
+
</div>,
|
|
43
|
+
{
|
|
44
|
+
duration: 2000,
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
onCopy?.(text);
|
|
50
|
+
|
|
15
51
|
setTimeout(() => {
|
|
16
52
|
setIsActive(false);
|
|
17
53
|
}, 1000);
|
|
@@ -20,11 +56,29 @@ function CopyIcon({ text }: CopyIconProps) {
|
|
|
20
56
|
}
|
|
21
57
|
}
|
|
22
58
|
|
|
23
|
-
|
|
24
|
-
<button
|
|
59
|
+
const button = (
|
|
60
|
+
<button
|
|
61
|
+
{...props}
|
|
62
|
+
type="button"
|
|
63
|
+
onClick={handleClick}
|
|
64
|
+
style={{ cursor: "pointer" }}
|
|
65
|
+
>
|
|
25
66
|
{isActive ? <Check /> : <Copy />}
|
|
26
67
|
</button>
|
|
27
68
|
);
|
|
69
|
+
|
|
70
|
+
if (!showTooltip) {
|
|
71
|
+
return button;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<Tooltip>
|
|
76
|
+
<TooltipTrigger asChild>{button}</TooltipTrigger>
|
|
77
|
+
<TooltipContent>
|
|
78
|
+
<p>{tooltipText}</p>
|
|
79
|
+
</TooltipContent>
|
|
80
|
+
</Tooltip>
|
|
81
|
+
);
|
|
28
82
|
}
|
|
29
83
|
|
|
30
84
|
export { CopyIcon };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { DataTable, type DataTableProps } from "./data-table";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof DataTable> = {
|
|
5
|
+
title: "Component/Data table",
|
|
6
|
+
component: DataTable,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof DataTable>;
|
|
12
|
+
|
|
13
|
+
function DataTableWrapper<TData, TValue>({
|
|
14
|
+
columns,
|
|
15
|
+
data,
|
|
16
|
+
}: DataTableProps<TData, TValue>) {
|
|
17
|
+
return <DataTable columns={columns} data={data} />;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
args: {
|
|
22
|
+
columns: [
|
|
23
|
+
{
|
|
24
|
+
header: "Name",
|
|
25
|
+
accessorKey: "name",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
header: "Age",
|
|
29
|
+
accessorKey: "age",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
data: [
|
|
33
|
+
{ name: "John Doe", age: 30 },
|
|
34
|
+
{ name: "Jane Smith", age: 25 },
|
|
35
|
+
{ name: "Bob Johnson", age: 42 },
|
|
36
|
+
{ name: "Alice Williams", age: 35 },
|
|
37
|
+
{ name: "Charlie Brown", age: 28 },
|
|
38
|
+
{ name: "Diana Prince", age: 31 },
|
|
39
|
+
{ name: "Edward Norton", age: 45 },
|
|
40
|
+
{ name: "Fiona Green", age: 27 },
|
|
41
|
+
{ name: "George Miller", age: 38 },
|
|
42
|
+
{ name: "Hannah Davis", age: 33 },
|
|
43
|
+
{ name: "Ian Moore", age: 29 },
|
|
44
|
+
{ name: "Julia Taylor", age: 41 },
|
|
45
|
+
{ name: "Kevin Anderson", age: 36 },
|
|
46
|
+
{ name: "Laura Thomas", age: 32 },
|
|
47
|
+
{ name: "Michael Jackson", age: 44 },
|
|
48
|
+
{ name: "Nancy Wilson", age: 26 },
|
|
49
|
+
{ name: "Oscar Martinez", age: 39 },
|
|
50
|
+
{ name: "Patricia Lee", age: 34 },
|
|
51
|
+
{ name: "Quinn Harris", age: 37 },
|
|
52
|
+
{ name: "Rachel Clark", age: 40 },
|
|
53
|
+
{ name: "Samuel Wright", age: 43 },
|
|
54
|
+
{ name: "Tina Turner", age: 48 },
|
|
55
|
+
{ name: "Ulysses Grant", age: 52 },
|
|
56
|
+
{ name: "Victoria Baker", age: 29 },
|
|
57
|
+
{ name: "William Scott", age: 35 },
|
|
58
|
+
{ name: "Xavier Adams", age: 31 },
|
|
59
|
+
{ name: "Yolanda King", age: 38 },
|
|
60
|
+
{ name: "Zachary Nelson", age: 27 },
|
|
61
|
+
{ name: "Amy Carter", age: 33 },
|
|
62
|
+
{ name: "Benjamin Hall", age: 46 },
|
|
63
|
+
{ name: "Catherine Allen", age: 24 },
|
|
64
|
+
{ name: "David Young", age: 41 },
|
|
65
|
+
{ name: "Emily Walker", age: 36 },
|
|
66
|
+
{ name: "Frank Robinson", age: 39 },
|
|
67
|
+
{ name: "Grace White", age: 28 },
|
|
68
|
+
{ name: "Henry Lewis", age: 47 },
|
|
69
|
+
{ name: "Isabella Hill", age: 32 },
|
|
70
|
+
{ name: "Jack Martin", age: 34 },
|
|
71
|
+
{ name: "Katherine Garcia", age: 30 },
|
|
72
|
+
{ name: "Louis Rodriguez", age: 45 },
|
|
73
|
+
{ name: "Margaret Martinez", age: 37 },
|
|
74
|
+
{ name: "Nathan Hernandez", age: 26 },
|
|
75
|
+
{ name: "Olivia Lopez", age: 29 },
|
|
76
|
+
{ name: "Peter Gonzalez", age: 43 },
|
|
77
|
+
{ name: "Quincy Wilson", age: 38 },
|
|
78
|
+
{ name: "Rebecca Anderson", age: 31 },
|
|
79
|
+
{ name: "Steven Thomas", age: 44 },
|
|
80
|
+
{ name: "Teresa Taylor", age: 35 },
|
|
81
|
+
{ name: "Ursula Moore", age: 40 },
|
|
82
|
+
{ name: "Victor Jackson", age: 42 },
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
parameters: {
|
|
86
|
+
layout: "fullscreen",
|
|
87
|
+
},
|
|
88
|
+
render: (args) => <DataTableWrapper {...args} />,
|
|
89
|
+
};
|