diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json
index 64f18a0..0191c9c 100644
--- a/.obsidian/workspace.json
+++ b/.obsidian/workspace.json
@@ -4,21 +4,17 @@
"type": "split",
"children": [
{
- "id": "b1afd552ee0aa86f",
+ "id": "30ead2b90dc646d4",
"type": "tabs",
"children": [
{
- "id": "343836aed0394d03",
+ "id": "e53cb40c752bba12",
"type": "leaf",
"state": {
- "type": "markdown",
- "state": {
- "file": "WORK & PROJECTS/Mol/Планы и диаграммы/Разработка - ЭПИКИ.md",
- "mode": "source",
- "source": false
- },
+ "type": "empty",
+ "state": {},
"icon": "lucide-file",
- "title": "Разработка - ЭПИКИ"
+ "title": "New tab"
}
}
]
@@ -78,7 +74,7 @@
}
],
"direction": "horizontal",
- "width": 469.5
+ "width": 314.5
},
"right": {
"id": "5a12b65cf742d665",
@@ -140,17 +136,24 @@
"state": {
"type": "outline",
"state": {
- "file": "WORK & PROJECTS/Mol/Планы и диаграммы/Разработка - ЭПИКИ.md",
- "followCursor": false,
- "showSearch": false,
- "searchQuery": ""
+ "file": "WORK & PROJECTS/Ulab/Доступы к точкам.md"
},
"icon": "lucide-list",
- "title": "Outline of Разработка - ЭПИКИ"
+ "title": "Структура Доступы к точкам"
+ }
+ },
+ {
+ "id": "c463341da3a7d6da",
+ "type": "leaf",
+ "state": {
+ "type": "git-view",
+ "state": {},
+ "icon": "git-pull-request",
+ "title": "Source Control"
}
}
],
- "currentTab": 3
+ "currentTab": 4
}
],
"direction": "horizontal",
@@ -168,12 +171,10 @@
"obsidian-git:Open Git source control": false
}
},
- "active": "343836aed0394d03",
+ "active": "e53cb40c752bba12",
"lastOpenFiles": [
- "WORK & PROJECTS/Mol/Планы и диаграммы/План СИЛА.md",
+ "WORK & PROJECTS/Mol/Code Chunks/Tiptap resizeTableColumnWidth.md",
"PERSONAL PROJECTS/P2EP/cdRead.canvas",
- "conflict-files-obsidian-git.md",
- "My/Diet 2.md",
"PERSONAL PROJECTS/P2EP/pseudoCode/MakeSmallChar.md",
"PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80015674 Update Entity Stats.md",
"PERSONAL PROJECTS/P2EP/pseudoCode/FUN_800453e0 SystemEventManager.md",
@@ -184,6 +185,7 @@
"PERSONAL PROJECTS/PS1 DOCS/PSX code - Load texture from SECTOR!.md",
"PERSONAL PROJECTS/PS1 DOCS/PSX code texture load unpack show and fade.md",
"PERSONAL PROJECTS/Persona 1/Script Format.md",
+ "My/Diet 2.md",
"WORK & PROJECTS/Mol/Серверы/git.moldev.ru.md",
"PERSONAL PROJECTS/PS1 DOCS/CD_Execute_Reading.md",
"PERSONAL PROJECTS/PS1 DOCS/PSX code logo show.md",
diff --git a/WORK & PROJECTS/Mol/Code Chunks/Tiptap resizeTableColumnWidth.md b/WORK & PROJECTS/Mol/Code Chunks/Tiptap resizeTableColumnWidth.md
new file mode 100644
index 0000000..fd53b69
--- /dev/null
+++ b/WORK & PROJECTS/Mol/Code Chunks/Tiptap resizeTableColumnWidth.md
@@ -0,0 +1,318 @@
+
+# Creating a Tiptap Plugin for Resizable Table Columns in Vue 3
+
+To create a Tiptap plugin that allows users to resize table columns and persists the width information in the node's JSON, you'll need to:
+
+1. Extend the Table extension
+2. Add resize handles
+3. Handle mouse events for resizing
+4. Store column widths in node attributes
+
+Here's a comprehensive solution:
+
+## 1. First, install required dependencies (if not already installed)
+
+```bash
+npm install @tiptap/vue-3 @tiptap/pm @tiptap/starter-kit @tiptap/extension-table @tiptap/extension-table-row @tiptap/extension-table-header @tiptap/extension-table-cell
+```
+
+## 2. Create a custom Table extension with resizable columns
+
+```javascript
+// ResizableTableExtension.js
+import { Table } from '@tiptap/extension-table'
+import { Plugin, PluginKey } from '@tiptap/pm/state'
+
+export const ResizableTableExtension = Table.extend({
+ addAttributes() {
+ return {
+ ...this.parent?.(),
+ colWidths: {
+ default: null,
+ parseHTML: element => element.getAttribute('data-col-widths'),
+ renderHTML: attributes => {
+ if (!attributes.colWidths) {
+ return {}
+ }
+ return {
+ 'data-col-widths': attributes.colWidths.join(',')
+ }
+ }
+ }
+ }
+ },
+
+ addProseMirrorPlugins() {
+ const parentPlugins = this.parent?.() || []
+
+ return [
+ ...parentPlugins,
+ resizableColumnsPlugin({
+ handleWidth: 5,
+ cellMinWidth: 25,
+ onColumnResize: (colIndex, width, colWidths, node) => {
+ const transaction = this.editor.state.tr.setNodeMarkup(
+ this.editor.state.selection.$anchor.posAtIndex(0),
+ undefined,
+ {
+ ...node.attrs,
+ colWidths: colWidths
+ }
+ )
+ this.editor.view.dispatch(transaction)
+ }
+ })
+ ]
+ }
+})
+
+function resizableColumnsPlugin(options) {
+ const pluginKey = new PluginKey('resizableColumns')
+ let resizing = false
+ let startX, startWidth, colIndex, table, colWidths
+
+ return new Plugin({
+ key: pluginKey,
+ props: {
+ handleDOMEvents: {
+ mousedown: (view, event) => {
+ const target = event.target
+ if (target.classList.contains('column-resize-handle')) {
+ event.preventDefault()
+ startResizing(view, target, event.clientX)
+ return true
+ }
+ },
+ mousemove: (view, event) => {
+ if (!resizing) return
+ const tableRect = table.getBoundingClientRect()
+ const totalWidth = tableRect.width
+ const newWidth = startWidth + (event.clientX - startX)
+ const percentageWidth = (newWidth / totalWidth) * 100
+
+ // Update the column widths array
+ const newColWidths = [...colWidths]
+ newColWidths[colIndex] = Math.max(options.cellMinWidth, percentageWidth)
+
+ // Apply the new widths to the table columns
+ applyColumnWidths(table, newColWidths)
+
+ if (options.onColumnResize) {
+ const node = view.state.doc.nodeAt(view.state.selection.$anchor.posAtIndex(0))
+ options.onColumnResize(colIndex, percentageWidth, newColWidths, node)
+ }
+
+ return true
+ },
+ mouseup: () => {
+ if (resizing) {
+ resizing = false
+ document.body.style.cursor = ''
+ return true
+ }
+ }
+ }
+ },
+ view: (view) => {
+ return {
+ update: (view) => {
+ // Add resize handles to columns
+ const tables = view.dom.querySelectorAll('table')
+ tables.forEach(table => {
+ const rows = table.querySelectorAll('tr')
+ if (rows.length === 0) return
+
+ // Remove existing handles
+ const existingHandles = table.querySelectorAll('.column-resize-handle')
+ existingHandles.forEach(handle => handle.remove())
+
+ // Get column widths from node attributes or calculate equal distribution
+ const node = view.state.doc.nodeAt(view.state.selection.$anchor.posAtIndex(0))
+ const attrs = node?.attrs || {}
+ colWidths = attrs.colWidths
+ ? attrs.colWidths.split(',').map(Number)
+ : Array(rows[0].cells.length).fill(100 / rows[0].cells.length)
+
+ // Apply initial column widths
+ applyColumnWidths(table, colWidths)
+
+ // Add resize handles
+ const firstRow = rows[0]
+ Array.from(firstRow.cells).forEach((cell, index) => {
+ const handle = document.createElement('div')
+ handle.className = 'column-resize-handle'
+ handle.style.position = 'absolute'
+ handle.style.top = '0'
+ handle.style.right = '0'
+ handle.style.width = `${options.handleWidth}px`
+ handle.style.height = '100%'
+ handle.style.cursor = 'col-resize'
+ handle.style.backgroundColor = 'transparent'
+ handle.style.zIndex = '10'
+
+ cell.style.position = 'relative'
+ cell.appendChild(handle)
+ })
+ })
+ }
+ }
+ }
+ })
+
+ function startResizing(view, handle, clientX) {
+ resizing = true
+ startX = clientX
+ const cell = handle.parentElement
+ const row = cell.parentElement
+ table = row.closest('table')
+ colIndex = Array.from(row.cells).indexOf(cell)
+
+ // Get current column widths
+ const node = view.state.doc.nodeAt(view.state.selection.$anchor.posAtIndex(0))
+ const attrs = node?.attrs || {}
+ colWidths = attrs.colWidths
+ ? attrs.colWidths.split(',').map(Number)
+ : Array(row.cells.length).fill(100 / row.cells.length)
+
+ const tableRect = table.getBoundingClientRect()
+ const totalWidth = tableRect.width
+ startWidth = (colWidths[colIndex] / 100) * totalWidth
+
+ document.body.style.cursor = 'col-resize'
+ }
+
+ function applyColumnWidths(table, widths) {
+ const rows = table.querySelectorAll('tr')
+ if (rows.length === 0) return
+
+ rows.forEach(row => {
+ Array.from(row.cells).forEach((cell, index) => {
+ cell.style.width = `${widths[index]}%`
+ })
+ })
+ }
+}
+```
+
+## 3. Use the extension in your Vue 3 component
+
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+## Key Features of This Implementation:
+
+1. **Column Width Storage**: Column widths are stored in the table node's attributes as a comma-separated string of percentages.
+
+2. **Resize Handles**: Adds invisible resize handles to each column that become active on hover.
+
+3. **Persistence**: When you save the editor content to JSON, the column widths are preserved in the node attributes.
+
+4. **Initialization**: If no widths are specified, columns are initially equally distributed.
+
+5. **Minimum Width**: Enforces a minimum column width to prevent columns from becoming too narrow.
+
+## Usage Notes:
+
+- The plugin adds resize handles to the right side of each column header
+- Users can drag these handles to resize columns
+- The widths are stored as percentages to maintain responsiveness
+- The data is saved in the table node's attributes and will be included when you call `editor.getJSON()`
+
+## Customization Options:
+
+You can adjust these parameters in the plugin options:
+- `handleWidth`: Width of the resize handle in pixels
+- `cellMinWidth`: Minimum column width in percentage
+- `onColumnResize`: Callback function when a column is resized
+
+This implementation provides a complete solution for resizable table columns in Tiptap with Vue 3, with proper persistence of column widths in the document JSON.
\ No newline at end of file