@dou-ui/sheet 0.0.0-stage → 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/cell-types.js +20 -0
- package/dist/cell-types.js.map +1 -0
- package/dist/code/code-formula-bar.js +6 -0
- package/dist/code/code-formula-bar.js.map +1 -0
- package/dist/code/code-formula-bar.vue_vue_type_script_setup_true_lang.js +192 -0
- package/dist/code/code-formula-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/code/index.js +12 -0
- package/dist/code/index.js.map +1 -0
- package/dist/code/language.js +51 -0
- package/dist/code/language.js.map +1 -0
- package/dist/code/style.d.ts +1 -0
- package/dist/code/style.js +2 -0
- package/dist/collaboration/anchor.js +143 -0
- package/dist/collaboration/anchor.js.map +1 -0
- package/dist/collaboration/index.js +770 -0
- package/dist/collaboration/index.js.map +1 -0
- package/dist/collaboration/peers.js +87 -0
- package/dist/collaboration/peers.js.map +1 -0
- package/dist/collaboration/shared.js +450 -0
- package/dist/collaboration/shared.js.map +1 -0
- package/dist/components/cell-panel.js +6 -0
- package/dist/components/cell-panel.js.map +1 -0
- package/dist/components/cell-panel.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/cell-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/cell-renders.js +40 -0
- package/dist/components/cell-renders.js.map +1 -0
- package/dist/components/date-panel.js +6 -0
- package/dist/components/date-panel.js.map +1 -0
- package/dist/components/date-panel.vue_vue_type_script_setup_true_lang.js +48 -0
- package/dist/components/date-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/filter-panel.js +6 -0
- package/dist/components/filter-panel.js.map +1 -0
- package/dist/components/filter-panel.vue_vue_type_script_setup_true_lang.js +259 -0
- package/dist/components/filter-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-dialog.js +6 -0
- package/dist/components/format-dialog.js.map +1 -0
- package/dist/components/format-dialog.vue_vue_type_script_setup_true_lang.js +432 -0
- package/dist/components/format-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-list.js +6 -0
- package/dist/components/format-list.js.map +1 -0
- package/dist/components/format-list.vue_vue_type_script_setup_true_lang.js +187 -0
- package/dist/components/format-list.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-presets.js +97 -0
- package/dist/components/format-presets.js.map +1 -0
- package/dist/components/option-panel.js +6 -0
- package/dist/components/option-panel.js.map +1 -0
- package/dist/components/option-panel.vue_vue_type_script_setup_true_lang.js +117 -0
- package/dist/components/option-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-comment.js +6 -0
- package/dist/components/sheet-comment.js.map +1 -0
- package/dist/components/sheet-comment.vue_vue_type_script_setup_true_lang.js +104 -0
- package/dist/components/sheet-comment.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-formula-bar.js +6 -0
- package/dist/components/sheet-formula-bar.js.map +1 -0
- package/dist/components/sheet-formula-bar.vue_vue_type_script_setup_true_lang.js +124 -0
- package/dist/components/sheet-formula-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-link.js +6 -0
- package/dist/components/sheet-link.js.map +1 -0
- package/dist/components/sheet-link.vue_vue_type_script_setup_true_lang.js +249 -0
- package/dist/components/sheet-link.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-menu.js +6 -0
- package/dist/components/sheet-menu.js.map +1 -0
- package/dist/components/sheet-menu.vue_vue_type_script_setup_true_lang.js +115 -0
- package/dist/components/sheet-menu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-name-box.js +6 -0
- package/dist/components/sheet-name-box.js.map +1 -0
- package/dist/components/sheet-name-box.vue_vue_type_script_setup_true_lang.js +91 -0
- package/dist/components/sheet-name-box.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-note.js +6 -0
- package/dist/components/sheet-note.js.map +1 -0
- package/dist/components/sheet-note.vue_vue_type_script_setup_true_lang.js +146 -0
- package/dist/components/sheet-note.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-outline.js +6 -0
- package/dist/components/sheet-outline.js.map +1 -0
- package/dist/components/sheet-outline.vue_vue_type_script_setup_true_lang.js +237 -0
- package/dist/components/sheet-outline.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-tabs.js +6 -0
- package/dist/components/sheet-tabs.js.map +1 -0
- package/dist/components/sheet-tabs.vue_vue_type_script_setup_true_lang.js +487 -0
- package/dist/components/sheet-tabs.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-toolbar.js +6 -0
- package/dist/components/sheet-toolbar.js.map +1 -0
- package/dist/components/sheet-toolbar.vue_vue_type_script_setup_true_lang.js +1562 -0
- package/dist/components/sheet-toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/validation-dialog.js +6 -0
- package/dist/components/validation-dialog.js.map +1 -0
- package/dist/components/validation-dialog.vue_vue_type_script_setup_true_lang.js +370 -0
- package/dist/components/validation-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/context.js +12 -0
- package/dist/context.js.map +1 -0
- package/dist/core/address.js +256 -0
- package/dist/core/address.js.map +1 -0
- package/dist/core/axis.js +72 -0
- package/dist/core/axis.js.map +1 -0
- package/dist/core/cell-type.js +30 -0
- package/dist/core/cell-type.js.map +1 -0
- package/dist/core/clipboard.js +141 -0
- package/dist/core/clipboard.js.map +1 -0
- package/dist/core/commands.js +63 -0
- package/dist/core/commands.js.map +1 -0
- package/dist/core/comments.js +74 -0
- package/dist/core/comments.js.map +1 -0
- package/dist/core/conditional.js +362 -0
- package/dist/core/conditional.js.map +1 -0
- package/dist/core/csv.js +191 -0
- package/dist/core/csv.js.map +1 -0
- package/dist/core/data.js +118 -0
- package/dist/core/data.js.map +1 -0
- package/dist/core/document.js +187 -0
- package/dist/core/document.js.map +1 -0
- package/dist/core/extension.js +60 -0
- package/dist/core/extension.js.map +1 -0
- package/dist/core/file.js +336 -0
- package/dist/core/file.js.map +1 -0
- package/dist/core/fill.js +153 -0
- package/dist/core/fill.js.map +1 -0
- package/dist/core/find.js +42 -0
- package/dist/core/find.js.map +1 -0
- package/dist/core/format.js +404 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/group.js +134 -0
- package/dist/core/group.js.map +1 -0
- package/dist/core/history.js +68 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/index.js +17 -0
- package/dist/core/link.js +34 -0
- package/dist/core/link.js.map +1 -0
- package/dist/core/merge.js +105 -0
- package/dist/core/merge.js.map +1 -0
- package/dist/core/model.js +48 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/nav.js +44 -0
- package/dist/core/nav.js.map +1 -0
- package/dist/core/paint.js +106 -0
- package/dist/core/paint.js.map +1 -0
- package/dist/core/plain-cell-types.js +54 -0
- package/dist/core/plain-cell-types.js.map +1 -0
- package/dist/core/protect.js +246 -0
- package/dist/core/protect.js.map +1 -0
- package/dist/core/selection.js +37 -0
- package/dist/core/selection.js.map +1 -0
- package/dist/core/transaction.js +1582 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/validation.js +135 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/core/versions.js +161 -0
- package/dist/core/versions.js.map +1 -0
- package/dist/export/color.js +36 -0
- package/dist/export/color.js.map +1 -0
- package/dist/export/draw.js +316 -0
- package/dist/export/draw.js.map +1 -0
- package/dist/export/index.js +390 -0
- package/dist/export/index.js.map +1 -0
- package/dist/formula/edit.js +210 -0
- package/dist/formula/edit.js.map +1 -0
- package/dist/formula/engine.js +526 -0
- package/dist/formula/engine.js.map +1 -0
- package/dist/formula/error.js +39 -0
- package/dist/formula/error.js.map +1 -0
- package/dist/formula/functions.js +1493 -0
- package/dist/formula/functions.js.map +1 -0
- package/dist/formula/help.js +408 -0
- package/dist/formula/help.js.map +1 -0
- package/dist/formula/index.js +7 -0
- package/dist/formula/parse.js +369 -0
- package/dist/formula/parse.js.map +1 -0
- package/dist/formula/values.js +123 -0
- package/dist/formula/values.js.map +1 -0
- package/dist/formulas.js +30 -0
- package/dist/formulas.js.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/locale.js +1312 -0
- package/dist/locale.js.map +1 -0
- package/dist/sheet.js +6 -0
- package/dist/sheet.js.map +1 -0
- package/dist/sheet.vue_vue_type_script_setup_true_lang.js +7166 -0
- package/dist/sheet.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/style.d.ts +1 -0
- package/dist/style.js +17 -0
- package/dist/types/cell-types.d.ts +2 -0
- package/dist/types/code/code-formula-bar.vue.d.ts +3 -0
- package/dist/types/code/index.d.ts +12 -0
- package/dist/types/code/language.d.ts +13 -0
- package/dist/types/collaboration/anchor.d.ts +65 -0
- package/dist/types/collaboration/index.d.ts +59 -0
- package/dist/types/collaboration/peers.d.ts +21 -0
- package/dist/types/collaboration/shared.d.ts +75 -0
- package/dist/types/components/cell-panel.vue.d.ts +20 -0
- package/dist/types/components/cell-renders.d.ts +9 -0
- package/dist/types/components/date-panel.vue.d.ts +9 -0
- package/dist/types/components/filter-panel.vue.d.ts +21 -0
- package/dist/types/components/format-dialog.vue.d.ts +24 -0
- package/dist/types/components/format-list.vue.d.ts +25 -0
- package/dist/types/components/format-presets.d.ts +30 -0
- package/dist/types/components/option-panel.vue.d.ts +13 -0
- package/dist/types/components/sheet-comment.vue.d.ts +29 -0
- package/dist/types/components/sheet-formula-bar.vue.d.ts +3 -0
- package/dist/types/components/sheet-link.vue.d.ts +32 -0
- package/dist/types/components/sheet-menu.vue.d.ts +20 -0
- package/dist/types/components/sheet-name-box.vue.d.ts +3 -0
- package/dist/types/components/sheet-note.vue.d.ts +22 -0
- package/dist/types/components/sheet-outline.vue.d.ts +36 -0
- package/dist/types/components/sheet-tabs.vue.d.ts +9 -0
- package/dist/types/components/sheet-toolbar.vue.d.ts +11 -0
- package/dist/types/components/validation-dialog.vue.d.ts +25 -0
- package/dist/types/context.d.ts +189 -0
- package/dist/types/core/address.d.ts +109 -0
- package/dist/types/core/axis.d.ts +23 -0
- package/dist/types/core/cell-type.d.ts +157 -0
- package/dist/types/core/clipboard.d.ts +48 -0
- package/dist/types/core/commands.d.ts +76 -0
- package/dist/types/core/comments.d.ts +22 -0
- package/dist/types/core/conditional.d.ts +114 -0
- package/dist/types/core/csv.d.ts +93 -0
- package/dist/types/core/data.d.ts +26 -0
- package/dist/types/core/document.d.ts +49 -0
- package/dist/types/core/extension.d.ts +177 -0
- package/dist/types/core/file.d.ts +301 -0
- package/dist/types/core/fill.d.ts +23 -0
- package/dist/types/core/find.d.ts +39 -0
- package/dist/types/core/format.d.ts +47 -0
- package/dist/types/core/group.d.ts +76 -0
- package/dist/types/core/history.d.ts +27 -0
- package/dist/types/core/index.d.ts +33 -0
- package/dist/types/core/link.d.ts +14 -0
- package/dist/types/core/merge.d.ts +26 -0
- package/dist/types/core/model.d.ts +363 -0
- package/dist/types/core/nav.d.ts +15 -0
- package/dist/types/core/paint.d.ts +19 -0
- package/dist/types/core/plain-cell-types.d.ts +6 -0
- package/dist/types/core/protect.d.ts +34 -0
- package/dist/types/core/selection.d.ts +25 -0
- package/dist/types/core/transaction.d.ts +470 -0
- package/dist/types/core/validation.d.ts +55 -0
- package/dist/types/core/versions.d.ts +38 -0
- package/dist/types/export/color.d.ts +7 -0
- package/dist/types/export/draw.d.ts +98 -0
- package/dist/types/export/index.d.ts +47 -0
- package/dist/types/formula/edit.d.ts +62 -0
- package/dist/types/formula/engine.d.ts +99 -0
- package/dist/types/formula/error.d.ts +30 -0
- package/dist/types/formula/functions.d.ts +62 -0
- package/dist/types/formula/help.d.ts +12 -0
- package/dist/types/formula/index.d.ts +13 -0
- package/dist/types/formula/parse.d.ts +92 -0
- package/dist/types/formula/values.d.ts +65 -0
- package/dist/types/formulas.d.ts +32 -0
- package/dist/types/index.d.ts +225 -0
- package/dist/types/locale.d.ts +531 -0
- package/dist/types/sheet.vue.d.ts +60 -0
- package/dist/types/types.d.ts +498 -0
- package/dist/types/use-comments.d.ts +47 -0
- package/dist/types/use-messages.d.ts +7 -0
- package/dist/use-comments.js +130 -0
- package/dist/use-comments.js.map +1 -0
- package/dist/use-messages.js +29 -0
- package/dist/use-messages.js.map +1 -0
- package/package.json +93 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/collaboration/index.ts"],"sourcesContent":["import {\n applySharedCommentAction,\n collaborationColors,\n readSharedComments,\n type CommentThread,\n type SharedCommentMap,\n} from 'dou-ui'\nimport { nextTick, shallowRef, watch } from 'vue'\nimport * as Y from 'yjs'\nimport type { SheetBounds, SheetPoint } from '../core/address'\nimport { boundsOf } from '../core/address'\nimport type { SheetContext } from '../context'\nimport { defineSheetExtension, type SheetExtension } from '../core/extension'\nimport {\n colCountOf,\n rowCountOf,\n type SheetData,\n type SheetStyle,\n type SheetTypeSetup,\n} from '../core/model'\nimport type { SheetSelection } from '../core/selection'\nimport {\n sheetKey,\n type SheetAxisName,\n type SheetBookPatch,\n type SheetPatch,\n type SheetTransaction,\n} from '../core/transaction'\nimport { anchorCell, hasRefs, lineOf, resolveCell, SheetLayout, type SheetLines } from './anchor'\nimport { createPeers, type SheetPeer } from './peers'\nimport {\n ANCHORED_META,\n anchorMeta,\n cellAt,\n cellKey,\n cellOfKey,\n fillBook,\n increasingRun,\n isBookKey,\n isMetaKey,\n layoutSheet,\n makeIds,\n partsOf,\n readLayout,\n readSheet,\n resolveMeta,\n sheetParts,\n splitThread,\n threadKey,\n syncList,\n writeSheet,\n type SharedMap,\n withThread,\n type SharedParts,\n} from './shared'\n\nexport { fillBook, readBook } from './shared'\n\n/** The part of an `Awareness` (`y-protocols/awareness`) the sheet uses. */\nexport interface AwarenessLike {\n clientID: number\n getLocalState(): Record<string, unknown> | null\n setLocalStateField(field: string, value: unknown): void\n getStates(): Map<number, Record<string, unknown>>\n on(event: 'change', listener: (...args: unknown[]) => void): void\n off(event: 'change', listener: (...args: unknown[]) => void): void\n}\n\n/** How the people editing together see each other. */\nexport interface CollaborationUser {\n name: string\n /** The color of this user's marks, any CSS color. Picked from the client id when left out. */\n color?: string\n}\n\nexport interface CollaborationOptions {\n /** Where the workbook lives, e.g. `ydoc.getMap('book')`. */\n book: Y.Map<unknown>\n /** Shares what each person has selected and is editing (`y-protocols/awareness`). */\n awareness?: AwarenessLike\n /** This user, shown to the others. Needs `awareness`. */\n user?: CollaborationUser\n /**\n * Where the comment threads live, e.g. `ydoc.getMap('comments')`, so\n * they reach everyone with the workbook. `v-model:comments` then only\n * mirrors them. Without it, the cells' anchors still travel with the\n * workbook and the threads are the app's to share.\n */\n comments?: Y.Map<unknown>\n}\n\n/** A line by its id, or by number when it is past the lines the sheet has. */\ntype LineAt = string | number\n\n/** What each person shares under the awareness field `sheet`: lines by id, so they read right everywhere. */\nexport interface SheetPresence {\n /** The `id` of the sheet they have open. */\n sheet: string\n /** Their active cell, `[row, col]`. */\n active: [LineAt, LineAt]\n /** What they have selected, each range `[top, left, bottom, right]`. */\n ranges: [LineAt, LineAt, LineAt, LineAt][]\n /** Whether they are editing the active cell. */\n editing: boolean\n}\n\nexport { collaborationColors }\n\ntype Json = Record<string, unknown>\n\nconst same = (a: unknown, b: unknown) =>\n a === b ||\n ((a == null || a === '') && (b == null || b === '')) ||\n (typeof a === 'object' && typeof b === 'object' && JSON.stringify(a) === JSON.stringify(b))\n\nconst selectionOf = (active: SheetPoint, ranges: SheetBounds[]): SheetSelection => ({\n active,\n ranges: ranges.map((b) => ({\n start: { row: b.top, col: b.left },\n end: { row: b.bottom, col: b.right },\n })),\n})\n\n/** Writes the named styles or types a change touched. */\nfunction writeNamed(names: Set<string>, map: SharedMap, own?: Record<string, unknown>) {\n for (const name of names) {\n const value = own?.[name]\n if (value === undefined) map.delete(name)\n else if (!same(map.get(name), value)) map.set(name, value)\n }\n}\n\n/** Writes the sizes of the lines a change touched, by line id. */\nfunction writeSizes(\n keys: Set<string>,\n map: SharedMap,\n lines: SheetLines,\n own?: Record<number, number>,\n) {\n for (const line of keys) {\n const at = lines.indexOf(line)\n if (at < 0) continue\n const size = own?.[at]\n if (size == null) map.delete(line)\n else if (map.get(line) !== size) map.set(line, size)\n }\n}\n\nconst isEmpty = (cell: unknown) => cell == null || cell === ''\n\n/** What the shared document changed, gathered over one Yjs transaction. */\ninterface SheetDirty {\n lines: { row: boolean; col: boolean }\n cells: Set<string>\n rowSizes: Set<string>\n colSizes: Set<string>\n meta: Set<string>\n}\n\ninterface Dirty {\n /** Read everything again, e.g. after the workbook was filled anew. */\n all: boolean\n /** Sheets added, removed or moved. */\n sheets: boolean\n /** Sheets replaced whole. */\n whole: Set<string>\n /** A sheet was renamed: formulas naming it read anew. */\n names: boolean\n styles: Set<string>\n types: Set<string>\n bySheet: Map<string, SheetDirty>\n}\n\nconst dirtyNone = (): Dirty => ({\n all: false,\n sheets: false,\n whole: new Set(),\n names: false,\n styles: new Set(),\n types: new Set(),\n bySheet: new Map(),\n})\n\nconst isDirty = (d: Dirty) =>\n d.all ||\n d.sheets ||\n d.whole.size > 0 ||\n d.styles.size > 0 ||\n d.types.size > 0 ||\n d.bySheet.size > 0\n\nfunction sheetDirty(dirty: Dirty, id: string) {\n let entry = dirty.bySheet.get(id)\n if (!entry)\n dirty.bySheet.set(\n id,\n (entry = {\n lines: { row: false, col: false },\n cells: new Set(),\n rowSizes: new Set(),\n colSizes: new Set(),\n meta: new Set(),\n }),\n )\n return entry\n}\n\n/** Notes what a Yjs event changed. Paths are from the `book` map. */\nfunction collect(dirty: Dirty, event: Y.YEvent<any>) {\n const path = event.path\n const keys = event instanceof Y.YMapEvent ? event.keysChanged : new Set<string>()\n if (path.length === 0) return void (dirty.all = true)\n const [top, id, part] = path as string[]\n if (top === 'styles') for (const key of keys) dirty.styles.add(key)\n else if (top === 'types') for (const key of keys) dirty.types.add(key)\n else if (top === 'order') dirty.sheets = true\n else if (top === 'sheets') {\n if (path.length === 1) {\n dirty.sheets = true\n for (const key of keys) dirty.whole.add(key)\n } else if (path.length === 2) dirty.whole.add(id!)\n else {\n const entry = sheetDirty(dirty, id!)\n if (part === 'rows') entry.lines.row = true\n else if (part === 'cols') entry.lines.col = true\n else if (part === 'cells') for (const key of keys) entry.cells.add(key)\n else if (part === 'rowSizes') for (const key of keys) entry.rowSizes.add(key)\n else if (part === 'colSizes') for (const key of keys) entry.colSizes.add(key)\n else if (part === 'meta')\n for (const key of keys) {\n entry.meta.add(key)\n if (key === 'name') dirty.names = true\n }\n }\n }\n}\n\n/**\n * Steps that bring a sheet's lines from `from` to `to`, both lists of ids:\n * removed lines first, then the fewest moves, then the new lines. The\n * cells move with their lines; the new lines are empty.\n */\nfunction stepLines(\n tr: SheetTransaction,\n sheet: string,\n axis: SheetAxisName,\n from: readonly string[],\n to: readonly string[],\n) {\n const ids = from.slice()\n let changed = false\n const wanted = new Set(to)\n for (let i = ids.length - 1; i >= 0;) {\n if (wanted.has(ids[i]!)) {\n i--\n continue\n }\n let start = i\n while (start > 0 && !wanted.has(ids[start - 1]!)) start--\n tr.step({ type: 'removeLines', sheet, axis, index: start, count: i - start + 1 })\n ids.splice(start, i - start + 1)\n changed = true\n i = start - 1\n }\n const present = new Set(ids)\n const target = to.filter((id) => present.has(id))\n const rank = new Map(target.map((id, i) => [id, i]))\n const run = increasingRun(ids.map((id) => rank.get(id)!))\n const placed = new Set(ids.filter((_, i) => run.has(i)))\n target.forEach((id, k) => {\n if (placed.has(id)) return\n const at = ids.indexOf(id)\n ids.splice(at, 1)\n const dest = k === 0 ? 0 : ids.indexOf(target[k - 1]!) + 1\n ids.splice(dest, 0, id)\n placed.add(id)\n // `to` is numbered as before the move\n tr.step({\n type: 'moveLines',\n sheet,\n axis,\n from: at,\n count: 1,\n to: dest >= at ? dest + 1 : dest,\n })\n changed = true\n })\n for (let k = 0; k < to.length;) {\n if (present.has(to[k]!)) {\n k++\n continue\n }\n let end = k\n while (end < to.length && !present.has(to[end]!)) end++\n tr.step({ type: 'insertLines', sheet, axis, index: k, count: end - k })\n changed = true\n k = end\n }\n return changed\n}\n\n/**\n * Edit a workbook together through a Yjs document. Every row and column\n * has an id there; cells, sizes, formulas and rules are kept by those ids,\n * so two people inserting, deleting or moving lines at once keep each\n * other's cells in place, and formulas still point at the cells they were\n * written for. The grid's `v-model` only mirrors the shared workbook: a\n * workbook set through `v-model` from outside is not written back. Undo\n * only takes back this user's own changes. With `awareness`, each person\n * sees the others' selections and the cells they edit, in their colors.\n */\nexport function collaboration(options: CollaborationOptions): SheetExtension {\n const { book, awareness, user } = options\n const ydoc = book.doc\n if (!ydoc) throw new Error('[@dou-ui/sheet] the book map must be in a Y.Doc')\n if (awareness && user) {\n const color = user.color ?? collaborationColors[ydoc.clientID % collaborationColors.length]\n awareness.setLocalStateField('user', { name: user.name, color })\n }\n\n /** This grid's own changes, which undo can take back. */\n const tracked = { sheet: 'tracked' }\n /** Changes undo leaves alone, e.g. filling the shared workbook. */\n const untracked = { sheet: 'untracked' }\n const undoManager = new Y.UndoManager(book, {\n trackedOrigins: new Set([tracked]),\n captureTimeout: 500,\n })\n const ids = makeIds(ydoc)\n let context: SheetContext | undefined\n let parts: SharedParts | null = null\n /** The sheets and lines the grid shows, by id: the shared workbook as last applied. */\n let layout = new SheetLayout()\n /** Set while shared changes are applied to the grid, so they aren't written back. */\n let applying = false\n /** What undo or redo is running, to name the change. */\n let travelling: 'undo' | 'redo' | null = null\n let restore: StoredView | undefined\n let lastGroup: string | undefined\n /** Counts the changes applied from the shared workbook, for what draws by line ids. */\n const revision = shallowRef(0)\n\n // Selections, by line ids --------------------------------------------------------------\n\n interface StoredView {\n sheet: string\n active: [LineAt, LineAt]\n ranges: [LineAt, LineAt, LineAt, LineAt][]\n }\n\n function storeView(sheet: string, selection: SheetSelection): StoredView | undefined {\n const here = layout.sheets.get(sheet)\n if (!here) return undefined\n const row = (n: number): LineAt => here.rows.ids[n] ?? n\n const col = (n: number): LineAt => here.cols.ids[n] ?? n\n return {\n sheet,\n active: [row(selection.active.row), col(selection.active.col)],\n ranges: selection.ranges.slice(0, 20).map((range) => {\n const b = boundsOf(range)\n // whole rows and columns run past the last line\n return [row(b.top), col(b.left), row(b.bottom), col(b.right)]\n }),\n }\n }\n\n function readView(view: StoredView) {\n const here = layout.sheets.get(view.sheet)\n if (!here) return null\n const ranges: SheetBounds[] = []\n for (const [top, left, bottom, right] of view.ranges) {\n const b = {\n top: lineOf(here.rows, top),\n left: lineOf(here.cols, left),\n bottom: lineOf(here.rows, bottom),\n right: lineOf(here.cols, right),\n }\n if (b.top >= 0 && b.left >= 0 && b.bottom >= 0 && b.right >= 0)\n ranges.push({\n top: Math.min(b.top, b.bottom),\n left: Math.min(b.left, b.right),\n bottom: Math.max(b.top, b.bottom),\n right: Math.max(b.left, b.right),\n })\n }\n const row = lineOf(here.rows, view.active[0])\n const col = lineOf(here.cols, view.active[1])\n const active: SheetPoint | null =\n row >= 0 && col >= 0\n ? { row, col }\n : ranges[0]\n ? { row: ranges[0].top, col: ranges[0].left }\n : null\n return { active, ranges }\n }\n\n // Undo puts back the selection from before each change.\n undoManager.on('stack-item-added', (event: { stackItem: { meta: Map<string, unknown> } }) => {\n const id = context?.sheet.value.id\n const view = id != null && context ? storeView(id, context.selection.value) : undefined\n if (view) event.stackItem.meta.set('view', view)\n })\n undoManager.on('stack-item-popped', (event: { stackItem: { meta: Map<string, unknown> } }) => {\n restore = event.stackItem.meta.get('view') as StoredView | undefined\n })\n\n // Writing this grid's changes ----------------------------------------------------------\n\n interface Touched {\n cells: Set<string>\n rowSizes: Set<string>\n colSizes: Set<string>\n meta: Set<string>\n lines: { row: boolean; col: boolean }\n removed: { row: string[]; col: string[] }\n }\n\n /** Writes what a transaction changed into the shared workbook. */\n function writeChanges(tr: SheetTransaction, shared: SharedParts) {\n const touched = new Map<string, Touched>()\n const touch = (id: string) => {\n let entry = touched.get(id)\n if (!entry)\n touched.set(\n id,\n (entry = {\n cells: new Set(),\n rowSizes: new Set(),\n colSizes: new Set(),\n meta: new Set(),\n lines: { row: false, col: false },\n removed: { row: [], col: [] },\n }),\n )\n return entry\n }\n let sheetsChanged = false\n /** Sheets added in this change, also ones taken out and put back: written whole. */\n const fresh = new Set<string>()\n const styles = new Set<string>()\n const types = new Set<string>()\n /** The workbook's own settings that changed, such as `protect`. */\n const bookKeys = new Set<string>()\n\n // follow the lines through the steps, so each cell is known by the ids it had when written\n for (const step of tr.steps) {\n if (step.type === 'setStyle') styles.add(step.name)\n else if (step.type === 'setType') types.add(step.name)\n else if (step.type === 'insertSheet') {\n sheetsChanged = true\n if (step.data.id != null) fresh.add(step.data.id)\n } else if (step.type === 'removeSheet' || step.type === 'moveSheet') sheetsChanged = true\n else if (step.type === 'updateBook')\n for (const key of Object.keys(step.patch)) bookKeys.add(key)\n else {\n const here = fresh.has(step.sheet) ? undefined : layout.sheets.get(step.sheet)\n if (!here) continue\n const t = touch(here.id)\n // a line past the ids known, e.g. a cell written below the last row\n const lineAt = (axis: SheetAxisName, index: number) => {\n const lines = axis === 'row' ? here.rows : here.cols\n if (index >= lines.ids.length) {\n lines.ids.push(...ids.many(index + 1 - lines.ids.length))\n lines.changed()\n t.lines[axis] = true\n }\n return lines.ids[index]!\n }\n if (step.type === 'setCell')\n t.cells.add(cellKey(lineAt('row', step.row), lineAt('col', step.col)))\n else if (step.type === 'setSize')\n (step.axis === 'row' ? t.rowSizes : t.colSizes).add(lineAt(step.axis, step.index))\n else if (step.type === 'updateSheet')\n for (const key of Object.keys(step.patch)) t.meta.add(key)\n else {\n const { axis } = step\n const lines = axis === 'row' ? here.rows : here.cols\n t.lines[axis] = true\n if (step.type === 'insertLines') {\n if (step.index > 0) lineAt(axis, step.index - 1)\n const added = ids.many(step.count)\n lines.ids.splice(step.index, 0, ...added)\n lines.changed()\n // what comes back with the lines, as when a removal is undone\n step.cells?.forEach((part, r) =>\n part?.forEach((cell, c) => {\n if (isEmpty(cell)) return\n t.cells.add(\n axis === 'row'\n ? cellKey(added[r]!, lineAt('col', c))\n : cellKey(lineAt('row', r), added[c]!),\n )\n }),\n )\n step.sizes?.forEach((size, i) => {\n if (size != null) (axis === 'row' ? t.rowSizes : t.colSizes).add(added[i]!)\n })\n } else if (step.type === 'removeLines') {\n t.removed[axis].push(...lines.ids.splice(step.index, step.count))\n lines.changed()\n } else {\n lineAt(axis, Math.max(step.from + step.count, step.to) - 1)\n const block = lines.ids.splice(step.from, step.count)\n lines.ids.splice(step.to > step.from ? step.to - step.count : step.to, 0, ...block)\n lines.changed()\n }\n }\n }\n }\n\n const sheets = tr.doc.sheets\n const byId = new Map(sheets.map((sheet) => [sheet.id!, sheet]))\n if (sheetsChanged || sheets.some((sheet) => !layout.sheets.has(sheet.id!))) {\n for (const id of Array.from(layout.sheets.keys()))\n if (!byId.has(id) || fresh.has(id)) {\n shared.sheets.delete(id)\n layout.sheets.delete(id)\n touched.delete(id)\n }\n const added: SheetData[] = []\n for (const sheet of sheets)\n if (!layout.sheets.has(sheet.id!)) {\n layout.sheets.set(sheet.id!, layoutSheet(sheet, sheet.id!, ids))\n added.push(sheet)\n }\n for (const sheet of sheets) layout.sheets.get(sheet.id!)!.name = sheet.name\n for (const sheet of added)\n writeSheet(shared.sheets, sheet, layout.sheets.get(sheet.id!)!, layout)\n syncList(\n shared.order,\n sheets.map((sheet) => sheet.id!),\n )\n }\n // renames, so formulas name the sheets as they are called now\n for (const sheet of sheets) {\n const here = layout.sheets.get(sheet.id!)\n if (here) here.name = sheet.name\n }\n\n for (const [id, t] of touched) {\n const here = layout.sheets.get(id)\n const sheet = byId.get(id)\n const lists = sheetParts(shared.sheets.get(id))\n if (!here || !sheet || !lists) continue\n // lines added past the last one or taken off the end with the count\n const fit = (axis: SheetAxisName, count: number) => {\n const lines = axis === 'row' ? here.rows : here.cols\n if (lines.ids.length < count) lines.ids.push(...ids.many(count - lines.ids.length))\n else if (lines.ids.length > count) t.removed[axis].push(...lines.ids.splice(count))\n else return\n lines.changed()\n t.lines[axis] = true\n }\n if (t.lines.row || t.meta.has('rowCount')) fit('row', rowCountOf(sheet))\n if (t.lines.col || t.meta.has('colCount')) fit('col', colCountOf(sheet))\n if (t.lines.row) syncList(lists.rows, here.rows.ids)\n if (t.lines.col) syncList(lists.cols, here.cols.ids)\n // the cells and sizes of removed lines go with them\n const drop = (key: string) => {\n lists.cells.delete(key)\n lists.cells.delete(threadKey(key))\n }\n for (const row of t.removed.row) {\n for (const col of here.cols.ids) drop(cellKey(row, col))\n for (const col of t.removed.col) drop(cellKey(row, col))\n lists.rowSizes.delete(row)\n }\n for (const col of t.removed.col) {\n for (const row of here.rows.ids) drop(cellKey(row, col))\n lists.colSizes.delete(col)\n }\n for (const key of t.cells) {\n const { row, col } = cellAt(key, here)\n if (row < 0 || col < 0) continue\n const [own, thread] = splitThread(sheet.cells[row]?.[col])\n // the thread first: it changes apart from the cell, as undo leaves it\n const kept = lists.cells.get(threadKey(key))\n if (thread !== kept) {\n if (thread) lists.cells.set(threadKey(key), thread)\n else lists.cells.delete(threadKey(key))\n }\n const existing = lists.cells.get(key)\n /*\n * A formula only moved along with inserted or deleted lines reads the\n * same from its anchors: leave it, so it doesn't overwrite what\n * someone else changed in it at the same time.\n */\n if (same(resolveCell(existing, here, layout), own)) continue\n const stored = anchorCell(own, here, layout)\n if (isEmpty(stored)) lists.cells.delete(key)\n else lists.cells.set(key, stored)\n }\n writeSizes(t.rowSizes, lists.rowSizes, here.rows, sheet.rowSizes)\n writeSizes(t.colSizes, lists.colSizes, here.cols, sheet.colSizes)\n for (const key of t.meta) {\n if (!isMetaKey(key)) continue\n const value = (sheet as unknown as Json)[key]\n const existing = lists.meta.get(key)\n // rules and merges that only moved with their lines, as for formulas\n if (key !== 'name' && same(resolveMeta(key, existing, here, layout), value)) continue\n if (value === undefined) lists.meta.delete(key)\n else {\n const stored = anchorMeta(key, value, here, layout)\n if (!same(existing, stored)) lists.meta.set(key, stored)\n }\n }\n }\n\n writeNamed(styles, shared.styles, tr.doc.styles)\n writeNamed(types, shared.types, tr.doc.types)\n for (const key of bookKeys) {\n if (!isBookKey(key)) continue\n const value = (tr.doc as unknown as Json)[key]\n if (value === undefined) book.delete(key)\n else if (!same(book.get(key), value)) book.set(key, value)\n }\n }\n\n // Applying the shared workbook to the grid ---------------------------------------------\n\n /** Steps that bring the grid in line with the shared workbook, as `next` lays it out. */\n function applyShared(tr: SheetTransaction, shared: SharedParts, dirty: Dirty, next: SheetLayout) {\n const before = layout\n const inserted = new Set<string>()\n let refs = dirty.all || dirty.names\n\n const wanted = Array.from(next.sheets.keys())\n // an empty list is a workbook not filled yet: keep what is shown\n if ((dirty.all || dirty.sheets || dirty.whole.size) && wanted.length) {\n for (let i = tr.doc.sheets.length - 1; i >= 0; i--) {\n const sheet = tr.doc.sheets[i]!\n const id = sheet.id\n if (id == null || dirty.all || dirty.whole.has(id) || !next.sheets.has(id))\n tr.step({ type: 'removeSheet', sheet: sheetKey(sheet) })\n }\n wanted.forEach((id, index) => {\n const at = tr.indexOf(id)\n if (at === -1) {\n const here = next.sheets.get(id)!\n tr.step({\n type: 'insertSheet',\n index,\n data: readSheet(sheetParts(shared.sheets.get(id))!, here, next),\n })\n inserted.add(id)\n } else if (at !== index) tr.step({ type: 'moveSheet', sheet: id, index })\n })\n refs = true\n }\n\n for (const [id, here] of next.sheets) {\n if (inserted.has(id)) continue\n const d = dirty.bySheet.get(id)\n const old = before.sheets.get(id)\n const lists = sheetParts(shared.sheets.get(id))\n if (!d || !old || !lists || tr.indexOf(id) === -1) continue\n if (d.lines.row && stepLines(tr, id, 'row', old.rows.ids, here.rows.ids)) refs = true\n if (d.lines.col && stepLines(tr, id, 'col', old.cols.ids, here.cols.ids)) refs = true\n const counts: SheetPatch = {}\n if (rowCountOf(tr.getSheet(id)) !== here.rows.ids.length)\n counts.rowCount = here.rows.ids.length\n if (colCountOf(tr.getSheet(id)) !== here.cols.ids.length)\n counts.colCount = here.cols.ids.length\n if (Object.keys(counts).length) tr.updateSheet(counts, id)\n for (const key of new Set(Array.from(d.cells, cellOfKey))) {\n const { row, col } = cellAt(key, here)\n if (row < 0 || col < 0) continue\n const cell = withThread(\n resolveCell(lists.cells.get(key), here, next),\n lists.cells.get(threadKey(key)),\n )\n const at = { sheet: id, row, col }\n if (!same(tr.getCell(at), cell)) tr.setCell(at, cell)\n }\n const sizes = (axis: SheetAxisName, keys: Set<string>, map: SharedMap, lines: SheetLines) => {\n for (const line of keys) {\n const at = lines.indexOf(line)\n if (at < 0) continue\n const size = map.get(line)\n const own = tr.getSheet(id)[axis === 'row' ? 'rowSizes' : 'colSizes']?.[at]\n if (own !== size) tr.setSize(axis, at, typeof size === 'number' ? size : undefined, id)\n }\n }\n sizes('row', d.rowSizes, lists.rowSizes, here.rows)\n sizes('col', d.colSizes, lists.colSizes, here.cols)\n const patch: Json = {}\n for (const key of d.meta) {\n if (!isMetaKey(key)) continue\n const value = key === 'name' ? here.name : resolveMeta(key, lists.meta.get(key), here, next)\n if (!same((tr.getSheet(id) as unknown as Json)[key], value)) patch[key] = value\n }\n if (Object.keys(patch).length) tr.updateSheet(patch as SheetPatch, id)\n }\n\n // lines or names changed: every formula and rule reads its references again\n if (refs)\n for (const [id, here] of next.sheets) {\n if (inserted.has(id) || tr.indexOf(id) === -1) continue\n const lists = sheetParts(shared.sheets.get(id))\n if (!lists) continue\n lists.cells.forEach((stored, key) => {\n if (!hasRefs(stored)) return\n const { row, col } = cellAt(key, here)\n if (row < 0 || col < 0) return\n const cell = withThread(resolveCell(stored, here, next), lists.cells.get(threadKey(key)))\n const at = { sheet: id, row, col }\n if (!same(tr.getCell(at), cell)) tr.setCell(at, cell)\n })\n const patch: Json = {}\n for (const key of ANCHORED_META) {\n const value = resolveMeta(key, lists.meta.get(key), here, next)\n if (!same((tr.getSheet(id) as unknown as Json)[key], value)) patch[key] = value\n }\n if (Object.keys(patch).length) tr.updateSheet(patch as SheetPatch, id)\n }\n\n const styleNames = dirty.all\n ? new Set([...Object.keys(tr.doc.styles ?? {}), ...shared.styles.keys()])\n : dirty.styles\n for (const name of styleNames) {\n const value = shared.styles.get(name) as SheetStyle | undefined\n if (!same(tr.doc.styles?.[name], value)) tr.setStyle(name, value)\n }\n const typeNames = dirty.all\n ? new Set([...Object.keys(tr.doc.types ?? {}), ...shared.types.keys()])\n : dirty.types\n for (const name of typeNames) {\n const value = shared.types.get(name) as SheetTypeSetup | undefined\n if (!same(tr.doc.types?.[name], value)) tr.setType(name, value)\n }\n if (dirty.all) {\n // the workbook's own settings, such as `protect`\n const patch: Json = {}\n const keys = new Set([...Object.keys(tr.doc), ...book.keys()])\n for (const key of keys) {\n if (!isBookKey(key)) continue\n const value = book.get(key)\n if (!same((tr.doc as unknown as Json)[key], value)) patch[key] = value\n }\n if (Object.keys(patch).length) tr.updateBook(patch as SheetBookPatch)\n }\n }\n\n /** Brings the grid in line with the shared workbook. */\n function pull(dirty: Dirty) {\n parts = partsOf(book)\n if (!context || !parts) return\n const shared = parts\n const next = readLayout(shared)\n const meta = { history: false, origin: travelling ?? 'remote' } as const\n // the selection stays on its cells when others insert, delete or move lines around it\n const shown = context.sheet.value.id\n const selected = shown != null ? storeView(shown, context.selection.value) : undefined\n const kept = context.selection.value\n applying = true\n try {\n context.transact((tr) => applyShared(tr, shared, dirty, next), meta)\n } catch (error) {\n console.error(\n '[@dou-ui/sheet] could not apply a shared change; reading the workbook again',\n error,\n )\n try {\n context.transact((tr) => applyShared(tr, shared, { ...dirtyNone(), all: true }, next), meta)\n } catch (again) {\n console.error('[@dou-ui/sheet] could not read the shared workbook', again)\n }\n } finally {\n applying = false\n }\n layout = next\n if (dirty.all) {\n // the sheets were read anew, under new keys: once the grid has shown the sheet\n // again, put back the selection, e.g. the one bound with `v-model:selection`\n const sheet = context\n void nextTick(() => {\n const now = sheet.selection.value\n if (now.active.row !== kept.active.row || now.active.col !== kept.active.col)\n sheet.select(kept)\n })\n } else if (selected && !travelling && context.sheet.value.id === selected.sheet) {\n const view = readView(selected)\n const current = context.selection.value\n if (\n view?.active &&\n view.ranges.length &&\n (view.active.row !== current.active.row || view.active.col !== current.active.col)\n )\n context.select(selectionOf(view.active, view.ranges))\n }\n revision.value++\n // a line two people moved at once is in the list twice: everyone takes out the same one\n tidyLists(shared)\n }\n\n function tidyLists(shared: SharedParts) {\n const repeated: [Y.Array<string>, string[]][] = []\n const check = (list: Y.Array<string>, known: string[]) => {\n if (list.length !== known.length) repeated.push([list, known])\n }\n check(shared.order, Array.from(layout.sheets.keys()))\n for (const here of layout.sheets.values()) {\n const sheet = sheetParts(shared.sheets.get(here.id))\n if (!sheet) continue\n check(sheet.rows, here.rows.ids)\n check(sheet.cols, here.cols.ids)\n }\n if (!repeated.length) return\n queueMicrotask(() =>\n ydoc!.transact(() => {\n for (const [list] of repeated) {\n const items = list.toArray()\n const first = new Map<string, number>()\n items.forEach((id, i) => first.has(id) || first.set(id, i))\n for (let i = items.length - 1; i >= 0; i--)\n if (first.get(items[i]!) !== i) list.delete(i, 1)\n }\n }, untracked),\n )\n }\n\n function run(action: 'undo' | 'redo') {\n const stack = action === 'undo' ? undoManager.undoStack : undoManager.redoStack\n if (!stack.length) return false\n travelling = action\n restore = undefined\n try {\n undoManager[action]()\n } finally {\n travelling = null\n }\n // set by the undo manager while it ran\n const popped = restore as StoredView | undefined\n restore = undefined\n const view = popped && readView(popped)\n if (view && context && popped) {\n context.showSheet(popped.sheet)\n if (view.active && view.ranges.length) context.select(selectionOf(view.active, view.ranges))\n }\n return true\n }\n\n // Others --------------------------------------------------------------------------------\n\n const peers = shallowRef<SheetPeer[]>([])\n\n // Comments ------------------------------------------------------------------------------\n\n const commentMap = options.comments\n const sharedThreads = commentMap as SharedCommentMap | undefined\n const threads = shallowRef<readonly CommentThread[]>([])\n const readThreads = () => {\n if (sharedThreads) threads.value = readSharedComments(sharedThreads)\n }\n readThreads()\n\n return defineSheetExtension({\n name: 'collaboration',\n // after the other extensions, so it writes what they added\n priority: 0,\n transaction(tr) {\n if (applying || !parts) return\n // every sheet needs an id that stays when it is renamed, the same for everyone\n tr.doc.sheets.forEach((sheet, index) => {\n if (sheet.id != null) return\n let id = ids.next()\n while (tr.indexOf(id) !== -1) id = ids.next()\n tr.updateSheet({ id }, index)\n })\n const tracking = tr.meta.history !== false\n // like the grid's own history: only changes of one group undo together\n if (tracking && (!tr.meta.group || tr.meta.group !== lastGroup)) undoManager.stopCapturing()\n if (tracking) lastGroup = tr.meta.group\n const shared = parts\n ydoc.transact(() => writeChanges(tr, shared), tracking ? tracked : untracked)\n // the others' marks are kept by line ids: place them again\n if (tr.steps.some((step) => step.type.endsWith('Lines') || step.type.endsWith('Sheet')))\n revision.value++\n },\n comments: sharedThreads\n ? () => ({\n threads,\n apply: (action) => applySharedCommentAction(sharedThreads, action, untracked),\n })\n : undefined,\n history: () => ({\n undo: () => run('undo'),\n redo: () => run('redo'),\n canUndo: () => undoManager.undoStack.length > 0,\n canRedo: () => undoManager.redoStack.length > 0,\n }),\n // over the cells, under the grid's own marks, and kept out of the headers\n layers: awareness ? { below: [createPeers(peers)] } : undefined,\n setup(sheet) {\n context = sheet\n commentMap?.observe(readThreads)\n readThreads()\n parts = partsOf(book)\n if (!parts) {\n // the first to open the workbook brings its sheets, each with an id\n applying = true\n try {\n sheet.transact(\n (tr) =>\n tr.doc.sheets.forEach((data, index) => {\n if (data.id == null) tr.updateSheet({ id: ids.next() }, index)\n }),\n { history: false },\n )\n } finally {\n applying = false\n }\n ydoc.transact(() => fillBook(book, sheet.doc.value), untracked)\n parts = partsOf(book)\n if (parts) layout = readLayout(parts)\n } else {\n layout = new SheetLayout()\n pull({ ...dirtyNone(), all: true })\n }\n\n // changes from others, and from undo: applied once per Yjs transaction\n let dirty = dirtyNone()\n const observe = (events: Y.YEvent<any>[], transaction: Y.Transaction) => {\n if (transaction.origin === tracked || transaction.origin === untracked) return\n for (const event of events) collect(dirty, event)\n }\n const flush = () => {\n if (!isDirty(dirty)) return\n const changes = dirty\n dirty = dirtyNone()\n pull(changes)\n }\n book.observeDeep(observe)\n ydoc.on('afterTransaction', flush)\n\n let stopPresence: (() => void) | undefined\n let readPeers: (() => void) | undefined\n if (awareness) {\n readPeers = () => {\n const list: SheetPeer[] = []\n awareness.getStates().forEach((state, client) => {\n if (client === awareness.clientID) return\n const who = state.user as { name?: string; color?: string } | undefined\n const presence = state.sheet as SheetPresence | null | undefined\n if (!who || !presence) return\n const view = readView(presence)\n if (!view) return\n list.push({\n client,\n name: who.name ?? '',\n color: who.color ?? 'currentColor',\n sheet: presence.sheet,\n active: view.active,\n ranges: view.ranges,\n editing: !!presence.editing,\n })\n })\n peers.value = list\n }\n readPeers()\n awareness.on('change', readPeers)\n // the others' lines may have moved: read where they are again\n const stopRevision = watch(revision, () => readPeers?.())\n /*\n * Nothing is shared until this person first comes to the grid, so a\n * selection nobody made doesn't show on the others' screens. After\n * that it stays shared while the grid is not focused.\n */\n let arrived = false\n const stopShare = watch(\n () => [\n sheet.focused.value,\n sheet.sheet.value.id,\n sheet.selection.value,\n sheet.editor.cell.value,\n revision.value,\n ],\n () => {\n arrived ||= sheet.focused.value || !!sheet.editor.cell.value\n if (!arrived) return\n const id = sheet.sheet.value.id\n const view = id != null ? storeView(id, sheet.selection.value) : undefined\n awareness.setLocalStateField(\n 'sheet',\n view\n ? ({ ...view, editing: !!sheet.editor.cell.value } satisfies SheetPresence)\n : null,\n )\n },\n { immediate: true },\n )\n stopPresence = () => {\n stopRevision()\n stopShare()\n }\n }\n\n return () => {\n commentMap?.unobserve(readThreads)\n book.unobserveDeep(observe)\n ydoc.off('afterTransaction', flush)\n stopPresence?.()\n if (readPeers) awareness?.off('change', readPeers)\n awareness?.setLocalStateField('sheet', null)\n context = undefined\n }\n },\n })\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useSheet } from "../context.js";
|
|
2
|
+
import { defineComponent, h } from "vue";
|
|
3
|
+
import { PencilIcon } from "@dou-ui/icons";
|
|
4
|
+
// src/collaboration/peers.ts
|
|
5
|
+
var point = (p) => ({
|
|
6
|
+
top: p.row,
|
|
7
|
+
left: p.col,
|
|
8
|
+
bottom: p.row,
|
|
9
|
+
right: p.col
|
|
10
|
+
});
|
|
11
|
+
/** Edges the view cuts off are not drawn. */
|
|
12
|
+
var cutEdges = (cut) => ({
|
|
13
|
+
borderTopColor: cut.top ? "transparent" : void 0,
|
|
14
|
+
borderRightColor: cut.right ? "transparent" : void 0,
|
|
15
|
+
borderBottomColor: cut.bottom ? "transparent" : void 0,
|
|
16
|
+
borderLeftColor: cut.left ? "transparent" : void 0
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* A layer that shows the other people on the sheet shown, in their colors:
|
|
20
|
+
* a tint over what they have selected and a ring on their cell. Their name
|
|
21
|
+
* sits on the ring's corner, over the grid line rather than the cells'
|
|
22
|
+
* text; it fades a few seconds after they stop moving, and stays with a
|
|
23
|
+
* pencil while they edit.
|
|
24
|
+
*/
|
|
25
|
+
function createPeers(peers) {
|
|
26
|
+
return defineComponent({
|
|
27
|
+
name: "DouSheetPeers",
|
|
28
|
+
setup() {
|
|
29
|
+
const sheet = useSheet();
|
|
30
|
+
return () => {
|
|
31
|
+
const id = sheet.sheet.value.id;
|
|
32
|
+
const children = [];
|
|
33
|
+
for (const peer of peers.value) {
|
|
34
|
+
if (peer.sheet !== id) continue;
|
|
35
|
+
const style = { "--dou-sheet-peer": peer.color };
|
|
36
|
+
peer.ranges.forEach((bounds, i) => {
|
|
37
|
+
if (bounds.top === bounds.bottom && bounds.left === bounds.right) return;
|
|
38
|
+
const rect = sheet.rangeRect(bounds);
|
|
39
|
+
if (!rect) return;
|
|
40
|
+
children.push(h("div", {
|
|
41
|
+
key: `${peer.client}-${i}`,
|
|
42
|
+
class: "dou-sheet__peer-range",
|
|
43
|
+
style: {
|
|
44
|
+
...style,
|
|
45
|
+
left: `${rect.x}px`,
|
|
46
|
+
top: `${rect.y}px`,
|
|
47
|
+
width: `${rect.width}px`,
|
|
48
|
+
height: `${rect.height}px`,
|
|
49
|
+
...cutEdges(rect.cut)
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
});
|
|
53
|
+
const active = peer.active;
|
|
54
|
+
const shown = active && sheet.rangeRect(point(active));
|
|
55
|
+
if (!active || !shown) continue;
|
|
56
|
+
const rect = shown.cut.top || shown.cut.right || shown.cut.bottom || shown.cut.left ? shown : sheet.cellRect(active) ?? shown;
|
|
57
|
+
const above = active.row > 0 && !!sheet.rangeRect(point({
|
|
58
|
+
...active,
|
|
59
|
+
row: active.row - 1
|
|
60
|
+
}));
|
|
61
|
+
children.push(h("div", {
|
|
62
|
+
key: `${peer.client}-active`,
|
|
63
|
+
class: ["dou-sheet__peer-cell", { "is-editing": peer.editing }],
|
|
64
|
+
style: {
|
|
65
|
+
...style,
|
|
66
|
+
left: `${rect.x}px`,
|
|
67
|
+
top: `${rect.y}px`,
|
|
68
|
+
width: `${rect.width}px`,
|
|
69
|
+
height: `${rect.height}px`,
|
|
70
|
+
...cutEdges(shown.cut)
|
|
71
|
+
}
|
|
72
|
+
}, h("span", {
|
|
73
|
+
key: `${active.row}:${active.col}:${peer.editing}`,
|
|
74
|
+
class: ["dou-sheet__peer-name", above ? "is-above" : "is-below"]
|
|
75
|
+
}, [peer.editing ? h(PencilIcon, { class: "dou-sheet__peer-icon" }) : null, peer.name])));
|
|
76
|
+
}
|
|
77
|
+
return h("div", {
|
|
78
|
+
class: "dou-sheet__peers",
|
|
79
|
+
"aria-hidden": "true"
|
|
80
|
+
}, children);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
export { createPeers };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=peers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peers.js","names":[],"sources":["../../src/collaboration/peers.ts"],"sourcesContent":["import { PencilIcon } from '@dou-ui/icons'\nimport { defineComponent, h, type Component, type Ref, type VNode } from 'vue'\nimport type { SheetBounds, SheetPoint } from '../core/address'\nimport { useSheet, type SheetRangeRect } from '../context'\n\n/** A person editing the workbook too, with where they are, in this side's numbers. */\nexport interface SheetPeer {\n client: number\n name: string\n color: string\n /** The `id` of the sheet they have open. */\n sheet: string\n active: SheetPoint | null\n ranges: SheetBounds[]\n editing: boolean\n}\n\nconst point = (p: SheetPoint): SheetBounds => ({\n top: p.row,\n left: p.col,\n bottom: p.row,\n right: p.col,\n})\n\n/** Edges the view cuts off are not drawn. */\nconst cutEdges = (cut: SheetRangeRect['cut']) => ({\n borderTopColor: cut.top ? 'transparent' : undefined,\n borderRightColor: cut.right ? 'transparent' : undefined,\n borderBottomColor: cut.bottom ? 'transparent' : undefined,\n borderLeftColor: cut.left ? 'transparent' : undefined,\n})\n\n/**\n * A layer that shows the other people on the sheet shown, in their colors:\n * a tint over what they have selected and a ring on their cell. Their name\n * sits on the ring's corner, over the grid line rather than the cells'\n * text; it fades a few seconds after they stop moving, and stays with a\n * pencil while they edit.\n */\nexport function createPeers(peers: Ref<SheetPeer[]>): Component {\n return defineComponent({\n name: 'DouSheetPeers',\n setup() {\n const sheet = useSheet()\n return () => {\n const id = sheet.sheet.value.id\n const children: VNode[] = []\n for (const peer of peers.value) {\n if (peer.sheet !== id) continue\n const style = { '--dou-sheet-peer': peer.color }\n peer.ranges.forEach((bounds, i) => {\n // one cell is the ring alone\n if (bounds.top === bounds.bottom && bounds.left === bounds.right) return\n const rect = sheet.rangeRect(bounds)\n if (!rect) return\n children.push(\n h('div', {\n key: `${peer.client}-${i}`,\n class: 'dou-sheet__peer-range',\n style: {\n ...style,\n left: `${rect.x}px`,\n top: `${rect.y}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n ...cutEdges(rect.cut),\n },\n }),\n )\n })\n const active = peer.active\n // the cell as big as its merge, or only the part out from under the frozen panes\n const shown = active && sheet.rangeRect(point(active))\n if (!active || !shown) continue\n const cut = shown.cut.top || shown.cut.right || shown.cut.bottom || shown.cut.left\n const rect = cut ? shown : (sheet.cellRect(active) ?? shown)\n // the name sits on the top edge, or on the bottom edge at the top of the view\n const above =\n active.row > 0 && !!sheet.rangeRect(point({ ...active, row: active.row - 1 }))\n children.push(\n h(\n 'div',\n {\n key: `${peer.client}-active`,\n class: ['dou-sheet__peer-cell', { 'is-editing': peer.editing }],\n style: {\n ...style,\n left: `${rect.x}px`,\n top: `${rect.y}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n ...cutEdges(shown.cut),\n },\n },\n // a new key each time they move or start editing shows the name again\n h(\n 'span',\n {\n key: `${active.row}:${active.col}:${peer.editing}`,\n class: ['dou-sheet__peer-name', above ? 'is-above' : 'is-below'],\n },\n [peer.editing ? h(PencilIcon, { class: 'dou-sheet__peer-icon' }) : null, peer.name],\n ),\n ),\n )\n }\n return h('div', { class: 'dou-sheet__peers', 'aria-hidden': 'true' }, children)\n }\n },\n })\n}\n"],"mappings":";;;;AAiBA,IAAM,SAAS,OAAgC;CAC7C,KAAK,EAAE;CACP,MAAM,EAAE;CACR,QAAQ,EAAE;CACV,OAAO,EAAE;AACX;;AAGA,IAAM,YAAY,SAAgC;CAChD,gBAAgB,IAAI,MAAM,gBAAgB,KAAA;CAC1C,kBAAkB,IAAI,QAAQ,gBAAgB,KAAA;CAC9C,mBAAmB,IAAI,SAAS,gBAAgB,KAAA;CAChD,iBAAiB,IAAI,OAAO,gBAAgB,KAAA;AAC9C;;;;;;;;AASA,SAAgB,YAAY,OAAoC;CAC9D,OAAO,gBAAgB;EACrB,MAAM;EACN,QAAQ;GACN,MAAM,QAAQ,SAAS;GACvB,aAAa;IACX,MAAM,KAAK,MAAM,MAAM,MAAM;IAC7B,MAAM,WAAoB,CAAC;IAC3B,KAAK,MAAM,QAAQ,MAAM,OAAO;KAC9B,IAAI,KAAK,UAAU,IAAI;KACvB,MAAM,QAAQ,EAAE,oBAAoB,KAAK,MAAM;KAC/C,KAAK,OAAO,SAAS,QAAQ,MAAM;MAEjC,IAAI,OAAO,QAAQ,OAAO,UAAU,OAAO,SAAS,OAAO,OAAO;MAClE,MAAM,OAAO,MAAM,UAAU,MAAM;MACnC,IAAI,CAAC,MAAM;MACX,SAAS,KACP,EAAE,OAAO;OACP,KAAK,GAAG,KAAK,OAAO,GAAG;OACvB,OAAO;OACP,OAAO;QACL,GAAG;QACH,MAAM,GAAG,KAAK,EAAE;QAChB,KAAK,GAAG,KAAK,EAAE;QACf,OAAO,GAAG,KAAK,MAAM;QACrB,QAAQ,GAAG,KAAK,OAAO;QACvB,GAAG,SAAS,KAAK,GAAG;OACtB;MACF,CAAC,CACH;KACF,CAAC;KACD,MAAM,SAAS,KAAK;KAEpB,MAAM,QAAQ,UAAU,MAAM,UAAU,MAAM,MAAM,CAAC;KACrD,IAAI,CAAC,UAAU,CAAC,OAAO;KAEvB,MAAM,OADM,MAAM,IAAI,OAAO,MAAM,IAAI,SAAS,MAAM,IAAI,UAAU,MAAM,IAAI,OAC3D,QAAS,MAAM,SAAS,MAAM,KAAK;KAEtD,MAAM,QACJ,OAAO,MAAM,KAAK,CAAC,CAAC,MAAM,UAAU,MAAM;MAAE,GAAG;MAAQ,KAAK,OAAO,MAAM;KAAE,CAAC,CAAC;KAC/E,SAAS,KACP,EACE,OACA;MACE,KAAK,GAAG,KAAK,OAAO;MACpB,OAAO,CAAC,wBAAwB,EAAE,cAAc,KAAK,QAAQ,CAAC;MAC9D,OAAO;OACL,GAAG;OACH,MAAM,GAAG,KAAK,EAAE;OAChB,KAAK,GAAG,KAAK,EAAE;OACf,OAAO,GAAG,KAAK,MAAM;OACrB,QAAQ,GAAG,KAAK,OAAO;OACvB,GAAG,SAAS,MAAM,GAAG;MACvB;KACF,GAEA,EACE,QACA;MACE,KAAK,GAAG,OAAO,IAAI,GAAG,OAAO,IAAI,GAAG,KAAK;MACzC,OAAO,CAAC,wBAAwB,QAAQ,aAAa,UAAU;KACjE,GACA,CAAC,KAAK,UAAU,EAAE,YAAY,EAAE,OAAO,uBAAuB,CAAC,IAAI,MAAM,KAAK,IAAI,CACpF,CACF,CACF;IACF;IACA,OAAO,EAAE,OAAO;KAAE,OAAO;KAAoB,eAAe;IAAO,GAAG,QAAQ;GAChF;EACF;CACF,CAAC;AACH"}
|