@chalabi/svelte-sheets 2.0.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 +110 -0
- package/dist/Menu.svelte +97 -0
- package/dist/Menu.svelte.d.ts +30 -0
- package/dist/Open.svelte +35 -0
- package/dist/Open.svelte.d.ts +23 -0
- package/dist/Sheet.svelte +1167 -0
- package/dist/Sheet.svelte.d.ts +42 -0
- package/dist/Toolbar.svelte +69 -0
- package/dist/Toolbar.svelte.d.ts +22 -0
- package/dist/actions/copypaste.d.ts +1 -0
- package/dist/actions/copypaste.js +24 -0
- package/dist/actions/draggable.d.ts +3 -0
- package/dist/actions/draggable.js +37 -0
- package/dist/actions/index.d.ts +5 -0
- package/dist/actions/index.js +5 -0
- package/dist/actions/resizable.d.ts +3 -0
- package/dist/actions/resizable.js +37 -0
- package/dist/actions/rightclick.d.ts +1 -0
- package/dist/actions/rightclick.js +1 -0
- package/dist/actions/selected.d.ts +5 -0
- package/dist/actions/selected.js +10 -0
- package/dist/convert.d.ts +16 -0
- package/dist/convert.js +164 -0
- package/dist/defaultconfig.d.ts +138 -0
- package/dist/defaultconfig.js +195 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/utilities.d.ts +13 -0
- package/dist/utilities.js +211 -0
- package/package.json +182 -0
package/Readme.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Svelte Spreadsheets
|
|
2
|
+
|
|
3
|
+
Ultra fast excel sheets in the browser. Hugely inspired by JExcel, built on XLSX shoulders.
|
|
4
|
+
|
|
5
|
+
=> Find a live example [Here](https://ticruz38.github.io/svelte-sheets/)
|
|
6
|
+
|
|
7
|
+
### Motivation
|
|
8
|
+
|
|
9
|
+
Making excel sheets a reality in the browser can be incredibly difficult, keeping good performance while drawing and editing large amount of data in the DOM is the ultimate challenge for a web developper.
|
|
10
|
+
The best implementation I could find was the awesome vanillajs [jexcel](https://github.com/jspreadsheet/jexcel) by Paul Hodel. <br/>
|
|
11
|
+
However, opening really big spreadsheet would still block the JS thread for a minute or two.
|
|
12
|
+
Following Rich Harris talk about reactivity, I decided to take the idea behind Jexcel and adapt it to Svelte, making use of a Virtual List to keep the DOM small and light at all times.
|
|
13
|
+
|
|
14
|
+
### Known limitation
|
|
15
|
+
|
|
16
|
+
You will need to have typescript svelte-preprocess enabled in your webpack/rollup configuration
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
19
|
+
|
|
20
|
+
`npm i -S @chalabi/svelte-sheets`
|
|
21
|
+
|
|
22
|
+
### Example
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<script>
|
|
26
|
+
import { Sheet } from "@chalabi/svelte-sheets";
|
|
27
|
+
|
|
28
|
+
let style = {
|
|
29
|
+
A1: "background-color: red",
|
|
30
|
+
};
|
|
31
|
+
let mergeCells = {
|
|
32
|
+
A1: [5, 0], // 5 horizontally merged cell (colspan), 0 vertically merged cells (rowspan)
|
|
33
|
+
};
|
|
34
|
+
let columns = [{ width: "50px" }];
|
|
35
|
+
let data = [
|
|
36
|
+
["mazda", "renault", "volkswagen"][("10000km", "20000km", "300000km")],
|
|
37
|
+
];
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<Sheet {style} {mergeCells} {columns} {data} />
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Alternatively you can use the toolbar to open any kind of excel files
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<script>
|
|
47
|
+
import { Sheet, Toolbar } from "@chalabi/svelte-sheets";
|
|
48
|
+
|
|
49
|
+
let sheetNames;
|
|
50
|
+
let sheets;
|
|
51
|
+
let active;
|
|
52
|
+
let data;
|
|
53
|
+
let columns;
|
|
54
|
+
let mergeCells;
|
|
55
|
+
let style;
|
|
56
|
+
|
|
57
|
+
$: {
|
|
58
|
+
data = sheets[active].data;
|
|
59
|
+
columns = sheets[active].columns;
|
|
60
|
+
mergeCells = sheets[active].mergeCells;
|
|
61
|
+
style = sheets[active].style;
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<Toolbar bind:sheetNames bind:sheets bind:active />
|
|
66
|
+
<Sheet {style} {mergeCells} {columns} {data} />
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
You can configure the table such as height and many other things with the options props:
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
let options = {
|
|
73
|
+
tableHeight: "90vh",
|
|
74
|
+
defaultColWidth: "50px",
|
|
75
|
+
readOnly: true,
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Common flags:
|
|
80
|
+
|
|
81
|
+
- `readOnly`: true to disable all edits and resizing
|
|
82
|
+
- `editable`: false to disable edits (equivalent to readOnly)
|
|
83
|
+
- `disableHover`: true to disable hover-based selection updates
|
|
84
|
+
|
|
85
|
+
Theme:
|
|
86
|
+
|
|
87
|
+
- `theme`: set to `"dark"` for the bundled dark tokens (default is `"light"`)
|
|
88
|
+
- `class` / `className`: pass a custom class to the root element to override CSS variables
|
|
89
|
+
|
|
90
|
+
Many of these options will be implemented later, so expect most of them to be unresponsive.
|
|
91
|
+
|
|
92
|
+
### Development
|
|
93
|
+
|
|
94
|
+
- The demo app lives in `src/routes/+page.svelte`
|
|
95
|
+
- `npm run dev` for the demo
|
|
96
|
+
- `npm test` to run unit tests
|
|
97
|
+
- `npm run package` to build the library output
|
|
98
|
+
|
|
99
|
+
### Things yet to be done
|
|
100
|
+
|
|
101
|
+
- Make a svelte REPL demonstrating the library (awaiting repl typescript support)
|
|
102
|
+
- ✅ Undo/Redo (mapping keyboard shortcuts)
|
|
103
|
+
- ✅ shift+click should extend the selection
|
|
104
|
+
- ✅ Resizing rows/columns
|
|
105
|
+
- Filtering
|
|
106
|
+
- ✅ Copy/Paste
|
|
107
|
+
- Comments on cells
|
|
108
|
+
- Support more that number, string or boolean in cells. let's say charts, datepickers etc...
|
|
109
|
+
- ✅ Implement a tooltip when right clicking a cell with a list of actions
|
|
110
|
+
- All other excel features you can think of
|
package/dist/Menu.svelte
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<script lang="ts">export let show = false;
|
|
2
|
+
export let x;
|
|
3
|
+
export let y;
|
|
4
|
+
export let data = [];
|
|
5
|
+
export let selected;
|
|
6
|
+
export let copy;
|
|
7
|
+
export let cut;
|
|
8
|
+
export let paste;
|
|
9
|
+
export let clear;
|
|
10
|
+
// delete is a reserved word...
|
|
11
|
+
export let delet;
|
|
12
|
+
export let readOnly = false;
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div class="menu" class:hidden={!show} style={`top: ${y}px; left: ${x}px`}>
|
|
16
|
+
<div
|
|
17
|
+
class="item flex justify-between"
|
|
18
|
+
class:disabled={readOnly}
|
|
19
|
+
on:click={(e) => !readOnly && cut(e)}
|
|
20
|
+
>
|
|
21
|
+
<div>Cut</div>
|
|
22
|
+
<div class="disabled">⌘X</div>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="item flex justify-between" on:click={(e) => copy(e)}>
|
|
25
|
+
<div>Copy</div>
|
|
26
|
+
<div class="disabled">⌘C</div>
|
|
27
|
+
</div>
|
|
28
|
+
<div
|
|
29
|
+
class="item flex justify-between"
|
|
30
|
+
class:disabled={readOnly}
|
|
31
|
+
on:click={(e) => !readOnly && paste(e)}
|
|
32
|
+
>
|
|
33
|
+
<div>Paste</div>
|
|
34
|
+
<div class="disabled">⌘P</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="divider" />
|
|
37
|
+
<div class="item" class:disabled={readOnly}>Insert</div>
|
|
38
|
+
<div
|
|
39
|
+
class="item"
|
|
40
|
+
class:disabled={readOnly}
|
|
41
|
+
on:click={(e) => !readOnly && delet(e)}
|
|
42
|
+
>
|
|
43
|
+
Delete
|
|
44
|
+
</div>
|
|
45
|
+
<div
|
|
46
|
+
class="item"
|
|
47
|
+
class:disabled={readOnly}
|
|
48
|
+
on:click={(e) => !readOnly && clear(e)}
|
|
49
|
+
>
|
|
50
|
+
Clear contents
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<style>
|
|
55
|
+
.menu {
|
|
56
|
+
padding: 0.5rem 0.25rem;
|
|
57
|
+
position: fixed;
|
|
58
|
+
z-index: 20;
|
|
59
|
+
min-width: 10rem;
|
|
60
|
+
background: var(--sheet-menu-bg);
|
|
61
|
+
border-radius: 10px;
|
|
62
|
+
color: var(--sheet-text);
|
|
63
|
+
}
|
|
64
|
+
.disabled {
|
|
65
|
+
color: var(--sheet-muted);
|
|
66
|
+
}
|
|
67
|
+
.divider {
|
|
68
|
+
padding-top: 0.5rem;
|
|
69
|
+
margin-bottom: 0.5rem;
|
|
70
|
+
border-bottom: 1px solid #aaa;
|
|
71
|
+
}
|
|
72
|
+
.hidden {
|
|
73
|
+
display: none;
|
|
74
|
+
}
|
|
75
|
+
.flex {
|
|
76
|
+
display: flex;
|
|
77
|
+
}
|
|
78
|
+
.justify-between {
|
|
79
|
+
justify-content: space-between;
|
|
80
|
+
}
|
|
81
|
+
.item {
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
padding: 0.25rem 0.5rem;
|
|
84
|
+
border-radius: 0.25rem;
|
|
85
|
+
}
|
|
86
|
+
.item:hover {
|
|
87
|
+
background-color: var(--sheet-accent);
|
|
88
|
+
color: var(--sheet-bg);
|
|
89
|
+
}
|
|
90
|
+
.item.disabled {
|
|
91
|
+
cursor: not-allowed;
|
|
92
|
+
opacity: 0.6;
|
|
93
|
+
}
|
|
94
|
+
.item.disabled:hover {
|
|
95
|
+
background-color: transparent;
|
|
96
|
+
}
|
|
97
|
+
</style>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: Props & {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const Menu: $$__sveltets_2_IsomorphicComponent<{
|
|
15
|
+
show?: boolean;
|
|
16
|
+
x: any;
|
|
17
|
+
y: any;
|
|
18
|
+
data?: (string | number | boolean)[][];
|
|
19
|
+
selected: string;
|
|
20
|
+
copy: (e: any) => void;
|
|
21
|
+
cut: (e: any) => void;
|
|
22
|
+
paste: (e: any) => any[][];
|
|
23
|
+
clear: (e: any) => any[][];
|
|
24
|
+
delet: (e: any) => any[][];
|
|
25
|
+
readOnly?: boolean;
|
|
26
|
+
}, {
|
|
27
|
+
[evt: string]: CustomEvent<any>;
|
|
28
|
+
}, {}, {}, string>;
|
|
29
|
+
type Menu = InstanceType<typeof Menu>;
|
|
30
|
+
export default Menu;
|
package/dist/Open.svelte
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script lang="ts">import XLSX from "xlsx";
|
|
2
|
+
import { convert } from "./convert.js";
|
|
3
|
+
export let onload;
|
|
4
|
+
export let sheetNames;
|
|
5
|
+
export let sheets = [];
|
|
6
|
+
export let open;
|
|
7
|
+
// declare all possible table object
|
|
8
|
+
let files;
|
|
9
|
+
$: files && files[0] && reader && reader.readAsArrayBuffer(files[0]);
|
|
10
|
+
let reader;
|
|
11
|
+
if (typeof FileReader != "undefined") {
|
|
12
|
+
reader = new FileReader();
|
|
13
|
+
reader.onload = () => {
|
|
14
|
+
sheets = [];
|
|
15
|
+
const wb = XLSX.read(new Uint8Array(reader.result), {
|
|
16
|
+
type: "array",
|
|
17
|
+
cellFormula: true,
|
|
18
|
+
cellStyles: true,
|
|
19
|
+
});
|
|
20
|
+
sheets = convert(wb);
|
|
21
|
+
sheetNames = sheets.map((s) => s.sheetName);
|
|
22
|
+
onload && onload(sheets, sheetNames);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<input type="file" class="hidden" name="file" bind:this={open} bind:files />
|
|
28
|
+
|
|
29
|
+
<style>
|
|
30
|
+
.hidden {
|
|
31
|
+
height: 0;
|
|
32
|
+
width: 0;
|
|
33
|
+
opacity: 0;
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: Props & {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const Open: $$__sveltets_2_IsomorphicComponent<{
|
|
15
|
+
onload: (sheets: any[], sheetNames: any[]) => void;
|
|
16
|
+
sheetNames: any;
|
|
17
|
+
sheets?: any[];
|
|
18
|
+
open: any;
|
|
19
|
+
}, {
|
|
20
|
+
[evt: string]: CustomEvent<any>;
|
|
21
|
+
}, {}, {}, string>;
|
|
22
|
+
type Open = InstanceType<typeof Open>;
|
|
23
|
+
export default Open;
|