@oaspect/react 0.1.0

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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +14 -0
  3. package/dist/api-reference.js +476 -0
  4. package/dist/api-reference.js.map +1 -0
  5. package/dist/auth-panel.js +116 -0
  6. package/dist/auth-panel.js.map +1 -0
  7. package/dist/code-block.js +105 -0
  8. package/dist/code-block.js.map +1 -0
  9. package/dist/i18n/ar.js +89 -0
  10. package/dist/i18n/ar.js.map +1 -0
  11. package/dist/i18n/context.js +50 -0
  12. package/dist/i18n/context.js.map +1 -0
  13. package/dist/i18n/en.js +89 -0
  14. package/dist/i18n/en.js.map +1 -0
  15. package/dist/i18n/index.js +37 -0
  16. package/dist/i18n/index.js.map +1 -0
  17. package/dist/i18n/tr.js +89 -0
  18. package/dist/i18n/tr.js.map +1 -0
  19. package/dist/icons.js +55 -0
  20. package/dist/icons.js.map +1 -0
  21. package/dist/index.d.ts +78 -0
  22. package/dist/index.js +12 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/intro.js +132 -0
  25. package/dist/intro.js.map +1 -0
  26. package/dist/lazy.js +41 -0
  27. package/dist/lazy.js.map +1 -0
  28. package/dist/logo.js +12 -0
  29. package/dist/logo.js.map +1 -0
  30. package/dist/markdown.js +170 -0
  31. package/dist/markdown.js.map +1 -0
  32. package/dist/method-badge.js +37 -0
  33. package/dist/method-badge.js.map +1 -0
  34. package/dist/models.js +27 -0
  35. package/dist/models.js.map +1 -0
  36. package/dist/oaspect.css +1703 -0
  37. package/dist/operation.js +267 -0
  38. package/dist/operation.js.map +1 -0
  39. package/dist/samples.js +129 -0
  40. package/dist/samples.js.map +1 -0
  41. package/dist/schema-tree.js +160 -0
  42. package/dist/schema-tree.js.map +1 -0
  43. package/dist/send.js +58 -0
  44. package/dist/send.js.map +1 -0
  45. package/dist/sidebar.js +125 -0
  46. package/dist/sidebar.js.map +1 -0
  47. package/dist/spec-context.js +23 -0
  48. package/dist/spec-context.js.map +1 -0
  49. package/dist/storage.js +30 -0
  50. package/dist/storage.js.map +1 -0
  51. package/dist/try-it.js +277 -0
  52. package/dist/try-it.js.map +1 -0
  53. package/package.json +66 -0
  54. package/tailwind.css +21 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/try-it.jsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { useT } from \"./i18n/context\";\nimport { buildRequest, defaultBody, defaultValues, isMultipart } from \"@oaspect/core\";\nimport CodeBlock, { CodeEditor } from \"./code-block\";\nimport MethodBadge, { statusTone } from \"./method-badge\";\nimport { withAuth } from \"./samples\";\nimport { sendDirect, sendViaProxy } from \"./send\";\nimport { useSettings, useSpec } from \"./spec-context\";\nimport { CloseIcon } from \"./icons\";\n\n\n// Methods that never change server state; everything else asks first,\n// because the prefilled example values would overwrite real records.\nconst SAFE_METHODS = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\n\nconst LOCATIONS = [\n [\"path\", \"Path\"],\n [\"query\", \"Query\"],\n [\"header\", \"Header\"],\n [\"cookie\", \"Cookie\"],\n];\n\nfunction prettyBody(text) {\n try {\n return { code: JSON.stringify(JSON.parse(text), null, 2), language: \"json\" };\n } catch {\n return { code: text, language: \"text\" };\n }\n}\n\n// Modal request runner: edit parameters/body and send the request from the browser.\nexport default function TryIt({ operation, onClose }) {\n const spec = useSpec();\n const { server, authFor, proxyUrl, storage } = useSettings();\n const proxyEnabled = Boolean(proxyUrl);\n const dialog = useRef(null);\n const t = useT();\n const [values, setValues] = useState(() => defaultValues(spec, operation));\n const [{ contentType, body, form = [] }, setBody] = useState(() => defaultBody(spec, operation));\n // multipart: chosen File per form part index (file parts without one are left out).\n const [chosen, setChosen] = useState({});\n const multipart = isMultipart(contentType);\n const [state, setState] = useState({ status: \"idle\" });\n const [skipConfirm, setSkipConfirm] = useState(() => storage.get(\"skip-write-confirm\", null, \"session\") === \"1\");\n // \"proxy\" relays through proxyUrl (no CORS needed); \"direct\" calls from the browser.\n // When the server has the proxy disabled only \"direct\" is available.\n const [preferredMode, setMode] = useState(() => (storage.get(\"request-mode\") === \"direct\" ? \"direct\" : \"proxy\"));\n const mode = proxyEnabled ? preferredMode : \"direct\";\n\n function changeMode(next) {\n setMode(next);\n storage.set(\"request-mode\", next);\n }\n\n // No close() in cleanup: it fires the \"close\" event, which would call\n // onClose and immediately unmount the dialog under StrictMode's double\n // effect run. Unmounting removes the dialog anyway.\n useEffect(() => {\n const node = dialog.current;\n if (node && !node.open) node.showModal();\n }, []);\n\n const sent = form\n .map((field, index) => ({ field, file: chosen[index] }))\n .filter(({ field, file }) => !field.file || file)\n .map(({ field, file }) => ({ field: file ? { name: field.name, file: { name: file.name, type: file.type || undefined } } : field, file }));\n const request = buildRequest(operation, { server, ...withAuth(values, authFor(operation)), body, form: sent.map((item) => item.field), contentType });\n const files = sent.map((item) => item.file ?? null);\n\n function setFormValue(index, value) {\n setBody((current) => ({ ...current, form: current.form.map((field, i) => (i === index ? { ...field, value } : field)) }));\n }\n\n function setValue(location, name, value) {\n setValues((current) => ({ ...current, [location]: { ...current[location], [name]: value } }));\n }\n\n function send(event) {\n event.preventDefault();\n if (!SAFE_METHODS.has(request.method) && storage.get(\"skip-write-confirm\", null, \"session\") !== \"1\") {\n setState({ status: \"confirm\" });\n return;\n }\n execute();\n }\n\n function confirmSend() {\n if (skipConfirm) storage.set(\"skip-write-confirm\", \"1\", \"session\");\n execute();\n }\n\n async function execute() {\n setState({ status: \"loading\" });\n\n try {\n const result = mode === \"proxy\" ? await sendViaProxy(proxyUrl, request, files) : await sendDirect(request, files);\n setState({ ...result, code: result.status, status: \"done\" });\n } catch (error) {\n setState({ status: \"error\", message: error.message });\n }\n }\n\n return (\n <dialog\n ref={dialog}\n onClose={onClose}\n onClick={(event) => event.target === dialog.current && onClose()}\n className=\"m-auto h-[min(90dvh,56rem)] w-[min(96vw,72rem)] overflow-hidden rounded-2xl border border-border bg-background p-0 text-foreground backdrop:bg-black/50 backdrop:backdrop-blur-sm\"\n >\n <form onSubmit={send} className=\"flex h-full flex-col\">\n <header className=\"flex items-center gap-3 border-b border-border px-5 py-3\">\n <MethodBadge method={operation.method} />\n <code dir=\"ltr\" className=\"min-w-0 flex-1 truncate text-start font-mono text-sm\" title={request.url}>\n {request.url}\n </code>\n <button\n type=\"submit\"\n disabled={state.status === \"loading\"}\n className=\"rounded-lg bg-primary px-4 py-1.5 text-sm font-semibold text-primary-foreground hover:opacity-90 disabled:opacity-60\"\n >\n {state.status === \"loading\" ? t(\"tryIt.sending\") : t(\"tryIt.send\")}\n </button>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={t(\"dialog.close\")}\n className=\"rounded-lg p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n <CloseIcon className=\"size-4\" />\n </button>\n </header>\n\n <div className=\"grid min-h-0 flex-1 lg:grid-cols-2\">\n <div className=\"min-h-0 space-y-6 overflow-y-auto border-border p-5 lg:border-e\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <p className=\"text-xs text-muted-foreground\">\n {t(\"tryIt.settingsHint\")}\n </p>\n <div className=\"flex rounded-lg border border-border p-0.5 text-xs\" role=\"group\" aria-label={t(\"tryIt.mode.label\")}>\n {[\n [\"proxy\", \"Proxy\"],\n [\"direct\", t(\"tryIt.mode.direct\")],\n ].map(([key, label]) => (\n <button\n key={key}\n type=\"button\"\n onClick={() => changeMode(key)}\n disabled={key === \"proxy\" && !proxyEnabled}\n aria-pressed={mode === key}\n title={\n key === \"direct\"\n ? t(\"tryIt.mode.directHint\")\n : proxyEnabled\n ? t(\"tryIt.mode.proxyHint\")\n : t(\"tryIt.mode.proxyDisabled\")\n }\n className={`rounded-md px-2 py-1 font-medium transition disabled:cursor-not-allowed disabled:opacity-40 ${\n mode === key ? \"bg-foreground text-background\" : \"text-muted-foreground enabled:hover:text-foreground\"\n }`}\n >\n {label}\n </button>\n ))}\n </div>\n </div>\n {LOCATIONS.map(([location, label]) => {\n const params = operation.parameters.filter((param) => param.in === location);\n if (params.length === 0) return null;\n return (\n <fieldset key={location} className=\"space-y-2\">\n <legend className=\"mb-2 text-sm font-semibold\">{label}</legend>\n {params.map((param) => (\n <label key={param.name} className=\"grid grid-cols-[minmax(0,11rem)_minmax(0,1fr)] items-center gap-3\">\n <span className=\"truncate font-mono text-xs\" title={param.name}>\n {param.name}\n {param.required && <span className=\"text-rose-600\"> *</span>}\n </span>\n {param.schema?.enum ? (\n <select\n value={values[location]?.[param.name] ?? \"\"}\n onChange={(event) => setValue(location, param.name, event.target.value)}\n className=\"rounded-md border border-border bg-background px-2 py-1 text-xs\"\n >\n <option value=\"\">—</option>\n {param.schema.enum.map((option) => (\n <option key={String(option)} value={String(option)}>\n {String(option)}\n </option>\n ))}\n </select>\n ) : (\n <input\n value={values[location]?.[param.name] ?? \"\"}\n required={param.required}\n onChange={(event) => setValue(location, param.name, event.target.value)}\n dir=\"ltr\"\n className=\"rounded-md border border-border bg-background px-2 py-1 font-mono text-xs outline-none focus:border-primary\"\n />\n )}\n </label>\n ))}\n </fieldset>\n );\n })}\n\n {contentType && multipart && (\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-2 flex w-full items-center justify-between text-sm font-semibold\">\n Body <span className=\"font-mono text-[11px] font-normal text-muted-foreground\">{contentType}</span>\n </legend>\n {form.map((field, index) => (\n <label key={`${field.name}-${index}`} className=\"grid grid-cols-[minmax(0,11rem)_minmax(0,1fr)] items-center gap-3\">\n <span className=\"truncate font-mono text-xs\" title={field.name}>\n {field.name}\n {field.file && <span className=\"ms-1 rounded bg-muted px-1 text-[10px] text-muted-foreground\">file</span>}\n </span>\n {field.file ? (\n <input\n type=\"file\"\n onChange={(event) => setChosen((current) => ({ ...current, [index]: event.target.files?.[0] }))}\n className=\"text-xs file:me-2 file:rounded-md file:border file:border-border file:bg-background file:px-2 file:py-1 file:text-xs\"\n />\n ) : (\n <input\n value={field.value ?? \"\"}\n onChange={(event) => setFormValue(index, event.target.value)}\n dir=\"ltr\"\n className=\"rounded-md border border-border bg-background px-2 py-1 font-mono text-xs outline-none focus:border-primary\"\n />\n )}\n </label>\n ))}\n <p className=\"text-xs text-muted-foreground\">{t(\"tryIt.fileHint\")}</p>\n </fieldset>\n )}\n\n {contentType && !multipart && (\n <label className=\"block space-y-2\">\n <span className=\"flex items-center justify-between text-sm font-semibold\">\n Body <span className=\"font-mono text-[11px] font-normal text-muted-foreground\">{contentType}</span>\n </span>\n <CodeEditor value={body} onChange={(value) => setBody((current) => ({ ...current, body: value }))} />\n </label>\n )}\n </div>\n\n <div className=\"min-h-0 space-y-4 overflow-y-auto p-5\">\n {state.status === \"confirm\" && (\n <div role=\"alertdialog\" aria-labelledby=\"write-confirm-title\" className=\"space-y-3 rounded-xl border border-amber-500/40 bg-amber-500/10 p-4 text-sm\">\n <p id=\"write-confirm-title\" className=\"font-semibold text-amber-800 dark:text-amber-200\">\n {t(\"tryIt.confirm.title\")}\n </p>\n <p className=\"text-amber-900/80 dark:text-amber-100/80\">\n {t(\"tryIt.confirm.body\", {\n method: request.method,\n host: (() => {\n try {\n return new URL(request.url).host;\n } catch {\n return request.url;\n }\n })(),\n })}\n </p>\n <label className=\"flex items-center gap-2 text-xs text-amber-900/80 dark:text-amber-100/80\">\n <input type=\"checkbox\" checked={skipConfirm} onChange={(event) => setSkipConfirm(event.target.checked)} />\n {t(\"tryIt.confirm.skip\")}\n </label>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={confirmSend}\n autoFocus\n className=\"rounded-lg bg-amber-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-amber-700\"\n >\n {t(\"tryIt.confirm.send\")}\n </button>\n <button\n type=\"button\"\n onClick={() => setState({ status: \"idle\" })}\n className=\"rounded-lg border border-border px-3 py-1.5 text-xs font-medium hover:bg-muted\"\n >\n {t(\"tryIt.confirm.cancel\")}\n </button>\n </div>\n </div>\n )}\n {state.status === \"idle\" && (\n <p className=\"text-sm text-muted-foreground\">{t(\"tryIt.idle\")}</p>\n )}\n {state.status === \"loading\" && <p className=\"text-sm text-muted-foreground\">{t(\"tryIt.waiting\")}</p>}\n {state.status === \"error\" && (\n <div className=\"rounded-lg border border-rose-500/30 bg-rose-500/10 p-3 text-sm text-rose-700 dark:text-rose-300\">\n {t(\"tryIt.failed\", { message: state.message })}\n {mode === \"direct\" && ` — ${t(\"tryIt.corsHint\")}`}\n </div>\n )}\n {state.status === \"done\" && (\n <>\n <div className=\"flex items-baseline gap-3\">\n <span className={`font-mono text-lg font-bold ${statusTone(String(state.code))}`}>{state.code}</span>\n <span className=\"text-sm text-muted-foreground\">{state.statusText}</span>\n <span dir=\"ltr\" className=\"ms-auto text-xs text-muted-foreground\">{state.duration} ms</span>\n </div>\n <CodeBlock maxHeight=\"none\" {...prettyBody(state.body)} toolbar={<span className=\"px-2 text-xs text-white/60\">Body</span>} />\n <details className=\"text-xs\">\n <summary className=\"cursor-pointer font-semibold\">Headers ({state.headers.length})</summary>\n <dl className=\"mt-2 grid grid-cols-[auto_minmax(0,1fr)] gap-x-4 gap-y-1 font-mono\">\n {state.headers.map(([key, value]) => (\n <div key={key} className=\"contents\">\n <dt className=\"text-muted-foreground\">{key}</dt>\n <dd className=\"break-all\">{value}</dd>\n </div>\n ))}\n </dl>\n </details>\n </>\n )}\n </div>\n </div>\n </form>\n </dialog>\n );\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@oaspect/react",
3
+ "version": "0.1.0",
4
+ "description": "Interactive API reference for OpenAPI documents, as a React component.",
5
+ "license": "MIT",
6
+ "homepage": "https://oaspect.dev",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/oaspect/oaspect.git",
10
+ "directory": "packages/react"
11
+ },
12
+ "bugs": "https://github.com/oaspect/oaspect/issues",
13
+ "type": "module",
14
+ "sideEffects": [
15
+ "*.css"
16
+ ],
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ },
24
+ "./styles.css": "./dist/oaspect.css",
25
+ "./tailwind.css": "./tailwind.css"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "tailwind.css",
30
+ "README.md"
31
+ ],
32
+ "keywords": [
33
+ "openapi",
34
+ "swagger",
35
+ "api-documentation",
36
+ "api-reference",
37
+ "react"
38
+ ],
39
+ "dependencies": {
40
+ "@oaspect/core": "^0.1.0"
41
+ },
42
+ "peerDependencies": {
43
+ "react": ">=18",
44
+ "react-dom": ">=18"
45
+ },
46
+ "devDependencies": {
47
+ "@tailwindcss/cli": "^4.3.3",
48
+ "@types/react": "^19.3.0",
49
+ "postcss": "^8.5.28",
50
+ "react": "19.2.4",
51
+ "react-dom": "19.2.4",
52
+ "tailwindcss": "^4.3.3",
53
+ "tsup": "^8.5.1",
54
+ "typescript": "^5.9.3",
55
+ "vitest": "^3.2.7"
56
+ },
57
+ "publishConfig": {
58
+ "access": "public"
59
+ },
60
+ "scripts": {
61
+ "build": "tsup && node scripts/fix-extensions.mjs && node scripts/build-css.mjs && cp src/index.d.ts dist/index.d.ts",
62
+ "test": "vitest run",
63
+ "typecheck": "tsc --noEmit -p .",
64
+ "lint": "tsc --noEmit -p ."
65
+ }
66
+ }
package/tailwind.css ADDED
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Optional Tailwind CSS v4 bridge for hosts that render their own markup
3
+ * inside the viewer (e.g. a `logo`): exposes the viewer's colors as Tailwind
4
+ * colors and its theme as the `dark:` variant. Not needed for the viewer
5
+ * itself, which ships with dist/oaspect.css.
6
+ *
7
+ * @import "tailwindcss";
8
+ * @import "@oaspect/react/tailwind.css";
9
+ */
10
+
11
+ @custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
12
+
13
+ @theme inline {
14
+ --color-oaspect-background: var(--oaspect-background);
15
+ --color-oaspect-foreground: var(--oaspect-foreground);
16
+ --color-oaspect-card: var(--oaspect-card);
17
+ --color-oaspect-muted: var(--oaspect-muted);
18
+ --color-oaspect-border: var(--oaspect-border);
19
+ --color-oaspect-primary: var(--oaspect-primary);
20
+ --color-oaspect-muted-foreground: var(--oaspect-muted-foreground);
21
+ }