jsl-ui 9.28.7 → 10.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.
Files changed (166) hide show
  1. package/docs/AutoSuggestComponent.md +17 -0
  2. package/docs/ButtonComponent.md +14 -0
  3. package/docs/CheckBoxComponent.md +12 -0
  4. package/docs/DateComponent.md +12 -0
  5. package/docs/DateRangeComponent.md +13 -0
  6. package/docs/DateTimeComponent.md +13 -0
  7. package/docs/DialogComponent.md +15 -0
  8. package/docs/ExpanderComponent.md +13 -0
  9. package/docs/FormComponent.md +15 -0
  10. package/docs/FormFieldComponent.md +15 -0
  11. package/docs/GridComponent.md +19 -0
  12. package/docs/InputComponent.md +15 -0
  13. package/docs/IntervalComponent.md +13 -0
  14. package/docs/LoadingComponent.md +12 -0
  15. package/docs/NavigationComponent.md +17 -0
  16. package/docs/Notification.md +14 -0
  17. package/docs/NotificationComponent.md +13 -0
  18. package/docs/NumberComponent.md +12 -0
  19. package/docs/OverlayComponent.md +12 -0
  20. package/docs/ProgressComponent.md +12 -0
  21. package/docs/README.md +24 -0
  22. package/docs/RibbonMenuComponent.md +14 -0
  23. package/docs/SelectComponent.md +15 -0
  24. package/docs/SplitterComponent.md +14 -0
  25. package/docs/StackPanelComponent.md +13 -0
  26. package/docs/TabsComponent.md +16 -0
  27. package/docs/TimeComponent.md +13 -0
  28. package/docs/TreeViewComponent.md +16 -0
  29. package/examples/showcase/checks-and-expanders.ts +163 -0
  30. package/examples/showcase/cultures.ts +39 -0
  31. package/examples/showcase/dates.ts +182 -0
  32. package/examples/showcase/dialogs.ts +184 -0
  33. package/examples/showcase/feedback-and-navigation.ts +174 -0
  34. package/examples/showcase/fields.ts +178 -0
  35. package/examples/showcase/fonts/Jost-Variable.ttf +0 -0
  36. package/examples/showcase/fonts/OFL-Jost.txt +93 -0
  37. package/examples/showcase/grids.ts +150 -0
  38. package/examples/showcase/index.html +60 -0
  39. package/examples/showcase/layout-and-navigation.ts +47 -0
  40. package/examples/showcase/nivona.css +98 -0
  41. package/examples/showcase/selects.ts +158 -0
  42. package/examples/showcase/showcase.css +231 -0
  43. package/examples/showcase/showcase.ts +214 -0
  44. package/examples/showcase/tabs.ts +161 -0
  45. package/examples/showcase/themes.css +83 -0
  46. package/examples/showcase/themes.ts +54 -0
  47. package/lib/components/IntervalComponent.d.ts +5 -0
  48. package/lib/components/IntervalComponent.js +29 -13
  49. package/lib/components/auto-suggest/AutoSuggestComponent.d.ts +11 -9
  50. package/lib/components/auto-suggest/AutoSuggestComponent.js +25 -38
  51. package/lib/components/button/ButtonComponent.d.ts +30 -1
  52. package/lib/components/button/ButtonComponent.js +85 -4
  53. package/lib/components/checkbox/CheckBoxComponent.d.ts +11 -1
  54. package/lib/components/checkbox/CheckBoxComponent.js +66 -56
  55. package/lib/components/checkbox/CheckBoxStyle.scss +72 -85
  56. package/lib/components/date/DateComponent.d.ts +10 -0
  57. package/lib/components/date/DateComponent.js +92 -44
  58. package/lib/components/date-range/DateRangeComponent.d.ts +14 -3
  59. package/lib/components/date-range/DateRangeComponent.js +96 -86
  60. package/lib/components/date-range/DateRangeStyle.scss +35 -11
  61. package/lib/components/date-time/DateTimeComponent.d.ts +8 -0
  62. package/lib/components/date-time/DateTimeComponent.js +64 -23
  63. package/lib/components/date-time/DateTimeStyle.scss +10 -7
  64. package/lib/components/dialog/DialogComponent.d.ts +21 -7
  65. package/lib/components/dialog/DialogComponent.js +179 -122
  66. package/lib/components/expander/ExpanderComponent.d.ts +15 -1
  67. package/lib/components/expander/ExpanderComponent.js +85 -64
  68. package/lib/components/expander/ExpanderStyle.scss +61 -47
  69. package/lib/components/form-field/FormFieldComponent.d.ts +45 -15
  70. package/lib/components/form-field/FormFieldComponent.js +249 -96
  71. package/lib/components/form-field/FormFieldStyle.scss +36 -87
  72. package/lib/components/form-field/create-control.d.ts +7 -0
  73. package/lib/components/form-field/create-control.js +48 -0
  74. package/lib/components/input/InputComponent.d.ts +18 -1
  75. package/lib/components/input/InputComponent.js +68 -93
  76. package/lib/components/loading/LoadingComponent.d.ts +9 -2
  77. package/lib/components/loading/LoadingComponent.js +13 -12
  78. package/lib/components/loading/LoadingStyle.css +19 -29
  79. package/lib/components/navigation/NavigationComponent.d.ts +34 -10
  80. package/lib/components/navigation/NavigationComponent.js +261 -33
  81. package/lib/components/navigation/NavigationStyle.scss +62 -226
  82. package/lib/components/notification/Notification.d.ts +37 -4
  83. package/lib/components/notification/Notification.js +160 -41
  84. package/lib/components/notification/Notification.scss +103 -19
  85. package/lib/components/number/NumberComponent.d.ts +16 -2
  86. package/lib/components/number/NumberComponent.js +54 -53
  87. package/lib/components/overlay/OverlayComponent.d.ts +13 -7
  88. package/lib/components/overlay/OverlayComponent.js +46 -114
  89. package/lib/components/overlay/overlay.css +18 -57
  90. package/lib/components/progress/ProgressComponent.d.ts +1 -0
  91. package/lib/components/progress/ProgressComponent.js +6 -6
  92. package/lib/components/progress/ProgressStyle.scss +5 -15
  93. package/lib/components/ribbon-menu/RibbonMenuComponent.js +2 -2
  94. package/lib/components/ribbon-menu/RibbonMenuStyle.scss +6 -76
  95. package/lib/components/select/SelectComponent.d.ts +33 -3
  96. package/lib/components/select/SelectComponent.js +312 -278
  97. package/lib/components/select/SelectDDAreaComponent.d.ts +13 -7
  98. package/lib/components/select/SelectDDAreaComponent.js +215 -256
  99. package/lib/components/select/SelectStyle.scss +204 -186
  100. package/lib/components/slider/nouislider.css +40 -54
  101. package/lib/components/stack-panel/SplitterComponent.d.ts +19 -3
  102. package/lib/components/stack-panel/SplitterComponent.js +94 -111
  103. package/lib/components/stack-panel/SplitterStyle.scss +9 -45
  104. package/lib/components/stack-panel/StackPanelComponent.js +3 -3
  105. package/lib/components/stack-panel/StackPanelStyle.scss +10 -52
  106. package/lib/components/tabs/TabsComponent.d.ts +17 -1
  107. package/lib/components/tabs/TabsComponent.js +247 -123
  108. package/lib/components/tabs/TabsStyle.scss +138 -75
  109. package/lib/components/time/TimeComponent.d.ts +5 -0
  110. package/lib/components/time/TimeComponent.js +61 -69
  111. package/lib/components/time/TimeComponent.scss +4 -4
  112. package/lib/components/tree-view/TreeViewComponent.d.ts +10 -4
  113. package/lib/components/tree-view/TreeViewComponent.js +65 -32
  114. package/lib/components/tree-view/TreeViewStyle.scss +12 -96
  115. package/lib/core/date.d.ts +2 -0
  116. package/lib/core/date.js +6 -0
  117. package/lib/core/jq.js +11 -8
  118. package/lib/grid/slick-default-theme.css +107 -31
  119. package/lib/grid/slick.creator.js +23 -5
  120. package/lib/grid/slick.formatters.js +4 -3
  121. package/lib/grid/slick.grid.css +38 -26
  122. package/lib/grid/slick.grid.d.ts +1 -0
  123. package/lib/grid/slick.grid.js +2 -3
  124. package/lib/grid.css +3413 -454
  125. package/lib/index.css +2500 -1031
  126. package/lib/index.css.map +1 -1
  127. package/lib/index.d.ts +1 -0
  128. package/lib/index.js +1 -1
  129. package/lib/index.js.map +1 -1
  130. package/lib/interaction/moveable.d.ts +1 -0
  131. package/lib/interaction/moveable.js +8 -0
  132. package/lib/interaction/resizable.d.ts +1 -0
  133. package/lib/interaction/resizable.js +9 -0
  134. package/lib/ui/auto.suggest.css +31 -14
  135. package/lib/ui/auto.suggest.d.ts +1 -0
  136. package/lib/ui/auto.suggest.js +88 -18
  137. package/lib/ui/base.css +2 -48
  138. package/lib/ui/button.css +134 -0
  139. package/lib/ui/date-input.css +11 -0
  140. package/lib/ui/date.picker/css/tiny-date-picker.css +124 -325
  141. package/lib/ui/date.picker/date-picker-options.js +4 -3
  142. package/lib/ui/date.picker/lib/date-manip.js +9 -0
  143. package/lib/ui/date.picker/mode/base-mode.d.ts +2 -1
  144. package/lib/ui/date.picker/mode/base-mode.js +112 -22
  145. package/lib/ui/date.picker/mode/dropdown-mode.d.ts +2 -4
  146. package/lib/ui/date.picker/mode/dropdown-mode.js +29 -42
  147. package/lib/ui/date.picker/mode/index.d.ts +2 -1
  148. package/lib/ui/date.picker/mode/modal-mode.d.ts +2 -1
  149. package/lib/ui/date.picker/mode/modal-mode.js +4 -2
  150. package/lib/ui/date.picker/mode/permanent-mode.d.ts +2 -1
  151. package/lib/ui/date.picker/views/day-picker.js +24 -15
  152. package/lib/ui/date.picker/views/month-picker.js +1 -1
  153. package/lib/ui/date.picker/views/year-picker.js +3 -2
  154. package/lib/ui/date.picker.d.ts +2 -1
  155. package/lib/ui/dialog.css +144 -108
  156. package/lib/ui/dialog.d.ts +19 -1
  157. package/lib/ui/dialog.js +178 -60
  158. package/lib/ui/input.css +35 -0
  159. package/lib/ui/number.input.js +50 -37
  160. package/lib/ui/theme.css +28 -0
  161. package/package.json +12 -8
  162. package/lib/components/drop-down/DropDownComponent.d.ts +0 -27
  163. package/lib/components/drop-down/DropDownComponent.js +0 -60
  164. package/lib/components/expander/OldExpanderStyle.scss +0 -37
  165. package/lib/ui/drop.down.d.ts +0 -52
  166. package/lib/ui/drop.down.js +0 -2112
@@ -1,4 +1,4 @@
1
- import { IJSLComponent, IJSLVNode } from "jsl-render";
1
+ import { IJSLComponent, IJSLVNode, JSLRender } from "jsl-render";
2
2
  import { IDialogOptions, JSLDialog } from "../../ui/dialog";
3
3
  import { IMoveableOptions } from "../../interaction/moveable";
4
4
  import { IResizeOptions } from "../../interaction/resizable";
@@ -18,6 +18,9 @@ export interface IDialogComponentOptions extends IDialogOptions {
18
18
  resizeOptions?: IResizeOptions;
19
19
  moveOptions?: IMoveableOptions;
20
20
  class?: string;
21
+ /** Accessible name when the header does not provide a suitable title. */
22
+ ariaLabel?: string;
23
+ closeButtonLabel?: string;
21
24
  }
22
25
  export interface IDialogButtonOptions {
23
26
  content?: string;
@@ -26,11 +29,13 @@ export interface IDialogButtonOptions {
26
29
  raw?: boolean;
27
30
  }
28
31
  export declare class DialogComponent implements IJSLComponent {
32
+ private static renderedDialogs;
29
33
  static Button(options: IDialogButtonOptions): {
30
34
  tag: string;
31
35
  attr: {
36
+ type: string;
32
37
  class: string;
33
- click: () => Promise<void>;
38
+ click: (event: MouseEvent) => Promise<void>;
34
39
  };
35
40
  content: string;
36
41
  raw: boolean;
@@ -38,8 +43,9 @@ export declare class DialogComponent implements IJSLComponent {
38
43
  static Ok(onClick?: () => void | boolean | Promise<any>): {
39
44
  tag: string;
40
45
  attr: {
46
+ type: string;
41
47
  class: string;
42
- click: () => Promise<void>;
48
+ click: (event: MouseEvent) => Promise<void>;
43
49
  };
44
50
  content: string;
45
51
  raw: boolean;
@@ -47,21 +53,29 @@ export declare class DialogComponent implements IJSLComponent {
47
53
  static Cancel(): {
48
54
  tag: string;
49
55
  attr: {
56
+ type: string;
50
57
  class: string;
51
- click: () => Promise<void>;
58
+ click: (event: MouseEvent) => Promise<void>;
52
59
  };
53
60
  content: string;
54
61
  raw: boolean;
55
62
  };
56
63
  static show(options: IDialogComponentOptions): DialogComponent;
57
- private static lastRenderedDlg;
58
- private closeIcon;
59
- private resizeHandle;
64
+ private static get lastRenderedDlg();
60
65
  private ref;
66
+ private renderer;
61
67
  private options;
68
+ private titleId;
69
+ private moveable;
70
+ private resizable;
71
+ private onDispose;
62
72
  constructor(options: IDialogComponentOptions);
63
73
  render(): IJSLVNode;
74
+ onInit(renderer: JSLRender): void;
64
75
  onCreate(node: IJSLVNode): void;
76
+ onRemove(): void;
65
77
  getRef(): JSLDialog;
78
+ private normalizePosition;
79
+ private keepInViewport;
66
80
  private toNode;
67
81
  }
@@ -4,30 +4,49 @@ import { Moveable } from "../../interaction/moveable";
4
4
  import { EventHandler } from "../../interaction/eventhandler";
5
5
  import { Resizable } from "../../interaction/resizable";
6
6
  import { UILang } from "../../core/lang";
7
+ import { helper } from "../../core/helper";
7
8
  export class DialogComponent {
8
9
  static Button(options) {
9
10
  var _a, _b, _c;
10
- const res = {
11
+ return {
11
12
  tag: "button", attr: {
13
+ type: "button",
12
14
  class: "jsl-button " + ((_a = options.class) !== null && _a !== void 0 ? _a : ""),
13
- click: async () => {
14
- if (options.onClick != null) {
15
- let clickRes = options.onClick();
16
- const isPromise = clickRes && typeof clickRes.then === "function" && typeof clickRes.catch === "function";
17
- if (isPromise) {
18
- clickRes = await clickRes;
15
+ click: async (event) => {
16
+ var _a, _b, _c;
17
+ const button = event === null || event === void 0 ? void 0 : event.currentTarget;
18
+ if (button === null || button === void 0 ? void 0 : button.disabled) {
19
+ return;
20
+ }
21
+ const overlay = button === null || button === void 0 ? void 0 : button.closest(".jsl-dialog-overlay");
22
+ const owner = overlay === null || overlay === void 0 ? void 0 : overlay._component;
23
+ // Capture the owner before a callback opens another dialog or awaits.
24
+ const reference = (_a = (owner || DialogComponent.lastRenderedDlg)) === null || _a === void 0 ? void 0 : _a.getRef();
25
+ let pending = false;
26
+ try {
27
+ let result = (_b = options.onClick) === null || _b === void 0 ? void 0 : _b.call(options);
28
+ if (result && typeof result.then === "function") {
29
+ pending = true;
30
+ if (button) {
31
+ button.disabled = true;
32
+ button.setAttribute("aria-busy", "true");
33
+ }
34
+ result = await result;
19
35
  }
20
- if (clickRes === false) {
21
- return;
36
+ if (result !== false) {
37
+ reference === null || reference === void 0 ? void 0 : reference.close();
22
38
  }
23
39
  }
24
- if (DialogComponent.lastRenderedDlg != null) {
25
- DialogComponent.lastRenderedDlg.getRef().close();
40
+ finally {
41
+ if (pending && button) {
42
+ button.disabled = false;
43
+ button.removeAttribute("aria-busy");
44
+ }
45
+ (_c = owner === null || owner === void 0 ? void 0 : owner.renderer) === null || _c === void 0 ? void 0 : _c.refresh();
26
46
  }
27
47
  }
28
48
  }, content: (_b = options.content) !== null && _b !== void 0 ? _b : "OK", raw: (_c = options.raw) !== null && _c !== void 0 ? _c : false
29
49
  };
30
- return res;
31
50
  }
32
51
  static Ok(onClick) {
33
52
  return DialogComponent.Button({ content: UILang.core.Ok, onClick, class: "dlg-ok-btn" });
@@ -35,58 +54,77 @@ export class DialogComponent {
35
54
  static Cancel() {
36
55
  return DialogComponent.Button({ content: UILang.core.Cancel, class: "dlg-cancel-btn jsl-button-outline" });
37
56
  }
38
- // does not work -> dialog still exists in background and wrong renderer is active
39
- // public static closeAll() {
40
- // document.querySelectorAll(".jsl-dialog-overlay").forEach((x) => {
41
- // if (x.parentNode != null) {
42
- // x.parentNode.removeChild(x);
43
- // }
44
- // });
45
- // }
46
57
  static show(options) {
58
+ var _a;
47
59
  const container = document.createElement("div");
48
60
  document.body.appendChild(container);
49
- const oldRenderer = JSLRender.lastCreatedRenderer;
50
- const oldLastDlg = DialogComponent.lastRenderedDlg;
51
- const renderer = new JSLRender(container, oldRenderer != null);
52
- if (oldRenderer != null) {
53
- JSLRender.lastCreatedRenderer = renderer;
54
- }
55
- const o = { ...options };
56
- if (o.autoOpen == null) {
57
- o.autoOpen = true;
58
- }
59
- o.onClose = () => {
60
- if (options.onClose) {
61
- if (options.onClose() === false) {
62
- return;
61
+ const renderer = new JSLRender(container, false);
62
+ const entry = {
63
+ dialog: undefined,
64
+ renderer,
65
+ previousRenderer: JSLRender.lastCreatedRenderer
66
+ };
67
+ let disposed = false;
68
+ const cleanup = (renderContent = true) => {
69
+ var _a;
70
+ if (disposed) {
71
+ return;
72
+ }
73
+ disposed = true;
74
+ const index = DialogComponent.renderedDialogs.indexOf(entry);
75
+ if (index >= 0) {
76
+ DialogComponent.renderedDialogs.splice(index, 1);
77
+ }
78
+ // A parent can close while a nested or asynchronous dialog is still open.
79
+ for (const other of DialogComponent.renderedDialogs) {
80
+ if (other.previousRenderer === renderer) {
81
+ other.previousRenderer = entry.previousRenderer;
63
82
  }
64
83
  }
65
- renderer.render({ tag: "div" }); // necessary to call all onRemove functions in rendered content
66
- document.body.removeChild(container);
67
- JSLRender.lastCreatedRenderer = oldRenderer;
68
- if (oldRenderer != null) {
69
- oldRenderer.refresh();
84
+ if (JSLRender.lastCreatedRenderer === renderer) {
85
+ JSLRender.lastCreatedRenderer = entry.previousRenderer;
86
+ }
87
+ if (renderContent) {
88
+ renderer.render({ tag: "div" }); // Run onRemove for all dialog content.
70
89
  }
71
- DialogComponent.lastRenderedDlg = oldLastDlg;
90
+ container.remove();
91
+ (_a = JSLRender.lastCreatedRenderer) === null || _a === void 0 ? void 0 : _a.refresh();
72
92
  };
73
- const dlg = new DialogComponent(o);
74
- DialogComponent.lastRenderedDlg = dlg;
93
+ const dlg = entry.dialog = new DialogComponent({
94
+ ...options,
95
+ autoOpen: (_a = options.autoOpen) !== null && _a !== void 0 ? _a : true,
96
+ onClose: () => {
97
+ var _a;
98
+ if (((_a = options.onClose) === null || _a === void 0 ? void 0 : _a.call(options)) === false) {
99
+ renderer.refresh();
100
+ return false;
101
+ }
102
+ cleanup();
103
+ }
104
+ });
105
+ dlg.onDispose = () => cleanup(false);
106
+ DialogComponent.renderedDialogs.push(entry);
107
+ JSLRender.lastCreatedRenderer = renderer;
75
108
  renderer.render(dlg);
76
109
  return dlg;
77
110
  }
111
+ static get lastRenderedDlg() {
112
+ var _a;
113
+ const entries = DialogComponent.renderedDialogs;
114
+ return (_a = entries[entries.length - 1]) === null || _a === void 0 ? void 0 : _a.dialog;
115
+ }
78
116
  constructor(options) {
79
- this.closeIcon = {
80
- tag: "div", content: "✖" /*"🗙"*/, attr: {
81
- class: "dlg-close-btn", click: () => {
82
- this.ref.close();
83
- }
117
+ this.titleId = helper.newDomGuid();
118
+ this.keepInViewport = () => {
119
+ const overlay = this.ref.getOverlay();
120
+ const element = overlay.querySelector(".jsl-dialog");
121
+ if (element.style.transform !== "none" || !element.getClientRects().length) {
122
+ return;
84
123
  }
124
+ element.style.left = Math.max(0, Math.min(element.offsetLeft, overlay.clientWidth - element.offsetWidth)) + "px";
125
+ element.style.top = Math.max(0, Math.min(element.offsetTop, overlay.clientHeight - element.offsetHeight)) + "px";
85
126
  };
86
- this.resizeHandle = {
87
- tag: "div", attr: { class: "dlg-res-handle rs-b rs-r" }
88
- };
89
- this.options = { maxHeight: "calc(100vh - 7.5rem)", width: "50vw", ...options };
127
+ this.options = { maxHeight: "calc(100vh - 7.5rem)", width: "32rem", ...options };
90
128
  }
91
129
  render() {
92
130
  const header = this.toNode(this.options.header);
@@ -94,99 +132,118 @@ export class DialogComponent {
94
132
  const footer = this.toNode(this.options.footer);
95
133
  let styleW = "";
96
134
  let styleH = "";
97
- if (this.options.width != null) {
98
- styleW += "width:" + this.options.width + ";";
99
- }
100
- if (this.options.minWidth != null) {
101
- styleW += "min-width:" + this.options.minWidth + ";";
102
- }
103
- if (this.options.maxWidth != null) {
104
- styleW += "max-width:" + this.options.maxWidth + ";";
105
- }
106
- if (this.options.height != null) {
107
- styleH += "height:" + this.options.height + ";";
108
- }
109
- if (this.options.minHeight != null) {
110
- styleH += "min-height:" + this.options.minHeight + ";";
135
+ for (const property of ["width", "minWidth", "maxWidth"]) {
136
+ if (this.options[property] != null) {
137
+ styleW += property.replace(/[A-Z]/g, letter => "-" + letter.toLowerCase()) + ":" + this.options[property] + ";";
138
+ }
111
139
  }
112
- if (this.options.maxHeight != null) {
113
- styleH += "max-height:" + this.options.maxHeight + ";";
140
+ // Preserve the existing API: height options describe the content area.
141
+ for (const property of ["height", "minHeight", "maxHeight"]) {
142
+ if (this.options[property] != null) {
143
+ styleH += property.replace(/[A-Z]/g, letter => "-" + letter.toLowerCase()) + ":" + this.options[property] + ";";
144
+ }
114
145
  }
115
- const headerStyle = this.options.allowMove ? "cursor:move" : undefined;
146
+ const hasHeader = this.options.header != null && this.options.header !== "";
147
+ const hasFooter = this.options.footer != null && this.options.footer !== "";
116
148
  return {
117
- tag: "div", attr: {
118
- class: "jsl-dialog-overlay", wheel: (e) => {
119
- e.preventDefault();
120
- }
121
- }, children: [
122
- {
149
+ tag: "div", attr: { class: "jsl-dialog-overlay" }, children: [{
123
150
  tag: "div", attr: {
124
- class: "jsl-dialog " + (this.options.class || ""), style: styleW, wheel: (e) => {
125
- e.stopImmediatePropagation();
126
- e.stopPropagation();
127
- }
151
+ class: "jsl-dialog " + (this.options.allowMove ? "jsl-dialog-moveable " : "") + (this.options.class || ""),
152
+ style: styleW,
153
+ role: "dialog",
154
+ tabindex: "-1",
155
+ "aria-label": this.options.ariaLabel,
156
+ "aria-labelledby": !this.options.ariaLabel && hasHeader ? this.titleId : undefined
128
157
  }, children: [
129
158
  {
130
- tag: "div", attr: { class: "dlg-header", style: headerStyle },
131
- children: this.options.showCloseButton ? [header, this.closeIcon] : [header]
159
+ tag: "div", attr: {
160
+ class: "dlg-header",
161
+ hidden: !hasHeader && !this.options.showCloseButton ? "hidden" : undefined
162
+ }, children: [
163
+ { tag: "div", attr: { class: "dlg-title", id: this.titleId }, children: [header] },
164
+ this.options.showCloseButton ? {
165
+ tag: "button", attr: {
166
+ type: "button", class: "dlg-close-btn",
167
+ "aria-label": this.options.closeButtonLabel || "Close dialog",
168
+ title: this.options.closeButtonLabel || "Close dialog",
169
+ click: () => this.ref.close()
170
+ }
171
+ } : undefined
172
+ ]
132
173
  },
133
174
  { tag: "div", attr: { class: "dlg-body", style: styleH }, children: [body] },
134
- {
135
- tag: "div", attr: { class: "dlg-footer" },
136
- children: [footer]
137
- },
138
- this.options.allowResize ? this.resizeHandle : undefined
175
+ { tag: "div", attr: { class: "dlg-footer", hidden: !hasFooter ? "hidden" : undefined }, children: [footer] },
176
+ this.options.allowResize ? {
177
+ tag: "div", attr: { class: "dlg-res-handle rs-b rs-r", "aria-hidden": "true" }
178
+ } : undefined
139
179
  ]
140
- }
141
- ]
180
+ }]
142
181
  };
143
182
  }
183
+ onInit(renderer) {
184
+ this.renderer = renderer;
185
+ }
144
186
  onCreate(node) {
145
- this.ref = Dialog(node.dom, this.options);
187
+ const overlay = node.dom;
188
+ const element = overlay.querySelector(".jsl-dialog");
189
+ // Initialize first so onOpen can safely access getRef(), even on first render.
190
+ this.ref = Dialog(overlay, { ...this.options, autoOpen: false });
146
191
  if (this.options.allowMove) {
147
- Moveable(this.ref.getOverlay(), {
148
- onStart: new EventHandler((e) => {
149
- let headerWasClicked = false;
150
- let parent = e.evt.target;
151
- while (parent != null && !parent.classList.contains("jsl-dialog-overlay")) {
152
- if (parent.classList.contains("dlg-header")) {
153
- headerWasClicked = true;
154
- break;
155
- }
156
- parent = parent.parentElement;
157
- }
158
- if (headerWasClicked) {
159
- const rect = e.target.getBoundingClientRect();
160
- e.target.style.transform = "translate(0, 0)";
161
- e.target.style.left = rect.left + "px";
162
- e.target.style.top = rect.top + "px";
192
+ this.moveable = Moveable(overlay, {
193
+ ...this.options.moveOptions,
194
+ selector: ".jsl-dialog",
195
+ onStart: new EventHandler(event => {
196
+ var _a, _b;
197
+ const target = event.evt.target;
198
+ if (!target.closest(".dlg-header") ||
199
+ target.closest("button,input,select,textarea,a,[contenteditable]")) {
200
+ event.cancelEvent();
201
+ return;
163
202
  }
164
- else {
165
- e.cancelEvent();
166
- }
167
- }),
168
- ...this.options.moveOptions
203
+ this.normalizePosition(element);
204
+ event.x = element.offsetLeft;
205
+ event.y = element.offsetTop;
206
+ (_b = (_a = this.options.moveOptions) === null || _a === void 0 ? void 0 : _a.onStart) === null || _b === void 0 ? void 0 : _b.notify(event);
207
+ })
169
208
  });
170
209
  }
171
210
  if (this.options.allowResize) {
172
- const dlgEl = this.ref.getOverlay().querySelector(".jsl-dialog");
173
- Resizable(dlgEl, this.options.resizeOptions);
174
- const rect = dlgEl.getBoundingClientRect();
175
- dlgEl.style.transform = "translate(0, 0)";
176
- dlgEl.style.left = rect.left + "px";
177
- dlgEl.style.top = rect.top + "px";
178
- const bodyEl = dlgEl.querySelector(".dlg-body");
179
- const bodyRect = bodyEl.getBoundingClientRect();
180
- bodyEl.style.height = "calc(100% - " + (rect.height - bodyRect.height) + "px)";
211
+ this.resizable = Resizable(element, {
212
+ minWidth: 240, minHeight: 160,
213
+ ...this.options.resizeOptions,
214
+ onStart: new EventHandler(event => {
215
+ var _a, _b;
216
+ this.normalizePosition(element);
217
+ element.style.height = element.getBoundingClientRect().height + "px";
218
+ (_b = (_a = this.options.resizeOptions) === null || _a === void 0 ? void 0 : _a.onStart) === null || _b === void 0 ? void 0 : _b.notify(event);
219
+ })
220
+ });
181
221
  }
222
+ window.addEventListener("resize", this.keepInViewport);
223
+ if (this.options.autoOpen) {
224
+ this.ref.open();
225
+ }
226
+ }
227
+ onRemove() {
228
+ var _a, _b, _c, _d;
229
+ window.removeEventListener("resize", this.keepInViewport);
230
+ (_a = this.moveable) === null || _a === void 0 ? void 0 : _a.destroy();
231
+ (_b = this.resizable) === null || _b === void 0 ? void 0 : _b.destroy();
232
+ (_c = this.ref) === null || _c === void 0 ? void 0 : _c.destroy();
233
+ (_d = this.onDispose) === null || _d === void 0 ? void 0 : _d.call(this);
182
234
  }
183
235
  getRef() {
184
236
  return this.ref;
185
237
  }
238
+ normalizePosition(element) {
239
+ const rect = element.getBoundingClientRect();
240
+ const overlayRect = this.ref.getOverlay().getBoundingClientRect();
241
+ element.style.transform = "none";
242
+ element.style.left = rect.left - overlayRect.left + "px";
243
+ element.style.top = rect.top - overlayRect.top + "px";
244
+ }
186
245
  toNode(content) {
187
- if (typeof content === "string") {
188
- return { tag: "div", content };
189
- }
190
- return content;
246
+ return typeof content === "string" ? { tag: "div", content } : content;
191
247
  }
192
248
  }
249
+ DialogComponent.renderedDialogs = [];
@@ -1,5 +1,5 @@
1
1
  import "./ExpanderStyle.scss";
2
- import { IJSLComponent, IJSLVNode } from "jsl-render";
2
+ import { IJSLComponent, IJSLVNode, JSLRender } from "jsl-render";
3
3
  export interface IExpanderOptions {
4
4
  header: IJSLVNode | string | IJSLComponent;
5
5
  body: IJSLVNode | string | IJSLComponent;
@@ -11,17 +11,31 @@ export interface IExpanderOptions {
11
11
  class?: string;
12
12
  style?: string;
13
13
  iconSize?: string;
14
+ id?: string;
15
+ ariaLabel?: string;
16
+ enabled?: boolean;
14
17
  }
15
18
  export declare class ExpanderComponent implements IJSLComponent {
16
19
  State: {
17
20
  expanded: boolean;
18
21
  waitingForAnimation: boolean;
22
+ id?: string;
23
+ dom?: HTMLElement;
24
+ renderer?: JSLRender;
19
25
  };
20
26
  private options;
21
27
  constructor(optionsOrHeader: IExpanderOptions | IJSLVNode | string | IJSLComponent, body?: IJSLVNode | string | IJSLComponent, expanded?: boolean);
22
28
  getIcon(expanded: boolean): IJSLVNode;
23
29
  isEqual(node: IJSLComponent): boolean;
24
30
  render(): IJSLVNode;
31
+ onInit(renderer: JSLRender): void;
32
+ onCreate(node: IJSLVNode): void;
33
+ onRemove(): void;
34
+ isExpanded(): boolean;
35
+ /** Updates expansion silently. User activation and toggle() consult onToggle. */
36
+ setExpanded(expanded: boolean): void;
37
+ toggle(): void;
25
38
  private toggleExpand;
39
+ private restoreFocusFromBody;
26
40
  private toNode;
27
41
  }