@pixerate/editor-svelte 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/canvas/ShapeNode.svelte +57 -0
- package/dist/canvas/ShapeNode.svelte.d.ts +21 -0
- package/dist/canvas/ShapeNode.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasArrange.svelte.d.ts +7 -0
- package/dist/canvas/createCanvasArrange.svelte.d.ts.map +1 -1
- package/dist/canvas/index.d.ts +2 -0
- package/dist/canvas/index.d.ts.map +1 -1
- package/dist/canvas/index.js +3 -0
- package/dist/review/ReviewToolbar.svelte +15 -0
- package/dist/review/ReviewToolbar.svelte.d.ts +4 -0
- package/dist/review/ReviewToolbar.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/FormulaBar.svelte +12 -1
- package/dist/spreadsheet/FormulaBar.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte +21 -2
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts +1 -1
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/SpreadsheetEditor.svelte +45 -4
- package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/SpreadsheetGroupRow.svelte +1 -1
- package/dist/spreadsheet/spreadsheet.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/tableInteractions.d.ts.map +1 -1
- package/dist/spreadsheet/tableInteractions.js +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ Requires **Svelte 5** (the components use runes). Components ship as `.svelte` s
|
|
|
37
37
|
|
|
38
38
|
`content` sets the initial document. Read later changes from the bound `editor` (for example in `onUpdate`), as above. The editor is preloaded with `createRichTextPreset()`. Pass `markdown`, `image`, `uploadImage`, `extensions` or `richTextOptions` to configure it.
|
|
39
39
|
|
|
40
|
-
`fileImport` imports dropped/pasted `.md`, `.html`, `.txt` and `.
|
|
40
|
+
`fileImport` imports dropped/pasted `.md`, `.html`, `.txt`, `.rtf` and `.docx` files (plus any adapter you register, e.g. PDF or zipped exports) at the drop position, and `richClipboard` copies lossless slices between editors (both opt-in). `createFileImport(() => editor)` returns reactive `isImporting` / `error` plus `openFilePicker()` and `importFiles()` for an import button.
|
|
41
41
|
|
|
42
42
|
`useAgentToolProvider(registry, () => editor && createRichTextToolProvider(editor, { id: "doc" }))` registers an agent tool provider (see `ToolRegistry` in `@pixerate/editor/agent`) for the component's lifetime. Call it during component initialisation.
|
|
43
43
|
|
|
@@ -67,7 +67,7 @@ Requires **Svelte 5** (the components use runes). Components ship as `.svelte` s
|
|
|
67
67
|
<CommentsPanel {editor} />
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
Put `<CommentButton {editor} />` inside a `BubbleMenu` to comment on the selection. `createComments(editorOrStore)` and `createTrackChanges(editor)` are rune (and Svelte store) adapters for custom UIs.
|
|
70
|
+
`ReviewToolbar` steps through insertions, deletions, formatting and block changes and shows the current one's author and description (e.g. "Ada: Formatted: Bold"); hide it with `showDescription={false}` or restyle it with `descriptionClass`. Put `<CommentButton {editor} />` inside a `BubbleMenu` to comment on the selection. `createComments(editorOrStore)` and `createTrackChanges(editor)` are rune (and Svelte store) adapters for custom UIs.
|
|
71
71
|
|
|
72
72
|
## More exports
|
|
73
73
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import { getShapeRenderData, isShapeDescription, type ShapeDescription } from '@pixerate/editor/canvas';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
/** Node data; `data.shape` holds the shape description. */
|
|
7
|
+
data: { shape?: ShapeDescription; [key: string]: any };
|
|
8
|
+
/** Node width / height (SvelteFlow passes them to custom nodes). */
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
class?: string;
|
|
13
|
+
/** Rendered over the shape, e.g. SvelteFlow `<Handle>`s or a label. */
|
|
14
|
+
children?: Snippet;
|
|
15
|
+
[key: string]: any;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let { data, width, height, selected = false, class: className = '', children }: Props = $props();
|
|
19
|
+
|
|
20
|
+
const shape = $derived(isShapeDescription(data?.shape) ? data.shape : null);
|
|
21
|
+
const render = $derived(shape ? getShapeRenderData(shape, { width, height }) : null);
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<!--
|
|
25
|
+
Headless shape node: draws `data.shape` as one SVG path that fills the node box.
|
|
26
|
+
Register it as a SvelteFlow node type (`nodeTypes={{ shape: ShapeNode }}`), or wrap it
|
|
27
|
+
to add handles. Strokes keep their width when the node is resized.
|
|
28
|
+
-->
|
|
29
|
+
{#if shape && render}
|
|
30
|
+
<div
|
|
31
|
+
class="pixerate-shape-node {className}"
|
|
32
|
+
data-shape-kind={shape.kind}
|
|
33
|
+
data-selected={selected ? 'true' : undefined}
|
|
34
|
+
style="position: relative; width: 100%; height: 100%;"
|
|
35
|
+
>
|
|
36
|
+
<svg
|
|
37
|
+
viewBox={render.viewBox}
|
|
38
|
+
preserveAspectRatio="none"
|
|
39
|
+
width="100%"
|
|
40
|
+
height="100%"
|
|
41
|
+
style="display: block; overflow: visible;"
|
|
42
|
+
aria-hidden="true"
|
|
43
|
+
>
|
|
44
|
+
<path
|
|
45
|
+
d={render.d}
|
|
46
|
+
transform={render.transform}
|
|
47
|
+
fill={render.fill}
|
|
48
|
+
fill-rule={render.fillRule}
|
|
49
|
+
stroke={render.stroke}
|
|
50
|
+
stroke-width={render.strokeWidth}
|
|
51
|
+
opacity={render.opacity}
|
|
52
|
+
vector-effect="non-scaling-stroke"
|
|
53
|
+
/>
|
|
54
|
+
</svg>
|
|
55
|
+
{@render children?.()}
|
|
56
|
+
</div>
|
|
57
|
+
{/if}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type ShapeDescription } from '@pixerate/editor/canvas';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** Node data; `data.shape` holds the shape description. */
|
|
5
|
+
data: {
|
|
6
|
+
shape?: ShapeDescription;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
};
|
|
9
|
+
/** Node width / height (SvelteFlow passes them to custom nodes). */
|
|
10
|
+
width?: number;
|
|
11
|
+
height?: number;
|
|
12
|
+
selected?: boolean;
|
|
13
|
+
class?: string;
|
|
14
|
+
/** Rendered over the shape, e.g. SvelteFlow `<Handle>`s or a label. */
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
declare const ShapeNode: import("svelte").Component<Props, {}, "">;
|
|
19
|
+
type ShapeNode = ReturnType<typeof ShapeNode>;
|
|
20
|
+
export default ShapeNode;
|
|
21
|
+
//# sourceMappingURL=ShapeNode.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShapeNode.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/ShapeNode.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAA0C,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGvG,UAAU,KAAK;IACd,2DAA2D;IAC3D,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,gBAAgB,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvD,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACnB;AAwBF,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
|
@@ -33,6 +33,13 @@ export declare function createCanvasArrange<TNode extends CanvasNode = CanvasNod
|
|
|
33
33
|
unlock: (ids?: Iterable<string>) => string[];
|
|
34
34
|
toggleLock(ids?: Iterable<string>): string[];
|
|
35
35
|
isLocked: (id: string) => boolean;
|
|
36
|
+
combineShapes(operation: import("@pixerate/editor/canvas").ShapeOperation, ids?: Iterable<string>, combineOptions?: import("@pixerate/editor/canvas").CombineShapeNodesOptions): import("@pixerate/editor/canvas").CombineShapeNodesResult<any>;
|
|
37
|
+
unite: (ids?: Iterable<string>, o?: import("@pixerate/editor/canvas").CombineShapeNodesOptions) => import("@pixerate/editor/canvas").CombineShapeNodesResult<any>;
|
|
38
|
+
intersect: (ids?: Iterable<string>, o?: import("@pixerate/editor/canvas").CombineShapeNodesOptions) => import("@pixerate/editor/canvas").CombineShapeNodesResult<any>;
|
|
39
|
+
subtract: (ids?: Iterable<string>, o?: import("@pixerate/editor/canvas").CombineShapeNodesOptions) => import("@pixerate/editor/canvas").CombineShapeNodesResult<any>;
|
|
40
|
+
exclude: (ids?: Iterable<string>, o?: import("@pixerate/editor/canvas").CombineShapeNodesOptions) => import("@pixerate/editor/canvas").CombineShapeNodesResult<any>;
|
|
41
|
+
divide: (ids?: Iterable<string>, o?: import("@pixerate/editor/canvas").CombineShapeNodesOptions) => import("@pixerate/editor/canvas").CombineShapeNodesResult<any>;
|
|
42
|
+
canCombineShapes: (ids?: Iterable<string>) => boolean;
|
|
36
43
|
runAction(action: CanvasArrangeAction): boolean;
|
|
37
44
|
beginDrag(ids?: Iterable<string>): void;
|
|
38
45
|
drag(ids?: Iterable<string>): import("@pixerate/editor/canvas").SnapNodeDragResult | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasArrange.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasArrange.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,SAAS,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;AAEvD,MAAM,WAAW,0BAA0B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CAChF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACrE,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EACxE,OAAO,EAAE,0BAA0B,CAAC,KAAK,CAAC;;;;;;;
|
|
1
|
+
{"version":3,"file":"createCanvasArrange.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasArrange.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,SAAS,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;AAEvD,MAAM,WAAW,0BAA0B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CAChF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACrE,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EACxE,OAAO,EAAE,0BAA0B,CAAC,KAAK,CAAC;;;;;;;sBA2D2rlD,CAAC;sBAAiE,CAAC;sBAAiE,CAAC;oBAA+D,CAAC;cAAyD,CAAC;gBAAiD,CAAC;;;;;;;;;0BAA8tC,CAAC;;;;;;EAxCrvoD;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,IAAI,UAAU,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;AAEjH,MAAM,WAAW,6BAA6B;IAC7C,OAAO,EAAE;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,OAAO,CAAA;KAAE,CAAC;IACjE,uEAAuE;IACvE,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC;IAC1D,aAAa,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IACrC,QAAQ,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,6BAA6B,GAAG,MAAM,IAAI,CAqB/F"}
|
package/dist/canvas/index.d.ts
CHANGED
|
@@ -18,5 +18,7 @@ export { createCanvasArrange, createCanvasArrangeShortcuts, type CanvasArrange,
|
|
|
18
18
|
export { createCanvasScenes, type CanvasScenes, type CreateCanvasScenesOptions } from './createCanvasScenes.svelte.js';
|
|
19
19
|
export { default as CanvasGuidesLayer } from './CanvasGuidesLayer.svelte';
|
|
20
20
|
export { alignNodes, distributeNodes, matchSize, reorderNodes, applyNodeUpdates, invertNodeUpdates, lockNodes, unlockNodes, toggleLockNodes, isLocked, getNodeSize, getNodeRect, getAbsolutePosition, readStyleSize, withStyleSize, computeSnapGuides, createGuideIndex, createNodeGuideIndex, snapNodeDrag, findConnectorSnap, nearestHandlePositions, handlePoint, positionToSide, sideToPosition, oppositePosition, CONNECTION_LINE_TYPES, CanvasScenesStore, createCanvasScenesStore, parseCanvasScenes, fitViewportToRect, fitViewportToNodes, matchArrangeShortcut, DEFAULT_ARRANGE_SHORTCUTS, type AlignEdge, type DistributeAxis, type DistributeMode, type SizeDimension, type ZOrderOperation, type CanvasNodeUpdate, type GuideLine, type GuideIndex, type SnapGuidesOptions, type SnapResult, type ConnectorSnap, type ConnectorSnapTarget, type CanvasConnectionLineType, type CanvasScene, type CanvasScenesState, type CanvasViewport, type CanvasArrangeAction, type ArrangeShortcutBinding } from '@pixerate/editor/canvas';
|
|
21
|
+
export { default as ShapeNode } from './ShapeNode.svelte';
|
|
22
|
+
export { combineShapeNodes, canCombineShapeNodes, applyShapeCombination, revertShapeCombination, shapeNodeToPolygon, isShapeNode, getNodeShape, SHAPE_DATA_KEY, SHAPE_NODE_TYPE, SHAPE_OPERATIONS, SHAPE_KINDS, isShapeDescription, shapeToPolygon, getShapeSvg, getShapeRenderData, parseSvgPath, flattenSvgPath, polygonToSvgPath, simplifyRing, polygonBoolean, unionPolygons, intersectPolygons, subtractPolygons, xorPolygons, dividePolygons, polygonArea, multiPolygonArea, multiPolygonBounds, ringSignedArea, pointInRings, pointInMultiPolygon, type ShapeOperation, type ShapeDescription, type ShapeKind, type ShapePaint, type ShapeSize, type ShapeRenderData, type RectShape, type EllipseShape, type RegularPolygonShape, type StarShape, type PathShape, type PathCommand, type FlattenOptions, type PolygonToPathOptions, type CombineShapeNodesOptions, type CombineShapeNodesResult, type CombineShapeNodesRefusal, type ShapeNodePolygonOptions, type MultiPolygon, type PolygonWithHoles, type PolygonRing, type PolygonFillRule, type PolygonOperand, type PolygonInput, type PolygonPiece, type PolygonBooleanOperation, type PolygonBooleanOptions } from '@pixerate/editor/canvas';
|
|
21
23
|
export { realClock, ManualClock, layoutBounds, canvasHeight, estimateCanvasHeight, blendLayout, connectedOnly, type Clock, type CanvasHeightOptions } from '@pixerate/editor/canvas';
|
|
22
24
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/canvas/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/canvas/index.ts"],"names":[],"mappings":"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"}
|
package/dist/canvas/index.js
CHANGED
|
@@ -35,5 +35,8 @@ export { createCanvasArrange, createCanvasArrangeShortcuts } from './createCanva
|
|
|
35
35
|
export { createCanvasScenes } from './createCanvasScenes.svelte.js';
|
|
36
36
|
export { default as CanvasGuidesLayer } from './CanvasGuidesLayer.svelte';
|
|
37
37
|
export { alignNodes, distributeNodes, matchSize, reorderNodes, applyNodeUpdates, invertNodeUpdates, lockNodes, unlockNodes, toggleLockNodes, isLocked, getNodeSize, getNodeRect, getAbsolutePosition, readStyleSize, withStyleSize, computeSnapGuides, createGuideIndex, createNodeGuideIndex, snapNodeDrag, findConnectorSnap, nearestHandlePositions, handlePoint, positionToSide, sideToPosition, oppositePosition, CONNECTION_LINE_TYPES, CanvasScenesStore, createCanvasScenesStore, parseCanvasScenes, fitViewportToRect, fitViewportToNodes, matchArrangeShortcut, DEFAULT_ARRANGE_SHORTCUTS } from '@pixerate/editor/canvas';
|
|
38
|
+
export { default as ShapeNode } from './ShapeNode.svelte';
|
|
39
|
+
// Shape nodes and boolean operations (Unite / Intersect / Subtract / Exclude / Divide)
|
|
40
|
+
export { combineShapeNodes, canCombineShapeNodes, applyShapeCombination, revertShapeCombination, shapeNodeToPolygon, isShapeNode, getNodeShape, SHAPE_DATA_KEY, SHAPE_NODE_TYPE, SHAPE_OPERATIONS, SHAPE_KINDS, isShapeDescription, shapeToPolygon, getShapeSvg, getShapeRenderData, parseSvgPath, flattenSvgPath, polygonToSvgPath, simplifyRing, polygonBoolean, unionPolygons, intersectPolygons, subtractPolygons, xorPolygons, dividePolygons, polygonArea, multiPolygonArea, multiPolygonBounds, ringSignedArea, pointInRings, pointInMultiPolygon } from '@pixerate/editor/canvas';
|
|
38
41
|
// Clock and view helpers from core
|
|
39
42
|
export { realClock, ManualClock, layoutBounds, canvasHeight, estimateCanvasHeight, blendLayout, connectedOnly } from '@pixerate/editor/canvas';
|
|
@@ -5,11 +5,17 @@
|
|
|
5
5
|
interface Props {
|
|
6
6
|
editor?: Editor | null;
|
|
7
7
|
class?: string;
|
|
8
|
+
/** Show the current change's author and description. Defaults to `true`. */
|
|
9
|
+
showDescription?: boolean;
|
|
10
|
+
/** Class of the description label. */
|
|
11
|
+
descriptionClass?: string;
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
let {
|
|
11
15
|
editor = null,
|
|
12
16
|
class: className = "flex flex-wrap items-center gap-1 rounded-md border border-border bg-background p-1 text-sm",
|
|
17
|
+
showDescription = true,
|
|
18
|
+
descriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground",
|
|
13
19
|
}: Props = $props();
|
|
14
20
|
|
|
15
21
|
const buttonClass =
|
|
@@ -60,6 +66,15 @@
|
|
|
60
66
|
>
|
|
61
67
|
›
|
|
62
68
|
</button>
|
|
69
|
+
{#if showDescription && current}
|
|
70
|
+
<span
|
|
71
|
+
class={descriptionClass}
|
|
72
|
+
data-change-type={current.type}
|
|
73
|
+
title={`${current.author.name}: ${current.description}`}
|
|
74
|
+
>
|
|
75
|
+
{current.author.name ? `${current.author.name}: ` : ""}{current.description}
|
|
76
|
+
</span>
|
|
77
|
+
{/if}
|
|
63
78
|
<span class="mx-1 h-4 w-px bg-border" aria-hidden="true"></span>
|
|
64
79
|
<button
|
|
65
80
|
type="button"
|
|
@@ -2,6 +2,10 @@ import type { Editor } from "@tiptap/core";
|
|
|
2
2
|
interface Props {
|
|
3
3
|
editor?: Editor | null;
|
|
4
4
|
class?: string;
|
|
5
|
+
/** Show the current change's author and description. Defaults to `true`. */
|
|
6
|
+
showDescription?: boolean;
|
|
7
|
+
/** Class of the description label. */
|
|
8
|
+
descriptionClass?: string;
|
|
5
9
|
}
|
|
6
10
|
declare const ReviewToolbar: import("svelte").Component<Props, {}, "">;
|
|
7
11
|
type ReviewToolbar = ReturnType<typeof ReviewToolbar>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReviewToolbar.svelte.d.ts","sourceRoot":"","sources":["../../src/review/ReviewToolbar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAIzC,UAAU,KAAK;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"ReviewToolbar.svelte.d.ts","sourceRoot":"","sources":["../../src/review/ReviewToolbar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAIzC,UAAU,KAAK;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAiEH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -46,6 +46,15 @@
|
|
|
46
46
|
return value;
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
+
// A spilled cell shows its anchor's formula greyed out (it has no formula of its own).
|
|
50
|
+
let spillFormula = $derived.by(() => {
|
|
51
|
+
if (!sheetState || sheetState.editingCell || !sheetState.activeCell || effectiveValue) return '';
|
|
52
|
+
void sheetState.document;
|
|
53
|
+
const { row, col } = sheetState.activeCell;
|
|
54
|
+
const spill = sheetState.controller.getSpillAt(row, col);
|
|
55
|
+
return spill && (spill.anchor.row !== row || spill.anchor.col !== col) ? spill.formula : '';
|
|
56
|
+
});
|
|
57
|
+
|
|
49
58
|
function handleKeyDown(e: KeyboardEvent) {
|
|
50
59
|
// Keys typed here must not reach the grid's navigation handler.
|
|
51
60
|
e.stopPropagation();
|
|
@@ -101,7 +110,9 @@
|
|
|
101
110
|
placeholder="Enter a value or formula (e.g. =SUM(A1:A5))"
|
|
102
111
|
aria-label="Formula bar"
|
|
103
112
|
bind:this={inputEl}
|
|
104
|
-
|
|
113
|
+
data-spill-formula={spillFormula ? 'true' : undefined}
|
|
114
|
+
style={spillFormula ? 'color: var(--muted-foreground, #94a3b8);' : undefined}
|
|
115
|
+
value={effectiveValue || spillFormula}
|
|
105
116
|
oninput={handleInput}
|
|
106
117
|
onkeydown={handleKeyDown}
|
|
107
118
|
/>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormulaBar.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/FormulaBar.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIvE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"FormulaBar.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/FormulaBar.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIvE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAwGH,QAAA,MAAM,UAAU,gDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type
|
|
2
|
+
import { clampMenuPosition, type SpreadsheetMenuItem } from '@pixerate/editor/spreadsheet';
|
|
3
|
+
|
|
4
|
+
// Gap kept between the menu and the viewport edges.
|
|
5
|
+
const VIEWPORT_MARGIN = 4;
|
|
3
6
|
|
|
4
7
|
interface Props {
|
|
5
8
|
items: SpreadsheetMenuItem[];
|
|
@@ -10,6 +13,22 @@
|
|
|
10
13
|
|
|
11
14
|
let { items, x, y, onClose }: Props = $props();
|
|
12
15
|
let menuEl = $state<HTMLDivElement | null>(null);
|
|
16
|
+
let measured = $state<{ x: number; y: number } | null>(null);
|
|
17
|
+
const position = $derived(measured ?? { x, y });
|
|
18
|
+
|
|
19
|
+
// Keep the (fixed) menu inside the viewport: near the right or bottom edge
|
|
20
|
+
// it opens to the left of / above the pointer instead of being cut off.
|
|
21
|
+
$effect(() => {
|
|
22
|
+
void items; // re-measure when the items change
|
|
23
|
+
if (!menuEl || typeof window === 'undefined') return;
|
|
24
|
+
const { width, height } = menuEl.getBoundingClientRect();
|
|
25
|
+
measured = clampMenuPosition(
|
|
26
|
+
{ x, y },
|
|
27
|
+
{ width, height },
|
|
28
|
+
{ width: window.innerWidth, height: window.innerHeight },
|
|
29
|
+
VIEWPORT_MARGIN
|
|
30
|
+
);
|
|
31
|
+
});
|
|
13
32
|
|
|
14
33
|
// Close on outside press or Escape.
|
|
15
34
|
$effect(() => {
|
|
@@ -35,7 +54,7 @@
|
|
|
35
54
|
aria-label="Table actions"
|
|
36
55
|
tabindex="-1"
|
|
37
56
|
class="fixed z-50 min-w-[14rem] rounded-md border border-border bg-popover py-1 text-xs text-popover-foreground shadow-lg"
|
|
38
|
-
style="left: {x}px; top: {y}px; background: var(--popover, var(--background, #fff));"
|
|
57
|
+
style="left: {position.x}px; top: {position.y}px; max-height: calc(100vh - {VIEWPORT_MARGIN * 2}px); overflow-y: auto; background: var(--popover, var(--background, #fff));"
|
|
39
58
|
oncontextmenu={(e) => e.preventDefault()}
|
|
40
59
|
onkeydown={(e) => e.stopPropagation()}
|
|
41
60
|
>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpreadsheetContextMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetContextMenu.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"SpreadsheetContextMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetContextMenu.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGzF,UAAU,KAAK;IACb,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA6DH,QAAA,MAAM,sBAAsB,2CAAwC,CAAC;AACrE,KAAK,sBAAsB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACxE,eAAe,sBAAsB,CAAC"}
|
|
@@ -51,6 +51,18 @@
|
|
|
51
51
|
|
|
52
52
|
let gridContainer = $state<HTMLDivElement | null>(null);
|
|
53
53
|
let cellInput = $state<HTMLInputElement | null>(null);
|
|
54
|
+
|
|
55
|
+
// Focus the cell editor when it opens, with the caret after the draft
|
|
56
|
+
// (e.g. the key that started editing), so typing goes into the cell.
|
|
57
|
+
$effect(() => {
|
|
58
|
+
if (!cellInput) return;
|
|
59
|
+
// Editing started from the formula bar keeps focus there.
|
|
60
|
+
const active = typeof document !== 'undefined' ? document.activeElement : null;
|
|
61
|
+
if (active instanceof HTMLInputElement && active !== cellInput) return;
|
|
62
|
+
cellInput.focus();
|
|
63
|
+
const end = cellInput.value.length;
|
|
64
|
+
cellInput.setSelectionRange(end, end);
|
|
65
|
+
});
|
|
54
66
|
let resizingColId = $state<string | null>(null);
|
|
55
67
|
let hoveredColId = $state<string | null>(null);
|
|
56
68
|
let resizeStartX = $state(0);
|
|
@@ -76,6 +88,24 @@
|
|
|
76
88
|
return new Set(filter?.enabled ? filter.rules.map((r) => r.colId) : []);
|
|
77
89
|
});
|
|
78
90
|
let selection = $derived(sheetState.selectedRange ? normalizeRange(sheetState.selectedRange) : null);
|
|
91
|
+
// The dynamic array under the active cell (anchor or spilled cell) gets a border.
|
|
92
|
+
let activeSpill = $derived.by(() => {
|
|
93
|
+
void sheetState.document;
|
|
94
|
+
const cell = sheetState.activeCell;
|
|
95
|
+
return cell ? sheetState.controller.getSpillAt(cell.row, cell.col) : null;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
/** Thin border drawn on the outer edges of a dynamic array's spill range. */
|
|
99
|
+
function spillBorderStyle(range: CellRange, row: number, col: number): string {
|
|
100
|
+
const line = '1px solid color-mix(in srgb, var(--primary, #6366f1) 60%, transparent)';
|
|
101
|
+
return (
|
|
102
|
+
'position: absolute; inset: 0; pointer-events: none; z-index: 5;' +
|
|
103
|
+
(row === range.startRow ? ` border-top: ${line};` : '') +
|
|
104
|
+
(row === range.endRow ? ` border-bottom: ${line};` : '') +
|
|
105
|
+
(col === range.startCol ? ` border-left: ${line};` : '') +
|
|
106
|
+
(col === range.endCol ? ` border-right: ${line};` : '')
|
|
107
|
+
);
|
|
108
|
+
}
|
|
79
109
|
|
|
80
110
|
/** Fill handle: press, move over cells, release to autofill (one undo step). */
|
|
81
111
|
function startFill(e: MouseEvent) {
|
|
@@ -138,15 +168,21 @@
|
|
|
138
168
|
function handleKeyDown(e: KeyboardEvent) {
|
|
139
169
|
if (sheetState.editingCell) {
|
|
140
170
|
if (e.key === 'Escape') {
|
|
171
|
+
e.preventDefault();
|
|
141
172
|
sheetState.cancelEditing();
|
|
142
173
|
} else if (e.key === 'Enter') {
|
|
174
|
+
e.preventDefault();
|
|
143
175
|
sheetState.commitEditing();
|
|
144
176
|
sheetState.moveCursor('down');
|
|
145
177
|
} else if (e.key === 'Tab') {
|
|
146
178
|
e.preventDefault();
|
|
147
179
|
sheetState.commitEditing();
|
|
148
180
|
sheetState.moveCursor(e.shiftKey ? 'left' : 'right');
|
|
181
|
+
} else {
|
|
182
|
+
return;
|
|
149
183
|
}
|
|
184
|
+
// The cell input unmounts; keep focus on the grid so typing continues.
|
|
185
|
+
gridContainer?.focus();
|
|
150
186
|
return;
|
|
151
187
|
}
|
|
152
188
|
|
|
@@ -200,6 +236,9 @@
|
|
|
200
236
|
// Direct typing into cell starts editing
|
|
201
237
|
const col = sheetState.document.columns[sheetState.activeCell.col];
|
|
202
238
|
if (!col?.readOnly) {
|
|
239
|
+
// The key becomes the draft; without preventDefault the browser would
|
|
240
|
+
// also type it into the newly focused cell input ("1" -> "11").
|
|
241
|
+
e.preventDefault();
|
|
203
242
|
sheetState.startEditing(sheetState.activeCell.row, sheetState.activeCell.col, e.key);
|
|
204
243
|
}
|
|
205
244
|
}
|
|
@@ -420,9 +459,9 @@
|
|
|
420
459
|
<table class="border-collapse table-fixed w-max min-w-full">
|
|
421
460
|
<!-- Table Header Columns -->
|
|
422
461
|
<thead>
|
|
423
|
-
<tr class="h-7 bg-muted
|
|
462
|
+
<tr class="h-7 bg-muted sticky top-0 z-20 border-b border-border shadow-xs">
|
|
424
463
|
<!-- Top Left Corner Cell -->
|
|
425
|
-
<th class="w-12 min-w-[3rem] sticky left-0 z-30 bg-muted
|
|
464
|
+
<th class="w-12 min-w-[3rem] sticky left-0 z-30 bg-muted border-r border-border text-center text-[10px] text-muted-foreground font-medium">
|
|
426
465
|
#
|
|
427
466
|
</th>
|
|
428
467
|
{#each sheetState.viewModel.columns as viewCol (viewCol.column.id)}
|
|
@@ -492,7 +531,7 @@
|
|
|
492
531
|
>
|
|
493
532
|
<!-- Row Header Index -->
|
|
494
533
|
<td
|
|
495
|
-
class="w-12 min-w-[3rem] sticky left-0 z-10 bg-muted
|
|
534
|
+
class="w-12 min-w-[3rem] sticky left-0 z-10 bg-muted border-r border-border text-center text-[10px] text-muted-foreground font-mono select-none"
|
|
496
535
|
style={viewRow.frozen ? `top: ${COLUMN_HEADER_HEIGHT + viewRow.stickyTop}px; z-index: 15;` : undefined}
|
|
497
536
|
>
|
|
498
537
|
{displayRowIndex + 1}
|
|
@@ -540,7 +579,6 @@
|
|
|
540
579
|
bind:this={cellInput}
|
|
541
580
|
bind:value={sheetState.draftValue}
|
|
542
581
|
onblur={() => sheetState.commitEditing()}
|
|
543
|
-
|
|
544
582
|
/>
|
|
545
583
|
<FormulaHints input={cellInput} value={sheetState.draftValue} onAccept={(next) => (sheetState.draftValue = next)} />
|
|
546
584
|
{:else if customCellRenderer}
|
|
@@ -554,6 +592,9 @@
|
|
|
554
592
|
{cell.error || (cell.value ?? '')}
|
|
555
593
|
</span>
|
|
556
594
|
{/if}
|
|
595
|
+
{#if activeSpill && rangeContains(activeSpill.range, rIdx, cIdx)}
|
|
596
|
+
<span aria-hidden="true" class="spreadsheet-spill-border" style={spillBorderStyle(activeSpill.range, rIdx, cIdx)}></span>
|
|
597
|
+
{/if}
|
|
557
598
|
{#if showFillHandle}
|
|
558
599
|
<!-- svelte-ignore a11y_no_static_element_interactions, a11y_click_events_have_key_events -->
|
|
559
600
|
<div
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpreadsheetEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAMH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,EAKd,MAAM,8BAA8B,CAAC;AAKxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EACf,OAAO,CAAC,CAAC,QAAQ,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC,GACtD,OAAO,CAAC,CAAC;QAAE,GAAG,EAAE,cAAc,CAAC;QAAC,GAAG,EAAE,iBAAiB,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC,CAAC;IAC/E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD;
|
|
1
|
+
{"version":3,"file":"SpreadsheetEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAMH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,EAKd,MAAM,8BAA8B,CAAC;AAKxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EACf,OAAO,CAAC,CAAC,QAAQ,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC,GACtD,OAAO,CAAC,CAAC;QAAE,GAAG,EAAE,cAAc,CAAC;QAAC,GAAG,EAAE,iBAAiB,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC,CAAC;IAC/E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD;AA+hBH,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
<!-- A category header row: collapse toggle, label, row count and per-column summaries. -->
|
|
23
23
|
<tr class="border-b border-border bg-muted/40 font-semibold" data-group-key={group.key} style="height: 28px;">
|
|
24
|
-
<td class="w-12 min-w-[3rem] sticky left-0 z-10 bg-muted
|
|
24
|
+
<td class="w-12 min-w-[3rem] sticky left-0 z-10 bg-muted border-r border-border text-center">
|
|
25
25
|
<button
|
|
26
26
|
type="button"
|
|
27
27
|
aria-label="{group.collapsed ? 'Expand' : 'Collapse'} group {group.label}"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spreadsheet.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/spreadsheet.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AAEtC,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,4BAAiC;;
|
|
1
|
+
{"version":3,"file":"spreadsheet.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/spreadsheet.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AAEtC,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,4BAAiC;;aAmL8zuB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA/G33uB,MAAM;;mBAMX,MAAM,SAAS,MAAM,GAAG,QAAQ;wBAG3B,MAAM,SAAS,MAAM,OAAO,MAAM;oBAItC,MAAM,OAAO,MAAM;uBAKhB,SAAS;uBAIT,MAAM,QAAQ,MAAM,eAAe,MAAM;wBAMxC,MAAM;;oBAWV,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;wBAK5B,MAAM,WAAW,OAAO,CAAC,iBAAiB,CAAC;wBAI3C,MAAM;qBAIT,MAAM,WAAW,OAAO,CAAC,cAAc,CAAC;qBAIxC,MAAM;0BAID,MAAM,SAAS,MAAM;8BAIjB,MAAM,gBAAgB,MAAM;2BAI/B,mBAAmB;;2BAanB,qBAAqB;6BAInB,MAAM,GAAG,SAAS;;wBAQvB,SAAS,GAAG,IAAI;wBAGhB,MAAM;;;EAc7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tableInteractions.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/tableInteractions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEpH,yEAAyE;AACzE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,IAAI,CAAC;IACzC,mBAAmB,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,wBAAwB,CAAC;IACxE,kBAAkB,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC;IAChE,WAAW,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC;CAC/C;AAUD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,WAAW,GAAG,IAAI,EACjC,KAAK,EAAE,0BAA0B,EACjC,UAAU,EAAE,MAAM,OAAO;IAwBvB;;;;OAIG;;;
|
|
1
|
+
{"version":3,"file":"tableInteractions.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/tableInteractions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEpH,yEAAyE;AACzE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,IAAI,CAAC;IACzC,mBAAmB,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,wBAAwB,CAAC;IACxE,kBAAkB,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC;IAChE,WAAW,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC;CAC/C;AAUD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,WAAW,GAAG,IAAI,EACjC,KAAK,EAAE,0BAA0B,EACjC,UAAU,EAAE,MAAM,OAAO;IAwBvB;;;;OAIG;;;EAcN"}
|
|
@@ -47,8 +47,9 @@ export function attachSpreadsheetClipboard(getGrid, sheet, isReadOnly) {
|
|
|
47
47
|
copyShortcutFallback() {
|
|
48
48
|
copied = false;
|
|
49
49
|
setTimeout(() => {
|
|
50
|
+
// Rejected when clipboard access is denied; nothing else to fall back to.
|
|
50
51
|
if (!copied)
|
|
51
|
-
navigator.clipboard?.writeText(sheet.exportToTsv(sheet.selectedRange));
|
|
52
|
+
Promise.resolve(navigator.clipboard?.writeText(sheet.exportToTsv(sheet.selectedRange))).catch(() => { });
|
|
52
53
|
}, 0);
|
|
53
54
|
},
|
|
54
55
|
destroy() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixerate/editor-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
|
|
5
5
|
"author": "Pixerate",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@tiptap/extension-bubble-menu": "^2.11.5",
|
|
60
60
|
"@tiptap/extension-placeholder": "^2.11.5",
|
|
61
61
|
"@tiptap/starter-kit": "^2.11.5",
|
|
62
|
-
"@pixerate/editor": "0.
|
|
62
|
+
"@pixerate/editor": "0.22.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@dagrejs/dagre": "^1.1.4",
|