testomatio-editor-blocks 0.4.1 → 0.4.9

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.
@@ -12,6 +12,9 @@ export declare const stepBlock: {
12
12
  readonly expectedResult: {
13
13
  readonly default: "";
14
14
  };
15
+ readonly listStyle: {
16
+ readonly default: "bullet";
17
+ };
15
18
  };
16
19
  };
17
20
  implementation: import("@blocknote/core").TiptapBlockImplementation<{
@@ -27,6 +30,9 @@ export declare const stepBlock: {
27
30
  readonly expectedResult: {
28
31
  readonly default: "";
29
32
  };
33
+ readonly listStyle: {
34
+ readonly default: "bullet";
35
+ };
30
36
  };
31
37
  }, any, import("@blocknote/core").InlineContentSchema, import("@blocknote/core").StyleSchema>;
32
38
  };
@@ -56,6 +56,9 @@ export const stepBlock = createReactBlockSpec({
56
56
  expectedResult: {
57
57
  default: "",
58
58
  },
59
+ listStyle: {
60
+ default: "bullet",
61
+ },
59
62
  },
60
63
  }, {
61
64
  render: ({ block, editor }) => {
@@ -217,9 +220,9 @@ export const stepBlock = createReactBlockSpec({
217
220
  const canToggleData = !dataHasContent;
218
221
  const canToggleExpected = !expectedHasContent;
219
222
  if (viewMode === "horizontal") {
220
- return (_jsx(StepHorizontalView, { blockId: block.id, stepNumber: stepNumber, stepValue: combinedStepValue, expectedResult: expectedResult, onStepChange: handleCombinedStepChange, onExpectedChange: handleExpectedChange, onInsertNextStep: handleInsertNextStep, onFieldFocus: handleFieldFocus, viewToggle: _jsx("button", { type: "button", className: "bn-teststep__view-toggle bn-teststep__view-toggle--horizontal", "aria-label": "Switch step view", onClick: handleToggleView, children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [_jsx("mask", { id: "mask-toggle", style: { maskType: "alpha" }, maskUnits: "userSpaceOnUse", x: "0", y: "0", width: "16", height: "16", children: _jsx("rect", { width: "16", height: "16", fill: "#D9D9D9" }) }), _jsx("g", { mask: "url(#mask-toggle)", children: _jsx("path", { d: "M12.6667 2C13.0333 2 13.3472 2.13056 13.6083 2.39167C13.8694 2.65278 14 2.96667 14 3.33333L14 12.6667C14 13.0333 13.8694 13.3472 13.6083 13.6083C13.3472 13.8694 13.0333 14 12.6667 14L10 14C9.63333 14 9.31944 13.8694 9.05833 13.6083C8.79722 13.3472 8.66667 13.0333 8.66667 12.6667L8.66667 3.33333C8.66667 2.96667 8.79722 2.65278 9.05833 2.39167C9.31945 2.13055 9.63333 2 10 2L12.6667 2ZM6 2C6.36667 2 6.68056 2.13055 6.94167 2.39167C7.20278 2.65278 7.33333 2.96667 7.33333 3.33333L7.33333 12.6667C7.33333 13.0333 7.20278 13.3472 6.94167 13.6083C6.68055 13.8694 6.36667 14 6 14L3.33333 14C2.96667 14 2.65278 13.8694 2.39167 13.6083C2.13056 13.3472 2 13.0333 2 12.6667L2 3.33333C2 2.96667 2.13056 2.65278 2.39167 2.39167C2.65278 2.13055 2.96667 2 3.33333 2L6 2ZM3.33333 12.6667L6 12.6667L6 3.33333L3.33333 3.33333L3.33333 12.6667Z", fill: "currentColor" }) })] }) }) }));
223
+ return (_jsx(StepHorizontalView, { blockId: block.id, stepNumber: stepNumber, stepValue: combinedStepValue, expectedResult: expectedResult, onStepChange: handleCombinedStepChange, onExpectedChange: handleExpectedChange, onInsertNextStep: handleInsertNextStep, onFieldFocus: handleFieldFocus, viewToggle: _jsx("button", { type: "button", className: "bn-teststep__view-toggle bn-teststep__view-toggle--horizontal", "data-tooltip": "Switch step view", "aria-label": "Switch step view", onClick: handleToggleView, children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [_jsx("mask", { id: "mask-toggle", style: { maskType: "alpha" }, maskUnits: "userSpaceOnUse", x: "0", y: "0", width: "16", height: "16", children: _jsx("rect", { width: "16", height: "16", fill: "#D9D9D9" }) }), _jsx("g", { mask: "url(#mask-toggle)", children: _jsx("path", { d: "M12.6667 2C13.0333 2 13.3472 2.13056 13.6083 2.39167C13.8694 2.65278 14 2.96667 14 3.33333L14 12.6667C14 13.0333 13.8694 13.3472 13.6083 13.6083C13.3472 13.8694 13.0333 14 12.6667 14L10 14C9.63333 14 9.31944 13.8694 9.05833 13.6083C8.79722 13.3472 8.66667 13.0333 8.66667 12.6667L8.66667 3.33333C8.66667 2.96667 8.79722 2.65278 9.05833 2.39167C9.31945 2.13055 9.63333 2 10 2L12.6667 2ZM6 2C6.36667 2 6.68056 2.13055 6.94167 2.39167C7.20278 2.65278 7.33333 2.96667 7.33333 3.33333L7.33333 12.6667C7.33333 13.0333 7.20278 13.3472 6.94167 13.6083C6.68055 13.8694 6.36667 14 6 14L3.33333 14C2.96667 14 2.65278 13.8694 2.39167 13.6083C2.13056 13.3472 2 13.0333 2 12.6667L2 3.33333C2 2.96667 2.13056 2.65278 2.39167 2.39167C2.65278 2.13055 2.96667 2 3.33333 2L6 2ZM3.33333 12.6667L6 12.6667L6 3.33333L3.33333 3.33333L3.33333 12.6667Z", fill: "currentColor" }) })] }) }) }));
221
224
  }
222
- return (_jsxs("div", { className: "bn-teststep", "data-block-id": block.id, children: [_jsxs("div", { className: "bn-teststep__timeline", children: [_jsx("span", { className: "bn-teststep__number", children: stepNumber }), _jsx("div", { className: "bn-teststep__line" })] }), _jsxs("div", { className: "bn-teststep__content", children: [_jsxs("div", { className: "bn-teststep__header", children: [_jsx("span", { className: "bn-teststep__title", children: "Step" }), _jsx("button", { type: "button", className: "bn-teststep__view-toggle", "aria-label": "Switch step view", onClick: handleToggleView, children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [_jsx("mask", { id: "mask-toggle", style: { maskType: "alpha" }, maskUnits: "userSpaceOnUse", x: "0", y: "0", width: "16", height: "16", children: _jsx("rect", { width: "16", height: "16", fill: "#D9D9D9" }) }), _jsx("g", { mask: "url(#mask-toggle)", children: _jsx("path", { d: "M12.6667 2C13.0333 2 13.3472 2.13056 13.6083 2.39167C13.8694 2.65278 14 2.96667 14 3.33333L14 12.6667C14 13.0333 13.8694 13.3472 13.6083 13.6083C13.3472 13.8694 13.0333 14 12.6667 14L10 14C9.63333 14 9.31944 13.8694 9.05833 13.6083C8.79722 13.3472 8.66667 13.0333 8.66667 12.6667L8.66667 3.33333C8.66667 2.96667 8.79722 2.65278 9.05833 2.39167C9.31945 2.13055 9.63333 2 10 2L12.6667 2ZM6 2C6.36667 2 6.68056 2.13055 6.94167 2.39167C7.20278 2.65278 7.33333 2.96667 7.33333 3.33333L7.33333 12.6667C7.33333 13.0333 7.20278 13.3472 6.94167 13.6083C6.68055 13.8694 6.36667 14 6 14L3.33333 14C2.96667 14 2.65278 13.8694 2.39167 13.6083C2.13056 13.3472 2 13.0333 2 12.6667L2 3.33333C2 2.96667 2.13056 2.65278 2.39167 2.39167C2.65278 2.13055 2.96667 2 3.33333 2L6 2ZM3.33333 12.6667L6 12.6667L6 3.33333L3.33333 3.33333L3.33333 12.6667Z", fill: "currentColor" }) })] }) })] }), _jsx(StepField, { label: "Step", showLabel: false, value: stepTitle, placeholder: STEP_TITLE_PLACEHOLDER, onChange: handleStepTitleChange, autoFocus: stepTitle.length === 0, enableAutocomplete: true, fieldName: "title", suggestionFilter: (suggestion) => suggestion.isSnippet !== true, onFieldFocus: handleFieldFocus, enableImageUpload: false, showFormattingButtons: true, onImageFile: async (file) => {
225
+ return (_jsxs("div", { className: "bn-teststep", "data-block-id": block.id, children: [_jsxs("div", { className: "bn-teststep__timeline", children: [_jsx("span", { className: "bn-teststep__number", children: stepNumber }), _jsx("div", { className: "bn-teststep__line" })] }), _jsxs("div", { className: "bn-teststep__content", children: [_jsxs("div", { className: "bn-teststep__header", children: [_jsx("span", { className: "bn-teststep__title", children: "Step" }), _jsx("button", { type: "button", className: "bn-teststep__view-toggle", "data-tooltip": "Switch step view", "aria-label": "Switch step view", onClick: handleToggleView, children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [_jsx("mask", { id: "mask-toggle", style: { maskType: "alpha" }, maskUnits: "userSpaceOnUse", x: "0", y: "0", width: "16", height: "16", children: _jsx("rect", { width: "16", height: "16", fill: "#D9D9D9" }) }), _jsx("g", { mask: "url(#mask-toggle)", children: _jsx("path", { d: "M12.6667 2C13.0333 2 13.3472 2.13056 13.6083 2.39167C13.8694 2.65278 14 2.96667 14 3.33333L14 12.6667C14 13.0333 13.8694 13.3472 13.6083 13.6083C13.3472 13.8694 13.0333 14 12.6667 14L10 14C9.63333 14 9.31944 13.8694 9.05833 13.6083C8.79722 13.3472 8.66667 13.0333 8.66667 12.6667L8.66667 3.33333C8.66667 2.96667 8.79722 2.65278 9.05833 2.39167C9.31945 2.13055 9.63333 2 10 2L12.6667 2ZM6 2C6.36667 2 6.68056 2.13055 6.94167 2.39167C7.20278 2.65278 7.33333 2.96667 7.33333 3.33333L7.33333 12.6667C7.33333 13.0333 7.20278 13.3472 6.94167 13.6083C6.68055 13.8694 6.36667 14 6 14L3.33333 14C2.96667 14 2.65278 13.8694 2.39167 13.6083C2.13056 13.3472 2 13.0333 2 12.6667L2 3.33333C2 2.96667 2.13056 2.65278 2.39167 2.39167C2.65278 2.13055 2.96667 2 3.33333 2L6 2ZM3.33333 12.6667L6 12.6667L6 3.33333L3.33333 3.33333L3.33333 12.6667Z", fill: "currentColor" }) })] }) })] }), _jsx(StepField, { label: "Step", showLabel: false, value: stepTitle, placeholder: STEP_TITLE_PLACEHOLDER, onChange: handleStepTitleChange, autoFocus: stepTitle.length === 0, enableAutocomplete: true, fieldName: "title", suggestionFilter: (suggestion) => suggestion.isSnippet !== true, onFieldFocus: handleFieldFocus, enableImageUpload: false, showFormattingButtons: true, onImageFile: async (file) => {
223
226
  if (!uploadImage) {
224
227
  return;
225
228
  }
@@ -239,6 +242,6 @@ export const stepBlock = createReactBlockSpec({
239
242
  catch (error) {
240
243
  console.error("Failed to upload image to Step Data", error);
241
244
  }
242
- } }), isDataVisible ? (_jsx(StepField, { label: "Step data", placeholder: STEP_DATA_PLACEHOLDER, labelAction: canToggleData ? (_jsx("button", { type: "button", className: "bn-step-field__dismiss", onClick: handleHideData, "aria-label": "Hide step data", children: "\u00D7" })) : undefined, value: stepData, onChange: handleStepDataChange, autoFocus: shouldFocusDataField, focusSignal: dataFocusSignal, multiline: true, enableAutocomplete: true, enableImageUpload: true, showFormattingButtons: true, showImageButton: true, onFieldFocus: handleFieldFocus })) : null, isExpectedVisible ? (_jsx(StepField, { label: "Expected result", placeholder: EXPECTED_RESULT_PLACEHOLDER, labelAction: canToggleExpected ? (_jsx("button", { type: "button", className: "bn-step-field__dismiss", onClick: handleHideExpected, tabIndex: -1, "aria-label": "Hide expected result", children: "\u00D7" })) : undefined, value: expectedResult, onChange: handleExpectedChange, multiline: true, focusSignal: expectedFocusSignal, enableAutocomplete: true, enableImageUpload: true, showFormattingButtons: true, showImageButton: true, onFieldFocus: handleFieldFocus })) : null, _jsxs("div", { className: "bn-step-actions", children: [_jsxs("button", { type: "button", className: "bn-step-action-btn", onClick: handleInsertNextStep, children: [_jsx("svg", { className: "bn-step-action-btn__icon", width: "16", height: "16", viewBox: "0 0 13.334 13.334", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M6.667 0a6.667 6.667 0 1 1 0 13.334A6.667 6.667 0 0 1 6.667 0Zm0 1.334a5.333 5.333 0 1 0 0 10.666 5.333 5.333 0 0 0 0-10.666ZM7.334 3.334V6H10v1.334H7.334V10H6V7.334H3.334V6H6V3.334h1.334Z", fill: "currentColor" }) }), "Add new step"] }), !isDataVisible && (_jsxs("button", { type: "button", className: "bn-step-action-btn", onClick: handleShowData, children: [_jsx("svg", { className: "bn-step-action-btn__icon", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M8.666 7.333H12.666V8.667H8.666V12.667H7.332V8.667H3.332V7.333H7.332V3.333H8.666V7.333Z", fill: "currentColor" }) }), "Step data"] })), !isExpectedVisible && (_jsxs("button", { type: "button", className: "bn-step-action-btn", onClick: handleShowExpected, children: [_jsx("svg", { className: "bn-step-action-btn__icon", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M8.666 7.333H12.666V8.667H8.666V12.667H7.332V8.667H3.332V7.333H7.332V3.333H8.666V7.333Z", fill: "currentColor" }) }), "Expected result"] }))] })] })] }));
245
+ } }), isDataVisible ? (_jsx(StepField, { label: "Step data", placeholder: STEP_DATA_PLACEHOLDER, labelAction: canToggleData ? (_jsx("button", { type: "button", className: "bn-step-field__dismiss", "data-tooltip": "Hide step data", onClick: handleHideData, "aria-label": "Hide step data", children: "\u00D7" })) : undefined, value: stepData, onChange: handleStepDataChange, autoFocus: shouldFocusDataField, focusSignal: dataFocusSignal, multiline: true, enableAutocomplete: true, enableImageUpload: true, showFormattingButtons: true, showImageButton: true, onFieldFocus: handleFieldFocus })) : null, isExpectedVisible ? (_jsx(StepField, { label: "Expected result", placeholder: EXPECTED_RESULT_PLACEHOLDER, labelAction: canToggleExpected ? (_jsx("button", { type: "button", className: "bn-step-field__dismiss", "data-tooltip": "Hide expected result", onClick: handleHideExpected, tabIndex: -1, "aria-label": "Hide expected result", children: "\u00D7" })) : undefined, value: expectedResult, onChange: handleExpectedChange, multiline: true, focusSignal: expectedFocusSignal, enableAutocomplete: true, enableImageUpload: true, showFormattingButtons: true, showImageButton: true, onFieldFocus: handleFieldFocus })) : null, _jsxs("div", { className: "bn-step-actions", children: [_jsxs("button", { type: "button", className: "bn-step-action-btn", onClick: handleInsertNextStep, children: [_jsx("svg", { className: "bn-step-action-btn__icon", width: "16", height: "16", viewBox: "0 0 13.334 13.334", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M6.667 0a6.667 6.667 0 1 1 0 13.334A6.667 6.667 0 0 1 6.667 0Zm0 1.334a5.333 5.333 0 1 0 0 10.666 5.333 5.333 0 0 0 0-10.666ZM7.334 3.334V6H10v1.334H7.334V10H6V7.334H3.334V6H6V3.334h1.334Z", fill: "currentColor" }) }), "Add new step"] }), !isDataVisible && (_jsxs("button", { type: "button", className: "bn-step-action-btn", onClick: handleShowData, children: [_jsx("svg", { className: "bn-step-action-btn__icon", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M8.666 7.333H12.666V8.667H8.666V12.667H7.332V8.667H3.332V7.333H7.332V3.333H8.666V7.333Z", fill: "currentColor" }) }), "Step data"] })), !isExpectedVisible && (_jsxs("button", { type: "button", className: "bn-step-action-btn", onClick: handleShowExpected, children: [_jsx("svg", { className: "bn-step-action-btn__icon", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M8.666 7.333H12.666V8.667H8.666V12.667H7.332V8.667H3.332V7.333H7.332V3.333H8.666V7.333Z", fill: "currentColor" }) }), "Expected result"] }))] })] })] }));
243
246
  },
244
247
  });
@@ -1032,17 +1032,17 @@ export function StepField({ label, showLabel = true, labelToggle, labelAction, p
1032
1032
  }, tabIndex: -1, children: "Edit link" }), _jsx("a", { className: "bn-step-link-tooltip__btn", href: cursorLink.url, target: "_blank", rel: "noopener noreferrer", onMouseDown: (event) => event.stopPropagation(), tabIndex: -1, children: _jsxs("svg", { width: "12", height: "12", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true", children: [_jsx("path", { d: "M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z" }), _jsx("path", { d: "M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z" })] }) }), _jsx("button", { type: "button", className: "bn-step-link-tooltip__btn bn-step-link-tooltip__btn--danger", onMouseDown: (event) => {
1033
1033
  event.preventDefault();
1034
1034
  handleRemoveLink();
1035
- }, tabIndex: -1, children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { d: "M7 3h2a1 1 0 0 0-2 0ZM6 3a2 2 0 1 1 4 0h4a.5.5 0 0 1 0 1h-.564l-1.205 8.838A2.5 2.5 0 0 1 9.754 15H6.246a2.5 2.5 0 0 1-2.477-2.162L2.564 4H2a.5.5 0 0 1 0-1h4Zm1 3.5a.5.5 0 0 0-1 0v5a.5.5 0 0 0 1 0v-5ZM9.5 6a.5.5 0 0 0-.5.5v5a.5.5 0 0 0 1 0v-5a.5.5 0 0 0-.5-.5Z" }) }) })] })), showToolbar && (_jsxs("div", { className: "bn-step-toolbar", "aria-label": `${label} controls`, children: [showFormattingButtons && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "bn-step-toolbar__button", onMouseDown: (event) => {
1035
+ }, tabIndex: -1, children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { d: "M7 3h2a1 1 0 0 0-2 0ZM6 3a2 2 0 1 1 4 0h4a.5.5 0 0 1 0 1h-.564l-1.205 8.838A2.5 2.5 0 0 1 9.754 15H6.246a2.5 2.5 0 0 1-2.477-2.162L2.564 4H2a.5.5 0 0 1 0-1h4Zm1 3.5a.5.5 0 0 0-1 0v5a.5.5 0 0 0 1 0v-5ZM9.5 6a.5.5 0 0 0-.5.5v5a.5.5 0 0 0 1 0v-5a.5.5 0 0 0-.5-.5Z" }) }) })] })), showToolbar && (_jsxs("div", { className: "bn-step-toolbar", "aria-label": `${label} controls`, children: [showFormattingButtons && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "bn-step-toolbar__button", "data-tooltip": "Bold", onMouseDown: (event) => {
1036
1036
  event.preventDefault();
1037
1037
  handleToolbarAction("toggleBold");
1038
- }, "aria-label": "Bold", tabIndex: -1, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 2.66675H8.33333C8.92064 2.66677 9.49502 2.83918 9.98525 3.1626C10.4755 3.48602 10.86 3.94622 11.0911 4.48613C11.3223 5.02604 11.3898 5.62192 11.2855 6.19988C11.1811 6.77783 10.9094 7.31244 10.504 7.73741C11.0752 8.06825 11.5213 8.57823 11.7733 9.18833C12.0252 9.79844 12.0689 10.4746 11.8976 11.1121C11.7263 11.7495 11.3495 12.3127 10.8256 12.7143C10.3018 13.1159 9.66008 13.3335 9 13.3334H4V12.0001H4.66667V4.00008H4V2.66675ZM6 7.33341H8.33333C8.77536 7.33341 9.19928 7.15782 9.51184 6.84526C9.8244 6.5327 10 6.10878 10 5.66675C10 5.22472 9.8244 4.8008 9.51184 4.48824C9.19928 4.17568 8.77536 4.00008 8.33333 4.00008H6V7.33341ZM6 8.66675V12.0001H9C9.44203 12.0001 9.86595 11.8245 10.1785 11.5119C10.4911 11.1994 10.6667 10.7754 10.6667 10.3334C10.6667 9.89139 10.4911 9.46746 10.1785 9.1549C9.86595 8.84234 9.44203 8.66675 9 8.66675H6Z", fill: "currentColor" }) }) }), _jsx("button", { type: "button", className: "bn-step-toolbar__button", onMouseDown: (event) => {
1038
+ }, "aria-label": "Bold", tabIndex: -1, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 2.66675H8.33333C8.92064 2.66677 9.49502 2.83918 9.98525 3.1626C10.4755 3.48602 10.86 3.94622 11.0911 4.48613C11.3223 5.02604 11.3898 5.62192 11.2855 6.19988C11.1811 6.77783 10.9094 7.31244 10.504 7.73741C11.0752 8.06825 11.5213 8.57823 11.7733 9.18833C12.0252 9.79844 12.0689 10.4746 11.8976 11.1121C11.7263 11.7495 11.3495 12.3127 10.8256 12.7143C10.3018 13.1159 9.66008 13.3335 9 13.3334H4V12.0001H4.66667V4.00008H4V2.66675ZM6 7.33341H8.33333C8.77536 7.33341 9.19928 7.15782 9.51184 6.84526C9.8244 6.5327 10 6.10878 10 5.66675C10 5.22472 9.8244 4.8008 9.51184 4.48824C9.19928 4.17568 8.77536 4.00008 8.33333 4.00008H6V7.33341ZM6 8.66675V12.0001H9C9.44203 12.0001 9.86595 11.8245 10.1785 11.5119C10.4911 11.1994 10.6667 10.7754 10.6667 10.3334C10.6667 9.89139 10.4911 9.46746 10.1785 9.1549C9.86595 8.84234 9.44203 8.66675 9 8.66675H6Z", fill: "currentColor" }) }) }), _jsx("button", { type: "button", className: "bn-step-toolbar__button", "data-tooltip": "Italic", onMouseDown: (event) => {
1039
1039
  event.preventDefault();
1040
1040
  handleToolbarAction("toggleItalic");
1041
- }, "aria-label": "Italic", tabIndex: -1, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M8.66699 13.3334H4.66699V12.0001H5.95166L8.69566 4.00008H7.33366V2.66675H11.3337V4.00008H10.049L7.30499 12.0001H8.66699V13.3334Z", fill: "currentColor" }) }) })] })), enableImageUpload && uploadImage && showImageButton && (_jsx("button", { type: "button", className: "bn-step-toolbar__button", onMouseDown: (event) => {
1041
+ }, "aria-label": "Italic", tabIndex: -1, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M8.66699 13.3334H4.66699V12.0001H5.95166L8.69566 4.00008H7.33366V2.66675H11.3337V4.00008H10.049L7.30499 12.0001H8.66699V13.3334Z", fill: "currentColor" }) }) })] })), enableImageUpload && uploadImage && showImageButton && (_jsx("button", { type: "button", className: "bn-step-toolbar__button", "data-tooltip": "Insert image", onMouseDown: (event) => {
1042
1042
  var _a;
1043
1043
  event.preventDefault();
1044
1044
  (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
1045
- }, "aria-label": "Insert image", tabIndex: -1, disabled: isUploading, children: _jsx(ImageUploadIcon, {}) })), showFormattingButtons && Components && (_jsxs(Components.Generic.Popover.Root, { opened: showLinkPopover, position: "top", children: [_jsx(Components.Generic.Popover.Trigger, { children: _jsx("button", { type: "button", className: "bn-step-toolbar__button", onMouseDown: (event) => {
1045
+ }, "aria-label": "Insert image", tabIndex: -1, disabled: isUploading, children: _jsx(ImageUploadIcon, {}) })), showFormattingButtons && Components && (_jsxs(Components.Generic.Popover.Root, { opened: showLinkPopover, position: "top", children: [_jsx(Components.Generic.Popover.Trigger, { children: _jsx("button", { type: "button", className: "bn-step-toolbar__button", "data-tooltip": "Insert link", onMouseDown: (event) => {
1046
1046
  event.preventDefault();
1047
1047
  if (showLinkPopover) {
1048
1048
  setShowLinkPopover(false);
@@ -1058,7 +1058,7 @@ export function StepField({ label, showLabel = true, labelToggle, labelAction, p
1058
1058
  return "";
1059
1059
  const existing = linksRef.current.find((l) => l.start < sel.end && l.end > sel.start);
1060
1060
  return (_a = existing === null || existing === void 0 ? void 0 : existing.url) !== null && _a !== void 0 ? _a : "";
1061
- })(), text: (_b = (_a = linkSelectionRef.current) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : "", editLink: handleEditLink }) }) })] })), enableAutocomplete && (_jsxs(_Fragment, { children: [_jsx("div", { className: "bn-step-toolbar__divider" }), _jsx("button", { type: "button", className: "bn-step-toolbar__button", onMouseDown: (event) => {
1061
+ })(), text: (_b = (_a = linkSelectionRef.current) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : "", editLink: handleEditLink }) }) })] })), enableAutocomplete && (_jsxs(_Fragment, { children: [_jsx("div", { className: "bn-step-toolbar__divider" }), _jsx("button", { type: "button", className: "bn-step-toolbar__button", "data-tooltip": "Show suggestions", onMouseDown: (event) => {
1062
1062
  event.preventDefault();
1063
1063
  setShowAllSuggestions(true);
1064
1064
  textareaNode === null || textareaNode === void 0 ? void 0 : textareaNode.focus();
@@ -190,8 +190,8 @@ function flattenWithBlankLine(lines, appendBlank = false) {
190
190
  }
191
191
  return lines;
192
192
  }
193
- function serializeBlock(block, ctx, orderedIndex) {
194
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
193
+ function serializeBlock(block, ctx, orderedIndex, stepIndex) {
194
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
195
195
  const lines = [];
196
196
  const indent = ctx.listDepth > 0 ? " ".repeat(ctx.listDepth) : "";
197
197
  switch (block.type) {
@@ -292,7 +292,9 @@ function serializeBlock(block, ctx, orderedIndex) {
292
292
  .filter((segment) => segment.length > 0)
293
293
  .join(" ");
294
294
  if (normalizedTitle.length > 0) {
295
- lines.push(`* ${normalizedTitle}`);
295
+ const listStyle = (_m = block.props.listStyle) !== null && _m !== void 0 ? _m : "bullet";
296
+ const prefix = listStyle === "ordered" ? `${(stepIndex !== null && stepIndex !== void 0 ? stepIndex : 0) + 1}.` : "*";
297
+ lines.push(`${prefix} ${normalizedTitle}`);
296
298
  }
297
299
  }
298
300
  if (stepData.length > 0) {
@@ -348,7 +350,7 @@ function serializeBlock(block, ctx, orderedIndex) {
348
350
  return flattenWithBlankLine(lines, true);
349
351
  }
350
352
  const headerRowCount = rows.length
351
- ? Math.min(rows.length, Math.max((_m = tableContent.headerRows) !== null && _m !== void 0 ? _m : 1, 1))
353
+ ? Math.min(rows.length, Math.max((_o = tableContent.headerRows) !== null && _o !== void 0 ? _o : 1, 1))
352
354
  : 0;
353
355
  const columnAlignments = new Array(columnCount).fill("left");
354
356
  const getCellAlignment = (cell) => {
@@ -425,6 +427,7 @@ function serializeBlock(block, ctx, orderedIndex) {
425
427
  function serializeBlocks(blocks, ctx) {
426
428
  const lines = [];
427
429
  let orderedIndex = null;
430
+ let stepIndex = 0;
428
431
  for (const block of blocks) {
429
432
  if (block.type === "numberedListItem") {
430
433
  if (typeof block.props.start === "number") {
@@ -437,6 +440,13 @@ function serializeBlocks(blocks, ctx) {
437
440
  orderedIndex += 1;
438
441
  continue;
439
442
  }
443
+ if (block.type === "testStep") {
444
+ lines.push(...serializeBlock(block, ctx, undefined, stepIndex));
445
+ stepIndex += 1;
446
+ orderedIndex = null;
447
+ continue;
448
+ }
449
+ stepIndex = 0;
440
450
  orderedIndex = null;
441
451
  lines.push(...serializeBlock(block, ctx));
442
452
  }
@@ -616,7 +626,7 @@ function parseList(lines, startIndex, listType, indentLevel, allowEmptySteps = f
616
626
  // Only try to parse as testStep for top-level items (indentLevel === 0)
617
627
  // when we're under a Steps heading AND the list type is bullet
618
628
  // Numbered lists under Steps heading are only parsed as test steps if they look like test steps
619
- if (indentLevel === 0 && allowEmptySteps) {
629
+ if (indentLevel === 0 && (allowEmptySteps || listType === "bullet")) {
620
630
  // For bullet lists, always try to parse as test steps
621
631
  // For numbered lists, only try if they have step-like characteristics
622
632
  const looksLikeTestStep = listType === "bullet" ||
@@ -855,7 +865,8 @@ function parseTestStep(lines, index, allowEmpty = false, snippetId) {
855
865
  .map((line) => line.trimEnd())
856
866
  .join("\n")
857
867
  .trim();
858
- if (!isLikelyStep &&
868
+ if (!isBullet &&
869
+ !isLikelyStep &&
859
870
  !expectedResult &&
860
871
  stepDataLines.length === 0 &&
861
872
  !(allowEmpty && titleWithPlaceholders.length > 0)) {
@@ -875,6 +886,7 @@ function parseTestStep(lines, index, allowEmpty = false, snippetId) {
875
886
  stepTitle: titleWithPlaceholders,
876
887
  stepData: stepDataWithImages,
877
888
  expectedResult,
889
+ listStyle: isNumbered ? "ordered" : "bullet",
878
890
  };
879
891
  const parsedBlock = {
880
892
  type: blockType,
@@ -15,6 +15,9 @@ export declare const customSchema: BlockNoteSchema<import("@blocknote/core").Blo
15
15
  readonly expectedResult: {
16
16
  readonly default: "";
17
17
  };
18
+ readonly listStyle: {
19
+ readonly default: "bullet";
20
+ };
18
21
  };
19
22
  };
20
23
  implementation: import("@blocknote/core").TiptapBlockImplementation<{
@@ -30,6 +33,9 @@ export declare const customSchema: BlockNoteSchema<import("@blocknote/core").Blo
30
33
  readonly expectedResult: {
31
34
  readonly default: "";
32
35
  };
36
+ readonly listStyle: {
37
+ readonly default: "bullet";
38
+ };
33
39
  };
34
40
  }, any, import("@blocknote/core").InlineContentSchema, import("@blocknote/core").StyleSchema>;
35
41
  };
@@ -95,6 +95,163 @@
95
95
  --status-blocked-bg: rgba(239, 68, 68, 0.12);
96
96
  }
97
97
 
98
+ /* Dark mode variable overrides */
99
+ html.dark {
100
+ --color-white: #171717;
101
+ --color-slate-900: #fafafa;
102
+ --color-slate-400: #737373;
103
+
104
+ --text-primary: #fafafa;
105
+ --text-muted: rgba(250, 250, 250, 0.5);
106
+
107
+ --border-light: rgba(255, 255, 255, 0.1);
108
+ --border-default: rgba(255, 255, 255, 0.12);
109
+ --shadow-subtle: rgba(0, 0, 0, 0.2);
110
+ --shadow-medium: rgba(0, 0, 0, 0.35);
111
+ --shadow-heavy: rgba(0, 0, 0, 0.6);
112
+ --overlay-dark: rgba(0, 0, 0, 0.8);
113
+
114
+ --bg-white: rgba(38, 38, 38, 0.85);
115
+ --bg-white-solid: rgba(38, 38, 38, 0.92);
116
+ --bg-white-opaque: rgba(38, 38, 38, 0.98);
117
+ --bg-muted: rgba(255, 255, 255, 0.05);
118
+
119
+ /* Step block colors */
120
+ --step-card-bg: #1a1a1a;
121
+ --step-card-border: #333333;
122
+ --step-card-shadow: rgba(0, 0, 0, 0.2);
123
+ --step-input-border: #404040;
124
+ --step-input-border-focus: #6366f1;
125
+ --step-input-shadow: rgba(99, 102, 241, 0.25);
126
+ --step-text: #e5e5e5;
127
+ --step-muted: #737373;
128
+ --step-action: #a3a3a3;
129
+ --step-bg-button: #262626;
130
+ --step-bg-button-hover: #333333;
131
+ --step-border-focus: rgba(99, 102, 241, 0.4);
132
+ --step-border-light: rgba(255, 255, 255, 0.1);
133
+ --step-bg-light: rgba(255, 255, 255, 0.06);
134
+ --step-shadow-hover: rgba(0, 0, 0, 0.2);
135
+
136
+ /* Step timeline */
137
+ --step-number-bg: #404040;
138
+ --step-number-text: #fafafa;
139
+ --step-label-color: #a3a3a3;
140
+ --snippet-dropdown-bg: #262626;
141
+ --snippet-content-bg: #1a1a1a;
142
+ --snippet-content-border: #333333;
143
+
144
+ /* Snippet block colors */
145
+ --snippet-border: rgba(16, 185, 129, 0.6);
146
+ --snippet-bg: rgba(16, 185, 129, 0.08);
147
+ --snippet-shadow: rgba(16, 185, 129, 0.12);
148
+ --snippet-border-light: rgba(16, 185, 129, 0.2);
149
+ --snippet-border-medium: rgba(16, 185, 129, 0.3);
150
+ --snippet-border-strong: rgba(16, 185, 129, 0.45);
151
+ --snippet-border-focus: rgba(16, 185, 129, 0.6);
152
+ --snippet-bg-light: rgba(16, 185, 129, 0.08);
153
+ --snippet-bg-hover: rgba(16, 185, 129, 0.14);
154
+ --snippet-focus-ring: rgba(16, 185, 129, 0.15);
155
+
156
+ /* Status colors */
157
+ --status-default-bg: rgba(148, 163, 184, 0.08);
158
+ --status-ready-bg: rgba(34, 197, 94, 0.08);
159
+ --status-blocked-bg: rgba(239, 68, 68, 0.08);
160
+ }
161
+
162
+ /* Dark mode hardcoded color overrides */
163
+ html.dark .bn-step-action-btn {
164
+ color: #a3a3a3;
165
+ }
166
+
167
+ html.dark .bn-step-toolbar__button {
168
+ color: #d4d4d4;
169
+ }
170
+
171
+ html.dark .bn-step-toolbar__divider {
172
+ background: #404040;
173
+ }
174
+
175
+ html.dark .bn-teststep__view-toggle svg {
176
+ color: #d4d4d4;
177
+ }
178
+
179
+ html.dark [data-tooltip]::after {
180
+ background: #262626;
181
+ }
182
+
183
+ html.dark .bn-step-field__dismiss {
184
+ color: #737373;
185
+ }
186
+
187
+ html.dark .bn-step-editor {
188
+ color: #fafafa;
189
+ }
190
+
191
+ html.dark .bn-step-editor .overtype-wrapper .overtype-input {
192
+ caret-color: #fafafa !important;
193
+ }
194
+
195
+ html.dark .bn-step-editor .overtype-wrapper .overtype-preview {
196
+ color: #fafafa !important;
197
+ }
198
+
199
+ html.dark .bn-step-editor .overtype-wrapper textarea.overtype-input::placeholder {
200
+ color: #525252 !important;
201
+ }
202
+
203
+ html.dark .bn-step-editor .overtype-wrapper textarea.overtype-input::-webkit-input-placeholder {
204
+ color: #525252 !important;
205
+ }
206
+
207
+ html.dark .bn-step-custom-caret {
208
+ background: #fafafa;
209
+ }
210
+
211
+ html.dark .bn-step-link-tooltip {
212
+ background: #262626;
213
+ border-color: #404040;
214
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
215
+ }
216
+
217
+ html.dark .bn-step-link-tooltip__url {
218
+ color: #737373;
219
+ }
220
+
221
+ html.dark .bn-snippet-dropdown__panel {
222
+ background: #262626;
223
+ border-color: #404040;
224
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
225
+ }
226
+
227
+ html.dark .bn-snippet-dropdown__search {
228
+ border-color: #404040;
229
+ }
230
+
231
+ html.dark .bn-snippet-dropdown__search-icon {
232
+ color: #525252;
233
+ }
234
+
235
+ html.dark .bn-snippet-dropdown__search-input {
236
+ color: #fafafa;
237
+ }
238
+
239
+ html.dark .bn-snippet-dropdown__search-input::placeholder {
240
+ color: #525252;
241
+ }
242
+
243
+ html.dark .bn-snippet-dropdown__list {
244
+ border-top-color: #404040;
245
+ }
246
+
247
+ html.dark .bn-snippet-dropdown__chevron {
248
+ color: #525252;
249
+ }
250
+
251
+ html.dark .bn-step-image-preview__content {
252
+ background: #262626;
253
+ }
254
+
98
255
  .testomatio-editor {
99
256
  font-family: "Inter", system-ui, -apple-system, sans-serif;
100
257
  }
@@ -249,8 +406,8 @@
249
406
  padding-bottom: 8px;
250
407
  }
251
408
 
252
- .bn-teststep__header + .bn-step-field {
253
- margin-top: calc(8px - var(--step-section-gap));
409
+ .bn-teststep__content > .bn-teststep__header + .bn-step-field {
410
+ margin-top: calc(4px - var(--step-section-gap));
254
411
  }
255
412
 
256
413
  .bn-teststep__header {
@@ -324,6 +481,22 @@
324
481
  transform: rotate(90deg);
325
482
  }
326
483
 
484
+ .bn-teststep__view-toggle[data-tooltip]::after {
485
+ bottom: auto;
486
+ left: auto;
487
+ right: calc(100% + 6px);
488
+ top: 50%;
489
+ transform: translateY(-50%);
490
+ }
491
+
492
+ .bn-teststep__view-toggle--horizontal[data-tooltip]::after {
493
+ right: auto;
494
+ top: auto;
495
+ bottom: calc(100% + 6px);
496
+ left: 50%;
497
+ transform: translateX(-50%) rotate(-90deg);
498
+ }
499
+
327
500
  .bn-teststep__horizontal-fields {
328
501
  display: flex;
329
502
  gap: 16px;
@@ -579,7 +752,7 @@
579
752
  .bn-step-field {
580
753
  display: flex;
581
754
  flex-direction: column;
582
- gap: 8px;
755
+ gap: 4px;
583
756
  position: relative;
584
757
  }
585
758
 
@@ -733,6 +906,41 @@
733
906
  background: var(--step-bg-button-hover);
734
907
  }
735
908
 
909
+ [data-tooltip] {
910
+ position: relative;
911
+ }
912
+
913
+ [data-tooltip]::after {
914
+ content: attr(data-tooltip);
915
+ position: absolute;
916
+ bottom: calc(100% + 6px);
917
+ left: 50%;
918
+ transform: translateX(-50%);
919
+ background: #0a0a0a;
920
+ color: #fafafa;
921
+ font-family: Inter, sans-serif;
922
+ font-weight: 400;
923
+ font-size: 14px;
924
+ line-height: 20px;
925
+ padding: 4px 12px;
926
+ border-radius: 8px;
927
+ white-space: nowrap;
928
+ pointer-events: none;
929
+ opacity: 0;
930
+ transition: opacity 120ms ease;
931
+ z-index: 1000;
932
+ }
933
+
934
+ [data-tooltip]:hover::after {
935
+ opacity: 1;
936
+ transition-delay: 300ms;
937
+ }
938
+
939
+ [data-tooltip]:active::after {
940
+ opacity: 0;
941
+ transition-delay: 0ms;
942
+ }
943
+
736
944
  .bn-step-editor {
737
945
  position: relative;
738
946
  border-radius: 0.6rem;
@@ -801,8 +1009,12 @@
801
1009
  font-weight: 400 !important;
802
1010
  }
803
1011
 
1012
+ .bn-step-editor .overtype-wrapper .overtype-placeholder {
1013
+ display: none !important;
1014
+ }
1015
+
804
1016
  .bn-step-editor .overtype-wrapper .overtype-preview {
805
- color: var(--text-primary) !important;
1017
+ color: #262626 !important;
806
1018
  }
807
1019
 
808
1020
  .bn-step-editor .overtype-wrapper .overtype-preview a.step-preview-link {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testomatio-editor-blocks",
3
- "version": "0.4.1",
3
+ "version": "0.4.9",
4
4
  "description": "Custom BlockNote schema, markdown conversion helpers, and UI for Testomatio-style test cases and steps.",
5
5
  "type": "module",
6
6
  "main": "./package/index.js",
package/src/App.css CHANGED
@@ -16,9 +16,8 @@
16
16
 
17
17
  .app__header {
18
18
  display: flex;
19
- flex-wrap: wrap;
20
19
  justify-content: space-between;
21
- align-items: center;
20
+ align-items: flex-start;
22
21
  gap: 1.5rem;
23
22
  }
24
23
 
@@ -26,6 +25,7 @@
26
25
  display: flex;
27
26
  align-items: center;
28
27
  gap: 0.75rem;
28
+ flex-shrink: 0;
29
29
  }
30
30
 
31
31
  .app__header h1 {
@@ -67,6 +67,25 @@
67
67
  box-shadow: 0 12px 24px rgba(37, 99, 235, 0.18);
68
68
  }
69
69
 
70
+ .app__dark-toggle {
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ width: 2.5rem;
75
+ height: 2.5rem;
76
+ border: 1px solid #e4e7ec;
77
+ border-radius: 0.75rem;
78
+ background: #fff;
79
+ color: #475467;
80
+ cursor: pointer;
81
+ transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
82
+ }
83
+
84
+ .app__dark-toggle:hover {
85
+ background: #f1f5f9;
86
+ color: #0f172a;
87
+ }
88
+
70
89
 
71
90
  .app__workspace {
72
91
  display: grid;
@@ -188,6 +207,80 @@
188
207
  color: rgba(15, 23, 42, 0.6);
189
208
  }
190
209
 
210
+ /* Dark mode overrides — neutral gray + indigo accent palette from Figma */
211
+ html.dark #root {
212
+ color: #fafafa;
213
+ }
214
+
215
+ html.dark .app__header h1 {
216
+ color: #fafafa;
217
+ }
218
+
219
+ html.dark .app__header p {
220
+ color: #a3a3a3;
221
+ }
222
+
223
+ html.dark .app__action {
224
+ background: linear-gradient(135deg, #6366f1, #4f46e5);
225
+ box-shadow: 0 10px 20px rgba(99, 102, 241, 0.25);
226
+ }
227
+
228
+ html.dark .app__action:hover {
229
+ box-shadow: 0 16px 32px rgba(99, 102, 241, 0.3);
230
+ }
231
+
232
+ html.dark .app__action--ghost {
233
+ background: rgba(99, 102, 241, 0.15);
234
+ color: #818cf8;
235
+ }
236
+
237
+ html.dark .app__action--ghost:hover {
238
+ box-shadow: 0 12px 24px rgba(99, 102, 241, 0.18);
239
+ }
240
+
241
+ html.dark .app__dark-toggle {
242
+ background: #262626;
243
+ border-color: #404040;
244
+ color: #d4d4d4;
245
+ }
246
+
247
+ html.dark .app__dark-toggle:hover {
248
+ background: #404040;
249
+ color: #fafafa;
250
+ }
251
+
252
+ html.dark .app__editor {
253
+ background: #171717;
254
+ border-color: #404040;
255
+ box-shadow: 0 12px 24px rgba(0, 0, 0, 0.4);
256
+ }
257
+
258
+ html.dark .app__panel {
259
+ background: #171717;
260
+ box-shadow: inset 0 0 0 1px rgba(64, 64, 64, 0.5);
261
+ }
262
+
263
+ html.dark .app__panel--light {
264
+ background: #262626;
265
+ color: #fafafa;
266
+ }
267
+
268
+ html.dark .app__panel-text {
269
+ color: #a3a3a3;
270
+ }
271
+
272
+ html.dark .app__step-list li {
273
+ background: rgba(99, 102, 241, 0.12);
274
+ }
275
+
276
+ html.dark .app__step-meta {
277
+ color: #737373;
278
+ }
279
+
280
+ html.dark .app__copy-status {
281
+ color: #818cf8;
282
+ }
283
+
191
284
  @media (max-width: 960px) {
192
285
  #root {
193
286
  padding: 1.5rem;
package/src/App.tsx CHANGED
@@ -389,6 +389,11 @@ function App() {
389
389
  const [copyBlocksStatus, setCopyBlocksStatus] = useState<"idle" | "copied" | "failed">(
390
390
  "idle",
391
391
  );
392
+ const [darkMode, setDarkMode] = useState(false);
393
+
394
+ useEffect(() => {
395
+ document.documentElement.classList.toggle("dark", darkMode);
396
+ }, [darkMode]);
392
397
 
393
398
  useEditorChange((editorInstance) => {
394
399
  try {
@@ -615,6 +620,18 @@ function App() {
615
620
  >
616
621
  Insert Snippet
617
622
  </button>
623
+ <button
624
+ type="button"
625
+ className="app__dark-toggle"
626
+ onClick={() => setDarkMode((v) => !v)}
627
+ title={darkMode ? "Switch to light mode" : "Switch to dark mode"}
628
+ >
629
+ {darkMode ? (
630
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" width="20" height="20"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
631
+ ) : (
632
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" width="20" height="20"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
633
+ )}
634
+ </button>
618
635
  </div>
619
636
  </header>
620
637
 
@@ -622,7 +639,7 @@ function App() {
622
639
  <div className="app__editor">
623
640
  <BlockNoteView
624
641
  editor={editor}
625
- theme="light"
642
+ theme={darkMode ? "dark" : "light"}
626
643
  slashMenu={false}
627
644
  className="markdown testomatio-editor"
628
645
  >