inkpen 0.7.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.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.rubocop.yml +8 -0
  4. data/.yardopts +11 -0
  5. data/CLAUDE.md +141 -0
  6. data/README.md +409 -0
  7. data/Rakefile +19 -0
  8. data/app/assets/javascripts/inkpen/controllers/editor_controller.js +2050 -0
  9. data/app/assets/javascripts/inkpen/controllers/sticky_toolbar_controller.js +667 -0
  10. data/app/assets/javascripts/inkpen/controllers/toolbar_controller.js +693 -0
  11. data/app/assets/javascripts/inkpen/export/html.js +637 -0
  12. data/app/assets/javascripts/inkpen/export/index.js +30 -0
  13. data/app/assets/javascripts/inkpen/export/markdown.js +697 -0
  14. data/app/assets/javascripts/inkpen/export/pdf.js +372 -0
  15. data/app/assets/javascripts/inkpen/extensions/advanced_table.js +640 -0
  16. data/app/assets/javascripts/inkpen/extensions/block_commands.js +300 -0
  17. data/app/assets/javascripts/inkpen/extensions/block_gutter.js +338 -0
  18. data/app/assets/javascripts/inkpen/extensions/callout.js +303 -0
  19. data/app/assets/javascripts/inkpen/extensions/columns.js +403 -0
  20. data/app/assets/javascripts/inkpen/extensions/database.js +990 -0
  21. data/app/assets/javascripts/inkpen/extensions/document_section.js +352 -0
  22. data/app/assets/javascripts/inkpen/extensions/drag_handle.js +407 -0
  23. data/app/assets/javascripts/inkpen/extensions/embed.js +629 -0
  24. data/app/assets/javascripts/inkpen/extensions/enhanced_image.js +566 -0
  25. data/app/assets/javascripts/inkpen/extensions/export_commands.js +271 -0
  26. data/app/assets/javascripts/inkpen/extensions/file_attachment.js +593 -0
  27. data/app/assets/javascripts/inkpen/extensions/inkpen_table/index.js +58 -0
  28. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table.js +638 -0
  29. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table_cell.js +100 -0
  30. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table_header.js +100 -0
  31. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_constants.js +152 -0
  32. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_helpers.js +254 -0
  33. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_menu.js +282 -0
  34. data/app/assets/javascripts/inkpen/extensions/preformatted.js +239 -0
  35. data/app/assets/javascripts/inkpen/extensions/section.js +281 -0
  36. data/app/assets/javascripts/inkpen/extensions/section_title.js +126 -0
  37. data/app/assets/javascripts/inkpen/extensions/slash_commands.js +439 -0
  38. data/app/assets/javascripts/inkpen/extensions/table_of_contents.js +474 -0
  39. data/app/assets/javascripts/inkpen/extensions/toggle_block.js +332 -0
  40. data/app/assets/javascripts/inkpen/index.js +87 -0
  41. data/app/assets/stylesheets/inkpen/advanced_table.css +514 -0
  42. data/app/assets/stylesheets/inkpen/animations.css +626 -0
  43. data/app/assets/stylesheets/inkpen/block_gutter.css +265 -0
  44. data/app/assets/stylesheets/inkpen/callout.css +359 -0
  45. data/app/assets/stylesheets/inkpen/columns.css +314 -0
  46. data/app/assets/stylesheets/inkpen/database.css +658 -0
  47. data/app/assets/stylesheets/inkpen/document_section.css +305 -0
  48. data/app/assets/stylesheets/inkpen/drag_drop.css +220 -0
  49. data/app/assets/stylesheets/inkpen/editor.css +652 -0
  50. data/app/assets/stylesheets/inkpen/embed.css +468 -0
  51. data/app/assets/stylesheets/inkpen/enhanced_image.css +453 -0
  52. data/app/assets/stylesheets/inkpen/export.css +499 -0
  53. data/app/assets/stylesheets/inkpen/file_attachment.css +347 -0
  54. data/app/assets/stylesheets/inkpen/footnotes.css +136 -0
  55. data/app/assets/stylesheets/inkpen/inkpen_table.css +608 -0
  56. data/app/assets/stylesheets/inkpen/preformatted.css +215 -0
  57. data/app/assets/stylesheets/inkpen/search_replace.css +58 -0
  58. data/app/assets/stylesheets/inkpen/section.css +236 -0
  59. data/app/assets/stylesheets/inkpen/slash_menu.css +252 -0
  60. data/app/assets/stylesheets/inkpen/sticky_toolbar.css +314 -0
  61. data/app/assets/stylesheets/inkpen/toc.css +386 -0
  62. data/app/assets/stylesheets/inkpen/toggle.css +260 -0
  63. data/app/helpers/inkpen/editor_helper.rb +114 -0
  64. data/app/views/inkpen/_editor.html.erb +139 -0
  65. data/config/importmap.rb +170 -0
  66. data/docs/.DS_Store +0 -0
  67. data/docs/CHANGELOG.md +571 -0
  68. data/docs/FEATURES.md +436 -0
  69. data/docs/ROADMAP.md +3029 -0
  70. data/docs/VISION.md +235 -0
  71. data/docs/extensions/INKPEN_TABLE.md +482 -0
  72. data/docs/thinking/CORRECTED_NO_VUE.md +756 -0
  73. data/docs/thinking/EXECUTIVE_SUMMARY.md +403 -0
  74. data/docs/thinking/INKPEN_CODE_SAMPLES.md +1479 -0
  75. data/docs/thinking/INKPEN_MASTER_GUIDE.md +891 -0
  76. data/docs/thinking/README_START_HERE.md +341 -0
  77. data/lib/inkpen/configuration.rb +175 -0
  78. data/lib/inkpen/editor.rb +204 -0
  79. data/lib/inkpen/engine.rb +32 -0
  80. data/lib/inkpen/extensions/base.rb +109 -0
  81. data/lib/inkpen/extensions/code_block_syntax.rb +177 -0
  82. data/lib/inkpen/extensions/document_section.rb +111 -0
  83. data/lib/inkpen/extensions/forced_document.rb +183 -0
  84. data/lib/inkpen/extensions/mention.rb +155 -0
  85. data/lib/inkpen/extensions/preformatted.rb +111 -0
  86. data/lib/inkpen/extensions/section.rb +139 -0
  87. data/lib/inkpen/extensions/slash_commands.rb +100 -0
  88. data/lib/inkpen/extensions/table.rb +182 -0
  89. data/lib/inkpen/extensions/task_list.rb +145 -0
  90. data/lib/inkpen/sticky_toolbar.rb +157 -0
  91. data/lib/inkpen/toolbar.rb +145 -0
  92. data/lib/inkpen/version.rb +5 -0
  93. data/lib/inkpen.rb +101 -0
  94. data/sig/inkpen.rbs +4 -0
  95. metadata +165 -0
@@ -0,0 +1,482 @@
1
+ # InkpenTable Extension
2
+
3
+ > **Version:** 0.8.0
4
+ > **Notion/Airtable-style enhanced tables**
5
+
6
+ A unified table extension that provides Notion-like row/column handles with context menus, text colors, background colors, and professional table features.
7
+
8
+ ---
9
+
10
+ ## Table of Contents
11
+
12
+ - [Overview](#overview)
13
+ - [Architecture](#architecture)
14
+ - [Features](#features)
15
+ - [Configuration](#configuration)
16
+ - [Commands](#commands)
17
+ - [Keyboard Shortcuts](#keyboard-shortcuts)
18
+ - [CSS Custom Properties](#css-custom-properties)
19
+ - [Migration Guide](#migration-guide)
20
+
21
+ ---
22
+
23
+ ## Overview
24
+
25
+ InkpenTable replaces both the basic `table` and `advanced_table` extensions with a unified, feature-rich implementation. It combines professional table features with Notion-style UX patterns.
26
+
27
+ ```
28
+ ┌─────────────────────────────────────────────────────────────────┐
29
+ │ InkpenTable = AdvancedTable + Notion-style Handles + Menus │
30
+ └─────────────────────────────────────────────────────────────────┘
31
+ ```
32
+
33
+ ### Key Differentiators
34
+
35
+ | Feature | table | advanced_table | inkpen_table |
36
+ |---------|-------|----------------|--------------|
37
+ | Row/Col handles | ❌ | ❌ | ✅ |
38
+ | Context menus | ❌ | ❌ | ✅ |
39
+ | Text colors | ❌ | ❌ | ✅ |
40
+ | Background colors | ❌ | ✅ | ✅ |
41
+ | Alignment | ❌ | ✅ | ✅ |
42
+ | Caption | ❌ | ✅ | ✅ |
43
+ | Variants | ❌ | ✅ | ✅ |
44
+ | Sticky header | ❌ | ✅ | ✅ |
45
+ | Quick add buttons | ❌ | ❌ | ✅ |
46
+
47
+ ---
48
+
49
+ ## Architecture
50
+
51
+ ### File Structure
52
+
53
+ ```
54
+ app/assets/javascripts/inkpen/extensions/inkpen_table/
55
+
56
+ ├── index.js # Main exports
57
+ │ └── exports: InkpenTable, InkpenTableRow, InkpenTableCell,
58
+ │ InkpenTableHeader, TableMenu, constants, helpers
59
+
60
+ ├── inkpen_table.js # Main Table extension
61
+ │ ├── InkpenTableRow # Extended TableRow
62
+ │ └── InkpenTable # Extended Table with NodeView
63
+ │ ├── addOptions() # Configuration
64
+ │ ├── addAttributes() # caption, variant, stickyHeader
65
+ │ ├── addNodeView() # DOM with handles
66
+ │ ├── addCommands() # Table + cell commands
67
+ │ └── addKeyboardShortcuts()
68
+
69
+ ├── inkpen_table_cell.js # Extended TableCell
70
+ │ └── Attributes: align, background, textColor, colspan, rowspan, colwidth
71
+
72
+ ├── inkpen_table_header.js # Extended TableHeader
73
+ │ └── Same attributes as cell
74
+
75
+ ├── table_menu.js # Context menu class
76
+ │ └── TableMenu
77
+ │ ├── showRowMenu()
78
+ │ ├── showColumnMenu()
79
+ │ └── #createMenuItem(), #showSubmenu()
80
+
81
+ ├── table_helpers.js # Utility functions
82
+ │ ├── createElement() # DOM creation
83
+ │ ├── nextFrame() # RAF promise
84
+ │ ├── positionBelow() # Menu positioning
85
+ │ ├── positionRight() # Submenu positioning
86
+ │ ├── getTableDimensions() # Row/col count
87
+ │ ├── onClickOutside() # Event handler
88
+ │ └── onEscapeKey() # Event handler
89
+
90
+ └── table_constants.js # Configuration constants
91
+ ├── TEXT_COLORS # 9 text color options
92
+ ├── BACKGROUND_COLORS # 9 background options
93
+ ├── TABLE_VARIANTS # 4 style variants
94
+ ├── ROW_MENU_ITEMS # Row context menu
95
+ ├── COLUMN_MENU_ITEMS # Column context menu
96
+ ├── ALIGNMENT_OPTIONS # Left/center/right
97
+ ├── DEFAULT_CONFIG # Default options
98
+ └── CSS_CLASSES # Class name constants
99
+ ```
100
+
101
+ ### DOM Structure (NodeView)
102
+
103
+ ```
104
+ ┌─ .inkpen-table-wrapper ─────────────────────────────────────────┐
105
+ │ │
106
+ │ ┌─ .inkpen-table__caption ────────────────────────────────┐ │
107
+ │ │ "Table Title" (contentEditable) │ │
108
+ │ └──────────────────────────────────────────────────────────┘ │
109
+ │ │
110
+ │ ┌─ .inkpen-table__col-handles ────────────────────────────┐ │
111
+ │ │ [⋮⋮] [⋮⋮] [⋮⋮] [⋮⋮] [+] │ │
112
+ │ │ ↓ ↓ ↓ ↓ add │ │
113
+ │ │ col col col col col │ │
114
+ │ └──────────────────────────────────────────────────────────┘ │
115
+ │ │
116
+ │ ┌─ .inkpen-table__body ───────────────────────────────────┐ │
117
+ │ │ │ │
118
+ │ │ ┌─ .inkpen-table__row-handles ─┐ ┌─ .inkpen-table__content ─┐
119
+ │ │ │ [⋮⋮] ← row 0 │ │ ┌───┬───┬───┬───┐ │
120
+ │ │ │ [⋮⋮] ← row 1 │ │ │ H │ H │ H │ H │ │
121
+ │ │ │ [⋮⋮] ← row 2 │ │ ├───┼───┼───┼───┤ │
122
+ │ │ │ │ │ │ │ │ │ │ │
123
+ │ │ └──────────────────────────────┘ │ ├───┼───┼───┼───┤ │
124
+ │ │ │ │ │ │ │ │ │
125
+ │ │ │ └───┴───┴───┴───┘ │
126
+ │ │ └──────────────────────────┘
127
+ │ └──────────────────────────────────────────────────────────┘ │
128
+ │ │
129
+ │ ┌─ .inkpen-table__add-row ────────────────────────────────┐ │
130
+ │ │ [+ New row] │ │
131
+ │ └──────────────────────────────────────────────────────────┘ │
132
+ │ │
133
+ └──────────────────────────────────────────────────────────────────┘
134
+ ```
135
+
136
+ ### Context Menu Structure
137
+
138
+ ```
139
+ ┌─ Row Menu ──────────────────┐ ┌─ Column Menu ───────────────┐
140
+ │ ↑ Add row above │ │ ← Add column left │
141
+ │ ↓ Add row below │ │ → Add column right │
142
+ │ ─────────────────────────── │ │ ─────────────────────────── │
143
+ │ ⧉ Duplicate row │ │ ⧉ Duplicate column │
144
+ │ ✕ Delete row 🔴 │ │ ✕ Delete column 🔴 │
145
+ │ ─────────────────────────── │ │ ─────────────────────────── │
146
+ │ ↑ Move up │ │ ← Move left │
147
+ │ ↓ Move down │ │ → Move right │
148
+ │ ─────────────────────────── │ │ ─────────────────────────── │
149
+ │ H Toggle header │ │ ≡ Alignment ▸ │
150
+ │ ─────────────────────────── │ │ ─────────────────────────── │
151
+ │ A Text color ▸ │ │ A Text color ▸ │
152
+ │ ◼ Background ▸ │ │ ◼ Background ▸ │
153
+ └─────────────────────────────┘ └─────────────────────────────┘
154
+
155
+ ┌─ Color Submenu (Grid) ──────┐ ┌─ Alignment Submenu ─────────┐
156
+ │ [∅][G][R][O][Y] │ │ ← Left │
157
+ │ [G][B][P][P][ ] │ │ ↔ Center │
158
+ │ │ │ → Right │
159
+ └─────────────────────────────┘ └─────────────────────────────┘
160
+ ```
161
+
162
+ ### Data Flow
163
+
164
+ ```
165
+ ┌────────────────────────────────────────────────────────────────────┐
166
+ │ User Interaction │
167
+ └─────────────────────────────────┬──────────────────────────────────┘
168
+
169
+
170
+ ┌─────────────────────────────────────────────────────────────────────┐
171
+ │ Handle Click │
172
+ │ ┌─────────────────┐ │
173
+ │ │ Row Handle [⋮⋮] │ ───▶ TableMenu.showRowMenu(handle) │
174
+ │ │ Col Handle [⋮⋮] │ ───▶ TableMenu.showColumnMenu(handle) │
175
+ │ └─────────────────┘ │
176
+ └─────────────────────────────────┬───────────────────────────────────┘
177
+
178
+
179
+ ┌─────────────────────────────────────────────────────────────────────┐
180
+ │ Menu Action │
181
+ │ ┌─────────────────────────────────────────────────────────────┐ │
182
+ │ │ handleMenuAction({ action, menuType, color, value }) │ │
183
+ │ └─────────────────────────────────────────────────────────────┘ │
184
+ │ │
185
+ │ Actions: │
186
+ │ ├── addRowAbove/Below ───▶ editor.commands.addRowBefore/After() │
187
+ │ ├── deleteRow/Column ────▶ editor.commands.deleteRow/Column() │
188
+ │ ├── textColor ───────────▶ editor.commands.setCellTextColor() │
189
+ │ ├── backgroundColor ─────▶ editor.commands.setCellBackground() │
190
+ │ └── alignment ───────────▶ editor.commands.setCellAlignment() │
191
+ └─────────────────────────────────┬───────────────────────────────────┘
192
+
193
+
194
+ ┌─────────────────────────────────────────────────────────────────────┐
195
+ │ ProseMirror Transaction │
196
+ │ ┌─────────────────────────────────────────────────────────────┐ │
197
+ │ │ tr.setNodeMarkup(pos, undefined, { ...attrs, textColor }) │ │
198
+ │ └─────────────────────────────────────────────────────────────┘ │
199
+ │ │
200
+ │ NodeView.update() ───▶ updateHandles() ───▶ Re-render handles │
201
+ └─────────────────────────────────────────────────────────────────────┘
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Features
207
+
208
+ ### Row/Column Handles
209
+
210
+ Grip icons (⋮⋮) appear on hover at the left of each row and top of each column. Click to open context menus.
211
+
212
+ ```
213
+ [⋮⋮] [⋮⋮] [⋮⋮] ← Column handles (top)
214
+ │ │ │
215
+ [⋮⋮] ─┼────┼────┼──── ← Row handle (left)
216
+ │ │ │
217
+ [⋮⋮] ─┼────┼────┼────
218
+ │ │ │
219
+ ```
220
+
221
+ ### Quick Add Buttons
222
+
223
+ - **"+ New row"** button at table bottom
224
+ - **"+"** button at right of column handles
225
+
226
+ ### Text Colors
227
+
228
+ 9 color options for cell text:
229
+
230
+ | Color | Value | CSS Variable |
231
+ |-------|-------|--------------|
232
+ | Default | null | inherit |
233
+ | Gray | #787774 | --inkpen-table-text-gray |
234
+ | Red | #d44c47 | --inkpen-table-text-red |
235
+ | Orange | #d9730d | --inkpen-table-text-orange |
236
+ | Yellow | #cb912f | --inkpen-table-text-yellow |
237
+ | Green | #448361 | --inkpen-table-text-green |
238
+ | Blue | #337ea9 | --inkpen-table-text-blue |
239
+ | Purple | #9065b0 | --inkpen-table-text-purple |
240
+ | Pink | #c14c8a | --inkpen-table-text-pink |
241
+
242
+ ### Background Colors
243
+
244
+ 9 color options for cell backgrounds (same palette, lower opacity).
245
+
246
+ ### Table Variants
247
+
248
+ | Variant | Description |
249
+ |---------|-------------|
250
+ | default | Standard bordered table |
251
+ | striped | Alternating row colors |
252
+ | borderless | No vertical borders |
253
+ | minimal | Clean, minimal borders |
254
+
255
+ ---
256
+
257
+ ## Configuration
258
+
259
+ ### Basic Usage
260
+
261
+ ```ruby
262
+ # config/initializers/inkpen.rb
263
+ Inkpen.configure do |config|
264
+ config.extensions = [:inkpen_table, ...]
265
+ end
266
+ ```
267
+
268
+ ### Full Options
269
+
270
+ ```ruby
271
+ config.extension_config = {
272
+ inkpen_table: {
273
+ resizable: true, # Column resize on drag
274
+ showHandles: true, # Row/column handle buttons
275
+ showAddButtons: true, # "+ New row" / "+" buttons
276
+ showCaption: true, # Editable table title
277
+ stickyHeader: false, # Fixed header on scroll
278
+ defaultVariant: "default" # default/striped/borderless/minimal
279
+ }
280
+ }
281
+ ```
282
+
283
+ ### Disable Advanced Features
284
+
285
+ For a simpler table without handles:
286
+
287
+ ```ruby
288
+ config.extension_config = {
289
+ inkpen_table: {
290
+ showHandles: false,
291
+ showAddButtons: false,
292
+ showCaption: false
293
+ }
294
+ }
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Commands
300
+
301
+ ### Table Commands (inherited)
302
+
303
+ | Command | Description |
304
+ |---------|-------------|
305
+ | `insertTable({ rows, cols, withHeaderRow })` | Insert new table |
306
+ | `addRowBefore()` | Add row above current |
307
+ | `addRowAfter()` | Add row below current |
308
+ | `deleteRow()` | Delete current row |
309
+ | `addColumnBefore()` | Add column to left |
310
+ | `addColumnAfter()` | Add column to right |
311
+ | `deleteColumn()` | Delete current column |
312
+ | `deleteTable()` | Remove entire table |
313
+ | `toggleHeaderRow()` | Toggle header row |
314
+ | `mergeCells()` | Merge selected cells |
315
+ | `splitCell()` | Split merged cell |
316
+
317
+ ### InkpenTable Commands (new)
318
+
319
+ | Command | Description |
320
+ |---------|-------------|
321
+ | `setTableCaption(text)` | Set table title |
322
+ | `setTableVariant(variant)` | Set style variant |
323
+ | `toggleStickyHeader()` | Toggle sticky header |
324
+ | `setCellAlignment(align)` | Set cell text alignment |
325
+ | `setCellBackground(color)` | Set cell background color |
326
+ | `clearCellBackground()` | Remove background color |
327
+ | `setCellTextColor(color)` | Set cell text color |
328
+ | `clearCellTextColor()` | Remove text color |
329
+
330
+ ---
331
+
332
+ ## Keyboard Shortcuts
333
+
334
+ | Shortcut | Action |
335
+ |----------|--------|
336
+ | `Cmd+Shift+L` | Align cell left |
337
+ | `Cmd+Shift+E` | Align cell center |
338
+ | `Cmd+Shift+R` | Align cell right |
339
+ | `Tab` | Move to next cell |
340
+ | `Shift+Tab` | Move to previous cell |
341
+
342
+ ---
343
+
344
+ ## CSS Custom Properties
345
+
346
+ ### Theme Variables
347
+
348
+ ```css
349
+ :root {
350
+ /* Selection (Notion-style blue) */
351
+ --inkpen-table-selection: rgba(35, 131, 226, 0.14);
352
+ --inkpen-table-selection-border: rgba(35, 131, 226, 0.5);
353
+
354
+ /* Text colors */
355
+ --inkpen-table-text-gray: #787774;
356
+ --inkpen-table-text-red: #d44c47;
357
+ --inkpen-table-text-orange: #d9730d;
358
+ --inkpen-table-text-yellow: #cb912f;
359
+ --inkpen-table-text-green: #448361;
360
+ --inkpen-table-text-blue: #337ea9;
361
+ --inkpen-table-text-purple: #9065b0;
362
+ --inkpen-table-text-pink: #c14c8a;
363
+
364
+ /* Background colors */
365
+ --inkpen-table-bg-gray: rgba(120, 120, 120, 0.12);
366
+ --inkpen-table-bg-red: rgba(239, 68, 68, 0.15);
367
+ /* ... etc */
368
+
369
+ /* Handle styling */
370
+ --inkpen-table-handle-size: 24px;
371
+ --inkpen-table-handle-color: #9ca3af;
372
+ --inkpen-table-handle-hover: #374151;
373
+ --inkpen-table-handle-active: #3b82f6;
374
+
375
+ /* Menu styling */
376
+ --inkpen-table-menu-bg: #ffffff;
377
+ --inkpen-table-menu-border: #e5e7eb;
378
+ --inkpen-table-menu-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
379
+ --inkpen-table-menu-hover: #f3f4f6;
380
+ }
381
+ ```
382
+
383
+ ### Dark Mode
384
+
385
+ All variables have dark mode variants automatically applied via `[data-theme="dark"]` or `.dark` class.
386
+
387
+ ---
388
+
389
+ ## Migration Guide
390
+
391
+ ### From `advanced_table`
392
+
393
+ Replace in your configuration:
394
+
395
+ ```ruby
396
+ # Before
397
+ config.extensions = [:advanced_table, ...]
398
+
399
+ # After
400
+ config.extensions = [:inkpen_table, ...]
401
+ ```
402
+
403
+ Configuration options are compatible:
404
+
405
+ ```ruby
406
+ # Before
407
+ config.extension_config = {
408
+ advanced_table: {
409
+ resizable: true,
410
+ showControls: true,
411
+ defaultVariant: "default"
412
+ }
413
+ }
414
+
415
+ # After
416
+ config.extension_config = {
417
+ inkpen_table: {
418
+ resizable: true,
419
+ showHandles: true, # replaces showControls
420
+ defaultVariant: "default"
421
+ }
422
+ }
423
+ ```
424
+
425
+ ### From `table`
426
+
427
+ ```ruby
428
+ # Before
429
+ config.extensions = [:table, ...]
430
+
431
+ # After
432
+ config.extensions = [:inkpen_table, ...]
433
+ config.extension_config = {
434
+ inkpen_table: {
435
+ showHandles: false, # for basic table behavior
436
+ showAddButtons: false,
437
+ showCaption: false
438
+ }
439
+ }
440
+ ```
441
+
442
+ ---
443
+
444
+ ## Code Patterns
445
+
446
+ ### Fizzy Patterns Used
447
+
448
+ ```javascript
449
+ // Private fields with #
450
+ #element = null
451
+ #menu = null
452
+
453
+ // Section comments
454
+ // Lifecycle
455
+ connect() { }
456
+ disconnect() { this.#cleanup() }
457
+
458
+ // Actions
459
+ show() { }
460
+
461
+ // Private
462
+ #createMenu() { }
463
+ #cleanup() { }
464
+
465
+ // Helper exports (named functions, NOT objects)
466
+ export function nextFrame() { }
467
+ export function positionBelow() { }
468
+ ```
469
+
470
+ ---
471
+
472
+ ## Version History
473
+
474
+ | Version | Date | Changes |
475
+ |---------|------|---------|
476
+ | 0.8.0 | 2025-01 | Initial release - unified InkpenTable |
477
+
478
+ ---
479
+
480
+ ## License
481
+
482
+ MIT License - See LICENSE file for details.