@bendyline/squisq-editor-react 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +10 -2
  2. package/dist/index.d.ts +505 -15
  3. package/dist/index.js +6035 -2283
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles/index.css +870 -40
  6. package/package.json +6 -5
  7. package/src/EditorContext.tsx +27 -0
  8. package/src/EditorShell.tsx +24 -0
  9. package/src/PreviewControls.tsx +20 -5
  10. package/src/PreviewPanel.tsx +5 -1
  11. package/src/RawEditor.tsx +12 -0
  12. package/src/RecorderEntry.tsx +3 -0
  13. package/src/Toolbar.tsx +315 -17
  14. package/src/WysiwygEditor.tsx +25 -11
  15. package/src/__tests__/buildPreviewDocContent.test.ts +17 -0
  16. package/src/__tests__/editorShellProps.test.tsx +65 -0
  17. package/src/__tests__/findMode.test.tsx +104 -0
  18. package/src/__tests__/findModel.test.ts +55 -0
  19. package/src/__tests__/markdownCodeFence.test.ts +45 -0
  20. package/src/__tests__/mediaReferences.test.ts +15 -0
  21. package/src/__tests__/previewControls.test.tsx +31 -0
  22. package/src/__tests__/tiptapBridge.test.ts +9 -0
  23. package/src/__tests__/toolbarSelectionConversion.test.tsx +26 -0
  24. package/src/__tests__/writeCanvasSettings.test.ts +15 -0
  25. package/src/asciiDiagram/__tests__/AsciiDiagramExtension.test.ts +20 -1
  26. package/src/buildPreviewDoc.ts +9 -7
  27. package/src/codeSnippet/CodeSnippetExtension.ts +205 -0
  28. package/src/codeSnippet/CodeSnippetWidget.tsx +109 -0
  29. package/src/codeSnippet/__tests__/CodeSnippetExtension.test.ts +95 -0
  30. package/src/codeSnippet/__tests__/codeSnippetLanguages.test.ts +50 -0
  31. package/src/codeSnippet/codeSnippetCommands.ts +21 -0
  32. package/src/codeSnippet/codeSnippetData.ts +43 -0
  33. package/src/codeSnippet/codeSnippetLanguages.ts +216 -0
  34. package/src/diagram/DiagramCanvas.tsx +1 -0
  35. package/src/find/FindHighlightExtension.ts +81 -0
  36. package/src/find/FindToolbar.tsx +314 -0
  37. package/src/find/findModel.ts +77 -0
  38. package/src/index.ts +89 -0
  39. package/src/markdownCodeFence.ts +72 -0
  40. package/src/mediaReferences.ts +5 -3
  41. package/src/mermaid/MermaidDiagramCanvas.tsx +693 -0
  42. package/src/mermaid/MermaidDiagramExtension.ts +243 -0
  43. package/src/mermaid/MermaidDiagramTypeThumbnail.tsx +184 -0
  44. package/src/mermaid/MermaidDiagramWidget.tsx +653 -0
  45. package/src/mermaid/MermaidShapePalette.tsx +245 -0
  46. package/src/mermaid/__tests__/MermaidDiagramExtension.test.ts +361 -0
  47. package/src/mermaid/__tests__/mermaidDiagramTypes.test.ts +35 -0
  48. package/src/mermaid/__tests__/mermaidRenderer.test.ts +49 -0
  49. package/src/mermaid/__tests__/mermaidSourceOps.test.ts +213 -0
  50. package/src/mermaid/__tests__/mermaidSyntax.test.ts +71 -0
  51. package/src/mermaid/mermaidCommands.ts +34 -0
  52. package/src/mermaid/mermaidData.ts +31 -0
  53. package/src/mermaid/mermaidDiagramTypes.ts +325 -0
  54. package/src/mermaid/mermaidModel.ts +31 -0
  55. package/src/mermaid/mermaidRenderer.ts +181 -0
  56. package/src/mermaid/mermaidShapes.ts +113 -0
  57. package/src/mermaid/mermaidSourceOps.ts +454 -0
  58. package/src/scene/Scene.tsx +46 -15
  59. package/src/scene/SceneBlockToolbar.tsx +29 -14
  60. package/src/scene/SceneViewControls.tsx +43 -0
  61. package/src/scene/__tests__/fitScale.test.ts +19 -0
  62. package/src/scene/__tests__/useScenePanZoom.test.ts +28 -1
  63. package/src/scene/fitScale.ts +17 -0
  64. package/src/scene/hooks/useScenePanZoom.ts +11 -4
  65. package/src/scene/scene.css +85 -3
  66. package/src/styles/code-snippet.css +76 -0
  67. package/src/styles/editor.css +322 -2
  68. package/src/styles/index.css +2 -0
  69. package/src/styles/mermaid-diagram.css +487 -0
  70. package/src/writeCanvasSettings.ts +30 -0
@@ -7341,6 +7341,99 @@
7341
7341
  flex: 1;
7342
7342
  min-width: 0;
7343
7343
  }
7344
+ .squisq-find-toolbar {
7345
+ display: flex;
7346
+ align-items: center;
7347
+ flex: 1 1 auto;
7348
+ gap: 3px;
7349
+ min-width: 180px;
7350
+ padding: 4px 6px;
7351
+ }
7352
+ .squisq-find-field {
7353
+ display: flex;
7354
+ align-items: center;
7355
+ flex: 0 1 420px;
7356
+ min-width: 130px;
7357
+ height: 28px;
7358
+ border: 1px solid #9ca3af;
7359
+ border-radius: 5px;
7360
+ background: #ffffff;
7361
+ color: #6b7280;
7362
+ box-sizing: border-box;
7363
+ }
7364
+ .squisq-find-field:focus-within {
7365
+ border-color: #2563eb;
7366
+ box-shadow: 0 0 0 1px #2563eb;
7367
+ }
7368
+ .squisq-find-field > i {
7369
+ margin-left: 8px;
7370
+ color: #6b7280;
7371
+ font-size: 11px;
7372
+ }
7373
+ .squisq-find-input {
7374
+ flex: 1 1 auto;
7375
+ min-width: 32px;
7376
+ height: 100%;
7377
+ padding: 0 7px;
7378
+ border: 0;
7379
+ outline: 0;
7380
+ background: transparent;
7381
+ color: #111827;
7382
+ font: inherit;
7383
+ font-size: 12.5px;
7384
+ }
7385
+ .squisq-find-input::-webkit-search-cancel-button {
7386
+ display: none;
7387
+ }
7388
+ .squisq-find-count {
7389
+ flex: 0 0 auto;
7390
+ padding-right: 7px;
7391
+ color: #6b7280;
7392
+ font-size: 11px;
7393
+ white-space: nowrap;
7394
+ }
7395
+ .squisq-find-button {
7396
+ display: inline-flex;
7397
+ align-items: center;
7398
+ justify-content: center;
7399
+ width: 28px;
7400
+ height: 28px;
7401
+ padding: 0;
7402
+ border: 0;
7403
+ border-radius: 4px;
7404
+ background: transparent;
7405
+ color: var(--squisq-toolbar-icon);
7406
+ cursor: pointer;
7407
+ }
7408
+ .squisq-find-button:hover:not(:disabled) {
7409
+ background: rgba(0, 0, 0, 0.08);
7410
+ color: #111827;
7411
+ }
7412
+ .squisq-find-button:disabled {
7413
+ opacity: 0.35;
7414
+ cursor: default;
7415
+ }
7416
+ .squisq-find-close {
7417
+ margin-left: 2px;
7418
+ }
7419
+ .squisq-find-match {
7420
+ border-radius: 2px;
7421
+ background: #fde68a !important;
7422
+ color: #111827 !important;
7423
+ }
7424
+ .squisq-find-match--selected {
7425
+ background: #f59e0b !important;
7426
+ box-shadow: 0 0 0 1px #b45309;
7427
+ }
7428
+ @container squisq-toolbar (max-width: 680px) {
7429
+ .squisq-find-toolbar {
7430
+ min-width: 120px;
7431
+ padding-right: 2px;
7432
+ }
7433
+ .squisq-find-count {
7434
+ display: none;
7435
+ }
7436
+ }
7344
7437
  .squisq-toolbar-contextual--clipped {
7345
7438
  visibility: hidden;
7346
7439
  }
@@ -7597,6 +7690,159 @@
7597
7690
  .squisq-insert-menu[data-theme=dark] .squisq-insert-menu-header--separated {
7598
7691
  border-top-color: #374151;
7599
7692
  }
7693
+ .squisq-code-snippet-menu {
7694
+ width: 220px;
7695
+ max-height: min(440px, calc(100vh - 16px));
7696
+ overflow-y: auto;
7697
+ }
7698
+ .squisq-code-snippet-language {
7699
+ justify-content: space-between;
7700
+ gap: 16px;
7701
+ }
7702
+ .squisq-code-snippet-language code {
7703
+ overflow: hidden;
7704
+ color: #9ca3af;
7705
+ font-family:
7706
+ ui-monospace,
7707
+ SFMono-Regular,
7708
+ Menlo,
7709
+ Consolas,
7710
+ "Liberation Mono",
7711
+ monospace;
7712
+ font-size: 11px;
7713
+ text-overflow: ellipsis;
7714
+ white-space: nowrap;
7715
+ }
7716
+ .squisq-mermaid-type-menu {
7717
+ width: min(520px, calc(100vw - 16px));
7718
+ max-height: min(600px, calc(100vh - 16px));
7719
+ padding: 0 8px 10px;
7720
+ overflow-y: auto;
7721
+ }
7722
+ .squisq-mermaid-type-menu-heading {
7723
+ position: sticky;
7724
+ z-index: 1;
7725
+ top: 0;
7726
+ display: flex;
7727
+ flex-direction: column;
7728
+ gap: 2px;
7729
+ margin: 0 -8px 4px;
7730
+ padding: 12px 14px 10px;
7731
+ color: #111827;
7732
+ background: #fff;
7733
+ border-bottom: 1px solid #e5e7eb;
7734
+ }
7735
+ .squisq-mermaid-type-menu-heading strong {
7736
+ font-size: 14px;
7737
+ }
7738
+ .squisq-mermaid-type-menu-heading span {
7739
+ color: #6b7280;
7740
+ font-size: 11px;
7741
+ line-height: 1.35;
7742
+ }
7743
+ .squisq-mermaid-type-section + .squisq-mermaid-type-section {
7744
+ margin-top: 4px;
7745
+ }
7746
+ .squisq-mermaid-type-grid {
7747
+ display: grid;
7748
+ grid-template-columns: repeat(2, minmax(0, 1fr));
7749
+ gap: 6px;
7750
+ }
7751
+ .squisq-mermaid-type-card {
7752
+ display: grid;
7753
+ grid-template-columns: 82px minmax(0, 1fr);
7754
+ align-items: center;
7755
+ min-width: 0;
7756
+ padding: 8px;
7757
+ color: #1f2937;
7758
+ font: inherit;
7759
+ text-align: left;
7760
+ background: #f9fafb;
7761
+ border: 1px solid #e5e7eb;
7762
+ border-radius: 7px;
7763
+ cursor: pointer;
7764
+ }
7765
+ .squisq-mermaid-type-card:hover,
7766
+ .squisq-mermaid-type-card:focus-visible {
7767
+ color: #1d4ed8;
7768
+ background: #eff6ff;
7769
+ border-color: #93c5fd;
7770
+ outline: none;
7771
+ }
7772
+ .squisq-mermaid-type-thumbnail {
7773
+ display: flex;
7774
+ height: 48px;
7775
+ align-items: center;
7776
+ justify-content: center;
7777
+ padding: 3px;
7778
+ color: currentcolor;
7779
+ }
7780
+ .squisq-mermaid-type-thumbnail svg {
7781
+ display: block;
7782
+ width: 100%;
7783
+ height: 100%;
7784
+ }
7785
+ .squisq-mermaid-type-copy,
7786
+ .squisq-mermaid-type-title {
7787
+ min-width: 0;
7788
+ }
7789
+ .squisq-mermaid-type-copy {
7790
+ display: flex;
7791
+ flex-direction: column;
7792
+ gap: 3px;
7793
+ }
7794
+ .squisq-mermaid-type-title {
7795
+ display: flex;
7796
+ align-items: center;
7797
+ gap: 5px;
7798
+ font-size: 12px;
7799
+ font-weight: 650;
7800
+ }
7801
+ .squisq-mermaid-type-description {
7802
+ display: -webkit-box;
7803
+ overflow: hidden;
7804
+ color: #6b7280;
7805
+ font-size: 10px;
7806
+ line-height: 1.3;
7807
+ -webkit-box-orient: vertical;
7808
+ -webkit-line-clamp: 2;
7809
+ }
7810
+ .squisq-mermaid-type-badge {
7811
+ flex: none;
7812
+ padding: 1px 4px;
7813
+ color: #92400e;
7814
+ font-size: 8px;
7815
+ font-weight: 700;
7816
+ letter-spacing: 0.03em;
7817
+ text-transform: uppercase;
7818
+ background: #fef3c7;
7819
+ border-radius: 999px;
7820
+ }
7821
+ .squisq-mermaid-type-menu[data-theme=dark] .squisq-mermaid-type-menu-heading {
7822
+ color: #f9fafb;
7823
+ background: #1f2937;
7824
+ border-bottom-color: #374151;
7825
+ }
7826
+ .squisq-mermaid-type-menu[data-theme=dark] .squisq-mermaid-type-menu-heading span,
7827
+ .squisq-mermaid-type-menu[data-theme=dark] .squisq-mermaid-type-description {
7828
+ color: #9ca3af;
7829
+ }
7830
+ .squisq-mermaid-type-menu[data-theme=dark] .squisq-mermaid-type-card {
7831
+ color: #e5e7eb;
7832
+ background: #111827;
7833
+ border-color: #374151;
7834
+ }
7835
+ .squisq-mermaid-type-menu[data-theme=dark] .squisq-mermaid-type-card:hover,
7836
+ .squisq-mermaid-type-menu[data-theme=dark] .squisq-mermaid-type-card:focus-visible {
7837
+ color: #bfdbfe;
7838
+ background: #1e3a5f;
7839
+ border-color: #3b82f6;
7840
+ }
7841
+ @media (max-width: 620px) {
7842
+ .squisq-mermaid-type-grid {
7843
+ grid-template-columns: 1fr;
7844
+ }
7845
+ }
7600
7846
  .squisq-template-picker {
7601
7847
  display: flex;
7602
7848
  align-items: center;
@@ -8635,6 +8881,7 @@
8635
8881
  background: var(--squisq-theme-bg, #fff);
8636
8882
  box-shadow: 0 2px 14px rgba(0, 0, 0, 0.12);
8637
8883
  font-family: var(--squisq-theme-body-font, inherit);
8884
+ font-size: var(--squisq-write-text-size, inherit);
8638
8885
  caret-color: var(--squisq-theme-text, #1f2937);
8639
8886
  cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='22' viewBox='0 0 16 22'><g fill='none' stroke-linecap='round'><path d='M5 3 L11 3 M5 19 L11 19 M8 3 L8 19' stroke='white' stroke-width='3.2'/><path d='M5 3 L11 3 M5 19 L11 19 M8 3 L8 19' stroke='%231f2937' stroke-width='1.4'/></g></svg>") 8 11, text;
8640
8887
  }
@@ -8682,12 +8929,15 @@
8682
8929
  font-size: 0.67em;
8683
8930
  margin: 1.6em 0 0.3em;
8684
8931
  }
8932
+ .squisq-heading-content:has(> br.ProseMirror-trailingBreak:only-child) {
8933
+ display: inline-block;
8934
+ }
8685
8935
  .squisq-wysiwyg-editor > :first-child {
8686
8936
  margin-top: 0;
8687
8937
  }
8688
8938
  .squisq-wysiwyg-editor p {
8689
- margin: 0.5em 0;
8690
- line-height: 1.7;
8939
+ margin: 0.625em 0;
8940
+ line-height: var(--squisq-write-line-spacing, 1.7);
8691
8941
  }
8692
8942
  .squisq-wysiwyg-editor blockquote {
8693
8943
  border-left: 3px solid var(--squisq-theme-text-muted, #d1d5db);
@@ -9205,6 +9455,26 @@
9205
9455
  background: rgba(255, 255, 255, 0.08);
9206
9456
  --squisq-toolbar-icon: #9ca3af;
9207
9457
  }
9458
+ .squisq-editor-shell[data-theme=dark] .squisq-find-field {
9459
+ border-color: #4b5563;
9460
+ background: #111827;
9461
+ color: #9ca3af;
9462
+ }
9463
+ .squisq-editor-shell[data-theme=dark] .squisq-find-field:focus-within {
9464
+ border-color: #60a5fa;
9465
+ box-shadow: 0 0 0 1px #60a5fa;
9466
+ }
9467
+ .squisq-editor-shell[data-theme=dark] .squisq-find-input {
9468
+ color: #f9fafb;
9469
+ }
9470
+ .squisq-editor-shell[data-theme=dark] .squisq-find-input::placeholder,
9471
+ .squisq-editor-shell[data-theme=dark] .squisq-find-count {
9472
+ color: #9ca3af;
9473
+ }
9474
+ .squisq-editor-shell[data-theme=dark] .squisq-find-button:hover:not(:disabled) {
9475
+ background: rgba(255, 255, 255, 0.1);
9476
+ color: #f9fafb;
9477
+ }
9208
9478
  .squisq-editor-shell[data-theme=dark] .squisq-toolbar-view-tabs {
9209
9479
  background: #111827;
9210
9480
  border-right-color: rgba(255, 255, 255, 0.15);
@@ -14057,54 +14327,543 @@
14057
14327
  filter: brightness(0.95);
14058
14328
  }
14059
14329
 
14060
- /* src/styles/tree-view.css */
14061
- .squisq-wysiwyg-editor pre.squisq-tree-fence-hidden {
14330
+ /* src/styles/mermaid-diagram.css */
14331
+ .squisq-wysiwyg-editor pre.squisq-mermaid-fence-hidden {
14062
14332
  display: none;
14063
14333
  }
14064
- .squisq-tree-widget-host {
14334
+ .squisq-wysiwyg-editor pre.squisq-mermaid-fence-source {
14335
+ font-family:
14336
+ ui-monospace,
14337
+ SFMono-Regular,
14338
+ Menlo,
14339
+ Consolas,
14340
+ "Liberation Mono",
14341
+ monospace;
14342
+ white-space: pre;
14343
+ overflow-x: auto;
14344
+ line-height: 1.35;
14345
+ tab-size: 2;
14346
+ }
14347
+ .squisq-mermaid-diagram-widget-host {
14065
14348
  margin: 0.75rem 0 1.25rem;
14066
14349
  }
14067
- .squisq-tree-outline {
14068
- border: 1px solid var(--squisq-border, #e2e8f0);
14069
- border-radius: 8px;
14070
- padding: 8px 10px;
14071
- background: var(--squisq-input-bg, #ffffff);
14072
- color: var(--squisq-text, #1e293b);
14073
- font-size: 14px;
14350
+ .squisq-mermaid-canvas {
14351
+ position: relative;
14352
+ width: 100%;
14353
+ height: 100%;
14354
+ background: var(--squisq-surface, #ffffff);
14074
14355
  }
14075
- .squisq-tree-toolbar {
14076
- display: flex;
14077
- gap: 6px;
14078
- margin-bottom: 6px;
14356
+ .squisq-mermaid-canvas-scroll {
14357
+ box-sizing: border-box;
14358
+ width: 100%;
14359
+ height: 100%;
14360
+ overflow: auto;
14361
+ padding: 44px 24px 24px;
14079
14362
  }
14080
- .squisq-tree-btn {
14081
- display: inline-flex;
14082
- align-items: center;
14083
- gap: 5px;
14084
- font-size: 12px;
14085
- padding: 3px 8px;
14086
- border: 1px solid var(--squisq-border, #e2e8f0);
14087
- border-radius: 5px;
14088
- background: var(--squisq-bg, #f8fafc);
14089
- color: var(--squisq-text, #1e293b);
14363
+ .squisq-mermaid-canvas-scroll[data-panning=true] {
14364
+ cursor: grabbing;
14365
+ user-select: none;
14366
+ }
14367
+ .squisq-mermaid-svg {
14368
+ position: relative;
14369
+ min-height: 100%;
14370
+ margin: 0 auto;
14371
+ will-change: transform;
14372
+ transition: width 120ms ease;
14373
+ }
14374
+ .squisq-mermaid-svg > div:first-child > svg {
14375
+ display: block;
14376
+ width: 100% !important;
14377
+ height: auto !important;
14378
+ max-width: none !important;
14379
+ margin: 0 auto;
14380
+ }
14381
+ .squisq-mermaid-svg g.node {
14090
14382
  cursor: pointer;
14091
14383
  }
14092
- .squisq-tree-btn:hover {
14093
- border-color: var(--squisq-text-muted, #94a3b8);
14384
+ .squisq-mermaid-svg g.node:focus-visible {
14385
+ outline: none;
14386
+ filter: drop-shadow(0 0 4px #4f46e5);
14094
14387
  }
14095
- .squisq-tree-outline .squisq-tree-rows {
14096
- list-style: none;
14097
- margin: 0;
14098
- padding: 0;
14388
+ .squisq-mermaid-svg g.squisq-mermaid-node-selected {
14389
+ filter: drop-shadow(0 0 5px #4f46e5);
14099
14390
  }
14100
- .squisq-tree-rows .squisq-tree-rows {
14101
- border-left: 1px solid var(--squisq-border, #e2e8f0);
14102
- margin-left: 8px;
14391
+ .squisq-mermaid-svg g.squisq-mermaid-connect-source {
14392
+ filter: drop-shadow(0 0 6px #0d9488);
14103
14393
  }
14104
- .squisq-tree-item {
14105
- position: relative;
14394
+ .squisq-mermaid-svg .edgePath,
14395
+ .squisq-mermaid-svg path.flowchart-link,
14396
+ .squisq-mermaid-svg .edgeLabel {
14397
+ cursor: pointer;
14106
14398
  }
14107
- .squisq-tree-row {
14399
+ .squisq-mermaid-svg path.squisq-mermaid-edge-hit-target {
14400
+ fill: none;
14401
+ stroke: rgba(0, 0, 0, 0.001);
14402
+ stroke-width: 14px;
14403
+ pointer-events: stroke;
14404
+ cursor: pointer;
14405
+ }
14406
+ .squisq-mermaid-svg .squisq-mermaid-edge-selected {
14407
+ filter: drop-shadow(0 0 3px #4f46e5);
14408
+ }
14409
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg {
14410
+ --squisq-mermaid-edge: #cbd5e1;
14411
+ --squisq-mermaid-edge-label-bg: rgba(15, 23, 42, 0.88);
14412
+ }
14413
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg :is(path.flowchart-link, .edgePath .path, .relationshipLine, .messageLine0, .messageLine1, .transition):not([style*="stroke:"]) {
14414
+ stroke: var(--squisq-mermaid-edge) !important;
14415
+ }
14416
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg :is(.marker, .arrowheadPath),
14417
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg marker :is(path, polygon) {
14418
+ stroke: var(--squisq-mermaid-edge) !important;
14419
+ }
14420
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg marker :is(path, polygon):not([fill=none]):not([style*="fill:none"]):not([style*="fill: none"]) {
14421
+ fill: var(--squisq-mermaid-edge) !important;
14422
+ }
14423
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg .edgeLabel,
14424
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg .edgeLabel :is(span, p) {
14425
+ color: var(--squisq-mermaid-edge) !important;
14426
+ }
14427
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg .edgeLabel p,
14428
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-svg .edgeLabel rect {
14429
+ background: var(--squisq-mermaid-edge-label-bg) !important;
14430
+ fill: var(--squisq-mermaid-edge-label-bg) !important;
14431
+ }
14432
+ .squisq-mermaid-selection-actions {
14433
+ position: absolute;
14434
+ z-index: 12;
14435
+ display: inline-flex;
14436
+ gap: 2px;
14437
+ padding: 3px;
14438
+ border: 1px solid var(--squisq-border, #cbd5e1);
14439
+ border-radius: 7px;
14440
+ background: var(--squisq-surface, #ffffff);
14441
+ box-shadow: 0 4px 14px rgba(15, 23, 42, 0.2);
14442
+ transform: translate(-50%, calc(-100% - 8px));
14443
+ }
14444
+ .squisq-mermaid-selection-actions[data-placement=below] {
14445
+ transform: translate(-50%, 8px);
14446
+ }
14447
+ .squisq-mermaid-inline-rename {
14448
+ position: absolute;
14449
+ z-index: 14;
14450
+ margin: 0;
14451
+ transform: translate(-50%, -50%);
14452
+ }
14453
+ .squisq-mermaid-inline-rename input {
14454
+ box-sizing: border-box;
14455
+ width: 100%;
14456
+ min-height: 36px;
14457
+ padding: 6px 10px;
14458
+ border: 2px solid var(--squisq-accent, #4f46e5);
14459
+ border-radius: 7px;
14460
+ outline: none;
14461
+ background: var(--squisq-surface, #ffffff);
14462
+ color: var(--squisq-text, #1e293b);
14463
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--squisq-accent, #4f46e5) 22%, transparent), 0 6px 18px rgba(15, 23, 42, 0.2);
14464
+ font: inherit;
14465
+ font-size: 16px;
14466
+ line-height: 1.3;
14467
+ text-align: center;
14468
+ }
14469
+ .squisq-mermaid-inline-rename input:invalid {
14470
+ border-color: #dc2626;
14471
+ }
14472
+ .squisq-mermaid-inline-rename span {
14473
+ position: absolute;
14474
+ top: calc(100% + 6px);
14475
+ left: 50%;
14476
+ padding: 3px 7px;
14477
+ border: 1px solid var(--squisq-border, #cbd5e1);
14478
+ border-radius: 5px;
14479
+ background: var(--squisq-surface, #ffffff);
14480
+ color: var(--squisq-text-muted, #64748b);
14481
+ box-shadow: 0 2px 8px rgba(15, 23, 42, 0.14);
14482
+ font-size: 11px;
14483
+ line-height: 1.2;
14484
+ white-space: nowrap;
14485
+ transform: translateX(-50%);
14486
+ pointer-events: none;
14487
+ }
14488
+ .squisq-mermaid-selection-actions button {
14489
+ width: 28px;
14490
+ height: 28px;
14491
+ padding: 0;
14492
+ border: 0;
14493
+ border-radius: 4px;
14494
+ background: transparent;
14495
+ color: var(--squisq-text, #1e293b);
14496
+ cursor: pointer;
14497
+ }
14498
+ .squisq-mermaid-selection-actions button:hover {
14499
+ background: var(--squisq-surface-hover, #f1f5f9);
14500
+ }
14501
+ .squisq-mermaid-selection-actions button[data-danger=true] {
14502
+ color: #b91c1c;
14503
+ }
14504
+ .squisq-mermaid-connect-hint {
14505
+ position: absolute;
14506
+ top: 10px;
14507
+ left: 50%;
14508
+ z-index: 11;
14509
+ padding: 6px 10px;
14510
+ border-radius: 999px;
14511
+ background: #312e81;
14512
+ color: #fff;
14513
+ font-size: 12px;
14514
+ transform: translateX(-50%);
14515
+ pointer-events: none;
14516
+ }
14517
+ .squisq-mermaid-shape-palette,
14518
+ .squisq-mermaid-direction-picker {
14519
+ position: absolute;
14520
+ top: calc(100% + 6px);
14521
+ left: 0;
14522
+ z-index: 40;
14523
+ display: flex;
14524
+ box-sizing: border-box;
14525
+ width: 360px;
14526
+ max-height: min(520px, 70vh);
14527
+ flex-direction: column;
14528
+ padding: 8px;
14529
+ border: 1px solid var(--squisq-border, #e2e8f0);
14530
+ border-radius: 8px;
14531
+ background: var(--squisq-surface, #ffffff);
14532
+ color: var(--squisq-text, #1e293b);
14533
+ box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
14534
+ }
14535
+ .squisq-mermaid-shape-search {
14536
+ box-sizing: border-box;
14537
+ width: 100%;
14538
+ margin-bottom: 6px;
14539
+ padding: 7px 8px;
14540
+ border: 1px solid var(--squisq-border, #cbd5e1);
14541
+ border-radius: 6px;
14542
+ background: var(--squisq-surface-subtle, #f8fafc);
14543
+ color: inherit;
14544
+ }
14545
+ .squisq-mermaid-shape-scroll {
14546
+ min-height: 0;
14547
+ flex: 1 1 auto;
14548
+ overflow-y: auto;
14549
+ overscroll-behavior: contain;
14550
+ }
14551
+ .squisq-mermaid-shape-heading {
14552
+ margin: 9px 3px 4px;
14553
+ color: var(--squisq-text-muted, #64748b);
14554
+ font-size: 11px;
14555
+ font-weight: 700;
14556
+ letter-spacing: 0.04em;
14557
+ text-transform: uppercase;
14558
+ }
14559
+ .squisq-mermaid-shape-grid {
14560
+ display: grid;
14561
+ grid-template-columns: repeat(2, minmax(0, 1fr));
14562
+ gap: 3px;
14563
+ }
14564
+ .squisq-mermaid-shape-item {
14565
+ display: flex;
14566
+ align-items: center;
14567
+ gap: 6px;
14568
+ min-width: 0;
14569
+ padding: 5px;
14570
+ border: 1px solid transparent;
14571
+ border-radius: 6px;
14572
+ background: transparent;
14573
+ color: inherit;
14574
+ cursor: pointer;
14575
+ font-size: 12px;
14576
+ text-align: left;
14577
+ }
14578
+ .squisq-mermaid-shape-item svg {
14579
+ width: 34px;
14580
+ height: 24px;
14581
+ flex: 0 0 34px;
14582
+ }
14583
+ .squisq-mermaid-shape-item span {
14584
+ overflow: hidden;
14585
+ text-overflow: ellipsis;
14586
+ white-space: nowrap;
14587
+ }
14588
+ .squisq-mermaid-shape-item:hover,
14589
+ .squisq-mermaid-shape-item--selected {
14590
+ border-color: #a5b4fc;
14591
+ background: #eef2ff;
14592
+ color: #3730a3;
14593
+ }
14594
+ .squisq-mermaid-direction-picker {
14595
+ display: grid;
14596
+ grid-template-columns: repeat(2, 1fr);
14597
+ gap: 7px;
14598
+ width: min(344px, calc(100vw - 24px));
14599
+ padding: 10px;
14600
+ overflow: auto;
14601
+ overscroll-behavior: contain;
14602
+ }
14603
+ .squisq-mermaid-direction-heading {
14604
+ display: flex;
14605
+ grid-column: 1 / -1;
14606
+ flex-direction: column;
14607
+ gap: 2px;
14608
+ padding: 1px 3px 5px;
14609
+ }
14610
+ .squisq-mermaid-direction-heading strong {
14611
+ font-size: 13px;
14612
+ }
14613
+ .squisq-mermaid-direction-heading span {
14614
+ color: var(--squisq-text-muted, #64748b);
14615
+ font-size: 11px;
14616
+ }
14617
+ .squisq-mermaid-direction-card {
14618
+ display: flex;
14619
+ min-width: 0;
14620
+ flex-direction: column;
14621
+ align-items: stretch;
14622
+ gap: 5px;
14623
+ padding: 7px;
14624
+ border: 1px solid var(--squisq-border, #cbd5e1);
14625
+ border-radius: 7px;
14626
+ background: transparent;
14627
+ color: inherit;
14628
+ cursor: pointer;
14629
+ font: inherit;
14630
+ text-align: left;
14631
+ }
14632
+ .squisq-mermaid-direction-card svg {
14633
+ width: 100%;
14634
+ height: 64px;
14635
+ border-radius: 5px;
14636
+ background: var(--squisq-surface-subtle, rgb(148 163 184 / 10%));
14637
+ color: var(--squisq-text, #334155);
14638
+ }
14639
+ .squisq-mermaid-direction-card svg rect,
14640
+ .squisq-mermaid-direction-card svg path {
14641
+ fill: none;
14642
+ stroke: currentcolor;
14643
+ stroke-width: 1.8;
14644
+ }
14645
+ .squisq-mermaid-direction-card svg polygon,
14646
+ .squisq-mermaid-direction-card svg text {
14647
+ fill: currentcolor;
14648
+ }
14649
+ .squisq-mermaid-direction-card svg text {
14650
+ font-size: 9px;
14651
+ text-anchor: middle;
14652
+ }
14653
+ .squisq-mermaid-direction-copy {
14654
+ display: flex;
14655
+ min-width: 0;
14656
+ flex-direction: column;
14657
+ gap: 1px;
14658
+ }
14659
+ .squisq-mermaid-direction-copy strong {
14660
+ overflow: hidden;
14661
+ font-size: 12px;
14662
+ text-overflow: ellipsis;
14663
+ white-space: nowrap;
14664
+ }
14665
+ .squisq-mermaid-direction-copy small {
14666
+ color: var(--squisq-text-muted, #64748b);
14667
+ font-size: 10px;
14668
+ }
14669
+ .squisq-mermaid-direction-card:hover,
14670
+ .squisq-mermaid-direction-card[aria-pressed=true] {
14671
+ border-color: #818cf8;
14672
+ background: #eef2ff;
14673
+ color: #3730a3;
14674
+ }
14675
+ .squisq-mermaid-direction-card:hover svg,
14676
+ .squisq-mermaid-direction-card[aria-pressed=true] svg {
14677
+ color: currentcolor;
14678
+ }
14679
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-direction-card svg {
14680
+ color: #cbd5e1;
14681
+ }
14682
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-connect-hint,
14683
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-shape-item:hover,
14684
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-shape-item--selected,
14685
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-direction-card:hover,
14686
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-direction-card[aria-pressed=true] {
14687
+ border-color: #6366f1;
14688
+ background: #312e81;
14689
+ color: #eef2ff;
14690
+ }
14691
+ .squisq-mermaid-edit-notice {
14692
+ margin-top: 6px;
14693
+ padding: 7px 9px;
14694
+ border: 1px solid #fbbf24;
14695
+ border-radius: 6px;
14696
+ background: #fffbeb;
14697
+ color: #92400e;
14698
+ font-size: 12px;
14699
+ }
14700
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-edit-notice {
14701
+ border-color: #92400e;
14702
+ background: #451a03;
14703
+ color: #fde68a;
14704
+ }
14705
+ .squisq-mermaid-status,
14706
+ .squisq-mermaid-error {
14707
+ display: flex;
14708
+ min-height: 180px;
14709
+ align-items: center;
14710
+ justify-content: center;
14711
+ color: var(--squisq-text-muted, #64748b);
14712
+ text-align: center;
14713
+ }
14714
+ .squisq-mermaid-error {
14715
+ box-sizing: border-box;
14716
+ flex-direction: column;
14717
+ gap: 8px;
14718
+ align-items: flex-start;
14719
+ justify-content: flex-start;
14720
+ padding: 16px;
14721
+ border: 1px solid #fca5a5;
14722
+ border-radius: 8px;
14723
+ background: #fef2f2;
14724
+ color: #991b1b;
14725
+ text-align: left;
14726
+ }
14727
+ .squisq-mermaid-error pre {
14728
+ width: 100%;
14729
+ max-height: 160px;
14730
+ overflow: auto;
14731
+ margin: 0;
14732
+ padding: 8px;
14733
+ white-space: pre-wrap;
14734
+ background: transparent;
14735
+ color: inherit;
14736
+ font-size: 12px;
14737
+ }
14738
+ .squisq-editor-shell[data-theme=dark] .squisq-mermaid-error {
14739
+ border-color: #7f1d1d;
14740
+ background: #450a0a;
14741
+ color: #fecaca;
14742
+ }
14743
+
14744
+ /* src/styles/code-snippet.css */
14745
+ .squisq-wysiwyg-editor pre.squisq-code-snippet-fence-hidden {
14746
+ display: none;
14747
+ }
14748
+ .squisq-code-snippet-widget-host {
14749
+ margin: 0.75rem 0 1.25rem;
14750
+ }
14751
+ .squisq-code-snippet-shell {
14752
+ box-sizing: border-box;
14753
+ display: flex;
14754
+ width: 100%;
14755
+ height: 240px;
14756
+ min-height: 128px;
14757
+ max-height: 70vh;
14758
+ flex-direction: column;
14759
+ overflow: hidden;
14760
+ resize: vertical;
14761
+ border: 1px solid var(--squisq-border, #d1d5db);
14762
+ border-radius: 8px;
14763
+ background: var(--squisq-surface, #ffffff);
14764
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
14765
+ }
14766
+ .squisq-code-snippet-header {
14767
+ box-sizing: border-box;
14768
+ display: flex;
14769
+ min-height: 34px;
14770
+ align-items: center;
14771
+ justify-content: space-between;
14772
+ gap: 12px;
14773
+ padding: 0 10px;
14774
+ border-bottom: 1px solid var(--squisq-border, #d1d5db);
14775
+ background: var(--squisq-surface-muted, #f8fafc);
14776
+ color: var(--squisq-text-muted, #64748b);
14777
+ font-family: var(--squisq-ux-font, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
14778
+ font-size: 12px;
14779
+ user-select: none;
14780
+ }
14781
+ .squisq-code-snippet-title {
14782
+ display: inline-flex;
14783
+ min-width: 0;
14784
+ align-items: center;
14785
+ gap: 7px;
14786
+ color: var(--squisq-text, #334155);
14787
+ font-weight: 600;
14788
+ }
14789
+ .squisq-code-snippet-header code {
14790
+ overflow: hidden;
14791
+ color: inherit;
14792
+ font-family:
14793
+ ui-monospace,
14794
+ SFMono-Regular,
14795
+ Menlo,
14796
+ Consolas,
14797
+ "Liberation Mono",
14798
+ monospace;
14799
+ text-overflow: ellipsis;
14800
+ white-space: nowrap;
14801
+ }
14802
+ .squisq-code-snippet-editor {
14803
+ position: relative;
14804
+ min-height: 0;
14805
+ flex: 1;
14806
+ overflow: hidden;
14807
+ }
14808
+ .squisq-code-snippet-loading {
14809
+ display: flex;
14810
+ width: 100%;
14811
+ height: 100%;
14812
+ align-items: center;
14813
+ justify-content: center;
14814
+ color: var(--squisq-text-muted, #64748b);
14815
+ font-family: var(--squisq-ux-font, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
14816
+ font-size: 12px;
14817
+ }
14818
+
14819
+ /* src/styles/tree-view.css */
14820
+ .squisq-wysiwyg-editor pre.squisq-tree-fence-hidden {
14821
+ display: none;
14822
+ }
14823
+ .squisq-tree-widget-host {
14824
+ margin: 0.75rem 0 1.25rem;
14825
+ }
14826
+ .squisq-tree-outline {
14827
+ border: 1px solid var(--squisq-border, #e2e8f0);
14828
+ border-radius: 8px;
14829
+ padding: 8px 10px;
14830
+ background: var(--squisq-input-bg, #ffffff);
14831
+ color: var(--squisq-text, #1e293b);
14832
+ font-size: 14px;
14833
+ }
14834
+ .squisq-tree-toolbar {
14835
+ display: flex;
14836
+ gap: 6px;
14837
+ margin-bottom: 6px;
14838
+ }
14839
+ .squisq-tree-btn {
14840
+ display: inline-flex;
14841
+ align-items: center;
14842
+ gap: 5px;
14843
+ font-size: 12px;
14844
+ padding: 3px 8px;
14845
+ border: 1px solid var(--squisq-border, #e2e8f0);
14846
+ border-radius: 5px;
14847
+ background: var(--squisq-bg, #f8fafc);
14848
+ color: var(--squisq-text, #1e293b);
14849
+ cursor: pointer;
14850
+ }
14851
+ .squisq-tree-btn:hover {
14852
+ border-color: var(--squisq-text-muted, #94a3b8);
14853
+ }
14854
+ .squisq-tree-outline .squisq-tree-rows {
14855
+ list-style: none;
14856
+ margin: 0;
14857
+ padding: 0;
14858
+ }
14859
+ .squisq-tree-rows .squisq-tree-rows {
14860
+ border-left: 1px solid var(--squisq-border, #e2e8f0);
14861
+ margin-left: 8px;
14862
+ }
14863
+ .squisq-tree-item {
14864
+ position: relative;
14865
+ }
14866
+ .squisq-tree-row {
14108
14867
  position: relative;
14109
14868
  display: flex;
14110
14869
  align-items: center;
@@ -14919,6 +15678,16 @@ button.squisq-ascii-timeline-track-name:focus-visible {
14919
15678
  background: #f1f5f9;
14920
15679
  border-color: #cbd5e1;
14921
15680
  }
15681
+ .squisq-scene-action--active,
15682
+ .squisq-scene-action--active:hover:not(:disabled) {
15683
+ background: #e0e7ff;
15684
+ border-color: #4f46e5;
15685
+ color: #4338ca;
15686
+ }
15687
+ .squisq-scene-action-popover-anchor {
15688
+ position: relative;
15689
+ display: inline-flex;
15690
+ }
14922
15691
  .squisq-scene-action:focus-visible {
14923
15692
  outline: 2px solid #6366f1;
14924
15693
  outline-offset: 1px;
@@ -14966,7 +15735,9 @@ button.squisq-ascii-timeline-track-name:focus-visible {
14966
15735
  color: #f8fafc;
14967
15736
  }
14968
15737
  .squisq-editor-shell[data-theme=dark] .squisq-scene-tool--active,
14969
- .squisq-editor-shell[data-theme=dark] .squisq-scene-tool--active:hover {
15738
+ .squisq-editor-shell[data-theme=dark] .squisq-scene-tool--active:hover,
15739
+ .squisq-editor-shell[data-theme=dark] .squisq-scene-action--active,
15740
+ .squisq-editor-shell[data-theme=dark] .squisq-scene-action--active:hover:not(:disabled) {
14970
15741
  background: #312e81;
14971
15742
  border-color: #818cf8;
14972
15743
  color: #f8fafc;
@@ -14989,7 +15760,8 @@ button.squisq-ascii-timeline-track-name:focus-visible {
14989
15760
  padding: 12px;
14990
15761
  }
14991
15762
  .squisq-scene-block-max > .squisq-diagram-canvas,
14992
- .squisq-scene-block-max > .squisq-scene-stage {
15763
+ .squisq-scene-block-max > .squisq-scene-stage,
15764
+ .squisq-scene-block-max > .squisq-mermaid-canvas {
14993
15765
  flex: 1;
14994
15766
  min-width: 0;
14995
15767
  min-height: 0;
@@ -15027,6 +15799,11 @@ button.squisq-ascii-timeline-track-name:focus-visible {
15027
15799
  left: auto;
15028
15800
  right: calc(100% + 6px);
15029
15801
  }
15802
+ .squisq-scene-side-toolbar .squisq-scene-action-popover-anchor > [role=dialog] {
15803
+ top: 0;
15804
+ left: auto;
15805
+ right: calc(100% + 6px);
15806
+ }
15030
15807
  .squisq-scene-inline-toolbar {
15031
15808
  display: flex;
15032
15809
  margin-bottom: 8px;
@@ -15037,6 +15814,59 @@ button.squisq-ascii-timeline-track-name:focus-visible {
15037
15814
  width: 100%;
15038
15815
  margin: 0;
15039
15816
  }
15817
+ .squisq-scene-view-controls {
15818
+ position: absolute;
15819
+ top: 8px;
15820
+ left: 8px;
15821
+ z-index: 10;
15822
+ display: inline-flex;
15823
+ align-items: center;
15824
+ overflow: hidden;
15825
+ border: 1px solid var(--squisq-border, #e2e8f0);
15826
+ border-radius: 6px;
15827
+ background: var(--squisq-surface, #ffffff);
15828
+ color: var(--squisq-text, #1e293b);
15829
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
15830
+ }
15831
+ .squisq-scene-view-controls button,
15832
+ .squisq-scene-view-scale {
15833
+ box-sizing: border-box;
15834
+ min-width: 32px;
15835
+ height: 32px;
15836
+ padding: 0 8px;
15837
+ border: 0;
15838
+ border-right: 1px solid var(--squisq-border, #e2e8f0);
15839
+ background: transparent;
15840
+ color: inherit;
15841
+ font: inherit;
15842
+ font-size: 12px;
15843
+ line-height: 32px;
15844
+ text-align: center;
15845
+ }
15846
+ .squisq-scene-view-controls button {
15847
+ cursor: pointer;
15848
+ }
15849
+ .squisq-scene-view-controls button:last-child {
15850
+ border-right: 0;
15851
+ }
15852
+ .squisq-scene-view-controls button:hover,
15853
+ .squisq-scene-view-fit[data-active=true] {
15854
+ background: var(--squisq-surface-hover, #f1f5f9);
15855
+ }
15856
+ .squisq-scene-view-fit[data-active=true] {
15857
+ color: #4338ca;
15858
+ font-weight: 600;
15859
+ }
15860
+ .squisq-editor-shell[data-theme=dark] .squisq-scene-view-controls {
15861
+ background: #111827;
15862
+ border-color: #475569;
15863
+ color: #e5e7eb;
15864
+ }
15865
+ .squisq-editor-shell[data-theme=dark] .squisq-scene-view-controls button:hover,
15866
+ .squisq-editor-shell[data-theme=dark] .squisq-scene-view-fit[data-active=true] {
15867
+ background: #312e81;
15868
+ color: #f8fafc;
15869
+ }
15040
15870
  .squisq-scene-maximize-btn {
15041
15871
  position: absolute;
15042
15872
  top: 8px;