flow-mindmap 0.4.0 → 0.4.1

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/dist/style.css CHANGED
@@ -1,4 +1,4 @@
1
- .zm-node-menu{position:fixed;z-index:40;min-width:168px;padding:4px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-shadow:0 8px 24px #0f172a24;display:flex;flex-direction:column;gap:2px;font-size:13px;color:#1e293b;-webkit-user-select:none;user-select:none}.zm-node-menu-item{display:flex;align-items:center;gap:8px;padding:6px 10px;border:none;background:transparent;color:inherit;font:inherit;text-align:left;border-radius:4px;cursor:pointer;width:100%;transition:background .1s}.zm-node-menu-item:hover:not(:disabled){background:#f1f5f9}.zm-node-menu-item:active:not(:disabled){background:#e2e8f0}.zm-node-menu-item:disabled{color:#94a3b8;cursor:not-allowed}.zm-node-menu-icon{display:inline-flex;align-items:center;justify-content:center;width:13px;height:13px;font-size:10px;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-weight:600;color:#64748b;flex-shrink:0}.zm-node-menu-icon-code{font-size:10px;letter-spacing:-1px}.zm-node-menu-icon-table{font-size:12px;font-family:inherit}.zm-canvas-menu{position:fixed;z-index:40;min-width:140px;padding:4px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-sizing:border-box;box-shadow:0 8px 24px #0f172a24;display:flex;flex-direction:column;gap:2px;font-size:13px;color:#1e293b;-webkit-user-select:none;user-select:none}.zm-canvas-menu-item{display:flex;align-items:center;gap:8px;padding:6px 10px;border:none;background:transparent;color:inherit;font:inherit;text-align:left;border-radius:4px;cursor:pointer;width:100%;box-sizing:border-box;transition:background .1s}.zm-canvas-menu-item:hover:not(:disabled){background:#f1f5f9}.zm-canvas-menu-item:active:not(:disabled){background:#e2e8f0}.zm-canvas-menu-item:disabled{color:#94a3b8;cursor:not-allowed}.zm-canvas-menu-item-has-submenu{position:relative;box-sizing:border-box}.zm-canvas-menu-item-has-submenu.is-open,.zm-canvas-menu-item-has-submenu:hover{background:#f1f5f9}.zm-canvas-menu-caret{margin-left:auto;color:#94a3b8;flex-shrink:0;display:inline-flex;align-items:center}.zm-canvas-submenu{position:fixed;z-index:41;min-width:160px;padding:4px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-sizing:border-box;box-shadow:0 8px 24px #0f172a24;display:flex;flex-direction:column;gap:2px;font-size:13px;color:#1e293b;-webkit-user-select:none;user-select:none;animation:zm-submenu-in .12s ease-out}@keyframes zm-submenu-in{0%{opacity:0;transform:translate(-4px)}to{opacity:1;transform:translate(0)}}pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
1
+ .zm-node-menu{position:fixed;z-index:40;min-width:168px;padding:4px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-shadow:0 8px 24px #0f172a24;display:flex;flex-direction:column;gap:2px;font-size:13px;color:#1e293b;-webkit-user-select:none;user-select:none}.zm-node-menu-item{display:flex;align-items:center;gap:8px;padding:6px 10px;border:none;background:transparent;color:inherit;font:inherit;text-align:left;border-radius:4px;cursor:pointer;width:100%;transition:background .1s}.zm-node-menu-item:hover:not(:disabled){background:#f1f5f9}.zm-node-menu-item:active:not(:disabled){background:#e2e8f0}.zm-node-menu-item:disabled{color:#94a3b8;cursor:not-allowed}.zm-node-menu-icon{display:inline-flex;align-items:center;justify-content:center;width:13px;height:13px;font-size:10px;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-weight:600;color:#64748b;flex-shrink:0}.zm-node-menu-icon-code{font-size:10px;letter-spacing:-1px}.zm-node-menu-icon-table{font-size:12px;font-family:inherit}.zm-canvas-menu{position:fixed;z-index:40;min-width:140px;padding:4px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-sizing:border-box;box-shadow:0 8px 24px #0f172a24;display:flex;flex-direction:column;gap:2px;font-size:13px;color:#1e293b;-webkit-user-select:none;user-select:none}.zm-canvas-menu-item{display:flex;align-items:center;gap:8px;padding:6px 10px;border:none;background:transparent;color:inherit;font:inherit;text-align:left;border-radius:4px;cursor:pointer;width:100%;box-sizing:border-box;transition:background .1s}.zm-canvas-menu-item:hover:not(:disabled){background:#f1f5f9}.zm-canvas-menu-item:active:not(:disabled){background:#e2e8f0}.zm-canvas-menu-item:disabled{color:#94a3b8;cursor:not-allowed}.zm-canvas-menu-item-has-submenu{position:relative;box-sizing:border-box}.zm-canvas-menu-item-has-submenu.is-open,.zm-canvas-menu-item-has-submenu:hover{background:#f1f5f9}.zm-canvas-menu-caret{margin-left:auto;color:#94a3b8;flex-shrink:0;display:inline-flex;align-items:center}.zm-canvas-submenu{position:fixed;z-index:41;min-width:160px;padding:4px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-sizing:border-box;box-shadow:0 8px 24px #0f172a24;display:flex;flex-direction:column;gap:2px;font-size:13px;color:#1e293b;-webkit-user-select:none;user-select:none;animation:zm-submenu-in .12s ease-out}@keyframes zm-submenu-in{0%{opacity:0;transform:translate(-4px)}to{opacity:1;transform:translate(0)}}.zm-mindmap{position:relative;width:100%;height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Microsoft YaHei,sans-serif;-webkit-user-select:none;user-select:none}.zm-canvas{position:absolute;top:0;right:0;bottom:0;left:0;cursor:grab}.zm-canvas:active{cursor:grabbing}.zm-world{position:absolute;left:0;top:0;transform-origin:0 0}.zm-svg-layer{position:absolute;pointer-events:none;overflow:visible}.zm-marquee{position:absolute;border:1px dashed #3b82f6;background:#3b82f614;pointer-events:none;z-index:5}.zm-svg{position:absolute;left:0;top:0;pointer-events:none;overflow:visible;shape-rendering:geometricPrecision}.zm-node{position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0 .8em;box-sizing:border-box;border-radius:8px;border:1px solid;line-height:1.2;cursor:default;transition:box-shadow .15s;box-shadow:0 1px 2px #0000000f;white-space:nowrap;z-index:1}.zm-node:hover{box-shadow:0 4px 12px #0000001a;z-index:2}.zm-node.is-root{font-weight:600}.zm-node.is-selected{outline:2px solid #3b82f6;outline-offset:2px;z-index:3}.zm-text{display:flex;align-items:center;justify-content:center;gap:4px;min-height:1.2em;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.zm-text-label{pointer-events:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;flex-shrink:1}.zm-input{border:none;outline:none;background:transparent;color:inherit;font:inherit;text-align:center;width:100%;min-width:40px}.zm-tooltip{position:absolute;max-width:240px;padding:6px 10px;background:#0f172af0;color:#f8fafc;font-size:12px;line-height:1.4;border-radius:6px;box-shadow:0 4px 14px #0000002e;pointer-events:none;z-index:1000;white-space:normal;word-break:break-word;transform:translate(-50%,-100%);animation:zm-tooltip-in .12s ease-out}.zm-tooltip.is-below{transform:translate(-50%)}.zm-tooltip:after{content:"";position:absolute;left:50%;top:100%;transform:translate(-50%);border:4px solid transparent;border-top-color:#0f172af0}.zm-tooltip.is-below:after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:#0f172af0}@keyframes zm-tooltip-in{0%{opacity:0;transform:translate(-50%,calc(-100% + 4px))}to{opacity:1;transform:translate(-50%,-100%)}}.zm-tooltip.is-below{animation-name:zm-tooltip-in-below}@keyframes zm-tooltip-in-below{0%{opacity:0;transform:translate(-50%,-4px)}to{opacity:1;transform:translate(-50%)}}.zm-rich{margin-top:6px;width:max-content;overflow:visible;font-size:.78em;line-height:1.35;text-align:left;background:#0000000a;border-radius:4px;padding:4px 6px;color:inherit}.zm-rich-above{margin:0 0 2px}.zm-rich-no-overflow{max-height:none;overflow:visible}.zm-rich-code{margin:0;padding:6px 8px;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.92em;white-space:pre-wrap;word-break:break-word;background:#ffffff8c;border:1px solid currentColor;border-radius:6px;box-shadow:0 1px 2px #0f172a14}.zm-rich-list{margin:0;padding-left:1.2em;list-style:disc}.zm-rich-list li{margin:1px 0}.zm-rich-table{width:100%;border-collapse:separate;border-spacing:0;font-size:.92em;background:#ffffff8c;border:1px solid currentColor;border-radius:6px;overflow:hidden;box-shadow:0 1px 2px #0f172a14}.zm-rich-table td{border-top:1px solid currentColor;border-right:1px solid currentColor;padding:3px 6px;opacity:.9}.zm-rich-table tr:last-child td{border-bottom:none}.zm-rich-table td:last-child{border-right:none}.zm-rich-table-sort{position:relative;background:#fff6;font-weight:600;text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none;padding:3px 6px;border-bottom:1px solid currentColor;border-right:1px solid currentColor;pointer-events:auto}.zm-rich-table-sort:last-child{border-right:none}.zm-rich-table-sort:hover{background:#ffffffa6}.zm-rich-table-sort.is-sorted{background:#ffffffb3}.zm-rich-sort-mark{position:absolute;right:4px;top:50%;transform:translateY(-50%);font-size:9px;color:#94a3b8}.zm-rich-table-sort.is-sorted .zm-rich-sort-mark{color:#1d4ed8}.zm-rich-edit{width:100%;min-height:90px;margin:0;padding:4px 6px;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.92em;line-height:1.4;color:inherit;background:#fff9;border:1px solid currentColor;border-radius:3px;outline:none;resize:vertical;white-space:pre;box-sizing:border-box}.zm-rich-edit:focus{border-color:#3b82f6;box-shadow:0 0 0 2px #3b82f626}.zm-rich-paragraph{white-space:pre-wrap;word-break:break-word}.zm-btn{position:absolute;width:18px;height:18px;border-radius:50%;border:none;background:#3b82f6;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:0;transition:opacity .15s,transform .15s;z-index:4}.zm-node:hover .zm-btn,.zm-node.is-selected .zm-btn{opacity:1}.zm-btn:hover{transform:scale(1.15)}.zm-collapse{right:-8px;top:50%;width:14px;height:14px;background:#fff;border:1.5px solid;transform:translateY(-50%);box-shadow:0 1px 3px #0f172a2e}.zm-collapse.is-on-left{right:auto;left:-8px}.zm-collapse:hover{transform:translateY(-50%) scale(1.15);background:#fff}.zm-collapse-badge{position:absolute;top:50%;transform:translateY(-50%);left:calc(100% + 8px);min-width:18px;height:18px;padding:0 5px;border-radius:5px;color:#fff;font-size:11px;font-weight:600;line-height:18px;text-align:center;box-shadow:0 1px 2px #00000026;cursor:pointer;-webkit-user-select:none;user-select:none;z-index:2;transition:filter .1s}.zm-collapse-badge.is-on-left{left:auto;right:calc(100% + 8px)}.zm-collapse-badge:hover{filter:brightness(.9)}.zm-node.has-image{flex-direction:column;padding:8px;gap:6px;white-space:normal}.zm-node-img{display:block;pointer-events:none;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;object-fit:contain;border-radius:4px}.zm-node-link,.zm-node-note-btn{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:currentColor;border-radius:3px;cursor:pointer;flex-shrink:0;text-decoration:none;opacity:.75;transition:opacity .1s,background .1s;pointer-events:auto}.zm-node-link:hover,.zm-node-note-btn:hover{opacity:1;background:#0f172a14}.zm-node-link svg,.zm-node-note-btn svg{display:block}.zm-img-resize-handle{position:absolute;right:-5px;bottom:-5px;width:10px;height:10px;background:#fff;border:1.5px solid #3b82f6;border-radius:2px;cursor:nwse-resize;z-index:4;box-shadow:0 1px 3px #0f172a33}.zm-node.is-resizing{cursor:nwse-resize!important}.zm-img-remove-btn{position:absolute;right:-5px;bottom:14px;width:14px;height:14px;background:#fff;border:1px solid #cbd5e1;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#64748b;padding:0;z-index:4;box-shadow:0 1px 2px #0f172a1f}.zm-img-remove-btn:hover{background:#fee2e2;color:#b91c1c;border-color:#fca5a5}.zm-order-badge{display:inline-block;margin-left:6px;padding:0 5px;font-size:10px;font-weight:600;line-height:16px;color:#475569;background:#e2e8f0;border-radius:3px;font-variant-numeric:tabular-nums;pointer-events:none;-webkit-user-select:none;user-select:none;vertical-align:middle}.zm-canvas-fab{position:absolute;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:#fff;border:1px solid #e2e8f0;border-radius:999px;box-shadow:0 2px 8px #0f172a14;color:#475569;cursor:pointer;z-index:11;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .18s ease,transform .18s ease,background .1s,color .1s}.zm-canvas-fab.is-visible{opacity:1;pointer-events:auto;transform:translateY(0)}.zm-canvas-fab:hover{background:#f1f5f9;color:#1e293b;box-shadow:0 4px 12px #0f172a1f}.zm-canvas-fab:active{transform:scale(.94)}.zm-canvas-fab-preview{top:16px;right:16px}.zm-canvas-fab-outline{top:16px;left:16px}.zm-toolbar{position:absolute;bottom:16px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:4px;padding:6px 10px;background:#fff;border:1px solid #e2e8f0;border-radius:999px;box-shadow:0 4px 12px #0000000f;z-index:10;transition:opacity .18s ease,transform .18s ease}.zm-toolbar.is-preview-only{opacity:0;pointer-events:none;transform:translate(-50%) translateY(8px)}.zm-toolbar.is-preview-only.is-hovered{opacity:1;pointer-events:auto;transform:translate(-50%) translateY(0)}.zm-tb-btn{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:transparent;border-radius:6px;cursor:pointer;color:#475569}.zm-tb-btn:hover{background:#f1f5f9;color:#1e293b}.zm-tb-btn img{filter:invert(20%) sepia(15%) saturate(500%) hue-rotate(180deg);transition:filter .1s}.zm-tb-btn:hover img{filter:invert(15%) sepia(30%) saturate(800%) hue-rotate(180deg)}.zm-tb-btn.active{background:var(--zm-tb-active, #fff7ed);color:var(--zm-tb-active-fg, #c2410c)}.zm-tb-divider{width:1px;height:18px;background:#e2e8f0;margin:0 4px}.zm-tb-tip{font-size:12px;color:#64748b;min-width:38px;text-align:center}.zm-outline-root{display:flex;flex-direction:column;height:100%}.zm-outline-actions{display:flex;justify-content:flex-end;padding:8px 10px 4px;flex-shrink:0}.zm-outline-action-btn{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;font-size:11px;font-family:inherit;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:5px;cursor:pointer;transition:all .1s}.zm-outline-action-btn:hover{background:#f1f5f9;color:#1e293b;border-color:#cbd5e1}.zm-outline-action-btn.is-success{background:#ecfdf5;color:#047857;border-color:#a7f3d0}.zm-outline{list-style:none;margin:0;padding:4px 0 8px;font-size:13px;overflow:auto;flex:1;min-height:0}.zm-outline-row{display:flex;align-items:center;gap:6px;padding-right:6px;padding-top:4px;padding-bottom:4px;cursor:grab;color:#334155;border-radius:4px;margin:0 6px;-webkit-user-select:none;user-select:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .1s;position:relative}.zm-outline-row:active{cursor:grabbing}.zm-outline-row:hover{background:#f1f5f9}.zm-outline-row.is-root{font-weight:600;color:#0f172a}.zm-outline-row.is-selected{background:#eff6ff;color:#1d4ed8}.zm-outline-row.is-selected .zm-outline-toggle,.zm-outline-row.is-selected .zm-outline-dot,.zm-outline-row.is-selected .zm-outline-row-copy,.zm-outline-row.is-selected .zm-outline-row-action{color:#1d4ed8}.zm-outline-row.is-drag-over-before:before,.zm-outline-row.is-drag-over-after:after{content:"";position:absolute;left:6px;right:6px;height:2px;background:#3b82f6;border-radius:1px;pointer-events:none}.zm-outline-row.is-drag-over-before:before{top:0}.zm-outline-row.is-drag-over-after:after{bottom:0}.zm-outline-row.is-drag-over-child{background:#dbeafe!important;outline:2px solid #3b82f6;outline-offset:-2px}.zm-outline-toggle{width:16px;height:16px;border:none;background:transparent;color:#94a3b8;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:3px;flex-shrink:0;padding:0}.zm-outline-toggle:hover{background:#e2e8f0;color:#475569}.zm-outline-dot{width:4px;height:4px;border-radius:50%;background:#cbd5e1;flex-shrink:0;margin:0 6px}.zm-outline-index{font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums;min-width:22px;flex-shrink:0;-webkit-user-select:none;user-select:none}.zm-outline-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.zm-outline-input{flex:1;font:inherit;font-size:13px;color:inherit;background:#fff;border:1px solid #3b82f6;border-radius:3px;padding:1px 4px;margin:-2px 0;outline:none}.zm-outline-row-action{width:20px;height:20px;border:1px solid transparent;background:transparent;color:#94a3b8;cursor:pointer;border-radius:4px;flex-shrink:0;padding:0;display:inline-flex;align-items:center;justify-content:center;opacity:0;transition:opacity .1s,background .1s,color .1s,border-color .1s}.zm-outline-row:hover .zm-outline-row-action,.zm-outline-row.is-selected .zm-outline-row-action{opacity:1}.zm-outline-row-action:hover{background:#e0e7ff;color:#4338ca;border-color:#c7d2fe}.zm-outline-row-action img{filter:invert(38%) sepia(94%) saturate(2417%) hue-rotate(229deg) brightness(91%) contrast(91%)}.zm-outline-row-copy{width:20px;height:20px;border:none;background:transparent;color:#94a3b8;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:3px;flex-shrink:0;padding:0;opacity:0;transition:opacity .1s,background .1s,color .1s}.zm-outline-row:hover .zm-outline-row-copy,.zm-outline-row.is-selected .zm-outline-row-copy{opacity:1}.zm-outline-row-copy:hover{background:#e2e8f0;color:#475569}.zm-outline-row-copy.is-success{opacity:1;color:#047857;background:#ecfdf5}.zm-drawer{display:flex;flex-direction:column;height:100%;background:#fff;border-right:1px solid #e2e8f0;overflow:hidden;flex-shrink:0}.zm-drawer-enter-active,.zm-drawer-leave-active{transition:width .22s ease,opacity .15s ease}.zm-drawer-enter-from,.zm-drawer-leave-to{width:0!important;opacity:0;border-right:none}.zm-drawer--right{border-right:none;border-left:1px solid #e2e8f0}.zm-drawer-header{display:flex;align-items:center;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9;flex-shrink:0}.zm-drawer-title{margin:0;flex:1;font-size:13px;font-weight:600;color:#1e293b;letter-spacing:.02em}.zm-drawer-close{width:24px;height:24px;border:none;background:transparent;color:#94a3b8;cursor:pointer;border-radius:4px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.zm-drawer-close:hover{background:#f1f5f9;color:#1e293b}.zm-drawer-body{flex:1;overflow:auto;min-height:0}.zm-jtv-root{font-family:SF Mono,Menlo,Consolas,monospace;font-size:12px;line-height:1.6;color:#334155}.zm-jtv-header{display:flex;align-items:center;gap:4px;cursor:pointer;border-radius:3px;padding-right:6px;-webkit-user-select:none;user-select:none}.zm-jtv-header:hover{background:#f1f5f9}.zm-jtv-toggle{display:inline-block;width:12px;text-align:center;font-size:9px;color:#94a3b8;flex-shrink:0}.zm-jtv-toggle.is-leaf{color:#cbd5e1}.zm-jtv-key{color:#1d4ed8;font-weight:500}.zm-jtv-colon{color:#94a3b8;margin-right:4px}.zm-jtv-size{color:#64748b;font-style:italic}.zm-jtv-bracket,.zm-jtv-brace{color:#94a3b8;font-weight:500;margin-left:4px}.zm-jtv-footer{color:#94a3b8;font-weight:500}.zm-jtv-leaf{display:flex;align-items:center;gap:4px;flex-wrap:wrap;padding-right:6px;border-radius:3px}.zm-jtv-leaf:hover{background:#f8fafc}.zm-jtv-value{word-break:break-all}.zm-jtv-string{color:#047857}.zm-jtv-number{color:#b45309}.zm-jtv-boolean{color:#7c3aed;font-weight:500}.zm-jtv-null,.zm-jtv-undefined{color:#94a3b8;font-style:italic}.zm-jtv-thumb-wrap{display:inline-flex;align-items:center;gap:4px;margin-left:6px;flex-shrink:0}.zm-jtv-thumb{max-width:48px;max-height:32px;border:1px solid #e2e8f0;border-radius:3px;background:#fff;object-fit:contain}.zm-jtv-thumb-link{font-size:10px;color:#3b82f6;text-decoration:none;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.zm-jtv-thumb-link:hover{text-decoration:underline}.zm-jtv-leaf mark,.zm-jtv-key mark{background:#fef08a;color:#422006;padding:0 1px;border-radius:2px}.zm-data-panel{display:flex;flex-direction:column;height:100%;background:#fff}.zm-data-header{display:flex;align-items:center;padding:8px 12px 6px;border-bottom:1px solid #f1f5f9;background:#f8fafc;flex-shrink:0}.zm-data-title{display:flex;align-items:baseline;gap:8px;flex:1;min-width:0}.zm-data-title-text{font-size:12px;font-weight:600;color:#1e293b;letter-spacing:.02em}.zm-data-title-meta{font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums}.zm-data-toolbar{display:flex;align-items:center;gap:4px;padding:6px 10px;border-bottom:1px solid #f1f5f9;background:#fff;flex-shrink:0;flex-wrap:wrap}.zm-data-btn{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;font-size:12px;font-family:inherit;color:#475569;background:#fff;border:1px solid #e2e8f0;border-radius:6px;cursor:pointer;transition:all .1s}.zm-data-btn:hover{background:#f1f5f9;color:#1e293b;border-color:#cbd5e1}.zm-data-btn.is-icon{padding:4px 8px}.zm-data-btn.is-active{background:#eff6ff;color:#1d4ed8;border-color:#bfdbfe}.zm-data-btn.is-success{background:#ecfdf5;color:#047857;border-color:#a7f3d0}.zm-data-btn.is-primary{background:#3b82f6;color:#fff;border-color:#3b82f6}.zm-data-btn.is-primary:hover{background:#2563eb;border-color:#2563eb;color:#fff}.zm-data-btn:disabled{opacity:.4;cursor:not-allowed}.zm-data-btn-label{font-size:11px}.zm-data-toolbar-spacer{flex:1;min-width:4px}.zm-data-search{display:flex;align-items:center;gap:4px;padding:3px 6px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;transition:all .1s;flex:0 1 160px;min-width:0}.zm-data-search:focus-within,.zm-data-search.is-active{background:#fff;border-color:#3b82f6}.zm-data-search svg{color:#94a3b8;flex-shrink:0}.zm-data-search input{flex:1;min-width:0;border:none;outline:none;background:transparent;font:inherit;font-size:11px;color:#1e293b;padding:0}.zm-data-search input::placeholder{color:#94a3b8}.zm-data-search-clear{border:none;background:transparent;color:#94a3b8;cursor:pointer;padding:0 2px;font-size:14px;line-height:1;border-radius:2px}.zm-data-search-clear:hover{background:#e2e8f0;color:#1e293b}.zm-data-paste{padding:8px 10px 10px;border-bottom:1px solid #f1f5f9;background:#f8fafc;flex-shrink:0}.zm-data-tabs{display:flex;gap:4px;margin-bottom:6px}.zm-data-tab{font:inherit;font-size:11px;padding:2px 8px;border:1px solid #e2e8f0;border-radius:4px;background:#fff;color:#475569;cursor:pointer;transition:all .1s}.zm-data-tab:hover{background:#f1f5f9}.zm-data-tab.is-active{background:#1e293b;border-color:#1e293b;color:#fff}.zm-data-paste textarea{width:100%;min-height:60px;max-height:160px;padding:6px 8px;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px;line-height:1.4;border:1px solid #e2e8f0;border-radius:4px;background:#fff;resize:vertical;box-sizing:border-box}.zm-data-paste textarea:focus{outline:none;border-color:#3b82f6}.zm-data-paste-actions{display:flex;gap:4px;margin-top:6px}.zm-data-error{margin-top:6px;font-size:11px;color:#dc2626}.zm-data-tree{flex:1;overflow:auto;padding:8px 4px 8px 6px;background:#fff}.zm-data-footer{padding:6px 12px;border-top:1px solid #f1f5f9;background:#f8fafc;font-size:10px;color:#94a3b8;line-height:1.5;flex-shrink:0}.zm-data-footer-hint code{font-family:SF Mono,Menlo,Consolas,monospace;font-size:10px;background:#fff;border:1px solid #e2e8f0;padding:0 3px;border-radius:3px;color:#475569;margin:0 1px}.zm-settings-panel[data-v-17ef65d1]{display:flex;flex-direction:column;gap:14px;padding:12px 12px 16px}.zm-settings-section[data-v-17ef65d1]{background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:12px}.zm-settings-section-title[data-v-17ef65d1]{margin:0 0 10px;font-size:12px;font-weight:600;color:#475569;text-transform:uppercase;letter-spacing:.04em;display:flex;align-items:baseline;gap:6px}.zm-settings-section-sub[data-v-17ef65d1]{font-size:11px;font-weight:500;color:#64748b;text-transform:none;letter-spacing:0;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.zm-settings-row[data-v-17ef65d1]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:6px 0;font-size:13px;color:#1e293b}.zm-settings-label[data-v-17ef65d1]{flex:1}.zm-settings-value-tag[data-v-17ef65d1]{font-size:11px;color:#64748b;background:#fff;border:1px solid #e2e8f0;border-radius:4px;padding:2px 6px;white-space:nowrap}.zm-settings-number[data-v-17ef65d1]{font-size:11px;color:#0f172a;background:#fff;border:1px solid #e2e8f0;border-radius:4px;padding:2px 6px;width:56px;text-align:right;-moz-appearance:textfield}.zm-settings-number[data-v-17ef65d1]::-webkit-outer-spin-button,.zm-settings-number[data-v-17ef65d1]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.zm-settings-number[data-v-17ef65d1]:focus{outline:none;border-color:#818cf8}.zm-settings-hint[data-v-17ef65d1]{margin:4px 0 0;font-size:11px;color:#94a3b8;line-height:1.5}.zm-slider[data-v-17ef65d1]{position:relative;height:20px;display:flex;align-items:center;margin:4px 0 8px}.zm-slider-track[data-v-17ef65d1]{position:absolute;top:8px;right:0;bottom:8px;left:0;background:#e2e8f0;border-radius:999px;pointer-events:none}.zm-slider input[type=range][data-v-17ef65d1]{position:relative;width:100%;margin:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;height:20px;cursor:pointer;z-index:1}.zm-slider input[type=range][data-v-17ef65d1]::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:#fff;border:2px solid #3b82f6;box-shadow:0 1px 3px #00000026;cursor:pointer}.zm-slider input[type=range][data-v-17ef65d1]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:#fff;border:2px solid #3b82f6;box-shadow:0 1px 3px #00000026;cursor:pointer}.zm-toggle[data-v-17ef65d1]{position:relative;width:36px;height:20px;border:none;background:#cbd5e1;border-radius:999px;padding:0;cursor:pointer;transition:background .15s;flex-shrink:0}.zm-toggle.is-on[data-v-17ef65d1]{background:#3b82f6}.zm-toggle-knob[data-v-17ef65d1]{position:absolute;top:2px;left:2px;width:16px;height:16px;background:#fff;border-radius:50%;box-shadow:0 1px 2px #00000026;transition:transform .15s}.zm-toggle.is-on .zm-toggle-knob[data-v-17ef65d1]{transform:translate(16px)}.zm-swatch-row[data-v-17ef65d1]{display:flex;flex-wrap:wrap;gap:4px;margin:4px 0 8px}.zm-swatch[data-v-17ef65d1]{width:22px;height:22px;border-radius:4px;border:1px solid #e2e8f0;cursor:pointer;padding:0;flex-shrink:0}.zm-swatch.is-reset[data-v-17ef65d1]{background:#fff;color:#94a3b8;font-size:12px;line-height:1}.zm-line-style-group[data-v-17ef65d1]{display:flex;gap:6px}.zm-line-style-btn[data-v-17ef65d1]{display:inline-flex;flex-direction:column;align-items:center;gap:2px;padding:4px 8px;background:#fff;border:1px solid #e2e8f0;border-radius:6px;cursor:pointer;color:#94a3b8;transition:all .12s;font-family:inherit;min-width:56px}.zm-line-style-btn[data-v-17ef65d1]:hover{border-color:#cbd5e1;color:#475569}.zm-line-style-btn.is-on[data-v-17ef65d1]{border-color:#3b82f6;background:#eff6ff;color:#3b82f6}.zm-line-style-label[data-v-17ef65d1]{font-size:11px;font-weight:500}.zm-settings-preview[data-v-17ef65d1]{margin-top:8px;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:6px 6px 4px}.zm-settings-preview svg[data-v-17ef65d1]{display:block}.zm-settings-preview-labels[data-v-17ef65d1]{display:flex;justify-content:space-between;font-size:10px;color:#94a3b8;margin-top:2px;padding:0 2px}.zm-data-paste-actions[data-v-17ef65d1]{display:flex;gap:6px;margin-top:6px}.zm-data-btn[data-v-17ef65d1]{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;font-size:12px;font-family:inherit;color:#475569;background:#fff;border:1px solid #e2e8f0;border-radius:6px;cursor:pointer;transition:all .1s}.zm-data-btn[data-v-17ef65d1]:hover{background:#f1f5f9;color:#1e293b;border-color:#cbd5e1}.zm-data-btn.is-primary[data-v-17ef65d1]{background:#3b82f6;color:#fff;border-color:#3b82f6}.zm-data-btn.is-primary[data-v-17ef65d1]:hover{background:#2563eb;border-color:#2563eb;color:#fff}.zm-settings-reset[data-v-17ef65d1]{width:100%;padding:6px 10px;font-size:12px;font-family:inherit;color:#475569;background:#fff;border:1px solid #e2e8f0;border-radius:6px;cursor:pointer;transition:all .1s}.zm-settings-reset[data-v-17ef65d1]:hover{background:#f1f5f9;color:#1e293b}.zm-palette-picker[data-v-17ef65d1]{margin:6px 0 8px}.zm-palette-picker-title[data-v-17ef65d1]{margin:6px 0;font-size:11px;font-weight:600;color:#475569;letter-spacing:.02em}.zm-palette-grid[data-v-17ef65d1]{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:6px}.zm-palette-card[data-v-17ef65d1]{display:flex;flex-direction:column;align-items:stretch;gap:6px;padding:6px 6px 8px;background:#fff;border:1px solid #e2e8f0;border-radius:6px;cursor:pointer;font-family:inherit;text-align:left;transition:all .12s;min-width:0}.zm-palette-card[data-v-17ef65d1]:hover{border-color:#cbd5e1;background:#f8fafc}.zm-palette-card.is-active[data-v-17ef65d1]{border-color:#3b82f6;box-shadow:0 0 0 2px #3b82f62e;background:#eff6ff}.zm-palette-card-name[data-v-17ef65d1]{font-size:11px;font-weight:500;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.zm-palette-card.is-active .zm-palette-card-name[data-v-17ef65d1]{color:#1d4ed8}.zm-palette-card-swatches[data-v-17ef65d1]{display:flex;gap:1px;height:8px;border-radius:3px;overflow:hidden}.zm-palette-card-swatch[data-v-17ef65d1]{flex:1;height:100%;min-width:0}.zm-palette-customs[data-v-17ef65d1]{margin-top:10px;display:flex;flex-direction:column;gap:8px}.zm-palette-custom[data-v-17ef65d1]{background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:8px;display:flex;flex-direction:column;gap:6px}.zm-palette-custom .zm-palette-card[data-v-17ef65d1]{border-style:dashed;background:#f8fafc}.zm-palette-textarea[data-v-17ef65d1]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:1.5;color:#0f172a;background:#f8fafc;border:1px solid #e2e8f0;border-radius:4px;padding:4px 6px;resize:vertical;min-height:32px;outline:none;transition:border-color .1s}.zm-palette-textarea[data-v-17ef65d1]:focus{border-color:#3b82f6;background:#fff}.zm-palette-custom-actions[data-v-17ef65d1]{display:flex;gap:6px}.zm-palette-add[data-v-17ef65d1]{margin-top:8px;width:100%;padding:6px 8px;font-size:12px;font-family:inherit;color:#475569;background:#fff;border:1px dashed #cbd5e1;border-radius:6px;cursor:pointer;transition:all .1s}.zm-palette-add[data-v-17ef65d1]:hover{background:#f1f5f9;color:#1e293b;border-color:#94a3b8}.zm-md-panel{display:flex;flex-direction:column;height:100%;background:#f8fafc}.zm-md-toolbar{display:flex;align-items:center;gap:6px;padding:8px 10px;border-bottom:1px solid #f1f5f9;background:#f8fafc;flex-shrink:0}.zm-md-spacer{flex:1}.zm-md-btn{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;font-size:12px;font-family:inherit;color:#475569;background:#fff;border:1px solid #e2e8f0;border-radius:6px;cursor:pointer;transition:all .1s;white-space:nowrap}.zm-md-btn:hover:not(:disabled){background:#f1f5f9;color:#1e293b;border-color:#cbd5e1}.zm-md-btn:disabled{opacity:.4;cursor:not-allowed}.zm-md-btn.is-primary{background:#3b82f6;color:#fff;border-color:#3b82f6}.zm-md-btn.is-primary:hover:not(:disabled){background:#2563eb;border-color:#2563eb;color:#fff}.zm-md-error{padding:6px 10px;font-size:11px;color:#dc2626;background:#fef2f2;border-bottom:1px solid #fee2e2;flex-shrink:0}.zm-md-split{flex:1;display:flex;flex-direction:column;min-height:0}.zm-md-edit,.zm-md-preview{display:flex;flex-direction:column;min-height:0;flex:1}.zm-md-pane-header{display:flex;align-items:center;gap:8px;padding:6px 10px;font-size:11px;font-weight:600;color:#475569;background:#f1f5f9;border-bottom:1px solid #e2e8f0;letter-spacing:.02em;flex-shrink:0}.zm-md-hint{margin-left:auto;font-weight:400;color:#94a3b8;font-size:10px}.zm-md-textarea{flex:1;width:100%;padding:10px 12px;font-family:SF Mono,Menlo,Consolas,monospace;font-size:12px;line-height:1.5;color:#1e293b;border:none;border-bottom:1px solid #e2e8f0;background:#fff;resize:none;outline:none;box-sizing:border-box}.zm-md-textarea:focus{background:#fafbfc}.zm-md-preview-body{flex:1;position:relative;min-height:0;background:#fff;border-bottom:1px solid #e2e8f0}.zm-md-footer{display:flex;justify-content:flex-end;padding:8px 10px;background:#f8fafc;border-top:1px solid #e2e8f0;flex-shrink:0}pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
2
2
  Theme: GitHub
3
3
  Description: Light theme as seen on github.com
4
4
  Author: github.com
@@ -7,4 +7,4 @@
7
7
 
8
8
  Outdated base version: https://github.com/primer/github-syntax-light
9
9
  Current colors taken from GitHub's CSS
10
- */.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}.zm-mindmap{position:relative;width:100%;height:100%;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Microsoft YaHei,sans-serif;-webkit-user-select:none;user-select:none}.zm-canvas{position:absolute;top:0;right:0;bottom:0;left:0;cursor:grab}.zm-canvas:active{cursor:grabbing}.zm-world{position:absolute;left:0;top:0;transform-origin:0 0}.zm-svg-layer{position:absolute;pointer-events:none;overflow:visible}.zm-marquee{position:absolute;border:1px dashed #3b82f6;background:#3b82f614;pointer-events:none;z-index:5}.zm-svg{position:absolute;left:0;top:0;pointer-events:none;overflow:visible;shape-rendering:geometricPrecision}.zm-node{position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0 .8em;box-sizing:border-box;border-radius:8px;border:1px solid;line-height:1.2;cursor:default;transition:box-shadow .15s;box-shadow:0 1px 2px #0000000f;white-space:nowrap;z-index:1}.zm-node:hover{box-shadow:0 4px 12px #0000001a;z-index:2}.zm-node.is-root{font-weight:600}.zm-node.is-selected{outline:2px solid #3b82f6;outline-offset:2px;z-index:3}.zm-text{display:flex;align-items:center;justify-content:center;gap:4px;min-height:1.2em;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.zm-text-label{pointer-events:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;flex-shrink:1}.zm-input{border:none;outline:none;background:transparent;color:inherit;font:inherit;text-align:center;width:100%;min-width:40px}.zm-rich{margin-top:6px;width:max-content;overflow:visible;font-size:.78em;line-height:1.35;text-align:left;background:#0000000a;border-radius:4px;padding:4px 6px;color:inherit}.zm-rich-above{margin:0 0 2px}.zm-rich-no-overflow{max-height:none;overflow:visible}.zm-rich-code{margin:0;padding:6px 8px;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.92em;white-space:pre-wrap;word-break:break-word;background:#ffffff8c;border:1px solid currentColor;border-radius:6px;box-shadow:0 1px 2px #0f172a14}.zm-rich-list{margin:0;padding-left:1.2em;list-style:disc}.zm-rich-list li{margin:1px 0}.zm-rich-table{width:100%;border-collapse:separate;border-spacing:0;font-size:.92em;background:#ffffff8c;border:1px solid currentColor;border-radius:6px;overflow:hidden;box-shadow:0 1px 2px #0f172a14}.zm-rich-table td{border-top:1px solid currentColor;border-right:1px solid currentColor;padding:3px 6px;opacity:.9}.zm-rich-table tr:last-child td{border-bottom:none}.zm-rich-table td:last-child{border-right:none}.zm-rich-table-sort{position:relative;background:#fff6;font-weight:600;text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none;padding:3px 6px;border-bottom:1px solid currentColor;border-right:1px solid currentColor;pointer-events:auto}.zm-rich-table-sort:last-child{border-right:none}.zm-rich-table-sort:hover{background:#ffffffa6}.zm-rich-table-sort.is-sorted{background:#ffffffb3}.zm-rich-sort-mark{position:absolute;right:4px;top:50%;transform:translateY(-50%);font-size:9px;color:#94a3b8}.zm-rich-table-sort.is-sorted .zm-rich-sort-mark{color:#1d4ed8}.zm-rich-edit{width:100%;min-height:90px;margin:0;padding:4px 6px;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.92em;line-height:1.4;color:inherit;background:#fff9;border:1px solid currentColor;border-radius:3px;outline:none;resize:vertical;white-space:pre;box-sizing:border-box}.zm-rich-edit:focus{border-color:#3b82f6;box-shadow:0 0 0 2px #3b82f626}.zm-rich-paragraph{white-space:pre-wrap;word-break:break-word}.zm-btn{position:absolute;width:18px;height:18px;border-radius:50%;border:none;background:#3b82f6;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:0;transition:opacity .15s,transform .15s;z-index:4}.zm-node:hover .zm-btn,.zm-node.is-selected .zm-btn{opacity:1}.zm-btn:hover{transform:scale(1.15)}.zm-collapse{right:-8px;top:50%;width:14px;height:14px;background:#fff;border:1.5px solid;transform:translateY(-50%);box-shadow:0 1px 3px #0f172a2e}.zm-collapse.is-on-left{right:auto;left:-8px}.zm-collapse:hover{transform:translateY(-50%) scale(1.15);background:#fff}.zm-collapse-badge{position:absolute;top:50%;transform:translateY(-50%);left:calc(100% + 8px);min-width:18px;height:18px;padding:0 5px;border-radius:5px;color:#fff;font-size:11px;font-weight:600;line-height:18px;text-align:center;box-shadow:0 1px 2px #00000026;cursor:pointer;-webkit-user-select:none;user-select:none;z-index:2;transition:filter .1s}.zm-collapse-badge.is-on-left{left:auto;right:calc(100% + 8px)}.zm-collapse-badge:hover{filter:brightness(.9)}.zm-node.has-image{flex-direction:column;padding:8px;gap:6px;white-space:normal}.zm-node-img{display:block;pointer-events:none;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;object-fit:contain;border-radius:4px}.zm-node-link,.zm-node-note-btn{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:currentColor;border-radius:3px;cursor:pointer;flex-shrink:0;text-decoration:none;opacity:.75;transition:opacity .1s,background .1s;pointer-events:auto}.zm-node-link:hover,.zm-node-note-btn:hover{opacity:1;background:#0f172a14}.zm-node-link svg,.zm-node-note-btn svg{display:block}.zm-img-resize-handle{position:absolute;right:-5px;bottom:-5px;width:10px;height:10px;background:#fff;border:1.5px solid #3b82f6;border-radius:2px;cursor:nwse-resize;z-index:4;box-shadow:0 1px 3px #0f172a33}.zm-node.is-resizing{cursor:nwse-resize!important}.zm-img-remove-btn{position:absolute;right:-5px;bottom:14px;width:14px;height:14px;background:#fff;border:1px solid #cbd5e1;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#64748b;padding:0;z-index:4;box-shadow:0 1px 2px #0f172a1f}.zm-img-remove-btn:hover{background:#fee2e2;color:#b91c1c;border-color:#fca5a5}.zm-order-badge{display:inline-block;margin-left:6px;padding:0 5px;font-size:10px;font-weight:600;line-height:16px;color:#475569;background:#e2e8f0;border-radius:3px;font-variant-numeric:tabular-nums;pointer-events:none;-webkit-user-select:none;user-select:none;vertical-align:middle}.zm-canvas-fab{position:absolute;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:#fff;border:1px solid #e2e8f0;border-radius:999px;box-shadow:0 2px 8px #0f172a14;color:#475569;cursor:pointer;z-index:11;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .18s ease,transform .18s ease,background .1s,color .1s}.zm-canvas-fab.is-visible{opacity:1;pointer-events:auto;transform:translateY(0)}.zm-canvas-fab:hover{background:#f1f5f9;color:#1e293b;box-shadow:0 4px 12px #0f172a1f}.zm-canvas-fab:active{transform:scale(.94)}.zm-canvas-fab-preview{top:16px;right:16px}.zm-canvas-fab-outline{top:16px;left:16px}.zm-toolbar{position:absolute;bottom:16px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:4px;padding:6px 10px;background:#fff;border:1px solid #e2e8f0;border-radius:999px;box-shadow:0 4px 12px #0000000f;z-index:10;transition:opacity .18s ease,transform .18s ease}.zm-toolbar.is-preview-only{opacity:0;pointer-events:none;transform:translate(-50%) translateY(8px)}.zm-toolbar.is-preview-only.is-hovered{opacity:1;pointer-events:auto;transform:translate(-50%) translateY(0)}.zm-tb-btn{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:transparent;border-radius:6px;cursor:pointer;color:#475569}.zm-tb-btn:hover{background:#f1f5f9;color:#1e293b}.zm-tb-btn img{filter:invert(20%) sepia(15%) saturate(500%) hue-rotate(180deg);transition:filter .1s}.zm-tb-btn:hover img{filter:invert(15%) sepia(30%) saturate(800%) hue-rotate(180deg)}.zm-tb-btn.active{background:var(--zm-tb-active, #fff7ed);color:var(--zm-tb-active-fg, #c2410c)}.zm-tb-divider{width:1px;height:18px;background:#e2e8f0;margin:0 4px}.zm-tb-tip{font-size:12px;color:#64748b;min-width:38px;text-align:center}.zm-outline-root{display:flex;flex-direction:column;height:100%}.zm-outline-actions{display:flex;justify-content:flex-end;padding:8px 10px 4px;flex-shrink:0}.zm-outline-action-btn{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;font-size:11px;font-family:inherit;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:5px;cursor:pointer;transition:all .1s}.zm-outline-action-btn:hover{background:#f1f5f9;color:#1e293b;border-color:#cbd5e1}.zm-outline-action-btn.is-success{background:#ecfdf5;color:#047857;border-color:#a7f3d0}.zm-outline{list-style:none;margin:0;padding:4px 0 8px;font-size:13px;overflow:auto;flex:1;min-height:0}.zm-outline-row{display:flex;align-items:center;gap:6px;padding-right:6px;padding-top:4px;padding-bottom:4px;cursor:grab;color:#334155;border-radius:4px;margin:0 6px;-webkit-user-select:none;user-select:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .1s;position:relative}.zm-outline-row:active{cursor:grabbing}.zm-outline-row:hover{background:#f1f5f9}.zm-outline-row.is-root{font-weight:600;color:#0f172a}.zm-outline-row.is-selected{background:#eff6ff;color:#1d4ed8}.zm-outline-row.is-selected .zm-outline-toggle,.zm-outline-row.is-selected .zm-outline-dot,.zm-outline-row.is-selected .zm-outline-row-copy,.zm-outline-row.is-selected .zm-outline-row-action{color:#1d4ed8}.zm-outline-row.is-drag-over-before:before,.zm-outline-row.is-drag-over-after:after{content:"";position:absolute;left:6px;right:6px;height:2px;background:#3b82f6;border-radius:1px;pointer-events:none}.zm-outline-row.is-drag-over-before:before{top:0}.zm-outline-row.is-drag-over-after:after{bottom:0}.zm-outline-row.is-drag-over-child{background:#dbeafe!important;outline:2px solid #3b82f6;outline-offset:-2px}.zm-outline-toggle{width:16px;height:16px;border:none;background:transparent;color:#94a3b8;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:3px;flex-shrink:0;padding:0}.zm-outline-toggle:hover{background:#e2e8f0;color:#475569}.zm-outline-dot{width:4px;height:4px;border-radius:50%;background:#cbd5e1;flex-shrink:0;margin:0 6px}.zm-outline-index{font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums;min-width:22px;flex-shrink:0;-webkit-user-select:none;user-select:none}.zm-outline-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.zm-outline-input{flex:1;font:inherit;font-size:13px;color:inherit;background:#fff;border:1px solid #3b82f6;border-radius:3px;padding:1px 4px;margin:-2px 0;outline:none}.zm-outline-row-action{width:20px;height:20px;border:1px solid transparent;background:transparent;color:#94a3b8;cursor:pointer;border-radius:4px;flex-shrink:0;padding:0;display:inline-flex;align-items:center;justify-content:center;opacity:0;transition:opacity .1s,background .1s,color .1s,border-color .1s}.zm-outline-row:hover .zm-outline-row-action,.zm-outline-row.is-selected .zm-outline-row-action{opacity:1}.zm-outline-row-action:hover{background:#e0e7ff;color:#4338ca;border-color:#c7d2fe}.zm-outline-row-action img{filter:invert(38%) sepia(94%) saturate(2417%) hue-rotate(229deg) brightness(91%) contrast(91%)}.zm-outline-row-copy{width:20px;height:20px;border:none;background:transparent;color:#94a3b8;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:3px;flex-shrink:0;padding:0;opacity:0;transition:opacity .1s,background .1s,color .1s}.zm-outline-row:hover .zm-outline-row-copy,.zm-outline-row.is-selected .zm-outline-row-copy{opacity:1}.zm-outline-row-copy:hover{background:#e2e8f0;color:#475569}.zm-outline-row-copy.is-success{opacity:1;color:#047857;background:#ecfdf5}
10
+ */.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}.zm-note-panel{display:flex;flex-direction:column;height:100%;padding:12px 12px 16px;gap:10px;background:#f8fafc}.zm-note-empty{padding:20px 12px;color:#64748b;font-size:13px;line-height:1.6}.zm-note-empty p{margin:0 0 6px}.zm-note-hint{color:#94a3b8;font-size:12px}.zm-note-header{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:4px;flex-shrink:0}.zm-note-title-row{display:flex;align-items:baseline;gap:8px;min-width:0}.zm-note-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#94a3b8;flex-shrink:0}.zm-note-name{font-size:13px;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}.zm-note-meta{font-size:11px;color:#94a3b8}.zm-note-scroll{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:10px;padding-right:2px}.zm-note-section{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:8px}.zm-note-section-head{display:flex;align-items:center;gap:8px;min-width:0}.zm-note-section-title{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#64748b;flex:1;min-width:0}.zm-note-section-hint{font-size:10px;color:#94a3b8}.zm-note-section-tag{font-size:10px;font-family:JetBrains Mono,Fira Code,Consolas,monospace;color:#475569;background:#f1f5f9;border:1px solid #e2e8f0;border-radius:4px;padding:1px 6px;line-height:1.4}.zm-note-section-actions{display:flex;justify-content:flex-end}.zm-note-textarea{width:100%;min-height:120px;padding:10px 12px;font:inherit;font-size:13px;line-height:20px;color:#1e293b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;resize:none;outline:none;box-sizing:border-box;font-family:inherit;overflow:hidden}.zm-note-textarea:focus{border-color:#3b82f6;background:#fff;box-shadow:0 0 0 3px #3b82f61f}.zm-note-textarea:disabled{background:#f8fafc;color:#94a3b8;cursor:not-allowed}.zm-note-textarea::placeholder{color:#94a3b8;white-space:pre-line}.zm-note-split{display:flex;flex-direction:column;gap:6px}.zm-note-preview-toggle{font:inherit;font-size:10px;color:#1d4ed8;background:transparent;border:1px solid #bfdbfe;border-radius:999px;padding:1px 8px;cursor:pointer;transition:all .1s;flex-shrink:0}.zm-note-preview-toggle:hover{background:#eff6ff;border-color:#93c5fd}.zm-note-preview{background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;padding:8px 12px;max-height:240px;overflow:auto;font-size:13px;line-height:1.6;color:#1e293b}.zm-note-preview-hint{color:#94a3b8;font-size:12px;font-style:italic}.zm-note-preview-body h1,.zm-note-preview-body h2,.zm-note-preview-body h3{margin:8px 0 4px;font-weight:600;color:#0f172a}.zm-note-preview-body h1{font-size:16px}.zm-note-preview-body h2{font-size:14px}.zm-note-preview-body h3{font-size:13px}.zm-note-preview-body h4,.zm-note-preview-body h5,.zm-note-preview-body h6{margin:6px 0 4px;font-size:12px;font-weight:600;color:#334155}.zm-note-preview-body p{margin:0 0 6px}.zm-note-preview-body p:last-child{margin-bottom:0}.zm-note-preview-body ul,.zm-note-preview-body ol{margin:0 0 6px;padding-left:20px}.zm-note-preview-body li{margin:0 0 2px}.zm-note-preview-body blockquote{margin:0 0 6px;padding:4px 10px;border-left:3px solid #cbd5e1;color:#475569;background:#f1f5f9}.zm-note-preview-body code{font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:12px;background:#f1f5f9;padding:1px 4px;border-radius:3px;color:#be185d}.zm-note-preview-body pre{margin:0 0 6px;padding:8px 10px;background:#f1f5f9;border:1px solid #e2e8f0;border-radius:6px;overflow:auto}.zm-note-preview-body pre code{background:transparent;padding:0;color:inherit;font-size:12px;line-height:1.55}.zm-note-preview-body a{color:#1d4ed8;text-decoration:underline;text-decoration-color:#bfdbfe}.zm-note-preview-body a:hover{text-decoration-color:#1d4ed8}.zm-note-preview-body table{border-collapse:collapse;margin:0 0 6px;font-size:12px}.zm-note-preview-body th,.zm-note-preview-body td{border:1px solid #e2e8f0;padding:4px 8px;text-align:left}.zm-note-preview-body th{background:#f1f5f9;font-weight:600}.zm-note-preview-body hr{border:none;border-top:1px solid #e2e8f0;margin:8px 0}.zm-note-preview-body img{max-width:100%;max-height:200px;border-radius:4px;display:block}.zm-note-input{width:100%;padding:7px 10px;font:inherit;font-size:12px;line-height:1.5;color:#1e293b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;outline:none;box-sizing:border-box;font-family:inherit}.zm-note-input:focus{border-color:#3b82f6;background:#fff;box-shadow:0 0 0 3px #3b82f61f}.zm-note-input:disabled{background:#f8fafc;color:#94a3b8;cursor:not-allowed}.zm-note-input-code{font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;min-height:80px;resize:none;white-space:pre;line-height:20px;overflow:hidden}.zm-note-add-row{display:flex;flex-wrap:wrap;gap:6px;padding:2px 2px 0}.zm-note-add-chip{font:inherit;font-size:11px;color:#64748b;background:#fff;border:1px dashed #cbd5e1;border-radius:999px;padding:3px 10px;cursor:pointer;transition:all .1s}.zm-note-add-chip:hover{color:#1d4ed8;border-color:#93c5fd;background:#eff6ff}.zm-note-link-chip{display:inline-block;max-width:100%;padding:6px 10px;background:#eff6ff;border:1px solid #bfdbfe;border-radius:6px;color:#1d4ed8;font-size:12px;text-decoration:none;word-break:break-all;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;transition:background .1s}.zm-note-link-chip:hover{background:#dbeafe}.zm-note-image{display:block;max-width:100%;max-height:240px;object-fit:contain;border-radius:6px;background:#f1f5f9;margin:0 auto}.zm-note-code{margin:0;padding:10px 12px;background:#f1f5f9;color:#24292e;border:1px solid #e2e8f0;border-radius:8px;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:12px;line-height:1.55;white-space:pre-wrap;word-break:break-word;max-height:320px;overflow:auto;box-shadow:0 1px 3px #0f172a14}.zm-note-code code{font:inherit;color:inherit;background:transparent;padding:0}.zm-note-table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px;color:#1e293b;table-layout:auto;background:#fffbeb;border:1px solid #fcd34d;border-radius:8px;overflow:hidden;box-shadow:0 1px 3px #92400e14}.zm-note-table td{border-top:1px solid #fde68a;border-right:1px solid #fde68a;padding:6px 10px;text-align:left;vertical-align:top;word-break:break-word;background:#fffbeb}.zm-note-table tr:last-child td{border-bottom:none}.zm-note-table td:last-child{border-right:none}.zm-note-table-sort{background:#fef3c7;font-weight:600;padding:6px 10px;border-bottom:1px solid #fcd34d;border-right:1px solid #fde68a;text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none;position:relative}.zm-note-table-sort:last-child{border-right:none}.zm-note-table-sort:hover{background:#fde68a}.zm-note-table-sort.is-sorted{background:#fde68a;color:#92400e}.zm-note-table-sort-mark{position:absolute;right:6px;top:50%;transform:translateY(-50%);font-size:10px;color:#94a3b8}.zm-note-table-sort.is-sorted .zm-note-table-sort-mark{color:#1d4ed8}.zm-note-action-btn{padding:4px 10px;font-size:12px;font-family:inherit;color:#fff;background:#3b82f6;border:1px solid #3b82f6;border-radius:6px;cursor:pointer;transition:all .1s}.zm-note-action-btn.is-danger{color:#b91c1c;background:#fff;border-color:#fca5a5}.zm-note-action-btn.is-danger:hover{background:#fee2e2;border-color:#f87171}.zm-app{display:flex;width:100%;height:100%;background:#f8fafc;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Microsoft YaHei,sans-serif;font-size:14px;color:#1e293b;overflow:hidden}.zm-app-main{flex:1;display:flex;flex-direction:column;min-width:0}.zm-app-toolbar{display:flex;align-items:center;gap:6px;padding:6px 10px;background:#fff;border-bottom:1px solid #e2e8f0;flex-shrink:0}.zm-app-icon-btn{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:1px solid #e2e8f0;background:#fff;border-radius:6px;cursor:pointer;color:#475569}.zm-app-icon-btn:hover{background:#f1f5f9;color:#1e293b}.zm-app-spacer{flex:1}.zm-app-tip{font-size:12px;color:#64748b}.zm-app-icon-btn.is-on{background:#e0e7ff;color:#4338ca}.zm-app-preview-exit{position:absolute;top:12px;right:12px;z-index:10;width:32px;height:32px;border:1px solid #e2e8f0;background:#fff;color:#475569;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 2px 8px #0f172a14;transition:background .1s,color .1s,transform .1s}.zm-app-preview-exit:hover{background:#f1f5f9;color:#0f172a;transform:scale(1.05)}.zm-app-canvas{flex:1;position:relative;min-height:0}.zm-settings-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;background:#0f172a26;z-index:49;pointer-events:none}.zm-settings-popover{position:absolute;top:50px;right:16px;width:320px;max-height:calc(100% - 64px);z-index:50;display:flex;flex-direction:column}.zm-settings-popover>*{pointer-events:auto}.zm-settings-popover .zm-settings-popover-header,.zm-settings-popover .zm-settings-panel{background:#fff;border:1px solid #e2e8f0;border-radius:10px;box-shadow:0 8px 28px #0f172a1f;overflow:auto}.zm-settings-popover .zm-settings-popover-header{display:flex;align-items:center;padding:8px 10px 8px 14px;border-bottom:1px solid #f1f5f9;flex-shrink:0}.zm-settings-popover-title{flex:1;font-size:13px;font-weight:600;color:#1e293b;letter-spacing:.02em}.zm-settings-close{width:24px;height:24px;display:flex;align-items:center;justify-content:center;border:none;background:transparent;color:#94a3b8;border-radius:4px;cursor:pointer}.zm-settings-close:hover{background:#f1f5f9;color:#1e293b}
package/dist/tree.d.ts ADDED
@@ -0,0 +1,96 @@
1
+ import type { MindMapNode } from './types';
2
+ export declare function uid(): string;
3
+ export declare function clone<T>(o: T): T;
4
+ export declare function findNode(root: MindMapNode, id: string): MindMapNode | null;
5
+ export declare function findParent(root: MindMapNode, id: string, parent?: MindMapNode | null): MindMapNode | null;
6
+ export declare function removeNode(root: MindMapNode, id: string): boolean;
7
+ /** Replace the text of a node by id. Returns true on success, false
8
+ * if the node was not found. No-op on an empty / same string. */
9
+ export declare function setNodeText(root: MindMapNode, id: string, text: string): boolean;
10
+ /** Position relative to a target node when moving a sibling. */
11
+ export type MovePosition = 'before' | 'after' | 'child';
12
+ /** Move a node to a new location in the tree.
13
+ * - 'before' / 'after': insert as a sibling of the target at that slot
14
+ * (target's parent's children array).
15
+ * - 'child': insert as the last child of the target.
16
+ * No-op (returns false) if src === root, or if the move would
17
+ * create a cycle (i.e. the target lives inside the src subtree, or
18
+ * src is already in the target's desired position). */
19
+ export declare function moveNode(root: MindMapNode, srcId: string, targetId: string, position: MovePosition): boolean;
20
+ export declare function addChild(root: MindMapNode, parentId: string, text?: string): MindMapNode | null;
21
+ export declare function addSibling(root: MindMapNode, nodeId: string, text?: string): MindMapNode | null;
22
+ /**
23
+ * Insert a new sibling node BEFORE the given node (Shift+Enter in xmind).
24
+ * Returns the new node, or null if the target is the root.
25
+ */
26
+ export declare function addSiblingBefore(root: MindMapNode, nodeId: string, text?: string): MindMapNode | null;
27
+ /**
28
+ * Deep-clone a node (with all its descendants) and insert the copy as a
29
+ * sibling immediately after the original. New ids are generated so the
30
+ * result is a real duplicate. Returns the new node, or null if the
31
+ * target is the root.
32
+ */
33
+ export declare function duplicateNode(root: MindMapNode, nodeId: string): MindMapNode | null;
34
+ export declare function countDescendants(n: MindMapNode): number;
35
+ export declare const DEFAULT_NEW_NODE_TEXT = "\u65B0\u8282\u70B9";
36
+ /**
37
+ * Parse a Markdown string into a MindMapNode tree. Each heading
38
+ * becomes a node; its level sets the depth.
39
+ * - `# Title` → root text (overrides `rootText`)
40
+ * - `## Sub` → child of the previous #/##/... heading
41
+ * - bullet / paragraph text between headings → first child
42
+ * of the preceding heading (so a `# Topic\n- detail` tree
43
+ * gives one root node with one child).
44
+ *
45
+ * Inline fields parsed from a heading's body (in order, attached
46
+ * to the heading that precedes them):
47
+ * - `![alt](url)` → image
48
+ * - `[label](url)` → link (label becomes the node's text)
49
+ * - ` ```note ... ``` ` → note (the fence body becomes note.text)
50
+ *
51
+ * Empty input, or input with no `#` heading, returns a single
52
+ * root with the fallback text.
53
+ */
54
+ export declare function markdownToMindMap(md: string, rootText?: string): MindMapNode;
55
+ /**
56
+ * Round-trip-safe Markdown export of a MindMapNode tree. Each
57
+ * heading is emitted as `#…`, then any inline fields (link /
58
+ * image / note) in a fixed order so the same source produces
59
+ * byte-stable output across re-exports.
60
+ *
61
+ * The `note` field round-trips through a ` ```note ` fence so a
62
+ * user opening the export in any markdown editor sees a clearly
63
+ * labeled block. The link is emitted as a standard `[label](url)`
64
+ * with the node's text as the label — this keeps the export
65
+ * human-readable and lets `markdownToMindMap` re-attach the
66
+ * link to the right heading.
67
+ */
68
+ export declare function mindMapToMarkdown(n: MindMapNode, depth?: number): string;
69
+ /**
70
+ * Parse a whole markdown document into a MindMapNode tree where
71
+ * every block (heading, paragraph, list, code fence, table)
72
+ * becomes a node. Body blocks carry their original markdown
73
+ * payload in `node.richContent` so the renderer can show code,
74
+ * tables, lists, etc. inside the node box. Headings form the
75
+ * hierarchy; everything else is attached to the most recent
76
+ * heading as a child (or to the synthetic root if no heading
77
+ * has been seen yet).
78
+ *
79
+ * Unlike `markdownToMindMap`, this does NOT collapse body into
80
+ * a single child of the heading, and the depth is unbounded —
81
+ * a paragraph under `## Foo` becomes a child of `Foo`, and a
82
+ * paragraph that follows a list under the same heading becomes
83
+ * a sibling of that list, etc. This is the mode the user
84
+ * asked for: "every paragraph becomes a child, no depth limit".
85
+ *
86
+ * A document with no `#` heading still produces a valid tree —
87
+ * every block lands under the synthetic root.
88
+ */
89
+ export declare function markdownToRichMindMap(md: string, rootText?: string): MindMapNode;
90
+ /**
91
+ * Serialize a single node's rich body (if any) back to the
92
+ * original markdown it came from. Used by `mindMapToMarkdown`
93
+ * to round-trip a tree built by `markdownToRichMindMap`.
94
+ * Returns '' when the node has no rich body.
95
+ */
96
+ export declare function richBlockToMarkdown(n: MindMapNode): string;
@@ -0,0 +1,270 @@
1
+ export interface MindMapNode {
2
+ id: string;
3
+ text: string;
4
+ children: MindMapNode[];
5
+ collapsed?: boolean;
6
+ /**
7
+ * Reserved for the layout algorithm — do not set or read from
8
+ * your own code. After a drag, MindMap writes the dragged
9
+ * node's offset into the data tree so a subsequent layout with
10
+ * `preservePositions: true` can keep the node where the user
11
+ * put it. Cleared on the next data-mutating action (add,
12
+ * remove, edit, import) so unrelated re-layouts don't keep
13
+ * stale overrides around.
14
+ */
15
+ _x?: number;
16
+ _y?: number;
17
+ /**
18
+ * Optional embedded image shown above the node text. The
19
+ * image is stored as either a remote URL (preferred) or a
20
+ * data: URL (fallback for local-file uploads); width/height
21
+ * reflect the rendered size, which the user can resize via
22
+ * a drag handle. naturalW/naturalH preserve the source
23
+ * aspect ratio so a resize keeps the original proportions.
24
+ */
25
+ image?: MindMapImage;
26
+ /**
27
+ * Optional external link. When set, the node renders a
28
+ * small link icon next to its text; clicking the icon
29
+ * navigates to `url` in a new tab. No validation is
30
+ * performed at write time — the rendering layer is
31
+ * responsible for rejecting dangerous schemes (javascript:,
32
+ * data:, …) before following the link.
33
+ */
34
+ link?: {
35
+ url: string;
36
+ };
37
+ /**
38
+ * Optional free-form note. When set, the node renders a
39
+ * small note icon next to its text; clicking the icon
40
+ * expands an inline textarea below the node for editing,
41
+ * hovering the icon shows a tooltip preview. An empty
42
+ * `text` field is treated as "no note" by the UI.
43
+ */
44
+ note?: {
45
+ text: string;
46
+ };
47
+ /**
48
+ * Optional rich body. When set, the node renders the raw
49
+ * markdown payload in a small framed block under the title
50
+ * (code fences get monospace styling, lists get bullet
51
+ * markers, tables get a mini grid, paragraphs get plain
52
+ * text). Produced by `markdownToRichMindMap` so a whole
53
+ * markdown document can be previewed as a mindmap without
54
+ * losing its body content. The first line of `raw` is
55
+ * still available as `text` so the node always has a
56
+ * meaningful label.
57
+ */
58
+ richContent?: RichContent;
59
+ }
60
+ /**
61
+ * A node body that came from a markdown block. `raw` is the
62
+ * original markdown source for the block (preserved verbatim so
63
+ * `mindMapToMarkdown` can re-emit it byte-for-byte). `kind`
64
+ * tells the renderer which layout to use.
65
+ */
66
+ export interface RichContent {
67
+ kind: 'code' | 'list' | 'table' | 'paragraph';
68
+ /** Original markdown source. Always non-empty. */
69
+ raw: string;
70
+ /**
71
+ * Optional language tag for code blocks (the info string after
72
+ * the opening fence). `undefined` for non-code kinds.
73
+ */
74
+ lang?: string;
75
+ }
76
+ export interface MindMapImage {
77
+ /** Remote URL or data URL. Always a string — never undefined. */
78
+ src: string;
79
+ /** Source image intrinsic size, in px. Used to lock aspect
80
+ * ratio during a user-driven resize. */
81
+ naturalW: number;
82
+ naturalH: number;
83
+ /** Current rendered size, in px. Drag handle writes to these
84
+ * fields. Clamped to a sane range by the layout (≥24, ≤400). */
85
+ width: number;
86
+ height: number;
87
+ }
88
+ export interface MindMapOptions {
89
+ data: MindMapNode;
90
+ theme?: MindMapTheme;
91
+ }
92
+ export interface MindMapTheme {
93
+ rootBg?: string;
94
+ rootText?: string;
95
+ branchBg?: string;
96
+ branchText?: string;
97
+ lineColor?: string;
98
+ bgColor?: string;
99
+ fontSize?: number;
100
+ /** Stroke width of SVG connecting paths at the *parent-end* of the
101
+ * edge, in px. Default 2.2. */
102
+ lineWidthStart?: number;
103
+ /** Stroke width at the *child-end* of the edge, in px. Default 0.8. */
104
+ lineWidthEnd?: number;
105
+ /**
106
+ * When true, each top-level branch gets its own color (root stays
107
+ * neutral, every child[0] of root takes a different hue, and that
108
+ * hue propagates down the subtree). Default false.
109
+ */
110
+ rainbowBranch?: boolean;
111
+ }
112
+ export type LineStyle = 'curve' | 'straight';
113
+ export type LayoutMode = 'mindmap' | 'tree' | 'org';
114
+ /** Identifier for a branch palette — the id of a built-in (e.g.
115
+ * 'default', 'classic', 'vivid', 'dev', 'mint') or a user-defined
116
+ * custom palette. Strings rather than a string union so users
117
+ * can add their own ids without recompiling the type. */
118
+ export type BranchPaletteId = string;
119
+ /**
120
+ * A named 8-color palette cycled across top-level branches when
121
+ * `rainbowBranch` is on. Exposed in the public API so the library
122
+ * consumer can register their own scheme (e.g. a corporate brand
123
+ * palette) via `setBranchPalette` / `customPalettes`.
124
+ */
125
+ export interface BranchPalette {
126
+ id: BranchPaletteId;
127
+ name: string;
128
+ /** Hex colors cycled across top-level branches, in display order.
129
+ * When a palette has fewer than the number of branches, colors
130
+ * wrap around with modulo. */
131
+ colors: string[];
132
+ }
133
+ export interface MindMapSettings {
134
+ /** When the user adds a new node or finishes a drag, automatically
135
+ * snap the layout back to balanced mode. Default false. */
136
+ autoBalanceOnChange: boolean;
137
+ /** Stroke width of SVG edges at the parent end. */
138
+ lineWidthStart: number;
139
+ /** Stroke width of SVG edges at the child end. */
140
+ lineWidthEnd: number;
141
+ /** Color-cycle the top-level branches. */
142
+ rainbowBranch: boolean;
143
+ /** Which named palette to use when rainbowBranch is on. Built-in
144
+ * ids: 'default' | 'classic' | 'vivid' | 'dev' | 'mint'. Any
145
+ * custom palette id in `customPalettes` is also valid. Default
146
+ * 'default'. */
147
+ branchPaletteId: BranchPaletteId;
148
+ /** User-defined palettes. The settings panel lets the user add,
149
+ * edit (via a textarea of hex codes), and delete entries. The
150
+ * canvas treats these as first-class palettes alongside the
151
+ * built-ins. Persisted by the host app. */
152
+ customPalettes: BranchPalette[];
153
+ /** Edge shape between parent and child. 'curve' = fish-gill bezier
154
+ * (xmind default), 'straight' = direct line segment. */
155
+ lineStyle: LineStyle;
156
+ /** Layout mode (1.html parity). 'mindmap' = center + left/right
157
+ * fans; 'tree' = single column expanding to the right; 'org' =
158
+ * downward hierarchy. Default 'mindmap'. */
159
+ layoutMode: LayoutMode;
160
+ /** When true (default), each edge tapers independently — its
161
+ * parent-end width comes from the parent node's tier and its
162
+ * child-end width comes from `lineWidthEnd`. Visually you get
163
+ * discrete ribbons where the parent side of a level-2 edge can
164
+ * be thicker than the child side of a level-1 edge.
165
+ * When false, the whole tree forms a single tapered band:
166
+ * every edge's parent end = the previous edge's child end, so
167
+ * widths interpolate continuously from root to leaves. */
168
+ taperedEdge: boolean;
169
+ /** When true, every node shows a small badge with its zero-based
170
+ * position in its parent's children array ("1.", "2.", "3.").
171
+ * Default false — useful when verifying the data-tree order
172
+ * against the visual layout. */
173
+ showOrderBadge: boolean;
174
+ }
175
+ export interface NodeStyle {
176
+ bg?: string;
177
+ textColor?: string;
178
+ borderColor?: string;
179
+ fontWeight?: 400 | 600;
180
+ }
181
+ export interface MindMapExpose {
182
+ addChild: (parentId: string) => void;
183
+ addSibling: (nodeId: string) => void;
184
+ removeNode: (nodeId: string) => void;
185
+ duplicateNode: (nodeId: string) => void;
186
+ /** Set a node's text (no-op if unchanged). Used by the outline
187
+ * panel's inline edit; the canvas has its own dblclick → input
188
+ * flow. */
189
+ setNodeText: (nodeId: string, text: string) => void;
190
+ /** Move a node to a new location. `position` is relative to
191
+ * `targetId`: 'before' / 'after' insert as siblings, 'child'
192
+ * makes it the last child of target. Used by the outline panel's
193
+ * drag-and-drop. Returns true on success, false (no-op) if the
194
+ * move would create a cycle or hit another invalid case. */
195
+ moveNode: (srcId: string, targetId: string, position: 'before' | 'after' | 'child') => boolean;
196
+ getData: () => MindMapNode;
197
+ setData: (data: MindMapNode) => void;
198
+ resetView: () => void;
199
+ exportData: () => string;
200
+ importData: (json: string) => boolean;
201
+ /** Serialize the current data tree as markdown. */
202
+ getMarkdown: () => string;
203
+ /** Replace the data tree with the result of parsing `md`. The
204
+ * `emitMarkdownChange` flag (default true) controls whether the
205
+ * change is also echoed via `markdownChange` — set false to
206
+ * avoid feedback loops when the host just wrote back the
207
+ * value the component emitted. */
208
+ setMarkdown: (md: string, emitMarkdownChange?: boolean) => void;
209
+ setBalanced: (value: boolean) => void;
210
+ isBalanced: () => boolean;
211
+ balance: () => void;
212
+ /** Apply or update the per-node style override (empty object clears it). */
213
+ applyNodeStyle: (nodeId: string, style: NodeStyle) => void;
214
+ /** Read the current per-node style override. */
215
+ getNodeStyle: (nodeId: string) => NodeStyle;
216
+ /** Set a node's external link. Pass an empty string to clear. */
217
+ applyNodeLink: (nodeId: string, url: string) => void;
218
+ /** Remove a node's link (no-op if absent). */
219
+ removeNodeLink: (nodeId: string) => void;
220
+ /** Set a node's note text. Pass an empty string to clear. */
221
+ applyNodeNote: (nodeId: string, text: string) => void;
222
+ /** Remove a node's note (no-op if absent). */
223
+ removeNodeNote: (nodeId: string) => void;
224
+ /** Set a node's image from a URL or data: URI. Fetches the
225
+ * asset to read its natural dimensions; clamps to IMG_MAX_W
226
+ * with a preserved aspect ratio. Empty string removes the
227
+ * image. */
228
+ applyNodeImageByUrl: (nodeId: string, url: string) => void;
229
+ /** Set a node's image from a fully-resolved MindMapImage.
230
+ * Used by the file-picker flow (readImageFile) and the drag
231
+ * resize handle. Prefer `applyNodeImageByUrl` from the
232
+ * panel — it fetches the natural dimensions for you. */
233
+ applyNodeImage: (nodeId: string, image: MindMapImage) => void;
234
+ /** Remove a node's image (no-op if absent). */
235
+ removeNodeImage: (nodeId: string) => void;
236
+ /** Set a node's rich body (code block or table). Pass `null`
237
+ * to remove the body. The renderer reads `kind` to decide
238
+ * which preview layout to use. */
239
+ applyNodeRichContent: (nodeId: string, content: {
240
+ kind: 'code' | 'table';
241
+ raw: string;
242
+ lang?: string;
243
+ } | null) => void;
244
+ undo: () => void;
245
+ redo: () => void;
246
+ canUndo: () => boolean;
247
+ canRedo: () => boolean;
248
+ /** Apply a partial settings object — keys you omit are left as-is. */
249
+ applySettings: (s: Partial<MindMapSettings>) => void;
250
+ /** Read the current effective settings. */
251
+ getSettings: () => MindMapSettings;
252
+ /** Set the active branch palette by id. The id may be a built-in
253
+ * ('default' / 'classic' / 'vivid' / 'dev' / 'mint') or a custom
254
+ * palette id from `customPalettes`. No-op if the id is unknown. */
255
+ setBranchPalette: (id: BranchPaletteId) => void;
256
+ /** Read the active palette id. */
257
+ getBranchPalette: () => BranchPaletteId;
258
+ /** Read every palette the canvas knows about — built-ins first,
259
+ * then the user's custom palettes. Useful for the host app to
260
+ * render a picker. */
261
+ getBranchPalettes: () => BranchPalette[];
262
+ /** Stroke width used for the parent end of an edge that starts at
263
+ * a node of the given depth. Lets the canvas taper sharply
264
+ * (root → 1st → 2nd → 3rd+) instead of using a single global
265
+ * width. */
266
+ lineWidthForDepth: (depth: number) => number;
267
+ /** Stroke width used for the child end of an edge that ends at
268
+ * a node of the given depth. */
269
+ endWidthForDepth: (depth: number) => number;
270
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flow-mindmap",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "A modern, minimalist mind mapping tool 闂?xmind-style, embeddable as a Vue component.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",