@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 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":"AACA,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;;;CA4I5F,CAAA"}
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 { getPathItemOperation as l } from "@scalar/workspace-store/helpers/for-each-path-item-operation";
9
- import { getFirstServer as u } from "@scalar/workspace-store/helpers/get-first-server";
10
- import { generateClientMutators as d } from "@scalar/workspace-store/mutators";
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 f = (e) => e === !0 ? "scalar-app dark-mode" : e === !1 ? "scalar-app light-mode" : "scalar-app", p = (p, m) => {
13
- let h = typeof p == "string" ? document.querySelector(p) : p;
14
- if (!h) throw Error(`Element not found: ${p}`);
15
- let g = a(), _ = e(), v = d(m.store), y = g.on("workspace:update:selected-client", (e) => v.workspace().workspace.updateSelectedClient(e)), b = g.on("workspace:update:selected-example", (e) => v.workspace().workspace.updateSelectedExample(e)), x = () => {
16
- let e = m.store.workspace.activeDocument;
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?.[m.path]), n = o(l(t, m.method));
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: u(n.servers ?? null, t?.servers ?? null, e.servers ?? null)
22
+ server: d(n.servers ?? null, t?.servers ?? null, e.servers ?? null)
22
23
  };
23
24
  };
24
- if (!x()) throw Error(`Operation not found: ${m.method.toUpperCase()} ${m.path}`);
25
- let S, C = () => {
26
- let e = x();
27
- return e && (S = e), e ?? S;
28
- }, w = i({
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 m.codeSampleUnavailable;
31
+ return h.codeSampleUnavailable;
31
32
  },
32
33
  get codeSampleLabel() {
33
- return m.codeSampleLabel;
34
+ return h.codeSampleLabel;
34
35
  },
35
36
  get operation() {
36
- return C().operation;
37
+ return w().operation;
37
38
  },
38
39
  get method() {
39
- return m.method;
40
+ return h.method;
40
41
  },
41
42
  get path() {
42
- return m.path;
43
+ return h.path;
43
44
  },
44
- clientOptions: _,
45
- eventBus: g,
45
+ clientOptions: v,
46
+ eventBus: _,
46
47
  get securitySchemes() {
47
- return m.securitySchemes ?? [];
48
+ return h.securitySchemes ?? [];
48
49
  },
49
50
  get selectedClient() {
50
- return m.store.workspace["x-scalar-default-client"] ?? m.selectedClient;
51
+ return h.store.workspace["x-scalar-default-client"] ?? h.selectedClient;
51
52
  },
52
53
  get selectedExample() {
53
- return m.store.workspace["x-scalar-default-example"] ?? m.selectedExample;
54
+ return h.store.workspace["x-scalar-default-example"] ?? h.selectedExample;
54
55
  },
55
56
  get selectedServer() {
56
- return m.selectedServer === void 0 ? C().server : m.selectedServer;
57
+ return h.selectedServer === void 0 ? w().server : h.selectedServer;
57
58
  }
58
- }), T = () => r("span", { class: "font-code text-c-2 min-w-0 truncate" }, m.path), E = n(() => r("div", { class: f(m.darkMode) }, [r(c, null, { default: () => r(t, w, { header: T }) })]));
59
- return E.provide(s, () => m.store.externalExamples()), E.mount(h), {
60
- app: E,
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
- y(), b(), E.unmount();
63
+ b(), x(), D.unmount();
63
64
  }
64
65
  };
65
66
  };
66
67
  //#endregion
67
- export { p as createCodeExample };
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,5 +1,5 @@
1
1
  //#region src/constants.ts
2
- var e = typeof OVERRIDE_PACKAGE_VERSION < "u" ? OVERRIDE_PACKAGE_VERSION : "0.5.3";
2
+ var e = typeof OVERRIDE_PACKAGE_VERSION < "u" ? OVERRIDE_PACKAGE_VERSION : "0.5.4";
3
3
  //#endregion
4
4
  export { e as APP_VERSION };
5
5
 
@@ -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 { ScalarMarkdown as s } from "@scalar/components/markdown";
3
- import { ScalarWrappingText as c } from "@scalar/components/wrapping-text";
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(c), {
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(s), { value: i.description }, null, 8, ["value"])])) : e("", !0)]));
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 { isArraySchema as p } from "@scalar/workspace-store/schemas/v3.2/strict/type-guards";
5
- import { ScalarWrappingText as m } from "@scalar/components/wrapping-text";
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" : p(l.value) && l.value.items ? "array" : e(l.value) && (l.value.properties || l.value.additionalProperties) ? "object" : "unknown");
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(p)(l.value) ? (u(), o(n, { key: 1 }, [c(" [] ")], 64)) : a("", !0),
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(m), {
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 b } from "@scalar/workspace-store/schemas/v3.2/strict/type-guards";
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 || !b(e) || !He(e.items)) return 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 || !b(e) || e.items === void 0 ? !1 : it.value;
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 || !b(e) || e.items === void 0) return;
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 || !b(e))) return oe(e.items);
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(x), {
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(x), {
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(x), {
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(x), {
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(x), {
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(x), {
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.3",
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.0",
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.9",
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.4",
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",