wx-svelte-grid 1.3.2 → 2.0.0-beta-2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wx-svelte-grid",
3
- "version": "1.3.2",
3
+ "version": "2.0.0-beta-2",
4
4
  "description": "A powerful and flexible DataGrid component written in Svelte",
5
5
  "productTag": "grid",
6
6
  "needsTrial": true,
@@ -8,7 +8,7 @@
8
8
  "scripts": {
9
9
  "build": "vite build",
10
10
  "build:tests": "vite build --mode test",
11
- "lint": "yarn eslint ./demos ./src --ext .svelte,.ts,.js",
11
+ "lint": "yarn eslint ./demos ./src",
12
12
  "start": "vite --open",
13
13
  "start:tests": "vite --open=/tests/ --mode test --host 0.0.0.0 --port 5100",
14
14
  "test": "true",
@@ -34,11 +34,11 @@
34
34
  "wx-lib-dom": "0.6.0",
35
35
  "wx-lib-state": "1.9.0",
36
36
  "wx-lib-svelte": "0.4.0",
37
- "wx-svelte-menu": "1.3.0",
38
- "wx-svelte-core": "1.3.1",
39
- "wx-grid-data-provider": "1.3.2",
40
- "wx-grid-locales": "1.3.2",
41
- "wx-grid-store": "1.3.2"
37
+ "wx-svelte-menu": "2.0.0-beta-2",
38
+ "wx-svelte-core": "2.0.0-beta-2",
39
+ "wx-grid-data-provider": "2.0.0-beta-2",
40
+ "wx-grid-locales": "2.0.0-beta-2",
41
+ "wx-grid-store": "2.0.0-beta-2"
42
42
  },
43
43
  "files": [
44
44
  "src",
@@ -2,13 +2,22 @@
2
2
  import { getStyle } from "../helpers/columnWidth";
3
3
  import { getRenderValue } from "wx-grid-store";
4
4
 
5
- export let row;
6
- export let col;
7
- export let cellStyle = null;
8
- export let columnStyle = null;
5
+ /**
6
+ * @typedef {Object} Props
7
+ * @property {any} row
8
+ * @property {any} col
9
+ * @property {any} [cellStyle]
10
+ * @property {any} [columnStyle]
11
+ * @property {import('svelte').Snippet} [children]
12
+ */
9
13
 
10
- let style, css;
11
- $: style = getStyle(col.width, col.flexgrow, col.fixed, col.left);
14
+ /** @type {Props} */
15
+ let { row, col, cellStyle = null, columnStyle = null, children } = $props();
16
+
17
+ let style = $derived(
18
+ getStyle(col.width, col.flexgrow, col.fixed, col.left)
19
+ ),
20
+ css = $derived(buildCellCss(columnStyle, cellStyle));
12
21
 
13
22
  function buildCellCss(columnStyle, cellStyle) {
14
23
  let css = "wx-cell";
@@ -17,7 +26,6 @@
17
26
  return css;
18
27
  }
19
28
  // params are needed for css update
20
- $: css = buildCellCss(columnStyle, cellStyle);
21
29
  </script>
22
30
 
23
31
  <div
@@ -29,20 +37,24 @@
29
37
  >
30
38
  {#if col.treetoggle}
31
39
  <div class="wx-tree-cell">
32
- <span style="margin-left:{row.$level * 28}px;" />
40
+ <span style="margin-left:{row.$level * 28}px;"></span>
33
41
  {#if row.$count}
34
42
  <i
35
43
  data-action="toggle-row"
36
44
  class="wx-table-tree-toggle wxi-menu-{row.open !== false
37
45
  ? 'down'
38
46
  : 'right'}"
39
- />
47
+ ></i>
40
48
  {/if}
41
- <slot>{getRenderValue(row, col)}</slot>
49
+ {#if children}{@render children()}{:else}{getRenderValue(
50
+ row,
51
+ col
52
+ )}{/if}
42
53
  </div>
43
- {:else}
44
- <slot>{getRenderValue(row, col)}</slot>
45
- {/if}
54
+ {:else if children}{@render children()}{:else}{getRenderValue(
55
+ row,
56
+ col
57
+ )}{/if}
46
58
  </div>
47
59
 
48
60
  <style>
@@ -1,21 +1,19 @@
1
1
  <script>
2
2
  import { getStyle, getCssName } from "../helpers/columnWidth";
3
3
 
4
- export let cell;
5
- export let column;
6
- export let columnStyle;
4
+ let { cell, column, columnStyle } = $props();
7
5
 
8
- let style;
9
- $: style = getStyle(
10
- cell.width,
11
- cell.flexgrow,
12
- column.fixed,
13
- column.left,
14
- cell.height
6
+ let style = $derived(
7
+ getStyle(
8
+ cell.width,
9
+ cell.flexgrow,
10
+ column.fixed,
11
+ column.left,
12
+ cell.height
13
+ )
15
14
  );
16
15
 
17
- let css = "";
18
- $: css = getCssName(column, cell, columnStyle);
16
+ let css = $derived(getCssName(column, cell, columnStyle));
19
17
  </script>
20
18
 
21
19
  <div class="wx-cell {css} {cell.css || ''}" {style}>
@@ -1,8 +1,7 @@
1
1
  <script>
2
2
  // svelte core
3
- import { createEventDispatcher, getContext } from "svelte";
3
+ import { getContext, setContext } from "svelte";
4
4
  import { writable } from "svelte/store";
5
- const dispatch = createEventDispatcher();
6
5
 
7
6
  // core widgets lib
8
7
  import { Locale } from "wx-svelte-core";
@@ -15,68 +14,113 @@
15
14
  // ui
16
15
  import Layout from "./Layout.svelte";
17
16
 
18
- // incoming parameters
19
- export let data = [];
20
- export let columns = [];
17
+ let {
18
+ data = [],
19
+ columns = [],
20
+ rowStyle = null,
21
+ columnStyle = null,
22
+ cellStyle = null,
23
+ selectedRows = [],
24
+ select = true,
25
+ multiselect = false,
26
+ header = true,
27
+ footer = false,
28
+ dynamic = null,
29
+ editor = null,
30
+ filter = null,
31
+ overlay = null,
32
+ autoRowHeight = false,
33
+ sizes = {},
34
+ split = { left: 0 },
35
+ tree = false,
36
+ autoConfig = false,
37
+ init = null,
38
+ ...restProps
39
+ } = $props();
21
40
 
22
- export let rowStyle = null;
23
- export let columnStyle = null;
24
- export let cellStyle = null;
25
-
26
- export let selected = null;
27
- export let selectedRows = [];
28
- export let select = true;
29
- export let multiselect = false;
41
+ // init stores
42
+ const dataStore = new DataStore(writable);
30
43
 
31
- export let header = true;
32
- export let footer = false;
33
- export let dynamic = null;
34
- export let editor = null;
35
- export let filter = null;
36
- export let overlay = null;
37
- export let autoRowHeight = false;
38
- export let sizes = {};
39
- export let split = { left: 0 };
44
+ // define event route
45
+ let firstInRoute = dataStore.in;
40
46
 
41
- export let tree = false;
42
- export let autoConfig = false;
47
+ const dash = /-/g;
48
+ let lastInRoute = new EventBusRouter((a, b) => {
49
+ const name = "on" + a.replace(dash, "");
50
+ if (restProps[name]) {
51
+ restProps[name](b);
52
+ }
53
+ });
54
+ firstInRoute.setNext(lastInRoute);
43
55
 
44
- export let init = null;
56
+ // public API
57
+ export const // state
58
+ getState = dataStore.getState.bind(dataStore),
59
+ getReactiveState = dataStore.getReactive.bind(dataStore),
60
+ getStores = () => ({ data: dataStore }),
61
+ // events
62
+ exec = firstInRoute.exec,
63
+ setNext = ev => (lastInRoute = lastInRoute.setNext(ev)),
64
+ intercept = firstInRoute.intercept.bind(firstInRoute),
65
+ on = firstInRoute.on.bind(firstInRoute),
66
+ detach = firstInRoute.detach.bind(firstInRoute),
67
+ // extra api
68
+ getRow = id => dataStore.getRow(id),
69
+ getColumn = id => dataStore.getColumn(id);
70
+
71
+ const api = {
72
+ exec,
73
+ setNext,
74
+ intercept,
75
+ on,
76
+ detach,
77
+ getRow,
78
+ getColumn,
79
+ getState,
80
+ getReactiveState,
81
+ getStores,
82
+ };
45
83
 
84
+ // common API available in components
85
+ setContext("grid-store", {
86
+ getState: dataStore.getState.bind(dataStore),
87
+ getReactiveState: dataStore.getReactive.bind(dataStore),
88
+ exec: firstInRoute.exec.bind(firstInRoute),
89
+ getRow: dataStore.getRow.bind(dataStore),
90
+ });
46
91
  // auto config columns
47
- $: if (autoConfig && !columns.length && data.length) {
48
- const test = data[0];
49
-
50
- for (let key in test)
51
- if (key != "id" && key[0] != "$") {
52
- let col = {
53
- id: key,
54
- header: key[0].toUpperCase() + key.substr(1),
55
- };
56
-
57
- if (typeof autoConfig === "object")
58
- col = { ...col, ...autoConfig };
59
- columns.push(col);
92
+ const finalColumns = $derived.by(() => {
93
+ let res = columns;
94
+ if (autoConfig && !res.length && data.length) {
95
+ const test = data[0];
96
+
97
+ for (let key in test) {
98
+ if (key != "id" && key[0] != "$") {
99
+ let col = {
100
+ id: key,
101
+ header: key[0].toUpperCase() + key.substr(1),
102
+ };
103
+
104
+ if (typeof autoConfig === "object")
105
+ col = { ...col, ...autoConfig };
106
+ columns.push(col);
107
+ }
60
108
  }
61
- }
62
- //sync selection props
63
- $: {
64
- if (selectedRows.length) selected = selectedRows[0];
65
- else if (selected) selectedRows.push(selected);
66
- }
109
+ }
67
110
 
68
- $: _skin = getContext("wx-theme");
111
+ return columns;
112
+ });
69
113
 
70
- // init stores
71
- const dataStore = new DataStore(writable);
72
- $: {
114
+ let _skin = $derived(getContext("wx-theme"));
115
+
116
+ let init_once = true;
117
+ const reinitStore = () => {
73
118
  dataStore.init({
74
119
  data,
75
120
  editor,
76
- columns,
121
+ columns: finalColumns,
77
122
  split,
78
123
  sizes,
79
- selected,
80
124
  selectedRows,
81
125
  dynamic,
82
126
  filter,
@@ -84,45 +128,18 @@
84
128
  _skin,
85
129
  });
86
130
 
87
- if (init) {
131
+ if (init_once && init) {
88
132
  init(api);
89
- init = null;
133
+ init_once = false;
90
134
  }
91
- }
92
-
93
- // define event route
94
- let firstInRoute = dataStore.in;
95
- let lastInRoute = new EventBusRouter(dispatch);
96
- firstInRoute.setNext(lastInRoute);
97
-
98
- const actions = ev => {
99
- firstInRoute.exec(ev.detail.action, ev.detail.data);
100
135
  };
101
136
 
102
- // public API
103
- export const api = {
104
- // state
105
- getState: dataStore.getState.bind(dataStore),
106
- getReactiveState: dataStore.getReactive.bind(dataStore),
107
- getStores: () => ({ data: dataStore }),
108
-
109
- // events
110
- exec: firstInRoute.exec,
111
- setNext: ev => (lastInRoute = lastInRoute.setNext(ev)),
112
- intercept: firstInRoute.intercept.bind(firstInRoute),
113
- on: firstInRoute.on.bind(firstInRoute),
114
- detach: firstInRoute.detach.bind(firstInRoute),
115
-
116
- // extra api
117
- getRow: id => dataStore.getRow(id),
118
- getColumn: id => dataStore.getColumn(id),
119
- };
137
+ reinitStore();
138
+ $effect(reinitStore);
120
139
  </script>
121
140
 
122
141
  <Locale words={en} optional={true}>
123
142
  <Layout
124
- store={dataStore}
125
- {api}
126
143
  {header}
127
144
  {footer}
128
145
  {overlay}
@@ -132,7 +149,5 @@
132
149
  {select}
133
150
  {multiselect}
134
151
  {autoRowHeight}
135
- on:action={actions}
136
- on:data-request
137
152
  />
138
153
  </Locale>
@@ -1,15 +1,12 @@
1
1
  <script>
2
- import { createEventDispatcher } from "svelte";
2
+ import { getContext } from "svelte";
3
3
  import { resize } from "../helpers/actions/resize";
4
4
  import { getCssName, getStyle } from "../helpers/columnWidth";
5
5
 
6
- export let cell;
7
- export let column;
8
- export let row;
9
- export let lastRow;
10
- export let columnStyle;
6
+ let { cell, column, row, lastRow, columnStyle } = $props();
7
+
8
+ const api = getContext("grid-store");
11
9
 
12
- const dispatch = createEventDispatcher();
13
10
  let start;
14
11
 
15
12
  function down(node) {
@@ -17,44 +14,40 @@
17
14
  }
18
15
 
19
16
  function move(dx) {
20
- dispatch("action", {
21
- action: "resize-column",
22
- data: { id: cell.id, width: Math.max(1, start + dx) },
17
+ api.exec("resize-column", {
18
+ id: cell.id,
19
+ width: Math.max(1, start + dx),
23
20
  });
24
21
  }
25
22
 
26
23
  function sort(ev) {
27
- dispatch("action", {
28
- action: "sort-rows",
29
- data: { key: cell.id, add: ev.ctrlKey },
30
- });
24
+ api.exec("sort-rows", { key: cell.id, add: ev.ctrlKey });
31
25
  }
32
- function collapse() {
33
- dispatch("action", {
34
- action: "collapse-column",
35
- data: { id: cell.id, row },
36
- });
26
+ function collapse(ev) {
27
+ if (ev) ev.stopPropagation();
28
+ api.exec("collapse-column", { id: cell.id, row });
37
29
  }
38
30
 
39
- let style;
40
- $: style = getStyle(
41
- cell.width,
42
- cell.flexgrow,
43
- column.fixed,
44
- column.left,
45
- cell.height
31
+ let style = $derived(
32
+ getStyle(
33
+ cell.width,
34
+ cell.flexgrow,
35
+ column.fixed,
36
+ column.left,
37
+ cell.height
38
+ )
46
39
  );
47
40
 
48
- let css = "";
49
- $: css = getCssName(column, cell, columnStyle);
41
+ const css = $derived(getCssName(column, cell, columnStyle));
50
42
  </script>
51
43
 
52
44
  {#if cell.collapsed && column.collapsed}
53
- <!-- svelte-ignore a11y-click-events-have-key-events -->
45
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
46
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
54
47
  <div
55
48
  class="wx-cell {css} {cell.css || ''} wx-collapsed"
56
49
  {style}
57
- on:click|stopPropagation={collapse}
50
+ onclick={collapse}
58
51
  data-header-id={column.id}
59
52
  >
60
53
  <div class="wx-text">{cell.text || ""}</div>
@@ -66,21 +59,23 @@
66
59
  data-header-id={column.id}
67
60
  >
68
61
  {#if cell.collapsible}
69
- <!-- svelte-ignore a11y-click-events-have-key-events -->
70
- <div class="wx-collapse" on:click|stopPropagation={collapse}>
71
- <i class="wxi-angle-{cell.collapsed ? 'down' : 'right'}" />
62
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
63
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
64
+ <div class="wx-collapse" onclick={collapse}>
65
+ <i class="wxi-angle-{cell.collapsed ? 'down' : 'right'}"></i>
72
66
  </div>
73
67
  {/if}
74
68
 
75
69
  <div class="wx-text">{cell.text || ""}</div>
76
70
 
77
71
  {#if column.resize && lastRow}
78
- <div class="wx-grip" use:resize={{ down, move }} />
72
+ <div class="wx-grip" use:resize={{ down, move }}></div>
79
73
  {/if}
80
74
 
81
75
  {#if column.sort}
82
- <!-- svelte-ignore a11y-click-events-have-key-events -->
83
- <div class="wx-sort" on:click={sort}>
76
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
77
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
78
+ <div class="wx-sort" onclick={sort}>
84
79
  {#if column.$sort && lastRow}
85
80
  {#if column.$sort.index > 0}
86
81
  <div class="wx-order">{column.$sort.index}</div>
@@ -89,7 +84,7 @@
89
84
  class="wxi-arrow-{column.$sort.order === 'asc'
90
85
  ? 'up'
91
86
  : 'down'}"
92
- />
87
+ ></i>
93
88
  {/if}
94
89
  </div>
95
90
  {/if}
@@ -1,26 +1,30 @@
1
1
  <script>
2
+ import { getContext } from "svelte";
2
3
  import HeaderCell from "./HeaderCell.svelte";
3
4
  import FooterCell from "./FooterCell.svelte";
4
5
 
5
- export let deltaLeft;
6
- export let contentWidth;
7
- export let rowHeights;
8
- export let columns;
9
- export let type = "header";
6
+ let {
7
+ deltaLeft,
8
+ contentWidth,
9
+ columns,
10
+ type = "header",
11
+ columnStyle,
12
+ } = $props();
10
13
 
11
- export let columnStyle;
14
+ const api = getContext("grid-store");
15
+ const { _sizes: sizes } = api.getReactiveState();
16
+ let rowHeights = $derived($sizes[`${type}RowHeights`]);
12
17
 
13
- let renderedHeader = [];
14
- $: {
18
+ let renderedHeader = $derived.by(() => {
19
+ let res = [];
15
20
  if (columns.length) {
16
21
  const rowsCount = columns[0][type].length;
17
- renderedHeader = [];
18
22
  for (let ri = 0; ri < rowsCount; ri++) {
19
23
  let inSpan = 0;
20
- renderedHeader.push([]);
24
+ res.push([]);
21
25
  columns.forEach(col => {
22
26
  if (!inSpan) {
23
- renderedHeader[ri].push(col[type][ri]);
27
+ res[ri].push(col[type][ri]);
24
28
  }
25
29
 
26
30
  if (col[type][ri].colspan > 1) {
@@ -29,7 +33,8 @@
29
33
  });
30
34
  }
31
35
  }
32
- }
36
+ return res;
37
+ });
33
38
 
34
39
  function getColumn(id) {
35
40
  return columns.find(c => c.id === id);
@@ -58,7 +63,6 @@
58
63
  column={getColumn(cell.id)}
59
64
  row={i}
60
65
  lastRow={isLast(cell, i)}
61
- on:action
62
66
  />
63
67
  {:else}
64
68
  <FooterCell