x4js 1.4.22 → 1.4.27

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.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * ___ ___ __
3
+ * \ \/ / / _
4
+ * \ / /_| |_
5
+ * / \____ _|
6
+ * /__/\__\ |_|
7
+ *
8
+ * @file action.ts
9
+ * @author Etienne Cochard
10
+ *
11
+ * Copyright (c) 2019-2022 R-libre ingenierie
12
+ *
13
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ * of this software and associated documentation files (the "Software"), to deal
15
+ * in the Software without restriction, including without limitation the rights
16
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
17
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
18
+ * subject to the following conditions:
19
+ * The above copyright notice and this permission notice shall be included in all copies
20
+ * or substantial portions of the Software.
21
+ *
22
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
23
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
24
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ **/
29
+ import { BasicEvent } from './x4events';
30
+ import { BaseComponent, BaseComponentEventMap, BaseComponentProps } from './base_component';
31
+ import { IconID } from "./icon";
32
+ import { EvChange, EventHandler } from 'x4js';
33
+ export interface EvAction extends BasicEvent {
34
+ }
35
+ export declare function EvAction(source: Action): EvAction;
36
+ interface ActionEventMap extends BaseComponentEventMap {
37
+ run: EvAction;
38
+ change: EvChange;
39
+ }
40
+ interface ActionProps extends BaseComponentProps<ActionEventMap> {
41
+ id?: any;
42
+ text?: string;
43
+ icon?: IconID;
44
+ disabled?: boolean;
45
+ hidden?: boolean;
46
+ checked?: boolean;
47
+ run: EventHandler<EvAction>;
48
+ change?: EventHandler<EvChange>;
49
+ }
50
+ export declare class Action extends BaseComponent<ActionProps, ActionEventMap> {
51
+ constructor(props: ActionProps);
52
+ get props(): ActionProps;
53
+ set text(t: string);
54
+ set icon(i: IconID);
55
+ fire(): void;
56
+ }
57
+ export {};
package/lib/action.js ADDED
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /**
3
+ * ___ ___ __
4
+ * \ \/ / / _
5
+ * \ / /_| |_
6
+ * / \____ _|
7
+ * /__/\__\ |_|
8
+ *
9
+ * @file action.ts
10
+ * @author Etienne Cochard
11
+ *
12
+ * Copyright (c) 2019-2022 R-libre ingenierie
13
+ *
14
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ * of this software and associated documentation files (the "Software"), to deal
16
+ * in the Software without restriction, including without limitation the rights
17
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
18
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
19
+ * subject to the following conditions:
20
+ * The above copyright notice and this permission notice shall be included in all copies
21
+ * or substantial portions of the Software.
22
+ *
23
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
24
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
25
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
+ **/
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.Action = exports.EvAction = void 0;
32
+ const x4events_1 = require("./x4events");
33
+ const base_component_1 = require("./base_component");
34
+ const x4js_1 = require("x4js");
35
+ function EvAction(source) {
36
+ return (0, x4events_1.BasicEvent)({ source });
37
+ }
38
+ exports.EvAction = EvAction;
39
+ class Action extends base_component_1.BaseComponent {
40
+ constructor(props) {
41
+ super(props);
42
+ this.mapPropEvents(props, "run");
43
+ }
44
+ get props() {
45
+ return this.m_props;
46
+ }
47
+ set text(t) {
48
+ this.m_props.text = t;
49
+ this.emit("change", (0, x4js_1.EvChange)(this));
50
+ }
51
+ set icon(i) {
52
+ this.m_props.icon = i;
53
+ this.emit("change", (0, x4js_1.EvChange)(this));
54
+ }
55
+ fire() {
56
+ this.emit("run", EvAction(this));
57
+ }
58
+ }
59
+ exports.Action = Action;
@@ -91,8 +91,9 @@ export declare class Application<P extends ApplicationProps = ApplicationProps,
91
91
  *
92
92
  * let myApp = new Application( ... );
93
93
  * let mainView = new VLayout( ... );
94
- * myApp.setMainView( mainView );
94
+ * myApp.mainView = mainView;
95
95
  */
96
+ setMainView(root: Component, clearBefore: boolean): void;
96
97
  set mainView(root: Component);
97
98
  get mainView(): Component;
98
99
  setTitle(title: string): void;
@@ -33,7 +33,7 @@ const x4dom_1 = require("./x4dom");
33
33
  const base_component_1 = require("./base_component");
34
34
  const component_1 = require("./component");
35
35
  const settings_1 = require("./settings");
36
- const tools_1 = require("./tools");
36
+ const x4js_1 = require("x4js");
37
37
  const _x4_touch_time = Symbol();
38
38
  /**
39
39
  * Represents an x4 application, which is typically a single page app.
@@ -92,6 +92,7 @@ class Application extends base_component_1.BaseComponent {
92
92
  }
93
93
  }
94
94
  ApplicationCreated() {
95
+ this.setTitle('');
95
96
  }
96
97
  get app_name() {
97
98
  return this.m_app_name;
@@ -123,24 +124,31 @@ class Application extends base_component_1.BaseComponent {
123
124
  *
124
125
  * let myApp = new Application( ... );
125
126
  * let mainView = new VLayout( ... );
126
- * myApp.setMainView( mainView );
127
+ * myApp.mainView = mainView;
127
128
  */
128
- set mainView(root) {
129
+ setMainView(root, clearBefore) {
130
+ const ddom = this.m_props.renderTo ?? x4dom_1.x4document.body;
131
+ const dest = (0, x4js_1.flyWrap)(ddom);
132
+ if (!this.m_props.renderTo) {
133
+ dest.setStyleValue('position', 'absolute');
134
+ }
135
+ dest.addClass('x4-root-element');
136
+ if (clearBefore) {
137
+ dest._empty();
138
+ }
129
139
  this.m_mainView = root;
130
- this.mainView.addClass('x4-root-element');
131
- (0, tools_1.deferCall)(() => {
132
- const dest = this.m_props.renderTo ?? x4dom_1.x4document.body;
133
- while (dest.firstChild) {
134
- dest.removeChild(dest.firstChild);
135
- }
136
- dest.appendChild(root._build());
137
- });
140
+ root.setStyleValue('position', 'absolute');
141
+ root._build();
142
+ ddom.appendChild(root.dom);
143
+ }
144
+ set mainView(root) {
145
+ this.setMainView(root, false);
138
146
  }
139
147
  get mainView() {
140
148
  return this.m_mainView;
141
149
  }
142
150
  setTitle(title) {
143
- x4dom_1.x4document.title = this.m_app_name + ' > ' + title;
151
+ x4dom_1.x4document.title = this.m_app_name + (title ? (' > ' + title) : '');
144
152
  }
145
153
  disableZoomWheel() {
146
154
  window.addEventListener('wheel', function (ev) {
@@ -77,5 +77,11 @@ export declare class BaseComponent<P extends BaseComponentProps<BaseComponentEve
77
77
  * @param timeout
78
78
  */
79
79
  singleShot(callback: TimerCallback, timeout?: number): void;
80
+ /**
81
+ *
82
+ * @param props
83
+ * @param elements
84
+ */
85
+ mapPropEvents<N extends keyof E>(props: P, ...elements: N[]): void;
80
86
  }
81
87
  export {};
@@ -94,5 +94,18 @@ class BaseComponent extends x4events_1.EventSource {
94
94
  singleShot(callback, timeout = 0) {
95
95
  setTimeout(callback, timeout);
96
96
  }
97
+ /**
98
+ *
99
+ * @param props
100
+ * @param elements
101
+ */
102
+ mapPropEvents(props, ...elements) {
103
+ elements.forEach(name => {
104
+ const n = name;
105
+ if (props[n]) {
106
+ this._on(n, props[n]);
107
+ }
108
+ });
109
+ }
97
110
  }
98
111
  exports.BaseComponent = BaseComponent;
package/lib/button.d.ts CHANGED
@@ -28,6 +28,7 @@
28
28
  **/
29
29
  import { Component, CProps, CEventMap, HtmlString } from './component';
30
30
  import { EventCallback, EvClick, EvChange } from './x4events';
31
+ import { Action } from './action';
31
32
  import { IconID } from './icon';
32
33
  import { MenuItem, MenuOrSep } from './menu';
33
34
  /**
@@ -48,6 +49,7 @@ interface ButtonProps<E extends ButtonEventMap = ButtonEventMap> extends CProps<
48
49
  autoRepeat?: number;
49
50
  menu?: MenuOrSep[] | MenuCallBack;
50
51
  click?: EventCallback<EvClick>;
52
+ action?: Action;
51
53
  }
52
54
  /**
53
55
  * Base button
package/lib/button.js CHANGED
@@ -49,10 +49,21 @@ class BaseButton extends component_1.Component {
49
49
  this.mapPropEvents(props, 'click');
50
50
  }
51
51
  render(props) {
52
- let icon = props.icon ? new icon_1.Icon({ icon: props.icon, cls: 'left', ref: 'l_icon' }) : null;
53
- let label = new label_1.Label({ flex: 1, text: props.text ?? '', align: props.align, ref: 'label' });
54
- let ricon = props.rightIcon ? new icon_1.Icon({ icon: props.rightIcon, cls: 'right', ref: 'r_icon' }) : null;
55
- this.setContent([icon, label, ricon]);
52
+ const action = props.action;
53
+ let icon = props.icon;
54
+ let text = props.text;
55
+ if (action) {
56
+ if (!icon && action.props.icon) {
57
+ icon = action.props.icon;
58
+ }
59
+ if (text === undefined && action.props.text) {
60
+ text = action.props.text;
61
+ }
62
+ }
63
+ const ui_icon = icon ? new icon_1.Icon({ icon, cls: 'left', ref: 'l_icon' }) : null;
64
+ const ui_label = new label_1.Label({ flex: 1, text: text ?? '', align: props.align, ref: 'label' });
65
+ const ui_ricon = props.rightIcon ? new icon_1.Icon({ icon: props.rightIcon, cls: 'right', ref: 'r_icon' }) : null;
66
+ this.setContent([ui_icon, ui_label, ui_ricon]);
56
67
  this._setTabIndex(props.tabIndex);
57
68
  }
58
69
  /**
@@ -115,6 +126,9 @@ class BaseButton extends component_1.Component {
115
126
  }
116
127
  else {
117
128
  this.emit('click', (0, x4events_1.EvClick)());
129
+ if (this.m_props.action) {
130
+ this.m_props.action.fire();
131
+ }
118
132
  }
119
133
  }
120
134
  /**
@@ -314,7 +314,6 @@ export declare class Component<P extends CProps<BaseComponentEventMap> = CProps<
314
314
  *
315
315
  */
316
316
  clearDomEvent<K extends keyof X4ElementEventMap>(type: K): void;
317
- mapPropEvents<N extends keyof E>(props: P, ...elements: N[]): void;
318
317
  /**
319
318
  *
320
319
  * @param name
package/lib/component.js CHANGED
@@ -849,14 +849,6 @@ class Component extends base_component_1.BaseComponent {
849
849
  }
850
850
  }
851
851
  }
852
- mapPropEvents(props, ...elements) {
853
- elements.forEach(name => {
854
- const n = name;
855
- if (props[n]) {
856
- this._on(n, props[n]);
857
- }
858
- });
859
- }
860
852
  /**
861
853
  *
862
854
  * @param name
package/lib/dialog.js CHANGED
@@ -346,14 +346,14 @@ class Dialog extends popup_1.Popup {
346
346
  let trc = this.m_el_title.getBoundingRect();
347
347
  let dx = x - rc.left, dy = y - rc.top;
348
348
  let cstyle = this.getComputedStyle();
349
- let topw = cstyle.parse('marginTop') + cstyle.parse('paddingTop') + cstyle.parse('borderTopWidth');
350
- let botw = cstyle.parse('marginBottom') + cstyle.parse('paddingBottom') + cstyle.parse('borderBottomWidth');
351
- let lftw = cstyle.parse('marginLeft') + cstyle.parse('paddingLeft') + cstyle.parse('borderLeftWidth');
352
- let rgtw = cstyle.parse('marginRight') + cstyle.parse('paddingRight') + cstyle.parse('borderRightWidth');
353
- wrc.top += topw - trc.height;
354
- wrc.height -= topw + botw - trc.height;
355
- wrc.left += lftw;
356
- wrc.width -= lftw + rgtw;
349
+ //let topw = cstyle.parse('marginTop') + cstyle.parse('paddingTop') + cstyle.parse('borderTopWidth');
350
+ //let botw = cstyle.parse('marginBottom') + cstyle.parse('paddingBottom') + cstyle.parse('borderBottomWidth');
351
+ //let lftw = cstyle.parse('marginLeft') + cstyle.parse('paddingLeft') + cstyle.parse('borderLeftWidth');
352
+ //let rgtw = cstyle.parse('marginRight') + cstyle.parse('paddingRight') + cstyle.parse('borderRightWidth');
353
+ //wrc.top += topw - trc.height;
354
+ //wrc.height -= topw + botw - trc.height;
355
+ //wrc.left += lftw;
356
+ //wrc.width -= lftw + rgtw;
357
357
  // custom handling double click
358
358
  const now = Date.now();
359
359
  const delta = now - this.m_last_down;
@@ -367,19 +367,32 @@ class Dialog extends popup_1.Popup {
367
367
  return;
368
368
  }
369
369
  let __move = (ex, ey) => {
370
- let x = ex - dx, y = ey - dy;
371
- if (x + rc.width < wrc.left) {
372
- x = wrc.left - rc.width;
370
+ if (ex > wrc.right) {
371
+ ex = wrc.right;
373
372
  }
374
- else if (x > wrc.right) {
375
- x = wrc.right;
373
+ else if (ex < wrc.left) {
374
+ ex = wrc.left;
376
375
  }
377
- if (y < wrc.top) { // title grip is on top
378
- y = wrc.top;
376
+ if (ey > wrc.bottom) {
377
+ ey = wrc.bottom;
379
378
  }
380
- else if (y > wrc.bottom) {
381
- y = wrc.bottom;
379
+ else if (ey < wrc.top) {
380
+ ey = wrc.top;
382
381
  }
382
+ let x = ex - dx, y = ey - dy;
383
+ //if (x + rc.width < wrc.left) {
384
+ // x = wrc.left - rc.width;
385
+ //}
386
+ //else if (x > wrc.right) {
387
+ // x = wrc.right;
388
+ //}
389
+ //
390
+ //if (y < wrc.top) { // title grip is on top
391
+ // y = wrc.top;
392
+ //}
393
+ //else if (y > wrc.bottom) {
394
+ // y = wrc.bottom;
395
+ //}
383
396
  this.setStyle({
384
397
  left: x,
385
398
  top: y
@@ -55,10 +55,10 @@ export declare class ImageUpload extends FileUpload {
55
55
  * @param extensions - string - ex: '.doc,.docx'
56
56
  * @param cb - callback to call when user select a file
57
57
  */
58
- export declare function openFile(extensions: string, cb: (filename: FileList) => void, multiple?: boolean): void;
58
+ export declare function openFileDialog(extensions: string, cb: (filename: FileList) => void, multiple?: boolean): void;
59
59
  /**
60
60
  * open saveas dialog
61
61
  * @param defFileName - string - proposed filename
62
62
  * @param cb - callback to call when user choose the destination
63
63
  */
64
- export declare function saveFile(defFileName: string, extensions: string, cb: (filename: File) => void): void;
64
+ export declare function saveFileDialog(defFileName: string, extensions: string, cb: (filename: File) => void): void;
package/lib/fileupload.js CHANGED
@@ -28,7 +28,7 @@
28
28
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
29
  **/
30
30
  Object.defineProperty(exports, "__esModule", { value: true });
31
- exports.saveFile = exports.openFile = exports.ImageUpload = exports.FileUpload = void 0;
31
+ exports.saveFileDialog = exports.openFileDialog = exports.ImageUpload = exports.FileUpload = void 0;
32
32
  const x4dom_1 = require("./x4dom");
33
33
  const component_1 = require("./component");
34
34
  const layout_1 = require("./layout");
@@ -136,7 +136,7 @@ function _createFileInput() {
136
136
  * @param extensions - string - ex: '.doc,.docx'
137
137
  * @param cb - callback to call when user select a file
138
138
  */
139
- function openFile(extensions, cb, multiple = false) {
139
+ function openFileDialog(extensions, cb, multiple = false) {
140
140
  let fi = _createFileInput();
141
141
  fi.removeAttribute('nwsaveas');
142
142
  fi.setAttribute('accept', extensions);
@@ -149,13 +149,13 @@ function openFile(extensions, cb, multiple = false) {
149
149
  });
150
150
  fi.dom.click();
151
151
  }
152
- exports.openFile = openFile;
152
+ exports.openFileDialog = openFileDialog;
153
153
  /**
154
154
  * open saveas dialog
155
155
  * @param defFileName - string - proposed filename
156
156
  * @param cb - callback to call when user choose the destination
157
157
  */
158
- function saveFile(defFileName, extensions, cb) {
158
+ function saveFileDialog(defFileName, extensions, cb) {
159
159
  let fi = _createFileInput();
160
160
  fi.setAttribute('nwsaveas', defFileName);
161
161
  fi.setAttribute('accept', extensions);
@@ -167,4 +167,4 @@ function saveFile(defFileName, extensions, cb) {
167
167
  });
168
168
  fi.dom.click();
169
169
  }
170
- exports.saveFile = saveFile;
170
+ exports.saveFileDialog = saveFileDialog;
package/lib/gridview.js CHANGED
@@ -844,16 +844,18 @@ class GridView extends layout_1.VLayout {
844
844
  }
845
845
  this.m_footer.enumChilds((c) => {
846
846
  let cid = c.getData('col');
847
- let col = this.m_columns[cid];
848
- let fmt = col.formatter;
849
- let text;
850
- if (fmt && fmt instanceof Function) {
851
- text = fmt(rec[col.id], rec);
852
- }
853
- else {
854
- text = rec[col.id];
847
+ if (cid) {
848
+ let col = this.m_columns[cid];
849
+ let fmt = col.formatter;
850
+ let text;
851
+ if (fmt && fmt instanceof Function) {
852
+ text = fmt(rec[col.id], rec);
853
+ }
854
+ else {
855
+ text = rec[col.id];
856
+ }
857
+ c.setContent(text, false);
855
858
  }
856
- c.setContent(text, false);
857
859
  });
858
860
  }
859
861
  }
package/lib/listview.d.ts CHANGED
@@ -134,8 +134,8 @@ export declare class ListView extends VLayout<ListViewProps, ListViewEventMap> {
134
134
  /**
135
135
  * return the current selection or null
136
136
  */
137
- get selection(): ListViewItem;
138
- set selection(id: ListViewItem);
137
+ get selection(): any;
138
+ set selection(id: any);
139
139
  private _findItemWithId;
140
140
  /**
141
141
  * append or prepend a new item
package/lib/menu.d.ts CHANGED
@@ -28,6 +28,7 @@
28
28
  **/
29
29
  import { CEventMap, Component, CProps } from './component';
30
30
  import { EvClick, EventCallback } from './x4events';
31
+ import { Action } from './action';
31
32
  import { Popup, PopupProps } from './popup';
32
33
  import { IconID } from './icon';
33
34
  import { Label } from './label';
@@ -99,10 +100,13 @@ export interface MenuItemProps extends CProps {
99
100
  checked?: boolean;
100
101
  cls?: string;
101
102
  click?: EventCallback<EvClick>;
103
+ action?: Action;
102
104
  }
103
105
  export declare class MenuItem extends Component<MenuItemProps, MenuItemEventMap> {
104
106
  private m_menu;
105
107
  private m_isOpen;
108
+ private m_action;
109
+ constructor(action: Action);
106
110
  constructor(text: string, click: EventCallback<EvClick>);
107
111
  constructor(props: MenuItemProps);
108
112
  /** @ignore */
package/lib/menu.js CHANGED
@@ -32,6 +32,7 @@ exports.MenuBar = exports.MenuItem = exports.Menu = exports.MenuTitle = exports.
32
32
  const x4dom_1 = require("./x4dom");
33
33
  const component_1 = require("./component");
34
34
  const x4events_1 = require("./x4events");
35
+ const action_1 = require("./action");
35
36
  const popup_1 = require("./popup");
36
37
  const icon_1 = require("./icon");
37
38
  const label_1 = require("./label");
@@ -177,8 +178,15 @@ exports.Menu = Menu;
177
178
  class MenuItem extends component_1.Component {
178
179
  m_menu;
179
180
  m_isOpen;
181
+ m_action;
180
182
  constructor(a, b) {
181
- if ((0, tools_1.isString)(a)) {
183
+ if (a instanceof action_1.Action) {
184
+ super({
185
+ click: () => { a.fire(); }
186
+ });
187
+ this.m_action = a;
188
+ }
189
+ else if ((0, tools_1.isString)(a)) {
182
190
  super({
183
191
  text: a,
184
192
  click: b
@@ -195,15 +203,23 @@ class MenuItem extends component_1.Component {
195
203
  }
196
204
  /** @ignore */
197
205
  render(props) {
198
- let icon = props.icon ?? 0x20;
206
+ let icon = props.icon ?? 0;
199
207
  let text = props.text;
200
208
  if (props.checked !== undefined) {
201
- icon = props.checked ? 'cls(far fa-check)' : 0; //todo: use stylesheet
209
+ icon = props.checked ? 'var( --x4-icon-check )' : 0;
210
+ }
211
+ if (this.m_action) {
212
+ if (!icon) {
213
+ icon = this.m_action.props.icon;
214
+ }
215
+ if (text === undefined) {
216
+ text = this.m_action.props.text;
217
+ }
202
218
  }
203
219
  let popIco = null;
204
220
  if (this.isPopup) {
205
221
  this.addClass('@popup-menu-item');
206
- popIco = new icon_1.Icon("var( --x4-icon-chevron-right )");
222
+ popIco = new icon_1.Icon({ icon: "var( --x4-icon-chevron-right )", cls: "pop-mark" });
207
223
  }
208
224
  if (!text && !icon) {
209
225
  this.addClass('@separator');
package/lib/popup.js CHANGED
@@ -126,7 +126,10 @@ class Popup extends component_1.Container {
126
126
  }
127
127
  centerOnScreen() {
128
128
  let rc = this.getBoundingRect();
129
- let x = (x4dom_1.x4document.body.clientWidth - rc.width) / 2, y = (x4dom_1.x4document.body.clientHeight - rc.height) / 2;
129
+ //let x = (x4document.body.clientWidth - rc.width) / 2,
130
+ // y = (x4document.body.clientHeight - rc.height) / 2;
131
+ const x = `max( 0px, 50vw - ${rc.width / 2}px )`; //(x4dom_1.x4document.body.clientWidth - rc.width) / 2;
132
+ const y = `max( 0px, 50vh - ${rc.height / 2}px )`; //(x4dom_1.x4document.body.clientHeight - rc.height) / 2;
130
133
  this.setStyleValue('left', x);
131
134
  this.setStyleValue('top', y);
132
135
  }
package/lib/settings.js CHANGED
@@ -47,14 +47,14 @@ class Settings {
47
47
  }
48
48
  _save() {
49
49
  let data = JSON.stringify(this.m_data);
50
- localStorage.write(this.m_name, data);
50
+ localStorage.setItem(this.m_name, data);
51
51
  }
52
52
  _load() {
53
53
  if (this.m_data) {
54
54
  return;
55
55
  }
56
56
  this.m_data = {};
57
- let data = localStorage.read(this.m_name);
57
+ let data = localStorage.getItem(this.m_name);
58
58
  if (data !== null) {
59
59
  data = JSON.parse(data);
60
60
  if (data) {
@@ -389,6 +389,7 @@ class Spreadsheet extends layout_1.VLayout {
389
389
  if (this.m_recycler.length) {
390
390
  cell = this.m_recycler.pop();
391
391
  cell.clearClasses();
392
+ cell.addClass('@comp'); // todo: find better to reset to default
392
393
  }
393
394
  else {
394
395
  cell = new component_1.Component({
@@ -492,7 +493,8 @@ class Spreadsheet extends layout_1.VLayout {
492
493
  cell.setStyle({
493
494
  left: x,
494
495
  top: top + y,
495
- width: calcw[colIdx]
496
+ width: calcw[colIdx],
497
+ height: this.m_itemHeight
496
498
  });
497
499
  if (this.m_selection.row == rowIdx && this.m_selection.col == colIdx) {
498
500
  cell.addClass('@selected');
package/lib/x4.css CHANGED
@@ -58,7 +58,8 @@
58
58
  --x4-icon-xmark: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" fill="currentColor"><path d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"/></svg>';
59
59
  --x4-icon-angle-down: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" fill="currentColor"><path d="M192 384c-8.188 0-16.38-3.125-22.62-9.375l-160-160c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L192 306.8l137.4-137.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-160 160C208.4 380.9 200.2 384 192 384z"/></svg>';
60
60
  --x4-icon-calendar-days: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M160 32V64H288V32C288 14.33 302.3 0 320 0C337.7 0 352 14.33 352 32V64H400C426.5 64 448 85.49 448 112V160H0V112C0 85.49 21.49 64 48 64H96V32C96 14.33 110.3 0 128 0C145.7 0 160 14.33 160 32zM0 192H448V464C448 490.5 426.5 512 400 512H48C21.49 512 0 490.5 0 464V192zM64 304C64 312.8 71.16 320 80 320H112C120.8 320 128 312.8 128 304V272C128 263.2 120.8 256 112 256H80C71.16 256 64 263.2 64 272V304zM192 304C192 312.8 199.2 320 208 320H240C248.8 320 256 312.8 256 304V272C256 263.2 248.8 256 240 256H208C199.2 256 192 263.2 192 272V304zM336 256C327.2 256 320 263.2 320 272V304C320 312.8 327.2 320 336 320H368C376.8 320 384 312.8 384 304V272C384 263.2 376.8 256 368 256H336zM64 432C64 440.8 71.16 448 80 448H112C120.8 448 128 440.8 128 432V400C128 391.2 120.8 384 112 384H80C71.16 384 64 391.2 64 400V432zM208 384C199.2 384 192 391.2 192 400V432C192 440.8 199.2 448 208 448H240C248.8 448 256 440.8 256 432V400C256 391.2 248.8 384 240 384H208zM320 432C320 440.8 327.2 448 336 448H368C376.8 448 384 440.8 384 432V400C384 391.2 376.8 384 368 384H336C327.2 384 320 391.2 320 400V432z"/></svg>';
61
- --x4-icon-tip: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 464c-114.7 0-208-93.31-208-208S141.3 48 256 48s208 93.31 208 208S370.7 464 256 464zM296 336h-16V248C280 234.8 269.3 224 256 224H224C210.8 224 200 234.8 200 248S210.8 272 224 272h8v64h-16C202.8 336 192 346.8 192 360S202.8 384 216 384h80c13.25 0 24-10.75 24-24S309.3 336 296 336zM256 192c17.67 0 32-14.33 32-32c0-17.67-14.33-32-32-32S224 142.3 224 160C224 177.7 238.3 192 256 192z"/></svg>';
61
+ --x4-icon-tip: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 464c-114.7 0-208-93.31-208-208S141.3 48 256 48s208 93.31 208 208S370.7 464 256 464zM296 336h-16V248C280 234.8 269.3 224 256 224H224C210.8 224 200 234.8 200 248S210.8 272 224 272h8v64h-16C202.8 336 192 346.8 192 360S202.8 384 216 384h80c13.25 0 24-10.75 24-24S309.3 336 296 336zM256 192c17.67 0 32-14.33 32-32c0-17.67-14.33-32-32-32S224 142.3 224 160C224 177.7 238.3 192 256 192z"/></svg>';
62
+ --x4-check: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M440.1 103C450.3 112.4 450.3 127.6 440.1 136.1L176.1 400.1C167.6 410.3 152.4 410.3 143 400.1L7.029 264.1C-2.343 255.6-2.343 240.4 7.029 231C16.4 221.7 31.6 221.7 40.97 231L160 350.1L407 103C416.4 93.66 431.6 93.66 440.1 103V103z"/></svg>';
62
63
  }
63
64
  /* source: https://tailwindcss.com/docs/customizing-colors/#default-color-palette */
64
65
  :root {
@@ -693,6 +694,9 @@ textarea::selection {
693
694
  margin-right: 8px;
694
695
  color: var(--gray-700);
695
696
  }
697
+ .x-menu-item .x-icon.pop-mark {
698
+ height: 0.8em;
699
+ }
696
700
  .x-menu-item .x-label {
697
701
  padding: 4px;
698
702
  }
@@ -1079,6 +1083,10 @@ textarea::selection {
1079
1083
  color: var(--gray-900);
1080
1084
  height: 2em;
1081
1085
  }
1086
+ .x-spreadsheet .x-cell span,
1087
+ .x-grid-view .x-cell span {
1088
+ width: 100%;
1089
+ }
1082
1090
  .x-spreadsheet .x-footer,
1083
1091
  .x-grid-view .x-footer,
1084
1092
  .x-spreadsheet .x-header,
@@ -1123,6 +1131,16 @@ textarea::selection {
1123
1131
  display: flex;
1124
1132
  align-items: center;
1125
1133
  }
1134
+ .x-spreadsheet .x-header .x-cell span,
1135
+ .x-grid-view .x-header .x-cell span {
1136
+ width: unset;
1137
+ }
1138
+ .x-spreadsheet .x-header .x-cell .sort,
1139
+ .x-grid-view .x-header .x-cell .sort {
1140
+ width: 1em;
1141
+ height: 1em;
1142
+ padding-left: 4px;
1143
+ }
1126
1144
  .x-spreadsheet .x-row,
1127
1145
  .x-grid-view .x-row {
1128
1146
  position: absolute;
@@ -1178,6 +1196,8 @@ textarea::selection {
1178
1196
  border-right: 1px solid rgba(0, 0, 0, 0.1);
1179
1197
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
1180
1198
  height: 2em;
1199
+ align-items: center;
1200
+ display: flex;
1181
1201
  }
1182
1202
  .x-spreadsheet .x-cell.x-selected {
1183
1203
  background-color: rgba(0, 0, 0, 0.1);