@scalar/blocks 0.5.3 → 0.5.4
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/CHANGELOG.md +6 -0
- package/dist/code-example/mount.d.ts.map +1 -1
- package/dist/code-example/mount.js +32 -31
- package/dist/code-example/mount.js.map +1 -1
- package/dist/constants.js +1 -1
- package/dist/schema/SchemaEnumPropertyItem.vue.script.js +4 -4
- package/dist/schema/SchemaHeading.vue.script.js +5 -5
- package/dist/schema/SchemaProperty.vue.script.js +12 -12
- package/dist/style.css +8 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @scalar/blocks
|
|
2
2
|
|
|
3
|
+
## 0.5.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#10669](https://github.com/scalar/scalar/pull/10669): fix: wrap long operation paths in request example cards instead of truncating them, and move the client picker below the path when it does not fit
|
|
8
|
+
|
|
3
9
|
## 0.5.3
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/code-example/mount.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/code-example/mount.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAOpE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAA;AACzF,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAMjH,MAAM,MAAM,wBAAwB,GAAG;IACrC,uFAAuF;IACvF,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,yEAAyE;IACzE,KAAK,EAAE,cAAc,CAAA;IACrB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,cAAc,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACzC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;IACpC;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oDAAoD;IACpD,eAAe,CAAC,EAAE,0BAA0B,EAAE,CAAA;IAC9C;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAkBD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,IAAI,WAAW,GAAG,MAAM,EAAE,SAAS,wBAAwB;;;CA6I5F,CAAA"}
|
|
@@ -5,65 +5,66 @@ import { createWorkspaceEventBus as a } from "@scalar/workspace-store/events";
|
|
|
5
5
|
import { getResolvedRef as o } from "@scalar/workspace-store/helpers/get-resolved-ref";
|
|
6
6
|
import { EXTERNAL_EXAMPLES as s } from "@scalar/workspace-store/helpers/use-external-examples";
|
|
7
7
|
import { ScalarTeleportRoot as c } from "@scalar/components/teleport";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { ScalarWrappingText as l } from "@scalar/components/wrapping-text";
|
|
9
|
+
import { getPathItemOperation as u } from "@scalar/workspace-store/helpers/for-each-path-item-operation";
|
|
10
|
+
import { getFirstServer as d } from "@scalar/workspace-store/helpers/get-first-server";
|
|
11
|
+
import { generateClientMutators as f } from "@scalar/workspace-store/mutators";
|
|
11
12
|
//#region src/code-example/mount.ts
|
|
12
|
-
var
|
|
13
|
-
let
|
|
14
|
-
if (!
|
|
15
|
-
let
|
|
16
|
-
let e =
|
|
13
|
+
var p = (e) => e === !0 ? "scalar-app dark-mode" : e === !1 ? "scalar-app light-mode" : "scalar-app", m = (m, h) => {
|
|
14
|
+
let g = typeof m == "string" ? document.querySelector(m) : m;
|
|
15
|
+
if (!g) throw Error(`Element not found: ${m}`);
|
|
16
|
+
let _ = a(), v = e(), y = f(h.store), b = _.on("workspace:update:selected-client", (e) => y.workspace().workspace.updateSelectedClient(e)), x = _.on("workspace:update:selected-example", (e) => y.workspace().workspace.updateSelectedExample(e)), S = () => {
|
|
17
|
+
let e = h.store.workspace.activeDocument;
|
|
17
18
|
if (!e || !("paths" in e)) return;
|
|
18
|
-
let t = o(e.paths?.[
|
|
19
|
+
let t = o(e.paths?.[h.path]), n = o(u(t, h.method));
|
|
19
20
|
if (n) return {
|
|
20
21
|
operation: n,
|
|
21
|
-
server:
|
|
22
|
+
server: d(n.servers ?? null, t?.servers ?? null, e.servers ?? null)
|
|
22
23
|
};
|
|
23
24
|
};
|
|
24
|
-
if (!
|
|
25
|
-
let
|
|
26
|
-
let e =
|
|
27
|
-
return e && (
|
|
28
|
-
},
|
|
25
|
+
if (!S()) throw Error(`Operation not found: ${h.method.toUpperCase()} ${h.path}`);
|
|
26
|
+
let C, w = () => {
|
|
27
|
+
let e = S();
|
|
28
|
+
return e && (C = e), e ?? C;
|
|
29
|
+
}, T = i({
|
|
29
30
|
get codeSampleUnavailable() {
|
|
30
|
-
return
|
|
31
|
+
return h.codeSampleUnavailable;
|
|
31
32
|
},
|
|
32
33
|
get codeSampleLabel() {
|
|
33
|
-
return
|
|
34
|
+
return h.codeSampleLabel;
|
|
34
35
|
},
|
|
35
36
|
get operation() {
|
|
36
|
-
return
|
|
37
|
+
return w().operation;
|
|
37
38
|
},
|
|
38
39
|
get method() {
|
|
39
|
-
return
|
|
40
|
+
return h.method;
|
|
40
41
|
},
|
|
41
42
|
get path() {
|
|
42
|
-
return
|
|
43
|
+
return h.path;
|
|
43
44
|
},
|
|
44
|
-
clientOptions:
|
|
45
|
-
eventBus:
|
|
45
|
+
clientOptions: v,
|
|
46
|
+
eventBus: _,
|
|
46
47
|
get securitySchemes() {
|
|
47
|
-
return
|
|
48
|
+
return h.securitySchemes ?? [];
|
|
48
49
|
},
|
|
49
50
|
get selectedClient() {
|
|
50
|
-
return
|
|
51
|
+
return h.store.workspace["x-scalar-default-client"] ?? h.selectedClient;
|
|
51
52
|
},
|
|
52
53
|
get selectedExample() {
|
|
53
|
-
return
|
|
54
|
+
return h.store.workspace["x-scalar-default-example"] ?? h.selectedExample;
|
|
54
55
|
},
|
|
55
56
|
get selectedServer() {
|
|
56
|
-
return
|
|
57
|
+
return h.selectedServer === void 0 ? w().server : h.selectedServer;
|
|
57
58
|
}
|
|
58
|
-
}),
|
|
59
|
-
return
|
|
60
|
-
app:
|
|
59
|
+
}), E = () => r("span", { class: "font-code text-c-2 min-w-0" }, r(l, { text: h.path })), D = n(() => r("div", { class: p(h.darkMode) }, [r(c, null, { default: () => r(t, T, { header: E }) })]));
|
|
60
|
+
return D.provide(s, () => h.store.externalExamples()), D.mount(g), {
|
|
61
|
+
app: D,
|
|
61
62
|
destroy: () => {
|
|
62
|
-
|
|
63
|
+
b(), x(), D.unmount();
|
|
63
64
|
}
|
|
64
65
|
};
|
|
65
66
|
};
|
|
66
67
|
//#endregion
|
|
67
|
-
export {
|
|
68
|
+
export { m as createCodeExample };
|
|
68
69
|
|
|
69
70
|
//# sourceMappingURL=mount.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount.js","names":[],"sources":["../../src/code-example/mount.ts"],"sourcesContent":["import { ScalarTeleportRoot } from '@scalar/components/teleport'\nimport type { AvailableClients } from '@scalar/snippetz'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { createWorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getPathItemOperation } from '@scalar/workspace-store/helpers/for-each-path-item-operation'\nimport { getFirstServer } from '@scalar/workspace-store/helpers/get-first-server'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { EXTERNAL_EXAMPLES } from '@scalar/workspace-store/helpers/use-external-examples'\nimport { generateClientMutators } from '@scalar/workspace-store/mutators'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { createApp, h, reactive } from 'vue'\n\nimport CodeExample, { type CodeExampleProps } from './components/CodeExample.vue'\nimport { generateClientOptions } from './helpers/generate-client-options'\n\nexport type CreateCodeExampleOptions = {\n /** Localized status text shown when the selected example has no linked code sample. */\n codeSampleUnavailable?: string\n /** Localized accessible name for the focusable code sample scroller. */\n codeSampleLabel?: string\n /** Workspace store that holds the OpenAPI document(s) to render from. */\n store: WorkspaceStore\n /** Path of the operation to render, e.g. '/users/{id}'. */\n path: string\n /** HTTP method of the operation to render. */\n method: string\n /** Pre-selected client ID, e.g. 'shell/curl'. */\n selectedClient?: AvailableClients[number]\n /**\n * Server object override used to build the example request.\n *\n * When omitted, the server is derived from the active document (operation,\n * then path item, then document level), mirroring the API reference. Pass\n * `null` to force \"no server\".\n */\n selectedServer?: ServerObject | null\n /**\n * Pre-selected example key for parameters and the request body.\n *\n * The store is the source of truth once an example is picked, so\n * `x-scalar-default-example` wins over this initial seed and the selection\n * round-trips through the store like the client selection does.\n */\n selectedExample?: string\n /** Security schemes applicable to the operation. */\n securitySchemes?: SecuritySchemeObjectSecret[]\n /**\n * Force a color mode on the rendered block.\n *\n * When omitted, the block inherits the ambient theme of the host page.\n * Pass `true` for dark mode or `false` for light mode.\n */\n darkMode?: boolean\n}\n\n/**\n * Builds the wrapper classes for the mounted block.\n *\n * The `.scalar-app` class scopes the Tailwind utilities, and the optional\n * color-mode class lets consumers pin the block to dark or light.\n */\nconst getWrapperClass = (darkMode: boolean | undefined): string => {\n if (darkMode === true) {\n return 'scalar-app dark-mode'\n }\n if (darkMode === false) {\n return 'scalar-app light-mode'\n }\n return 'scalar-app'\n}\n\n/**\n * Mount the CodeExample block to a DOM element without Vue.\n *\n * The consumer creates and controls their own workspace store,\n * then passes it in along with the path and method to render.\n */\nexport const createCodeExample = (el: HTMLElement | string, options: CreateCodeExampleOptions) => {\n const element = typeof el === 'string' ? document.querySelector(el) : el\n if (!element) {\n throw new Error(`Element not found: ${el}`)\n }\n\n const eventBus = createWorkspaceEventBus()\n const clientOptions = generateClientOptions()\n\n // Persist client changes back to the store. The block emits\n // `workspace:update:selected-client` on its private bus when the user picks a\n // client; without this subscription the choice would never reach the store\n // and `x-scalar-default-client` (the source of truth read below) would stay\n // stale, so the selection would not survive a re-render or be shared with\n // other blocks reading from the same store.\n const mutators = generateClientMutators(options.store)\n const unsubscribeClient = eventBus.on('workspace:update:selected-client', (payload) =>\n mutators.workspace().workspace.updateSelectedClient(payload),\n )\n\n // Persist example changes back to the store as well, mirroring the client\n // round-trip above. The block emits `workspace:update:selected-example` when\n // the user picks an example; without this the choice would never reach\n // `x-scalar-default-example` (read below) and would neither survive a\n // re-render nor sync to other blocks reading from the same store.\n const unsubscribeExample = eventBus.on('workspace:update:selected-example', (payload) =>\n mutators.workspace().workspace.updateSelectedExample(payload),\n )\n\n type OperationContext = { operation: OperationObject; server: ServerObject | null }\n\n /**\n * Resolve the operation and its effective server from the active document.\n *\n * The server is resolved from the same document the operation came from\n * (operation, then path item, then document level), so a snippet never pairs\n * an operation with a server URL from a different spec.\n */\n const resolveContext = (): OperationContext | undefined => {\n // The active document may be an AsyncAPI document, which has no `paths`.\n const activeDocument = options.store.workspace.activeDocument\n if (!activeDocument || !('paths' in activeDocument)) {\n return undefined\n }\n const pathItem = getResolvedRef(activeDocument.paths?.[options.path])\n const operation = getResolvedRef(getPathItemOperation(pathItem, options.method))\n if (!operation) {\n return undefined\n }\n const server = getFirstServer(operation.servers ?? null, pathItem?.servers ?? null, activeDocument.servers ?? null)\n return { operation, server }\n }\n\n // Fail loudly if the path and method do not point at an operation in the store,\n // mirroring the \"element not found\" guard above.\n if (!resolveContext()) {\n throw new Error(`Operation not found: ${options.method.toUpperCase()} ${options.path}`)\n }\n\n // Remember the last context that resolved so a transient miss (e.g. the active\n // document is swapped to one without this path or method after mount) keeps\n // rendering the previous operation, paired with the server it actually came\n // from, instead of feeding `undefined` to the block.\n let lastContext: OperationContext | undefined\n\n /** Current operation + server, falling back to the last good resolution on a transient miss. */\n const currentContext = (): OperationContext => {\n const context = resolveContext()\n if (context) {\n lastContext = context\n }\n return (context ?? lastContext) as OperationContext\n }\n\n // Props are getters so the block tracks the reactive store (active document,\n // `x-scalar-default-client`, `x-scalar-default-example`) live. Change the\n // client, example, or server through the store to drive re-renders.\n const props = reactive<CodeExampleProps>({\n get codeSampleUnavailable() {\n return options.codeSampleUnavailable\n },\n get codeSampleLabel() {\n return options.codeSampleLabel\n },\n get operation(): OperationObject {\n return currentContext().operation\n },\n get method() {\n return options.method\n },\n get path() {\n return options.path\n },\n clientOptions,\n eventBus,\n get securitySchemes() {\n return options.securitySchemes ?? []\n },\n get selectedClient() {\n // The store is the source of truth once the user picks a client, so it\n // wins over the initial `options.selectedClient` seed and the selection\n // round-trips through the subscription above.\n return options.store.workspace['x-scalar-default-client'] ?? options.selectedClient\n },\n get selectedExample() {\n // Same as the client: the store wins over the initial seed so the example\n // selection survives re-renders and syncs across blocks.\n return options.store.workspace['x-scalar-default-example'] ?? options.selectedExample\n },\n get selectedServer() {\n // An explicit option wins (including an explicit `null` for \"no server\");\n // otherwise derive it from the same document the operation resolved from.\n return options.selectedServer !== undefined ? options.selectedServer : currentContext().server\n },\n })\n\n // Render the operation path in the header by default. The reference renders\n // this via the `#header` slot too, so the standalone block matches its look.\n const renderHeader = () => h('span', { class: 'font-code text-c-2 min-w-0 truncate' }, options.path)\n\n // Wrap the block in its own teleport root so floating UI (the client picker\n // popover) renders inside the themed `.scalar-app` wrapper instead of escaping\n // to `body`, where it would miss the color-mode variables and lose its styling.\n const app = createApp(() =>\n h('div', { class: getWrapperClass(options.darkMode) }, [\n h(ScalarTeleportRoot, null, { default: () => h(CodeExample, props, { header: renderHeader }) }),\n ]),\n )\n\n app.provide(EXTERNAL_EXAMPLES, () => options.store.externalExamples())\n app.mount(element)\n\n return {\n app,\n destroy: () => {\n unsubscribeClient()\n unsubscribeExample()\n app.unmount()\n },\n }\n}\n"],"mappings":";;;;;;;;;;;AA8DA,IAAM,KAAmB,MACnB,MAAa,KACR,yBAEL,MAAa,KACR,0BAEF,cASI,KAAqB,GAA0B,MAAsC;CAChG,IAAM,IAAU,OAAO,KAAO,WAAW,SAAS,cAAc,CAAE,IAAI;CACtE,IAAI,CAAC,GACH,MAAU,MAAM,sBAAsB,GAAI;CAG5C,IAAM,IAAW,EAAwB,GACnC,IAAgB,EAAsB,GAQtC,IAAW,EAAuB,EAAQ,KAAK,GAC/C,IAAoB,EAAS,GAAG,qCAAqC,MACzE,EAAS,UAAU,CAAC,CAAC,UAAU,qBAAqB,CAAO,CAC7D,GAOM,IAAqB,EAAS,GAAG,sCAAsC,MAC3E,EAAS,UAAU,CAAC,CAAC,UAAU,sBAAsB,CAAO,CAC9D,GAWM,UAAqD;EAEzD,IAAM,IAAiB,EAAQ,MAAM,UAAU;EAC/C,IAAI,CAAC,KAAkB,EAAE,WAAW,IAClC;EAEF,IAAM,IAAW,EAAe,EAAe,QAAQ,EAAQ,KAAK,GAC9D,IAAY,EAAe,EAAqB,GAAU,EAAQ,MAAM,CAAC;EAC1E,OAIL,OAAO;GAAE;GAAW,QADL,EAAe,EAAU,WAAW,MAAM,GAAU,WAAW,MAAM,EAAe,WAAW,IAC1F;EAAO;CAC7B;CAIA,IAAI,CAAC,EAAe,GAClB,MAAU,MAAM,wBAAwB,EAAQ,OAAO,YAAY,EAAE,GAAG,EAAQ,MAAM;CAOxF,IAAI,GAGE,UAAyC;EAC7C,IAAM,IAAU,EAAe;EAI/B,OAHI,MACF,IAAc,IAER,KAAW;CACrB,GAKM,IAAQ,EAA2B;EACvC,IAAI,wBAAwB;GAC1B,OAAO,EAAQ;EACjB;EACA,IAAI,kBAAkB;GACpB,OAAO,EAAQ;EACjB;EACA,IAAI,YAA6B;GAC/B,OAAO,EAAe,CAAC,CAAC;EAC1B;EACA,IAAI,SAAS;GACX,OAAO,EAAQ;EACjB;EACA,IAAI,OAAO;GACT,OAAO,EAAQ;EACjB;EACA;EACA;EACA,IAAI,kBAAkB;GACpB,OAAO,EAAQ,mBAAmB,CAAC;EACrC;EACA,IAAI,iBAAiB;GAInB,OAAO,EAAQ,MAAM,UAAU,8BAA8B,EAAQ;EACvE;EACA,IAAI,kBAAkB;GAGpB,OAAO,EAAQ,MAAM,UAAU,+BAA+B,EAAQ;EACxE;EACA,IAAI,iBAAiB;GAGnB,OAAO,EAAQ,mBAAmB,KAAA,IAAqC,EAAe,CAAC,CAAC,SAA1C,EAAQ;EACxD;CACF,CAAC,GAIK,UAAqB,EAAE,QAAQ,EAAE,OAAO,sCAAsC,GAAG,EAAQ,IAAI,GAK7F,IAAM,QACV,EAAE,OAAO,EAAE,OAAO,EAAgB,EAAQ,QAAQ,EAAE,GAAG,CACrD,EAAE,GAAoB,MAAM,EAAE,eAAe,EAAE,GAAa,GAAO,EAAE,QAAQ,EAAa,CAAC,EAAE,CAAC,CAChG,CAAC,CACH;CAKA,OAHA,EAAI,QAAQ,SAAyB,EAAQ,MAAM,iBAAiB,CAAC,GACrE,EAAI,MAAM,CAAO,GAEV;EACL;EACA,eAAe;GAGb,AAFA,EAAkB,GAClB,EAAmB,GACnB,EAAI,QAAQ;EACd;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"mount.js","names":[],"sources":["../../src/code-example/mount.ts"],"sourcesContent":["import { ScalarTeleportRoot } from '@scalar/components/teleport'\nimport { ScalarWrappingText } from '@scalar/components/wrapping-text'\nimport type { AvailableClients } from '@scalar/snippetz'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { createWorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getPathItemOperation } from '@scalar/workspace-store/helpers/for-each-path-item-operation'\nimport { getFirstServer } from '@scalar/workspace-store/helpers/get-first-server'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { EXTERNAL_EXAMPLES } from '@scalar/workspace-store/helpers/use-external-examples'\nimport { generateClientMutators } from '@scalar/workspace-store/mutators'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { createApp, h, reactive } from 'vue'\n\nimport CodeExample, { type CodeExampleProps } from './components/CodeExample.vue'\nimport { generateClientOptions } from './helpers/generate-client-options'\n\nexport type CreateCodeExampleOptions = {\n /** Localized status text shown when the selected example has no linked code sample. */\n codeSampleUnavailable?: string\n /** Localized accessible name for the focusable code sample scroller. */\n codeSampleLabel?: string\n /** Workspace store that holds the OpenAPI document(s) to render from. */\n store: WorkspaceStore\n /** Path of the operation to render, e.g. '/users/{id}'. */\n path: string\n /** HTTP method of the operation to render. */\n method: string\n /** Pre-selected client ID, e.g. 'shell/curl'. */\n selectedClient?: AvailableClients[number]\n /**\n * Server object override used to build the example request.\n *\n * When omitted, the server is derived from the active document (operation,\n * then path item, then document level), mirroring the API reference. Pass\n * `null` to force \"no server\".\n */\n selectedServer?: ServerObject | null\n /**\n * Pre-selected example key for parameters and the request body.\n *\n * The store is the source of truth once an example is picked, so\n * `x-scalar-default-example` wins over this initial seed and the selection\n * round-trips through the store like the client selection does.\n */\n selectedExample?: string\n /** Security schemes applicable to the operation. */\n securitySchemes?: SecuritySchemeObjectSecret[]\n /**\n * Force a color mode on the rendered block.\n *\n * When omitted, the block inherits the ambient theme of the host page.\n * Pass `true` for dark mode or `false` for light mode.\n */\n darkMode?: boolean\n}\n\n/**\n * Builds the wrapper classes for the mounted block.\n *\n * The `.scalar-app` class scopes the Tailwind utilities, and the optional\n * color-mode class lets consumers pin the block to dark or light.\n */\nconst getWrapperClass = (darkMode: boolean | undefined): string => {\n if (darkMode === true) {\n return 'scalar-app dark-mode'\n }\n if (darkMode === false) {\n return 'scalar-app light-mode'\n }\n return 'scalar-app'\n}\n\n/**\n * Mount the CodeExample block to a DOM element without Vue.\n *\n * The consumer creates and controls their own workspace store,\n * then passes it in along with the path and method to render.\n */\nexport const createCodeExample = (el: HTMLElement | string, options: CreateCodeExampleOptions) => {\n const element = typeof el === 'string' ? document.querySelector(el) : el\n if (!element) {\n throw new Error(`Element not found: ${el}`)\n }\n\n const eventBus = createWorkspaceEventBus()\n const clientOptions = generateClientOptions()\n\n // Persist client changes back to the store. The block emits\n // `workspace:update:selected-client` on its private bus when the user picks a\n // client; without this subscription the choice would never reach the store\n // and `x-scalar-default-client` (the source of truth read below) would stay\n // stale, so the selection would not survive a re-render or be shared with\n // other blocks reading from the same store.\n const mutators = generateClientMutators(options.store)\n const unsubscribeClient = eventBus.on('workspace:update:selected-client', (payload) =>\n mutators.workspace().workspace.updateSelectedClient(payload),\n )\n\n // Persist example changes back to the store as well, mirroring the client\n // round-trip above. The block emits `workspace:update:selected-example` when\n // the user picks an example; without this the choice would never reach\n // `x-scalar-default-example` (read below) and would neither survive a\n // re-render nor sync to other blocks reading from the same store.\n const unsubscribeExample = eventBus.on('workspace:update:selected-example', (payload) =>\n mutators.workspace().workspace.updateSelectedExample(payload),\n )\n\n type OperationContext = { operation: OperationObject; server: ServerObject | null }\n\n /**\n * Resolve the operation and its effective server from the active document.\n *\n * The server is resolved from the same document the operation came from\n * (operation, then path item, then document level), so a snippet never pairs\n * an operation with a server URL from a different spec.\n */\n const resolveContext = (): OperationContext | undefined => {\n // The active document may be an AsyncAPI document, which has no `paths`.\n const activeDocument = options.store.workspace.activeDocument\n if (!activeDocument || !('paths' in activeDocument)) {\n return undefined\n }\n const pathItem = getResolvedRef(activeDocument.paths?.[options.path])\n const operation = getResolvedRef(getPathItemOperation(pathItem, options.method))\n if (!operation) {\n return undefined\n }\n const server = getFirstServer(operation.servers ?? null, pathItem?.servers ?? null, activeDocument.servers ?? null)\n return { operation, server }\n }\n\n // Fail loudly if the path and method do not point at an operation in the store,\n // mirroring the \"element not found\" guard above.\n if (!resolveContext()) {\n throw new Error(`Operation not found: ${options.method.toUpperCase()} ${options.path}`)\n }\n\n // Remember the last context that resolved so a transient miss (e.g. the active\n // document is swapped to one without this path or method after mount) keeps\n // rendering the previous operation, paired with the server it actually came\n // from, instead of feeding `undefined` to the block.\n let lastContext: OperationContext | undefined\n\n /** Current operation + server, falling back to the last good resolution on a transient miss. */\n const currentContext = (): OperationContext => {\n const context = resolveContext()\n if (context) {\n lastContext = context\n }\n return (context ?? lastContext) as OperationContext\n }\n\n // Props are getters so the block tracks the reactive store (active document,\n // `x-scalar-default-client`, `x-scalar-default-example`) live. Change the\n // client, example, or server through the store to drive re-renders.\n const props = reactive<CodeExampleProps>({\n get codeSampleUnavailable() {\n return options.codeSampleUnavailable\n },\n get codeSampleLabel() {\n return options.codeSampleLabel\n },\n get operation(): OperationObject {\n return currentContext().operation\n },\n get method() {\n return options.method\n },\n get path() {\n return options.path\n },\n clientOptions,\n eventBus,\n get securitySchemes() {\n return options.securitySchemes ?? []\n },\n get selectedClient() {\n // The store is the source of truth once the user picks a client, so it\n // wins over the initial `options.selectedClient` seed and the selection\n // round-trips through the subscription above.\n return options.store.workspace['x-scalar-default-client'] ?? options.selectedClient\n },\n get selectedExample() {\n // Same as the client: the store wins over the initial seed so the example\n // selection survives re-renders and syncs across blocks.\n return options.store.workspace['x-scalar-default-example'] ?? options.selectedExample\n },\n get selectedServer() {\n // An explicit option wins (including an explicit `null` for \"no server\");\n // otherwise derive it from the same document the operation resolved from.\n return options.selectedServer !== undefined ? options.selectedServer : currentContext().server\n },\n })\n\n // Render the operation path in the header by default. The reference renders\n // this via the `#header` slot too, so the standalone block matches its look.\n const renderHeader = () =>\n h('span', { class: 'font-code text-c-2 min-w-0' }, h(ScalarWrappingText, { text: options.path }))\n\n // Wrap the block in its own teleport root so floating UI (the client picker\n // popover) renders inside the themed `.scalar-app` wrapper instead of escaping\n // to `body`, where it would miss the color-mode variables and lose its styling.\n const app = createApp(() =>\n h('div', { class: getWrapperClass(options.darkMode) }, [\n h(ScalarTeleportRoot, null, { default: () => h(CodeExample, props, { header: renderHeader }) }),\n ]),\n )\n\n app.provide(EXTERNAL_EXAMPLES, () => options.store.externalExamples())\n app.mount(element)\n\n return {\n app,\n destroy: () => {\n unsubscribeClient()\n unsubscribeExample()\n app.unmount()\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;AA+DA,IAAM,KAAmB,MACnB,MAAa,KACR,yBAEL,MAAa,KACR,0BAEF,cASI,KAAqB,GAA0B,MAAsC;CAChG,IAAM,IAAU,OAAO,KAAO,WAAW,SAAS,cAAc,CAAE,IAAI;CACtE,IAAI,CAAC,GACH,MAAU,MAAM,sBAAsB,GAAI;CAG5C,IAAM,IAAW,EAAwB,GACnC,IAAgB,EAAsB,GAQtC,IAAW,EAAuB,EAAQ,KAAK,GAC/C,IAAoB,EAAS,GAAG,qCAAqC,MACzE,EAAS,UAAU,CAAC,CAAC,UAAU,qBAAqB,CAAO,CAC7D,GAOM,IAAqB,EAAS,GAAG,sCAAsC,MAC3E,EAAS,UAAU,CAAC,CAAC,UAAU,sBAAsB,CAAO,CAC9D,GAWM,UAAqD;EAEzD,IAAM,IAAiB,EAAQ,MAAM,UAAU;EAC/C,IAAI,CAAC,KAAkB,EAAE,WAAW,IAClC;EAEF,IAAM,IAAW,EAAe,EAAe,QAAQ,EAAQ,KAAK,GAC9D,IAAY,EAAe,EAAqB,GAAU,EAAQ,MAAM,CAAC;EAC1E,OAIL,OAAO;GAAE;GAAW,QADL,EAAe,EAAU,WAAW,MAAM,GAAU,WAAW,MAAM,EAAe,WAAW,IAC1F;EAAO;CAC7B;CAIA,IAAI,CAAC,EAAe,GAClB,MAAU,MAAM,wBAAwB,EAAQ,OAAO,YAAY,EAAE,GAAG,EAAQ,MAAM;CAOxF,IAAI,GAGE,UAAyC;EAC7C,IAAM,IAAU,EAAe;EAI/B,OAHI,MACF,IAAc,IAER,KAAW;CACrB,GAKM,IAAQ,EAA2B;EACvC,IAAI,wBAAwB;GAC1B,OAAO,EAAQ;EACjB;EACA,IAAI,kBAAkB;GACpB,OAAO,EAAQ;EACjB;EACA,IAAI,YAA6B;GAC/B,OAAO,EAAe,CAAC,CAAC;EAC1B;EACA,IAAI,SAAS;GACX,OAAO,EAAQ;EACjB;EACA,IAAI,OAAO;GACT,OAAO,EAAQ;EACjB;EACA;EACA;EACA,IAAI,kBAAkB;GACpB,OAAO,EAAQ,mBAAmB,CAAC;EACrC;EACA,IAAI,iBAAiB;GAInB,OAAO,EAAQ,MAAM,UAAU,8BAA8B,EAAQ;EACvE;EACA,IAAI,kBAAkB;GAGpB,OAAO,EAAQ,MAAM,UAAU,+BAA+B,EAAQ;EACxE;EACA,IAAI,iBAAiB;GAGnB,OAAO,EAAQ,mBAAmB,KAAA,IAAqC,EAAe,CAAC,CAAC,SAA1C,EAAQ;EACxD;CACF,CAAC,GAIK,UACJ,EAAE,QAAQ,EAAE,OAAO,6BAA6B,GAAG,EAAE,GAAoB,EAAE,MAAM,EAAQ,KAAK,CAAC,CAAC,GAK5F,IAAM,QACV,EAAE,OAAO,EAAE,OAAO,EAAgB,EAAQ,QAAQ,EAAE,GAAG,CACrD,EAAE,GAAoB,MAAM,EAAE,eAAe,EAAE,GAAa,GAAO,EAAE,QAAQ,EAAa,CAAC,EAAE,CAAC,CAChG,CAAC,CACH;CAKA,OAHA,EAAI,QAAQ,SAAyB,EAAQ,MAAM,iBAAiB,CAAC,GACrE,EAAI,MAAM,CAAO,GAEV;EACL;EACA,eAAe;GAGb,AAFA,EAAkB,GAClB,EAAmB,GACnB,EAAI,QAAQ;EACd;CACF;AACF"}
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createCommentVNode as e, createElementBlock as t, createElementVNode as n, createVNode as r, defineComponent as i, openBlock as a, unref as o } from "vue";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { ScalarWrappingText as s } from "@scalar/components/wrapping-text";
|
|
3
|
+
import { ScalarMarkdown as c } from "@scalar/components/markdown";
|
|
4
4
|
//#region src/schema/SchemaEnumPropertyItem.vue?vue&type=script&setup=true&lang.ts
|
|
5
5
|
var l = { class: "property-enum-row flex flex-col gap-0.5 border-t px-3 py-2" }, u = { class: "property-enum-row-label font-code text-c-1 text-sm" }, d = {
|
|
6
6
|
key: 0,
|
|
@@ -12,10 +12,10 @@ var l = { class: "property-enum-row flex flex-col gap-0.5 border-t px-3 py-2" },
|
|
|
12
12
|
description: {}
|
|
13
13
|
},
|
|
14
14
|
setup(i) {
|
|
15
|
-
return (f, p) => (a(), t("li", l, [n("span", u, [r(o(
|
|
15
|
+
return (f, p) => (a(), t("li", l, [n("span", u, [r(o(s), {
|
|
16
16
|
preset: "property",
|
|
17
17
|
text: i.label
|
|
18
|
-
}, null, 8, ["text"])]), i.description ? (a(), t("span", d, [r(o(
|
|
18
|
+
}, null, 8, ["text"])]), i.description ? (a(), t("span", d, [r(o(c), { value: i.description }, null, 8, ["value"])])) : e("", !0)]));
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
//#endregion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isTypeObject as e } from "./helpers/is-type-object.js";
|
|
2
2
|
import { useLocalization as t } from "./localization/index.js";
|
|
3
3
|
import { Fragment as n, computed as r, createBlock as i, createCommentVNode as a, createElementBlock as o, createElementVNode as s, createTextVNode as c, defineComponent as l, openBlock as u, toDisplayString as d, unref as f } from "vue";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { ScalarWrappingText as p } from "@scalar/components/wrapping-text";
|
|
5
|
+
import { isArraySchema as m } from "@scalar/workspace-store/schemas/v3.2/strict/type-guards";
|
|
6
6
|
//#region src/schema/SchemaHeading.vue?vue&type=script&setup=true&lang.ts
|
|
7
7
|
var h = {
|
|
8
8
|
key: 0,
|
|
@@ -14,15 +14,15 @@ var h = {
|
|
|
14
14
|
name: {}
|
|
15
15
|
},
|
|
16
16
|
setup(l) {
|
|
17
|
-
let { translate: _ } = t(), v = r(() => "type" in l.value ? l.value.type : l.value.enum ? "enum" :
|
|
17
|
+
let { translate: _ } = t(), v = r(() => "type" in l.value ? l.value.type : l.value.enum ? "enum" : m(l.value) && l.value.items ? "array" : e(l.value) && (l.value.properties || l.value.additionalProperties) ? "object" : "unknown");
|
|
18
18
|
return (t, r) => typeof l.value == "object" ? (u(), o("span", h, [s("span", {
|
|
19
19
|
class: "schema-type-icon",
|
|
20
20
|
title: "type" in l.value && typeof l.value.type == "string" ? l.value.type : "type" in l.value && Array.isArray(l.value.type) ? l.value.type.join(" | ") : f(_)("schema.unknownType")
|
|
21
21
|
}, [
|
|
22
22
|
f(e)(l.value) ? (u(), o(n, { key: 0 }, [c(" {} ")], 64)) : a("", !0),
|
|
23
|
-
f(
|
|
23
|
+
f(m)(l.value) ? (u(), o(n, { key: 1 }, [c(" [] ")], 64)) : a("", !0),
|
|
24
24
|
l.value.enum ? (u(), o(n, { key: 2 }, [c(" enum ")], 64)) : a("", !0)
|
|
25
|
-
], 8, g), l.name ? (u(), i(f(
|
|
25
|
+
], 8, g), l.name ? (u(), i(f(p), {
|
|
26
26
|
key: 0,
|
|
27
27
|
preset: "property",
|
|
28
28
|
text: l.name
|
|
@@ -28,11 +28,11 @@ import Ce from "./SchemaGutterToggle.vue.js";
|
|
|
28
28
|
import we from "./SchemaPropertyHeading.vue.js";
|
|
29
29
|
import Te from "./Schema.vue.js";
|
|
30
30
|
import { Fragment as Ee, computed as s, createBlock as c, createCommentVNode as l, createElementBlock as u, createElementVNode as De, createSlots as Oe, createTextVNode as ke, createVNode as d, defineComponent as f, inject as Ae, mergeProps as p, normalizeClass as je, onBeforeUnmount as Me, onScopeDispose as Ne, openBlock as m, ref as Pe, renderList as Fe, resolveDynamicComponent as Ie, toDisplayString as Le, toHandlers as Re, toRef as ze, unref as h, useId as g, useTemplateRef as _, watch as v, withCtx as y } from "vue";
|
|
31
|
+
import { ScalarWrappingText as b } from "@scalar/components/wrapping-text";
|
|
31
32
|
import { resolve as Be } from "@scalar/workspace-store/resolve";
|
|
32
|
-
import { isArraySchema as
|
|
33
|
+
import { isArraySchema as x } from "@scalar/workspace-store/schemas/v3.2/strict/type-guards";
|
|
33
34
|
import { ScalarMarkdown as Ve } from "@scalar/components/markdown";
|
|
34
35
|
import { isDynamicRef as He, resolveDynamicRef as Ue } from "@scalar/workspace-store/helpers/dynamic-ref";
|
|
35
|
-
import { ScalarWrappingText as x } from "@scalar/components/wrapping-text";
|
|
36
36
|
//#region src/schema/SchemaProperty.vue?vue&type=script&setup=true&lang.ts
|
|
37
37
|
var We = ["id"], Ge = {
|
|
38
38
|
key: 0,
|
|
@@ -105,7 +105,7 @@ var We = ["id"], Ge = {
|
|
|
105
105
|
return S.level <= 2 || !!(e && t && e.length === t.length && e.every((e, n) => e === t[n]));
|
|
106
106
|
}), rt = s(() => D.value && (T.value?.length ?? 0) > 0), O = s(() => {
|
|
107
107
|
let e = C.value;
|
|
108
|
-
if (!e || !
|
|
108
|
+
if (!e || !x(e) || !He(e.items)) return e;
|
|
109
109
|
let t = Ue(e.items.$dynamicRef, tt);
|
|
110
110
|
return t ? {
|
|
111
111
|
...e,
|
|
@@ -118,7 +118,7 @@ var We = ["id"], Ge = {
|
|
|
118
118
|
return a(e) || !n;
|
|
119
119
|
}), A = s(() => {
|
|
120
120
|
let e = C.value;
|
|
121
|
-
return !e || !
|
|
121
|
+
return !e || !x(e) || e.items === void 0 ? !1 : it.value;
|
|
122
122
|
}), st = s(() => he(C.value)), ct = s(() => {
|
|
123
123
|
let e = ge(C.value);
|
|
124
124
|
return e ? I(e) : null;
|
|
@@ -141,12 +141,12 @@ var We = ["id"], Ge = {
|
|
|
141
141
|
return !1;
|
|
142
142
|
}), pt = (e) => e === "allOf" ? S.schema?.discriminator ?? S.discriminator : S.schema?.discriminator, N = s(() => {
|
|
143
143
|
let e = O.value;
|
|
144
|
-
if (!e || !
|
|
144
|
+
if (!e || !x(e) || e.items === void 0) return;
|
|
145
145
|
let t = Be.schema(e.items);
|
|
146
146
|
return et.some((e) => Array.isArray(t?.[e]) && t[e]?.length === 1) ? o(t) : t;
|
|
147
147
|
}), mt = s(() => {
|
|
148
148
|
let e = C.value;
|
|
149
|
-
if (!(!e || !
|
|
149
|
+
if (!(!e || !x(e))) return oe(e.items);
|
|
150
150
|
}), P = s(() => ({
|
|
151
151
|
compact: S.compact,
|
|
152
152
|
eventBus: S.eventBus,
|
|
@@ -288,13 +288,13 @@ var We = ["id"], Ge = {
|
|
|
288
288
|
key: 0,
|
|
289
289
|
breadcrumb: T.value
|
|
290
290
|
}, {
|
|
291
|
-
default: y(() => [De("span", { id: h(q) }, [f.variant === "patternProperties" ? (m(), u("span", Ge, [d(h(
|
|
291
|
+
default: y(() => [De("span", { id: h(q) }, [f.variant === "patternProperties" ? (m(), u("span", Ge, [d(h(b), {
|
|
292
292
|
preset: "property",
|
|
293
293
|
text: f.name
|
|
294
|
-
}, null, 8, ["text"])])) : f.variant === "additionalProperties" ? (m(), u("span", Ke, [d(h(
|
|
294
|
+
}, null, 8, ["text"])])) : f.variant === "additionalProperties" ? (m(), u("span", Ke, [d(h(b), {
|
|
295
295
|
preset: "property",
|
|
296
296
|
text: f.name
|
|
297
|
-
}, null, 8, ["text"])])) : (m(), c(h(
|
|
297
|
+
}, null, 8, ["text"])])) : (m(), c(h(b), {
|
|
298
298
|
key: 2,
|
|
299
299
|
preset: "property",
|
|
300
300
|
text: f.name
|
|
@@ -303,13 +303,13 @@ var We = ["id"], Ge = {
|
|
|
303
303
|
}, 8, ["breadcrumb"])) : (m(), u("span", {
|
|
304
304
|
key: 1,
|
|
305
305
|
id: h(q)
|
|
306
|
-
}, [f.variant === "patternProperties" ? (m(), u("span", Je, [d(h(
|
|
306
|
+
}, [f.variant === "patternProperties" ? (m(), u("span", Je, [d(h(b), {
|
|
307
307
|
preset: "property",
|
|
308
308
|
text: f.name
|
|
309
|
-
}, null, 8, ["text"])])) : f.variant === "additionalProperties" ? (m(), u("span", Ye, [d(h(
|
|
309
|
+
}, null, 8, ["text"])])) : f.variant === "additionalProperties" ? (m(), u("span", Ye, [d(h(b), {
|
|
310
310
|
preset: "property",
|
|
311
311
|
text: f.name
|
|
312
|
-
}, null, 8, ["text"])])) : (m(), c(h(
|
|
312
|
+
}, null, 8, ["text"])])) : (m(), c(h(b), {
|
|
313
313
|
key: 2,
|
|
314
314
|
preset: "property",
|
|
315
315
|
text: f.name
|
package/dist/style.css
CHANGED
|
@@ -2862,6 +2862,10 @@
|
|
|
2862
2862
|
flex: 1;
|
|
2863
2863
|
}
|
|
2864
2864
|
|
|
2865
|
+
.scalar-app .flex-auto {
|
|
2866
|
+
flex: auto;
|
|
2867
|
+
}
|
|
2868
|
+
|
|
2865
2869
|
.scalar-app .flex-shrink, .scalar-app .shrink {
|
|
2866
2870
|
flex-shrink: 1;
|
|
2867
2871
|
}
|
|
@@ -3104,6 +3108,10 @@
|
|
|
3104
3108
|
column-gap: 8px;
|
|
3105
3109
|
}
|
|
3106
3110
|
|
|
3111
|
+
.scalar-app .gap-y-1 {
|
|
3112
|
+
row-gap: 4px;
|
|
3113
|
+
}
|
|
3114
|
+
|
|
3107
3115
|
:where(.scalar-app .divide-y > :not(:last-child)) {
|
|
3108
3116
|
--tw-divide-y-reverse: 0;
|
|
3109
3117
|
border-bottom-style: var(--tw-border-style);
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"blocks",
|
|
18
18
|
"docs"
|
|
19
19
|
],
|
|
20
|
-
"version": "0.5.
|
|
20
|
+
"version": "0.5.4",
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=22"
|
|
23
23
|
},
|
|
@@ -62,15 +62,15 @@
|
|
|
62
62
|
"CHANGELOG.md"
|
|
63
63
|
],
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@scalar/components": "0.32.
|
|
65
|
+
"@scalar/components": "0.32.1",
|
|
66
66
|
"@scalar/helpers": "0.16.4",
|
|
67
67
|
"@scalar/icons": "0.7.7",
|
|
68
68
|
"@scalar/localization": "0.2.8",
|
|
69
|
-
"@scalar/snippetz": "0.10.
|
|
69
|
+
"@scalar/snippetz": "0.10.10",
|
|
70
70
|
"@scalar/themes": "0.19.2",
|
|
71
71
|
"@scalar/types": "0.24.0",
|
|
72
72
|
"@scalar/use-hooks": "0.4.21",
|
|
73
|
-
"@scalar/workspace-store": "0.68.
|
|
73
|
+
"@scalar/workspace-store": "0.68.5",
|
|
74
74
|
"@types/har-format": "^1.2.16",
|
|
75
75
|
"@vueuse/core": "13.9.0",
|
|
76
76
|
"js-base64": "^3.9.2",
|