@qamposer/react 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -39,32 +39,27 @@ Quantum mechanics and simulation results can be directly leveraged as game logic
39
39
  ### Basic Usage (QamposerMicro)
40
40
 
41
41
  ```tsx
42
- import { QamposerMicro, qiskitAdapter } from "@qamposer/react";
43
- import "@qamposer/react/styles.css";
42
+ import { QamposerMicro } from '@qamposer/react';
44
43
 
45
44
  function App() {
46
- return (
47
- <QamposerMicro
48
- adapter={qiskitAdapter("http://localhost:8000")}
49
- onSimulationComplete={(event) => {
50
- console.log("Result:", event.result);
51
- console.log("QASM:", event.qasm);
52
- }}
53
- />
54
- );
45
+ return <QamposerMicro />;
55
46
  }
56
47
  ```
57
48
 
49
+ > **Note**: By default, QamposerMicro runs in editor-only mode (no simulation). To enable simulation, see [With Backend](#with-backend-simulation) below.
50
+
58
51
  ### Full Version with Visualization (Qamposer)
59
52
 
53
+ The full version includes visualization components (histograms, Q-sphere) that require simulation results, so a backend adapter is needed:
54
+
60
55
  ```tsx
61
- import { Qamposer } from "@qamposer/react/visualization";
62
- import "@qamposer/react/styles.css";
56
+ import { Qamposer } from '@qamposer/react/visualization';
57
+ import { qiskitAdapter } from '@qamposer/react';
63
58
 
64
59
  function App() {
65
60
  return (
66
61
  <Qamposer
67
- adapter={qiskitAdapter("http://localhost:8000")}
62
+ adapter={qiskitAdapter('http://localhost:8080')}
68
63
  defaultTheme="dark"
69
64
  showThemeToggle
70
65
  />
@@ -102,11 +97,24 @@ This library provides two preset components to fit different use cases:
102
97
 
103
98
  ## Backend Requirements
104
99
 
105
- > **Important**: To run quantum simulations, you need to run the `qamposer-backend` server.
100
+ The React components work standalone for circuit editing. To run quantum simulations, you need the `qamposer-backend` server.
101
+
102
+ ### Editor-Only Mode
106
103
 
107
- The React components handle circuit editing and visualization, but actual quantum simulation requires a backend server running Qiskit.
104
+ By default, components run in editor-only mode without requiring a backend:
108
105
 
109
- ### Starting the Backend
106
+ ```tsx
107
+ import { QamposerMicro } from '@qamposer/react';
108
+
109
+ // No backend required - editor-only mode (default)
110
+ <QamposerMicro />;
111
+ ```
112
+
113
+ ### With Backend (Simulation)
114
+
115
+ To enable quantum simulation, start the backend and pass the `qiskitAdapter`:
116
+
117
+ Assuming localhost is used here, but please specify the actual deployment destination for the backend.
110
118
 
111
119
  ```bash
112
120
  # Clone and setup qamposer-backend
@@ -115,17 +123,16 @@ poetry install
115
123
  poetry run uvicorn backend.main:app --host 0.0.0.0 --port 8080 --reload
116
124
  ```
117
125
 
118
- The backend will start at `http://localhost:8000` by default.
119
-
120
- ### Editor-Only Mode (No Backend)
121
-
122
- If you only need the circuit editor without simulation capabilities, use the `noopAdapter`:
123
-
124
126
  ```tsx
125
- import { QamposerMicro, noopAdapter } from "@qamposer/react";
126
-
127
- // No backend required - simulation is disabled
128
- <QamposerMicro adapter={noopAdapter} />;
127
+ import { QamposerMicro, qiskitAdapter } from '@qamposer/react';
128
+
129
+ <QamposerMicro
130
+ adapter={qiskitAdapter('http://localhost:8080')}
131
+ onSimulationComplete={(event) => {
132
+ console.log('Result:', event.result);
133
+ console.log('QASM:', event.qasm);
134
+ }}
135
+ />;
129
136
  ```
130
137
 
131
138
  ## API Reference
@@ -140,7 +147,7 @@ interface QamposerProps {
140
147
  onCircuitChange?: (circuit: Circuit) => void;
141
148
 
142
149
  // Simulation
143
- adapter?: SimulationAdapter; // Backend adapter
150
+ adapter?: SimulationAdapter; // Backend adapter (default: noopAdapter)
144
151
  onSimulationComplete?: (event: SimulationCompleteEvent) => void;
145
152
 
146
153
  // Configuration
@@ -150,7 +157,7 @@ interface QamposerProps {
150
157
  className?: string;
151
158
  showHeader?: boolean; // Default: true
152
159
  title?: string; // Default: 'Qamposer'
153
- defaultTheme?: "light" | "dark"; // Default: 'dark'
160
+ defaultTheme?: 'light' | 'dark'; // Default: 'dark'
154
161
  showThemeToggle?: boolean; // Default: true
155
162
 
156
163
  // Layout (Qamposer only)
@@ -170,31 +177,31 @@ interface QamposerConfig {
170
177
  }
171
178
  ```
172
179
 
173
- ### Adapters
180
+ <!-- ### Adapters
174
181
 
175
182
  ```tsx
176
183
  // Qiskit Backend Adapter
177
- import { qiskitAdapter } from "@qamposer/react";
184
+ import { qiskitAdapter } from '@qamposer/react';
178
185
 
179
- const adapter = qiskitAdapter("http://localhost:8000");
186
+ const adapter = qiskitAdapter('http://localhost:8000');
180
187
 
181
188
  // With options
182
189
  const adapter = qiskitAdapter({
183
- baseUrl: "http://localhost:8000",
184
- headers: { Authorization: "Bearer token" },
190
+ baseUrl: 'http://localhost:8000',
191
+ headers: { Authorization: 'Bearer token' },
185
192
  timeout: 30000,
186
193
  });
187
194
 
188
195
  // No-op Adapter (editor only, no simulation)
189
- import { noopAdapter } from "@qamposer/react";
190
- ```
196
+ import { noopAdapter } from '@qamposer/react';
197
+ ``` -->
191
198
 
192
- ### useQamposer Hook
199
+ <!-- ### useQamposer Hook
193
200
 
194
201
  For building custom UIs, use the `useQamposer` hook within a `QamposerProvider`:
195
202
 
196
203
  ```tsx
197
- import { QamposerProvider, useQamposer } from '@qamposer/react';
204
+ import { QamposerProvider, useQamposer, qiskitAdapter } from '@qamposer/react';
198
205
 
199
206
  function CustomEditor() {
200
207
  const {
@@ -213,14 +220,24 @@ function CustomEditor() {
213
220
  );
214
221
  }
215
222
 
223
+ // Editor-only mode (default)
216
224
  function App() {
217
225
  return (
218
- <QamposerProvider adapter={qiskitAdapter('http://localhost:8000')}>
226
+ <QamposerProvider>
219
227
  <CustomEditor />
220
228
  </QamposerProvider>
221
229
  );
222
230
  }
223
- ```
231
+
232
+ // With backend simulation
233
+ function AppWithSimulation() {
234
+ return (
235
+ <QamposerProvider adapter={qiskitAdapter('http://localhost:8080')}>
236
+ <CustomEditor />
237
+ </QamposerProvider>
238
+ );
239
+ }
240
+ ``` -->
224
241
 
225
242
  <!-- ### Individual Components -->
226
243
 
@@ -241,7 +258,7 @@ import { QSphereView, ResultsPanel } from '@qamposer/react/visualization';
241
258
  ## OpenQASM Utilities
242
259
 
243
260
  ```tsx
244
- import { circuitToQasm, qasmToCircuit } from "@qamposer/react";
261
+ import { circuitToQasm, qasmToCircuit } from '@qamposer/react';
245
262
 
246
263
  // Convert Circuit to OpenQASM
247
264
  const qasm = circuitToQasm(circuit);
@@ -285,7 +302,7 @@ The library uses CSS variables for theming. You can customize colors by overridi
285
302
  Or use the theme hook:
286
303
 
287
304
  ```tsx
288
- import { useTheme } from "@qamposer/react";
305
+ import { useTheme } from '@qamposer/react';
289
306
 
290
307
  function ThemeToggle() {
291
308
  const { theme, toggleTheme } = useTheme();
@@ -43,7 +43,7 @@ interface Circuit {
43
43
  qubits: number;
44
44
  gates: Gate[];
45
45
  }
46
- type BackendType = 'ideal' | 'noisy_fake';
46
+ type BackendType = 'ideal' | 'noisy_fake' | 'real';
47
47
  interface SimulationProfile {
48
48
  type: BackendType;
49
49
  backend_name?: string;
@@ -43,7 +43,7 @@ interface Circuit {
43
43
  qubits: number;
44
44
  gates: Gate[];
45
45
  }
46
- type BackendType = 'ideal' | 'noisy_fake';
46
+ type BackendType = 'ideal' | 'noisy_fake' | 'real';
47
47
  interface SimulationProfile {
48
48
  type: BackendType;
49
49
  backend_name?: string;
package/dist/index.cjs CHANGED
@@ -321,6 +321,38 @@ function QamposerProvider({
321
321
  react.useEffect(() => {
322
322
  adapter.isAvailable().then(setCanSimulate);
323
323
  }, [adapter]);
324
+ const autoSimRequestId = react.useRef(0);
325
+ react.useEffect(() => {
326
+ if (!canSimulate || circuit.gates.length === 0) {
327
+ if (circuit.gates.length === 0) {
328
+ setResult(null);
329
+ }
330
+ return;
331
+ }
332
+ const requestId = ++autoSimRequestId.current;
333
+ setStatus("simulating");
334
+ setError(null);
335
+ const request = {
336
+ qubits: circuit.qubits,
337
+ gates: circuit.gates.map(({ id: _, ...gate }) => gate),
338
+ shots: 1024,
339
+ profile: { type: "ideal" }
340
+ };
341
+ adapter.simulate(request).then((simulationResult) => {
342
+ if (autoSimRequestId.current !== requestId) return;
343
+ setResult(simulationResult);
344
+ setStatus("idle");
345
+ onSimulationComplete?.({
346
+ result: simulationResult,
347
+ circuit: { ...circuit },
348
+ qasm: circuitToQasm(circuit)
349
+ });
350
+ }).catch((err) => {
351
+ if (autoSimRequestId.current !== requestId) return;
352
+ setError(err instanceof Error ? err : new Error(String(err)));
353
+ setStatus("error");
354
+ });
355
+ }, [circuit, canSimulate, adapter, onSimulationComplete]);
324
356
  const addGate = react.useCallback(
325
357
  (gate) => {
326
358
  if (circuit.gates.length >= config.maxGates) {
@@ -490,6 +522,7 @@ function QamposerProvider({
490
522
  }, [circuit]);
491
523
  const simulate = react.useCallback(
492
524
  async (shots = 1024, profile) => {
525
+ autoSimRequestId.current++;
493
526
  if (!canSimulate) {
494
527
  throw new Error("Simulation adapter is not available");
495
528
  }
@@ -2303,6 +2336,11 @@ var css3 = `.simulation-controls__run-btn {
2303
2336
  border-color: var(--qamposer-accent, #4285f4);
2304
2337
  background: rgba(66, 133, 244, 0.1);
2305
2338
  }
2339
+ .simulation-controls__backend-item--disabled {
2340
+ opacity: 0.5;
2341
+ cursor: not-allowed;
2342
+ pointer-events: none;
2343
+ }
2306
2344
  .simulation-controls__backend-item-content {
2307
2345
  flex: 1;
2308
2346
  min-width: 0;
@@ -2334,6 +2372,10 @@ var css3 = `.simulation-controls__run-btn {
2334
2372
  background: rgba(237, 137, 54, 0.2);
2335
2373
  color: #ed8936;
2336
2374
  }
2375
+ .simulation-controls__backend-type--real {
2376
+ background: rgba(160, 174, 192, 0.2);
2377
+ color: #a0aec0;
2378
+ }
2337
2379
  .simulation-controls__backend-desc {
2338
2380
  margin: 0;
2339
2381
  font-size: 0.75rem;
@@ -2425,7 +2467,7 @@ function SimulationControls({
2425
2467
  const [isDialogOpen, setIsDialogOpen] = react.useState(false);
2426
2468
  const [shots, setShots] = react.useState(1024);
2427
2469
  const [backends, setBackends] = react.useState([]);
2428
- const [selectedBackendId, setSelectedBackendId] = react.useState("ideal");
2470
+ const [selectedBackendId, setSelectedBackendId] = react.useState("");
2429
2471
  const [isLoadingBackends, setIsLoadingBackends] = react.useState(false);
2430
2472
  const [backendError, setBackendError] = react.useState(false);
2431
2473
  react.useEffect(() => {
@@ -2433,8 +2475,13 @@ function SimulationControls({
2433
2475
  setIsLoadingBackends(true);
2434
2476
  setBackendError(false);
2435
2477
  adapter.getBackends().then((result) => {
2436
- setBackends(result);
2437
- if (result.length === 1 && result[0].id === "ideal" && !canSimulate) {
2478
+ const nonIdealBackends = result.filter((b) => b.backend_type !== "ideal");
2479
+ setBackends(nonIdealBackends);
2480
+ const firstFake = nonIdealBackends.find((b) => b.backend_type === "noisy_fake");
2481
+ if (firstFake) {
2482
+ setSelectedBackendId(firstFake.id);
2483
+ }
2484
+ if (nonIdealBackends.length === 0 && !canSimulate) {
2438
2485
  setBackendError(true);
2439
2486
  }
2440
2487
  }).finally(() => setIsLoadingBackends(false));
@@ -2442,13 +2489,10 @@ function SimulationControls({
2442
2489
  }, [isDialogOpen, adapter, canSimulate]);
2443
2490
  const selectedBackend = backends.find((b) => b.id === selectedBackendId);
2444
2491
  const buildProfile = () => {
2445
- if (!selectedBackend || selectedBackend.backend_type === "ideal") {
2446
- return { type: "ideal" };
2492
+ if (!selectedBackend || selectedBackend.backend_type === "noisy_fake") {
2493
+ return selectedBackend ? { type: "noisy_fake", backend_name: selectedBackend.id } : void 0;
2447
2494
  }
2448
- return {
2449
- type: "noisy_fake",
2450
- backend_name: selectedBackend.id
2451
- };
2495
+ return void 0;
2452
2496
  };
2453
2497
  const handleRun = async () => {
2454
2498
  if (circuit.gates.length === 0) {
@@ -2535,31 +2579,35 @@ function SimulationControls({
2535
2579
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "simulation-controls__error-title", children: "Backend unavailable" }),
2536
2580
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "simulation-controls__error-desc", children: "Cannot connect to the simulation backend. Please check that the server is running and CORS is configured correctly." })
2537
2581
  ] })
2538
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "simulation-controls__backend-list", children: backends.map((backend) => /* @__PURE__ */ jsxRuntime.jsxs(
2539
- "button",
2540
- {
2541
- type: "button",
2542
- className: `simulation-controls__backend-item ${selectedBackendId === backend.id ? "simulation-controls__backend-item--selected" : ""}`,
2543
- onClick: () => setSelectedBackendId(backend.id),
2544
- children: [
2545
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__backend-item-content", children: [
2546
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__backend-item-header", children: [
2547
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "simulation-controls__backend-name", children: backend.name }),
2548
- /* @__PURE__ */ jsxRuntime.jsx(
2549
- "span",
2550
- {
2551
- className: `simulation-controls__backend-type simulation-controls__backend-type--${backend.backend_type}`,
2552
- children: backend.backend_type === "ideal" ? "Ideal" : "Noisy"
2553
- }
2554
- )
2582
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "simulation-controls__backend-list", children: backends.map((backend) => {
2583
+ const isReal = backend.backend_type === "real";
2584
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2585
+ "button",
2586
+ {
2587
+ type: "button",
2588
+ className: `simulation-controls__backend-item ${selectedBackendId === backend.id ? "simulation-controls__backend-item--selected" : ""} ${isReal ? "simulation-controls__backend-item--disabled" : ""}`,
2589
+ onClick: () => !isReal && setSelectedBackendId(backend.id),
2590
+ disabled: isReal,
2591
+ children: [
2592
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__backend-item-content", children: [
2593
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__backend-item-header", children: [
2594
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "simulation-controls__backend-name", children: backend.name }),
2595
+ /* @__PURE__ */ jsxRuntime.jsx(
2596
+ "span",
2597
+ {
2598
+ className: `simulation-controls__backend-type simulation-controls__backend-type--${backend.backend_type}`,
2599
+ children: backend.backend_type === "noisy_fake" ? "Noisy" : "Real"
2600
+ }
2601
+ )
2602
+ ] }),
2603
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "simulation-controls__backend-desc", children: isReal ? "Coming soon" : backend.description || `${backend.num_qubits} qubits` })
2555
2604
  ] }),
2556
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "simulation-controls__backend-desc", children: backend.description || `${backend.num_qubits} qubits` })
2557
- ] }),
2558
- selectedBackendId === backend.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "simulation-controls__backend-check", children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) })
2559
- ]
2560
- },
2561
- backend.id
2562
- )) })
2605
+ selectedBackendId === backend.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "simulation-controls__backend-check", children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) })
2606
+ ]
2607
+ },
2608
+ backend.id
2609
+ );
2610
+ }) })
2563
2611
  ] })
2564
2612
  ] }),
2565
2613
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__dialog-footer", children: [
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Q as QamposerProviderProps$1, T as Theme, C as Circuit, S as SimulationAdapter, a as SimulationCompleteEvent, b as QamposerConfig, c as QamposerContextValue, d as QasmParseResult } from './index-BbUFQqpD.cjs';
3
- export { h as CircuitRequest, G as Gate, g as GateInfo, f as GateType, j as QSpherePoint, i as SimulationResult, e as ThemeProvider, u as useTheme } from './index-BbUFQqpD.cjs';
2
+ import { Q as QamposerProviderProps$1, T as Theme, C as Circuit, S as SimulationAdapter, a as SimulationCompleteEvent, b as QamposerConfig, c as QamposerContextValue, d as QasmParseResult } from './index-BghK68a6.cjs';
3
+ export { h as CircuitRequest, G as Gate, g as GateInfo, f as GateType, j as QSpherePoint, i as SimulationResult, e as ThemeProvider, u as useTheme } from './index-BghK68a6.cjs';
4
4
  import { ReactNode } from 'react';
5
5
 
6
6
  interface QamposerMicroProps extends Omit<QamposerProviderProps$1, 'children'> {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Q as QamposerProviderProps$1, T as Theme, C as Circuit, S as SimulationAdapter, a as SimulationCompleteEvent, b as QamposerConfig, c as QamposerContextValue, d as QasmParseResult } from './index-BbUFQqpD.js';
3
- export { h as CircuitRequest, G as Gate, g as GateInfo, f as GateType, j as QSpherePoint, i as SimulationResult, e as ThemeProvider, u as useTheme } from './index-BbUFQqpD.js';
2
+ import { Q as QamposerProviderProps$1, T as Theme, C as Circuit, S as SimulationAdapter, a as SimulationCompleteEvent, b as QamposerConfig, c as QamposerContextValue, d as QasmParseResult } from './index-BghK68a6.js';
3
+ export { h as CircuitRequest, G as Gate, g as GateInfo, f as GateType, j as QSpherePoint, i as SimulationResult, e as ThemeProvider, u as useTheme } from './index-BghK68a6.js';
4
4
  import { ReactNode } from 'react';
5
5
 
6
6
  interface QamposerMicroProps extends Omit<QamposerProviderProps$1, 'children'> {
package/dist/index.js CHANGED
@@ -319,6 +319,38 @@ function QamposerProvider({
319
319
  useEffect(() => {
320
320
  adapter.isAvailable().then(setCanSimulate);
321
321
  }, [adapter]);
322
+ const autoSimRequestId = useRef(0);
323
+ useEffect(() => {
324
+ if (!canSimulate || circuit.gates.length === 0) {
325
+ if (circuit.gates.length === 0) {
326
+ setResult(null);
327
+ }
328
+ return;
329
+ }
330
+ const requestId = ++autoSimRequestId.current;
331
+ setStatus("simulating");
332
+ setError(null);
333
+ const request = {
334
+ qubits: circuit.qubits,
335
+ gates: circuit.gates.map(({ id: _, ...gate }) => gate),
336
+ shots: 1024,
337
+ profile: { type: "ideal" }
338
+ };
339
+ adapter.simulate(request).then((simulationResult) => {
340
+ if (autoSimRequestId.current !== requestId) return;
341
+ setResult(simulationResult);
342
+ setStatus("idle");
343
+ onSimulationComplete?.({
344
+ result: simulationResult,
345
+ circuit: { ...circuit },
346
+ qasm: circuitToQasm(circuit)
347
+ });
348
+ }).catch((err) => {
349
+ if (autoSimRequestId.current !== requestId) return;
350
+ setError(err instanceof Error ? err : new Error(String(err)));
351
+ setStatus("error");
352
+ });
353
+ }, [circuit, canSimulate, adapter, onSimulationComplete]);
322
354
  const addGate = useCallback(
323
355
  (gate) => {
324
356
  if (circuit.gates.length >= config.maxGates) {
@@ -488,6 +520,7 @@ function QamposerProvider({
488
520
  }, [circuit]);
489
521
  const simulate = useCallback(
490
522
  async (shots = 1024, profile) => {
523
+ autoSimRequestId.current++;
491
524
  if (!canSimulate) {
492
525
  throw new Error("Simulation adapter is not available");
493
526
  }
@@ -2301,6 +2334,11 @@ var css3 = `.simulation-controls__run-btn {
2301
2334
  border-color: var(--qamposer-accent, #4285f4);
2302
2335
  background: rgba(66, 133, 244, 0.1);
2303
2336
  }
2337
+ .simulation-controls__backend-item--disabled {
2338
+ opacity: 0.5;
2339
+ cursor: not-allowed;
2340
+ pointer-events: none;
2341
+ }
2304
2342
  .simulation-controls__backend-item-content {
2305
2343
  flex: 1;
2306
2344
  min-width: 0;
@@ -2332,6 +2370,10 @@ var css3 = `.simulation-controls__run-btn {
2332
2370
  background: rgba(237, 137, 54, 0.2);
2333
2371
  color: #ed8936;
2334
2372
  }
2373
+ .simulation-controls__backend-type--real {
2374
+ background: rgba(160, 174, 192, 0.2);
2375
+ color: #a0aec0;
2376
+ }
2335
2377
  .simulation-controls__backend-desc {
2336
2378
  margin: 0;
2337
2379
  font-size: 0.75rem;
@@ -2423,7 +2465,7 @@ function SimulationControls({
2423
2465
  const [isDialogOpen, setIsDialogOpen] = useState(false);
2424
2466
  const [shots, setShots] = useState(1024);
2425
2467
  const [backends, setBackends] = useState([]);
2426
- const [selectedBackendId, setSelectedBackendId] = useState("ideal");
2468
+ const [selectedBackendId, setSelectedBackendId] = useState("");
2427
2469
  const [isLoadingBackends, setIsLoadingBackends] = useState(false);
2428
2470
  const [backendError, setBackendError] = useState(false);
2429
2471
  useEffect(() => {
@@ -2431,8 +2473,13 @@ function SimulationControls({
2431
2473
  setIsLoadingBackends(true);
2432
2474
  setBackendError(false);
2433
2475
  adapter.getBackends().then((result) => {
2434
- setBackends(result);
2435
- if (result.length === 1 && result[0].id === "ideal" && !canSimulate) {
2476
+ const nonIdealBackends = result.filter((b) => b.backend_type !== "ideal");
2477
+ setBackends(nonIdealBackends);
2478
+ const firstFake = nonIdealBackends.find((b) => b.backend_type === "noisy_fake");
2479
+ if (firstFake) {
2480
+ setSelectedBackendId(firstFake.id);
2481
+ }
2482
+ if (nonIdealBackends.length === 0 && !canSimulate) {
2436
2483
  setBackendError(true);
2437
2484
  }
2438
2485
  }).finally(() => setIsLoadingBackends(false));
@@ -2440,13 +2487,10 @@ function SimulationControls({
2440
2487
  }, [isDialogOpen, adapter, canSimulate]);
2441
2488
  const selectedBackend = backends.find((b) => b.id === selectedBackendId);
2442
2489
  const buildProfile = () => {
2443
- if (!selectedBackend || selectedBackend.backend_type === "ideal") {
2444
- return { type: "ideal" };
2490
+ if (!selectedBackend || selectedBackend.backend_type === "noisy_fake") {
2491
+ return selectedBackend ? { type: "noisy_fake", backend_name: selectedBackend.id } : void 0;
2445
2492
  }
2446
- return {
2447
- type: "noisy_fake",
2448
- backend_name: selectedBackend.id
2449
- };
2493
+ return void 0;
2450
2494
  };
2451
2495
  const handleRun = async () => {
2452
2496
  if (circuit.gates.length === 0) {
@@ -2533,31 +2577,35 @@ function SimulationControls({
2533
2577
  /* @__PURE__ */ jsx("p", { className: "simulation-controls__error-title", children: "Backend unavailable" }),
2534
2578
  /* @__PURE__ */ jsx("p", { className: "simulation-controls__error-desc", children: "Cannot connect to the simulation backend. Please check that the server is running and CORS is configured correctly." })
2535
2579
  ] })
2536
- ] }) : /* @__PURE__ */ jsx("div", { className: "simulation-controls__backend-list", children: backends.map((backend) => /* @__PURE__ */ jsxs(
2537
- "button",
2538
- {
2539
- type: "button",
2540
- className: `simulation-controls__backend-item ${selectedBackendId === backend.id ? "simulation-controls__backend-item--selected" : ""}`,
2541
- onClick: () => setSelectedBackendId(backend.id),
2542
- children: [
2543
- /* @__PURE__ */ jsxs("div", { className: "simulation-controls__backend-item-content", children: [
2544
- /* @__PURE__ */ jsxs("div", { className: "simulation-controls__backend-item-header", children: [
2545
- /* @__PURE__ */ jsx("span", { className: "simulation-controls__backend-name", children: backend.name }),
2546
- /* @__PURE__ */ jsx(
2547
- "span",
2548
- {
2549
- className: `simulation-controls__backend-type simulation-controls__backend-type--${backend.backend_type}`,
2550
- children: backend.backend_type === "ideal" ? "Ideal" : "Noisy"
2551
- }
2552
- )
2580
+ ] }) : /* @__PURE__ */ jsx("div", { className: "simulation-controls__backend-list", children: backends.map((backend) => {
2581
+ const isReal = backend.backend_type === "real";
2582
+ return /* @__PURE__ */ jsxs(
2583
+ "button",
2584
+ {
2585
+ type: "button",
2586
+ className: `simulation-controls__backend-item ${selectedBackendId === backend.id ? "simulation-controls__backend-item--selected" : ""} ${isReal ? "simulation-controls__backend-item--disabled" : ""}`,
2587
+ onClick: () => !isReal && setSelectedBackendId(backend.id),
2588
+ disabled: isReal,
2589
+ children: [
2590
+ /* @__PURE__ */ jsxs("div", { className: "simulation-controls__backend-item-content", children: [
2591
+ /* @__PURE__ */ jsxs("div", { className: "simulation-controls__backend-item-header", children: [
2592
+ /* @__PURE__ */ jsx("span", { className: "simulation-controls__backend-name", children: backend.name }),
2593
+ /* @__PURE__ */ jsx(
2594
+ "span",
2595
+ {
2596
+ className: `simulation-controls__backend-type simulation-controls__backend-type--${backend.backend_type}`,
2597
+ children: backend.backend_type === "noisy_fake" ? "Noisy" : "Real"
2598
+ }
2599
+ )
2600
+ ] }),
2601
+ /* @__PURE__ */ jsx("p", { className: "simulation-controls__backend-desc", children: isReal ? "Coming soon" : backend.description || `${backend.num_qubits} qubits` })
2553
2602
  ] }),
2554
- /* @__PURE__ */ jsx("p", { className: "simulation-controls__backend-desc", children: backend.description || `${backend.num_qubits} qubits` })
2555
- ] }),
2556
- selectedBackendId === backend.id && /* @__PURE__ */ jsx("span", { className: "simulation-controls__backend-check", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
2557
- ]
2558
- },
2559
- backend.id
2560
- )) })
2603
+ selectedBackendId === backend.id && /* @__PURE__ */ jsx("span", { className: "simulation-controls__backend-check", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
2604
+ ]
2605
+ },
2606
+ backend.id
2607
+ );
2608
+ }) })
2561
2609
  ] })
2562
2610
  ] }),
2563
2611
  /* @__PURE__ */ jsxs("div", { className: "simulation-controls__dialog-footer", children: [
@@ -319,6 +319,38 @@ function QamposerProvider({
319
319
  react.useEffect(() => {
320
320
  adapter.isAvailable().then(setCanSimulate);
321
321
  }, [adapter]);
322
+ const autoSimRequestId = react.useRef(0);
323
+ react.useEffect(() => {
324
+ if (!canSimulate || circuit.gates.length === 0) {
325
+ if (circuit.gates.length === 0) {
326
+ setResult(null);
327
+ }
328
+ return;
329
+ }
330
+ const requestId = ++autoSimRequestId.current;
331
+ setStatus("simulating");
332
+ setError(null);
333
+ const request = {
334
+ qubits: circuit.qubits,
335
+ gates: circuit.gates.map(({ id: _, ...gate }) => gate),
336
+ shots: 1024,
337
+ profile: { type: "ideal" }
338
+ };
339
+ adapter.simulate(request).then((simulationResult) => {
340
+ if (autoSimRequestId.current !== requestId) return;
341
+ setResult(simulationResult);
342
+ setStatus("idle");
343
+ onSimulationComplete?.({
344
+ result: simulationResult,
345
+ circuit: { ...circuit },
346
+ qasm: circuitToQasm(circuit)
347
+ });
348
+ }).catch((err) => {
349
+ if (autoSimRequestId.current !== requestId) return;
350
+ setError(err instanceof Error ? err : new Error(String(err)));
351
+ setStatus("error");
352
+ });
353
+ }, [circuit, canSimulate, adapter, onSimulationComplete]);
322
354
  const addGate = react.useCallback(
323
355
  (gate) => {
324
356
  if (circuit.gates.length >= config.maxGates) {
@@ -488,6 +520,7 @@ function QamposerProvider({
488
520
  }, [circuit]);
489
521
  const simulate = react.useCallback(
490
522
  async (shots = 1024, profile) => {
523
+ autoSimRequestId.current++;
491
524
  if (!canSimulate) {
492
525
  throw new Error("Simulation adapter is not available");
493
526
  }
@@ -2999,6 +3032,11 @@ var css6 = `.simulation-controls__run-btn {
2999
3032
  border-color: var(--qamposer-accent, #4285f4);
3000
3033
  background: rgba(66, 133, 244, 0.1);
3001
3034
  }
3035
+ .simulation-controls__backend-item--disabled {
3036
+ opacity: 0.5;
3037
+ cursor: not-allowed;
3038
+ pointer-events: none;
3039
+ }
3002
3040
  .simulation-controls__backend-item-content {
3003
3041
  flex: 1;
3004
3042
  min-width: 0;
@@ -3030,6 +3068,10 @@ var css6 = `.simulation-controls__run-btn {
3030
3068
  background: rgba(237, 137, 54, 0.2);
3031
3069
  color: #ed8936;
3032
3070
  }
3071
+ .simulation-controls__backend-type--real {
3072
+ background: rgba(160, 174, 192, 0.2);
3073
+ color: #a0aec0;
3074
+ }
3033
3075
  .simulation-controls__backend-desc {
3034
3076
  margin: 0;
3035
3077
  font-size: 0.75rem;
@@ -3121,7 +3163,7 @@ function SimulationControls({
3121
3163
  const [isDialogOpen, setIsDialogOpen] = react.useState(false);
3122
3164
  const [shots, setShots] = react.useState(1024);
3123
3165
  const [backends, setBackends] = react.useState([]);
3124
- const [selectedBackendId, setSelectedBackendId] = react.useState("ideal");
3166
+ const [selectedBackendId, setSelectedBackendId] = react.useState("");
3125
3167
  const [isLoadingBackends, setIsLoadingBackends] = react.useState(false);
3126
3168
  const [backendError, setBackendError] = react.useState(false);
3127
3169
  react.useEffect(() => {
@@ -3129,8 +3171,13 @@ function SimulationControls({
3129
3171
  setIsLoadingBackends(true);
3130
3172
  setBackendError(false);
3131
3173
  adapter.getBackends().then((result) => {
3132
- setBackends(result);
3133
- if (result.length === 1 && result[0].id === "ideal" && !canSimulate) {
3174
+ const nonIdealBackends = result.filter((b) => b.backend_type !== "ideal");
3175
+ setBackends(nonIdealBackends);
3176
+ const firstFake = nonIdealBackends.find((b) => b.backend_type === "noisy_fake");
3177
+ if (firstFake) {
3178
+ setSelectedBackendId(firstFake.id);
3179
+ }
3180
+ if (nonIdealBackends.length === 0 && !canSimulate) {
3134
3181
  setBackendError(true);
3135
3182
  }
3136
3183
  }).finally(() => setIsLoadingBackends(false));
@@ -3138,13 +3185,10 @@ function SimulationControls({
3138
3185
  }, [isDialogOpen, adapter, canSimulate]);
3139
3186
  const selectedBackend = backends.find((b) => b.id === selectedBackendId);
3140
3187
  const buildProfile = () => {
3141
- if (!selectedBackend || selectedBackend.backend_type === "ideal") {
3142
- return { type: "ideal" };
3188
+ if (!selectedBackend || selectedBackend.backend_type === "noisy_fake") {
3189
+ return selectedBackend ? { type: "noisy_fake", backend_name: selectedBackend.id } : void 0;
3143
3190
  }
3144
- return {
3145
- type: "noisy_fake",
3146
- backend_name: selectedBackend.id
3147
- };
3191
+ return void 0;
3148
3192
  };
3149
3193
  const handleRun = async () => {
3150
3194
  if (circuit.gates.length === 0) {
@@ -3231,31 +3275,35 @@ function SimulationControls({
3231
3275
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "simulation-controls__error-title", children: "Backend unavailable" }),
3232
3276
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "simulation-controls__error-desc", children: "Cannot connect to the simulation backend. Please check that the server is running and CORS is configured correctly." })
3233
3277
  ] })
3234
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "simulation-controls__backend-list", children: backends.map((backend) => /* @__PURE__ */ jsxRuntime.jsxs(
3235
- "button",
3236
- {
3237
- type: "button",
3238
- className: `simulation-controls__backend-item ${selectedBackendId === backend.id ? "simulation-controls__backend-item--selected" : ""}`,
3239
- onClick: () => setSelectedBackendId(backend.id),
3240
- children: [
3241
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__backend-item-content", children: [
3242
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__backend-item-header", children: [
3243
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "simulation-controls__backend-name", children: backend.name }),
3244
- /* @__PURE__ */ jsxRuntime.jsx(
3245
- "span",
3246
- {
3247
- className: `simulation-controls__backend-type simulation-controls__backend-type--${backend.backend_type}`,
3248
- children: backend.backend_type === "ideal" ? "Ideal" : "Noisy"
3249
- }
3250
- )
3278
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "simulation-controls__backend-list", children: backends.map((backend) => {
3279
+ const isReal = backend.backend_type === "real";
3280
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3281
+ "button",
3282
+ {
3283
+ type: "button",
3284
+ className: `simulation-controls__backend-item ${selectedBackendId === backend.id ? "simulation-controls__backend-item--selected" : ""} ${isReal ? "simulation-controls__backend-item--disabled" : ""}`,
3285
+ onClick: () => !isReal && setSelectedBackendId(backend.id),
3286
+ disabled: isReal,
3287
+ children: [
3288
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__backend-item-content", children: [
3289
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__backend-item-header", children: [
3290
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "simulation-controls__backend-name", children: backend.name }),
3291
+ /* @__PURE__ */ jsxRuntime.jsx(
3292
+ "span",
3293
+ {
3294
+ className: `simulation-controls__backend-type simulation-controls__backend-type--${backend.backend_type}`,
3295
+ children: backend.backend_type === "noisy_fake" ? "Noisy" : "Real"
3296
+ }
3297
+ )
3298
+ ] }),
3299
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "simulation-controls__backend-desc", children: isReal ? "Coming soon" : backend.description || `${backend.num_qubits} qubits` })
3251
3300
  ] }),
3252
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "simulation-controls__backend-desc", children: backend.description || `${backend.num_qubits} qubits` })
3253
- ] }),
3254
- selectedBackendId === backend.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "simulation-controls__backend-check", children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) })
3255
- ]
3256
- },
3257
- backend.id
3258
- )) })
3301
+ selectedBackendId === backend.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "simulation-controls__backend-check", children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) })
3302
+ ]
3303
+ },
3304
+ backend.id
3305
+ );
3306
+ }) })
3259
3307
  ] })
3260
3308
  ] }),
3261
3309
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "simulation-controls__dialog-footer", children: [
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Q as QamposerProviderProps, T as Theme } from './index-BbUFQqpD.cjs';
2
+ import { Q as QamposerProviderProps, T as Theme } from './index-BghK68a6.cjs';
3
3
  import 'react';
4
4
 
5
5
  interface QamposerProps extends Omit<QamposerProviderProps, 'children'> {
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { Q as QamposerProviderProps, T as Theme } from './index-BbUFQqpD.js';
2
+ import { Q as QamposerProviderProps, T as Theme } from './index-BghK68a6.js';
3
3
  import 'react';
4
4
 
5
5
  interface QamposerProps extends Omit<QamposerProviderProps, 'children'> {
@@ -313,6 +313,38 @@ function QamposerProvider({
313
313
  useEffect(() => {
314
314
  adapter.isAvailable().then(setCanSimulate);
315
315
  }, [adapter]);
316
+ const autoSimRequestId = useRef(0);
317
+ useEffect(() => {
318
+ if (!canSimulate || circuit.gates.length === 0) {
319
+ if (circuit.gates.length === 0) {
320
+ setResult(null);
321
+ }
322
+ return;
323
+ }
324
+ const requestId = ++autoSimRequestId.current;
325
+ setStatus("simulating");
326
+ setError(null);
327
+ const request = {
328
+ qubits: circuit.qubits,
329
+ gates: circuit.gates.map(({ id: _, ...gate }) => gate),
330
+ shots: 1024,
331
+ profile: { type: "ideal" }
332
+ };
333
+ adapter.simulate(request).then((simulationResult) => {
334
+ if (autoSimRequestId.current !== requestId) return;
335
+ setResult(simulationResult);
336
+ setStatus("idle");
337
+ onSimulationComplete?.({
338
+ result: simulationResult,
339
+ circuit: { ...circuit },
340
+ qasm: circuitToQasm(circuit)
341
+ });
342
+ }).catch((err) => {
343
+ if (autoSimRequestId.current !== requestId) return;
344
+ setError(err instanceof Error ? err : new Error(String(err)));
345
+ setStatus("error");
346
+ });
347
+ }, [circuit, canSimulate, adapter, onSimulationComplete]);
316
348
  const addGate = useCallback(
317
349
  (gate) => {
318
350
  if (circuit.gates.length >= config.maxGates) {
@@ -482,6 +514,7 @@ function QamposerProvider({
482
514
  }, [circuit]);
483
515
  const simulate = useCallback(
484
516
  async (shots = 1024, profile) => {
517
+ autoSimRequestId.current++;
485
518
  if (!canSimulate) {
486
519
  throw new Error("Simulation adapter is not available");
487
520
  }
@@ -2993,6 +3026,11 @@ var css6 = `.simulation-controls__run-btn {
2993
3026
  border-color: var(--qamposer-accent, #4285f4);
2994
3027
  background: rgba(66, 133, 244, 0.1);
2995
3028
  }
3029
+ .simulation-controls__backend-item--disabled {
3030
+ opacity: 0.5;
3031
+ cursor: not-allowed;
3032
+ pointer-events: none;
3033
+ }
2996
3034
  .simulation-controls__backend-item-content {
2997
3035
  flex: 1;
2998
3036
  min-width: 0;
@@ -3024,6 +3062,10 @@ var css6 = `.simulation-controls__run-btn {
3024
3062
  background: rgba(237, 137, 54, 0.2);
3025
3063
  color: #ed8936;
3026
3064
  }
3065
+ .simulation-controls__backend-type--real {
3066
+ background: rgba(160, 174, 192, 0.2);
3067
+ color: #a0aec0;
3068
+ }
3027
3069
  .simulation-controls__backend-desc {
3028
3070
  margin: 0;
3029
3071
  font-size: 0.75rem;
@@ -3115,7 +3157,7 @@ function SimulationControls({
3115
3157
  const [isDialogOpen, setIsDialogOpen] = useState(false);
3116
3158
  const [shots, setShots] = useState(1024);
3117
3159
  const [backends, setBackends] = useState([]);
3118
- const [selectedBackendId, setSelectedBackendId] = useState("ideal");
3160
+ const [selectedBackendId, setSelectedBackendId] = useState("");
3119
3161
  const [isLoadingBackends, setIsLoadingBackends] = useState(false);
3120
3162
  const [backendError, setBackendError] = useState(false);
3121
3163
  useEffect(() => {
@@ -3123,8 +3165,13 @@ function SimulationControls({
3123
3165
  setIsLoadingBackends(true);
3124
3166
  setBackendError(false);
3125
3167
  adapter.getBackends().then((result) => {
3126
- setBackends(result);
3127
- if (result.length === 1 && result[0].id === "ideal" && !canSimulate) {
3168
+ const nonIdealBackends = result.filter((b) => b.backend_type !== "ideal");
3169
+ setBackends(nonIdealBackends);
3170
+ const firstFake = nonIdealBackends.find((b) => b.backend_type === "noisy_fake");
3171
+ if (firstFake) {
3172
+ setSelectedBackendId(firstFake.id);
3173
+ }
3174
+ if (nonIdealBackends.length === 0 && !canSimulate) {
3128
3175
  setBackendError(true);
3129
3176
  }
3130
3177
  }).finally(() => setIsLoadingBackends(false));
@@ -3132,13 +3179,10 @@ function SimulationControls({
3132
3179
  }, [isDialogOpen, adapter, canSimulate]);
3133
3180
  const selectedBackend = backends.find((b) => b.id === selectedBackendId);
3134
3181
  const buildProfile = () => {
3135
- if (!selectedBackend || selectedBackend.backend_type === "ideal") {
3136
- return { type: "ideal" };
3182
+ if (!selectedBackend || selectedBackend.backend_type === "noisy_fake") {
3183
+ return selectedBackend ? { type: "noisy_fake", backend_name: selectedBackend.id } : void 0;
3137
3184
  }
3138
- return {
3139
- type: "noisy_fake",
3140
- backend_name: selectedBackend.id
3141
- };
3185
+ return void 0;
3142
3186
  };
3143
3187
  const handleRun = async () => {
3144
3188
  if (circuit.gates.length === 0) {
@@ -3225,31 +3269,35 @@ function SimulationControls({
3225
3269
  /* @__PURE__ */ jsx("p", { className: "simulation-controls__error-title", children: "Backend unavailable" }),
3226
3270
  /* @__PURE__ */ jsx("p", { className: "simulation-controls__error-desc", children: "Cannot connect to the simulation backend. Please check that the server is running and CORS is configured correctly." })
3227
3271
  ] })
3228
- ] }) : /* @__PURE__ */ jsx("div", { className: "simulation-controls__backend-list", children: backends.map((backend) => /* @__PURE__ */ jsxs(
3229
- "button",
3230
- {
3231
- type: "button",
3232
- className: `simulation-controls__backend-item ${selectedBackendId === backend.id ? "simulation-controls__backend-item--selected" : ""}`,
3233
- onClick: () => setSelectedBackendId(backend.id),
3234
- children: [
3235
- /* @__PURE__ */ jsxs("div", { className: "simulation-controls__backend-item-content", children: [
3236
- /* @__PURE__ */ jsxs("div", { className: "simulation-controls__backend-item-header", children: [
3237
- /* @__PURE__ */ jsx("span", { className: "simulation-controls__backend-name", children: backend.name }),
3238
- /* @__PURE__ */ jsx(
3239
- "span",
3240
- {
3241
- className: `simulation-controls__backend-type simulation-controls__backend-type--${backend.backend_type}`,
3242
- children: backend.backend_type === "ideal" ? "Ideal" : "Noisy"
3243
- }
3244
- )
3272
+ ] }) : /* @__PURE__ */ jsx("div", { className: "simulation-controls__backend-list", children: backends.map((backend) => {
3273
+ const isReal = backend.backend_type === "real";
3274
+ return /* @__PURE__ */ jsxs(
3275
+ "button",
3276
+ {
3277
+ type: "button",
3278
+ className: `simulation-controls__backend-item ${selectedBackendId === backend.id ? "simulation-controls__backend-item--selected" : ""} ${isReal ? "simulation-controls__backend-item--disabled" : ""}`,
3279
+ onClick: () => !isReal && setSelectedBackendId(backend.id),
3280
+ disabled: isReal,
3281
+ children: [
3282
+ /* @__PURE__ */ jsxs("div", { className: "simulation-controls__backend-item-content", children: [
3283
+ /* @__PURE__ */ jsxs("div", { className: "simulation-controls__backend-item-header", children: [
3284
+ /* @__PURE__ */ jsx("span", { className: "simulation-controls__backend-name", children: backend.name }),
3285
+ /* @__PURE__ */ jsx(
3286
+ "span",
3287
+ {
3288
+ className: `simulation-controls__backend-type simulation-controls__backend-type--${backend.backend_type}`,
3289
+ children: backend.backend_type === "noisy_fake" ? "Noisy" : "Real"
3290
+ }
3291
+ )
3292
+ ] }),
3293
+ /* @__PURE__ */ jsx("p", { className: "simulation-controls__backend-desc", children: isReal ? "Coming soon" : backend.description || `${backend.num_qubits} qubits` })
3245
3294
  ] }),
3246
- /* @__PURE__ */ jsx("p", { className: "simulation-controls__backend-desc", children: backend.description || `${backend.num_qubits} qubits` })
3247
- ] }),
3248
- selectedBackendId === backend.id && /* @__PURE__ */ jsx("span", { className: "simulation-controls__backend-check", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
3249
- ]
3250
- },
3251
- backend.id
3252
- )) })
3295
+ selectedBackendId === backend.id && /* @__PURE__ */ jsx("span", { className: "simulation-controls__backend-check", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
3296
+ ]
3297
+ },
3298
+ backend.id
3299
+ );
3300
+ }) })
3253
3301
  ] })
3254
3302
  ] }),
3255
3303
  /* @__PURE__ */ jsxs("div", { className: "simulation-controls__dialog-footer", children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qamposer/react",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "React components for quantum circuit composition",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -26,8 +26,7 @@
26
26
  "types": "./dist/visualization.d.cts",
27
27
  "default": "./dist/visualization.cjs"
28
28
  }
29
- },
30
- "./styles.css": "./dist/styles.css"
29
+ }
31
30
  },
32
31
  "files": [
33
32
  "dist"
@@ -77,6 +76,7 @@
77
76
  "eslint": "^9.39.2",
78
77
  "eslint-plugin-react-hooks": "^7.0.1",
79
78
  "happy-dom": "^20.4.0",
79
+ "prettier": "^3.8.1",
80
80
  "react": "^19.0.0",
81
81
  "react-dom": "^19.0.0",
82
82
  "sass": "^1.97.1",