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
@@ -7,6 +7,7 @@ import yearPicker from '../views/year-picker';
7
7
  import { bufferFn, noop } from '../lib/fns';
8
8
  import { on, CustomEvent, Key } from '../lib/dom';
9
9
  import { constrainDate } from '../lib/date-manip';
10
+ import { helper } from '../../../core/helper';
10
11
  var views = {
11
12
  day: dayPicker,
12
13
  year: yearPicker,
@@ -16,23 +17,30 @@ export default function BaseMode(input, emit, opts) {
16
17
  var detatchInputEvents; // A function that detaches all events from the input
17
18
  var closing = false; // A hack to prevent calendar from re-opening when closing.
18
19
  var selectedDate; // The currently selected date
20
+ var silentUpdate = false;
21
+ var originalControls = input.getAttribute('aria-controls');
22
+ var originalExpanded = input.getAttribute('aria-expanded');
23
+ var originalHasPopup = input.getAttribute('aria-haspopup');
19
24
  var dp = {
20
25
  // The root DOM element for the date picker, initialized on first open.
21
26
  el: undefined,
22
27
  opts: opts,
28
+ destroyed: false,
23
29
  shouldFocusOnBlur: true,
24
30
  shouldFocusOnRender: true,
25
31
  state: initialState(),
26
32
  adjustPosition: noop,
27
33
  containerHTML: '<div class="dp"></div>',
28
34
  attachToDom: function () {
29
- opts.appendTo.appendChild(dp.el);
35
+ (opts.appendTo || input.closest('.jsl-dialog') || document.body).appendChild(dp.el);
30
36
  },
31
37
  updateInput: function (selectedDate) {
32
38
  var e = new CustomEvent('change', { bubbles: true });
33
39
  e.simulated = true;
34
40
  input.value = selectedDate ? opts.format(selectedDate) : '';
35
- input.dispatchEvent(e);
41
+ if (!silentUpdate) {
42
+ input.dispatchEvent(e);
43
+ }
36
44
  },
37
45
  computeSelectedDate: function () {
38
46
  return opts.parse(input.value);
@@ -41,17 +49,29 @@ export default function BaseMode(input, emit, opts) {
41
49
  return views[dp.state.view];
42
50
  },
43
51
  open: function () {
44
- if (closing) {
52
+ if (closing || dp.destroyed || input.disabled || dp.isVisible()) {
45
53
  return;
46
54
  }
47
55
  if (!dp.el) {
48
56
  dp.el = createContainerElement(opts, dp.containerHTML);
57
+ dp.el.id = helper.newDomGuid();
58
+ if (opts.mode !== 'dp-permanent') {
59
+ input.setAttribute('aria-controls', dp.el.id);
60
+ }
49
61
  attachContainerEvents(dp);
50
62
  }
51
- selectedDate = constrainDate(dp.computeSelectedDate(), opts.min, opts.max);
63
+ try {
64
+ selectedDate = constrainDate(dp.computeSelectedDate(), opts.min, opts.max);
65
+ }
66
+ catch (_a) {
67
+ selectedDate = null;
68
+ }
52
69
  dp.state.hilightedDate = selectedDate || opts.hilightedDate;
53
70
  dp.state.view = 'day';
54
71
  dp.attachToDom();
72
+ if (opts.mode !== 'dp-permanent') {
73
+ input.setAttribute('aria-expanded', 'true');
74
+ }
55
75
  dp.render();
56
76
  emit('open');
57
77
  },
@@ -69,6 +89,7 @@ export default function BaseMode(input, emit, opts) {
69
89
  },
70
90
  close: function (becauseOfBlur) {
71
91
  var el = dp.el;
92
+ var hadFocus = dp.hasFocus();
72
93
  if (!dp.isVisible()) {
73
94
  return;
74
95
  }
@@ -77,7 +98,8 @@ export default function BaseMode(input, emit, opts) {
77
98
  parent && parent.removeChild(el);
78
99
  }
79
100
  closing = true;
80
- if (becauseOfBlur && dp.shouldFocusOnBlur) {
101
+ input.setAttribute('aria-expanded', 'false');
102
+ if (!dp.destroyed && (hadFocus || (becauseOfBlur && dp.shouldFocusOnBlur))) {
81
103
  focusInput(input);
82
104
  }
83
105
  // When we close, the input often gains refocus, which
@@ -89,32 +111,59 @@ export default function BaseMode(input, emit, opts) {
89
111
  emit('close');
90
112
  },
91
113
  destroy: function () {
114
+ var _a;
115
+ dp.destroyed = true;
92
116
  dp.close();
117
+ (_a = dp.el) === null || _a === void 0 ? void 0 : _a.remove();
93
118
  detatchInputEvents();
119
+ [['aria-controls', originalControls], ['aria-expanded', originalExpanded], ['aria-haspopup', originalHasPopup]].forEach(function (entry) {
120
+ if (entry[1] == null) {
121
+ input.removeAttribute(entry[0]);
122
+ }
123
+ else {
124
+ input.setAttribute(entry[0], entry[1]);
125
+ }
126
+ });
94
127
  },
95
128
  render: function () {
96
- if (!dp.el) {
129
+ if (!dp.isVisible() || dp.destroyed) {
97
130
  return;
98
131
  }
99
132
  var hadFocus = dp.hasFocus();
100
133
  var html = dp.currentView().render(dp);
101
134
  html && (dp.el.firstChild.innerHTML = html);
102
135
  dp.adjustPosition();
103
- if (hadFocus || dp.shouldFocusOnRender) {
136
+ if (hadFocus || (!silentUpdate && dp.shouldFocusOnRender)) {
104
137
  focusCurrent(dp);
105
138
  }
106
139
  },
107
140
  // Conceptually similar to setState in React, updates
108
141
  // the view state and re-renders.
109
- setState: function (state) {
110
- for (var key in state) {
111
- dp.state[key] = state[key];
142
+ setState: function (state, silent = false) {
143
+ var previousSilent = silentUpdate;
144
+ silentUpdate = silent;
145
+ try {
146
+ for (var key in state) {
147
+ if (key === 'hilightedDate' && !state[key]) {
148
+ continue;
149
+ }
150
+ dp.state[key] = state[key];
151
+ }
152
+ if (!silent) {
153
+ emit('statechange');
154
+ }
155
+ dp.render();
156
+ }
157
+ finally {
158
+ silentUpdate = previousSilent;
112
159
  }
113
- emit('statechange');
114
- dp.render();
115
160
  },
116
161
  };
117
162
  detatchInputEvents = attachInputEvents(input, dp);
163
+ if (opts.mode !== 'dp-permanent') {
164
+ input.setAttribute('aria-haspopup', 'dialog');
165
+ input.setAttribute('aria-expanded', 'false');
166
+ }
118
167
  // Builds the initial view state
119
168
  // selectedDate is a special case and causes changes to hilightedDate
120
169
  // hilightedDate is set on open, so remains undefined initially
@@ -125,8 +174,11 @@ export default function BaseMode(input, emit, opts) {
125
174
  return selectedDate;
126
175
  },
127
176
  set selectedDate(dt) {
128
- if (dt && !opts.inRange(dt)) {
129
- return;
177
+ if (dt) {
178
+ dt = opts.parse(dt);
179
+ if (!dt || !opts.inRange(dt)) {
180
+ return;
181
+ }
130
182
  }
131
183
  if (dt) {
132
184
  selectedDate = new Date(dt);
@@ -136,8 +188,10 @@ export default function BaseMode(input, emit, opts) {
136
188
  selectedDate = dt;
137
189
  }
138
190
  dp.updateInput(selectedDate);
139
- emit('select');
140
- dp.close();
191
+ if (!silentUpdate) {
192
+ emit('select');
193
+ dp.close();
194
+ }
141
195
  },
142
196
  view: 'day',
143
197
  hilightedDate: undefined
@@ -148,11 +202,19 @@ export default function BaseMode(input, emit, opts) {
148
202
  function createContainerElement(opts, containerHTML) {
149
203
  var el = document.createElement('div');
150
204
  el.className = opts.mode;
205
+ el.setAttribute('role', opts.mode === 'dp-permanent' ? 'group' : 'dialog');
206
+ el.setAttribute('aria-label', 'Choose a date');
207
+ if (opts.mode === 'dp-modal') {
208
+ el.setAttribute('aria-modal', 'true');
209
+ }
151
210
  el.innerHTML = containerHTML;
152
211
  return el;
153
212
  }
154
213
  function attachInputEvents(input, dp) {
155
214
  var bufferShow = bufferFn(5, function () {
215
+ if (dp.destroyed) {
216
+ return;
217
+ }
156
218
  if (dp.shouldHide()) {
157
219
  dp.close();
158
220
  }
@@ -162,7 +224,7 @@ function attachInputEvents(input, dp) {
162
224
  });
163
225
  var off = [
164
226
  on('blur', input, bufferFn(150, function () {
165
- if (!dp.hasFocus()) {
227
+ if (!dp.destroyed && !dp.hasFocus()) {
166
228
  dp.close(true);
167
229
  }
168
230
  })),
@@ -172,6 +234,21 @@ function attachInputEvents(input, dp) {
172
234
  }
173
235
  }),
174
236
  on('focus', input, bufferShow),
237
+ on('keydown', input, function (e) {
238
+ if (e.key === 'Escape' && dp.isVisible()) {
239
+ e.preventDefault();
240
+ e.stopPropagation();
241
+ dp.close();
242
+ }
243
+ else if (e.key === 'ArrowDown') {
244
+ e.preventDefault();
245
+ e.stopPropagation();
246
+ dp.open();
247
+ if (dp.isVisible()) {
248
+ focusCurrent(dp);
249
+ }
250
+ }
251
+ }),
175
252
  on('input', input, function (e) {
176
253
  try {
177
254
  var date = dp.opts.parse(e.target.value);
@@ -192,7 +269,7 @@ function attachInputEvents(input, dp) {
192
269
  };
193
270
  }
194
271
  function focusCurrent(dp) {
195
- var current = dp.el.querySelector('.dp-current');
272
+ var current = dp.el.querySelector('.dp-current:not(:disabled)') || dp.el.querySelector('button:not(:disabled)');
196
273
  return current && current.focus();
197
274
  }
198
275
  function attachContainerEvents(dp) {
@@ -201,6 +278,9 @@ function attachContainerEvents(dp) {
201
278
  // Hack to get iOS to show active CSS states
202
279
  el.ontouchstart = noop;
203
280
  function onClick(e) {
281
+ if (e.target.disabled) {
282
+ return;
283
+ }
204
284
  e.target.className.split(' ').forEach(function (evt) {
205
285
  var handler = dp.currentView().onClick[evt];
206
286
  handler && handler(e, dp);
@@ -213,15 +293,25 @@ function attachContainerEvents(dp) {
213
293
  // would be to set context.redrawing = true on redraw and
214
294
  // set it to false in the blur event.
215
295
  on('blur', calEl, bufferFn(150, function () {
216
- if (!dp.hasFocus()) {
296
+ if (!dp.destroyed && !dp.hasFocus()) {
217
297
  dp.close(true);
218
298
  }
219
299
  }));
220
300
  on('keydown', el, function (e) {
221
- if (e.keyCode === Key.enter) {
222
- onClick(e);
301
+ var _a;
302
+ if (e.key === 'Tab' && dp.opts.mode === 'dp-modal') {
303
+ var buttons = Array.from(el.querySelectorAll('button:not(:disabled)[tabindex="0"], button:not(:disabled):not([tabindex])'));
304
+ var index = buttons.indexOf(document.activeElement);
305
+ if (e.shiftKey && index <= 0 || !e.shiftKey && index === buttons.length - 1) {
306
+ e.preventDefault();
307
+ (_a = buttons[e.shiftKey ? buttons.length - 1 : 0]) === null || _a === void 0 ? void 0 : _a.focus();
308
+ }
223
309
  }
224
- else {
310
+ else if (e.keyCode !== Key.enter && e.key !== ' ') {
311
+ if (e.keyCode === Key.esc || [Key.left, Key.right, Key.up, Key.down].indexOf(e.keyCode) >= 0) {
312
+ e.preventDefault();
313
+ e.stopPropagation();
314
+ }
225
315
  dp.currentView().onKeyDown(e, dp);
226
316
  }
227
317
  });
@@ -1,9 +1,7 @@
1
- /**
2
- * @file Defines the dropdown date picker behavior.
3
- */
4
1
  export default function DropdownMode(input: any, emit: any, opts: any): {
5
2
  el: any;
6
3
  opts: any;
4
+ destroyed: boolean;
7
5
  shouldFocusOnBlur: boolean;
8
6
  shouldFocusOnRender: boolean;
9
7
  state: {
@@ -24,5 +22,5 @@ export default function DropdownMode(input: any, emit: any, opts: any): {
24
22
  close: (becauseOfBlur?: boolean) => void;
25
23
  destroy: () => void;
26
24
  render: () => void;
27
- setState: (state: any) => void;
25
+ setState: (state: any, silent?: boolean) => void;
28
26
  };
@@ -1,50 +1,37 @@
1
- /**
2
- * @file Defines the dropdown date picker behavior.
3
- */
4
- import BaseMode from './base-mode';
1
+ import BaseMode from "./base-mode";
5
2
  export default function DropdownMode(input, emit, opts) {
6
3
  var dp = BaseMode(input, emit, opts);
7
4
  dp.shouldFocusOnBlur = false;
8
- Object.defineProperty(dp, 'shouldFocusOnRender', {
9
- get: function () {
10
- return input !== document.activeElement;
11
- }
5
+ Object.defineProperty(dp, "shouldFocusOnRender", {
6
+ get: function () { return input !== document.activeElement; }
12
7
  });
13
8
  dp.adjustPosition = function () {
14
- autoPosition(input, dp);
9
+ if (!dp.isVisible()) {
10
+ return;
11
+ }
12
+ var cal = dp.el;
13
+ var rect = input.getBoundingClientRect();
14
+ cal.style.left = "0px";
15
+ cal.style.top = "0px";
16
+ // A transformed dialog establishes its own fixed-position containing block.
17
+ var origin = cal.getBoundingClientRect();
18
+ var left = Math.max(8, Math.min(rect.left, window.innerWidth - cal.offsetWidth - 8));
19
+ var above = rect.bottom + 8 + cal.offsetHeight > window.innerHeight && rect.top > cal.offsetHeight + 8;
20
+ var top = above ? rect.top - cal.offsetHeight - 8 : rect.bottom + 8;
21
+ top = Math.max(8, Math.min(top, window.innerHeight - cal.offsetHeight - 8));
22
+ cal.style.left = (left - origin.left) + "px";
23
+ cal.style.top = (top - origin.top) + "px";
24
+ cal.classList.toggle("dp-is-above", above);
25
+ cal.classList.toggle("dp-is-below", !above);
26
+ };
27
+ var reposition = () => dp.adjustPosition();
28
+ window.addEventListener("resize", reposition);
29
+ window.addEventListener("scroll", reposition, true);
30
+ var destroy = dp.destroy;
31
+ dp.destroy = function () {
32
+ window.removeEventListener("resize", reposition);
33
+ window.removeEventListener("scroll", reposition, true);
34
+ destroy();
15
35
  };
16
36
  return dp;
17
37
  }
18
- function autoPosition(input, dp) {
19
- var inputPos = input.getBoundingClientRect();
20
- var win = window;
21
- adjustCalY(dp, inputPos, win);
22
- adjustCalX(dp, inputPos, win);
23
- dp.el.style.visibility = '';
24
- }
25
- function adjustCalX(dp, inputPos, win) {
26
- var cal = dp.el;
27
- var scrollLeft = win.pageXOffset;
28
- var inputLeft = inputPos.left + scrollLeft;
29
- var maxRight = win.innerWidth + scrollLeft;
30
- var offsetWidth = cal.offsetWidth;
31
- var calRight = inputLeft + offsetWidth;
32
- var shiftedLeft = maxRight - offsetWidth;
33
- var left = calRight > maxRight && shiftedLeft > 0 ? shiftedLeft : inputLeft;
34
- cal.style.left = left + 'px';
35
- }
36
- function adjustCalY(dp, inputPos, win) {
37
- var cal = dp.el;
38
- var scrollTop = win.pageYOffset;
39
- var inputTop = scrollTop + inputPos.top;
40
- var calHeight = cal.offsetHeight;
41
- var belowTop = inputTop + inputPos.height + 8;
42
- var aboveTop = inputTop - calHeight - 8;
43
- var isAbove = (aboveTop > 0 && belowTop + calHeight > scrollTop + win.innerHeight);
44
- var top = isAbove ? aboveTop : belowTop;
45
- if (cal.classList) {
46
- cal.classList.toggle('dp-is-above', isAbove);
47
- cal.classList.toggle('dp-is-below', !isAbove);
48
- }
49
- cal.style.top = top + 'px';
50
- }
@@ -4,6 +4,7 @@
4
4
  export default function Mode(input: any, emit: any, opts: any): {
5
5
  el: any;
6
6
  opts: any;
7
+ destroyed: boolean;
7
8
  shouldFocusOnBlur: boolean;
8
9
  shouldFocusOnRender: boolean;
9
10
  state: {
@@ -24,5 +25,5 @@ export default function Mode(input: any, emit: any, opts: any): {
24
25
  close: (becauseOfBlur?: boolean) => void;
25
26
  destroy: () => void;
26
27
  render: () => void;
27
- setState: (state: any) => void;
28
+ setState: (state: any, silent?: boolean) => void;
28
29
  };
@@ -1,6 +1,7 @@
1
1
  export default function ModalMode(input: any, emit: any, opts: any): {
2
2
  el: any;
3
3
  opts: any;
4
+ destroyed: boolean;
4
5
  shouldFocusOnBlur: boolean;
5
6
  shouldFocusOnRender: boolean;
6
7
  state: {
@@ -21,5 +22,5 @@ export default function ModalMode(input: any, emit: any, opts: any): {
21
22
  close: (becauseOfBlur?: boolean) => void;
22
23
  destroy: () => void;
23
24
  render: () => void;
24
- setState: (state: any) => void;
25
+ setState: (state: any, silent?: boolean) => void;
25
26
  };
@@ -6,12 +6,14 @@ export default function ModalMode(input, emit, opts) {
6
6
  var dp = BaseMode(input, emit, opts);
7
7
  // In modal mode, users really shouldn't be able to type in
8
8
  // the input, as all input is done via the calendar.
9
- input.readonly = true;
9
+ var wasReadOnly = input.readOnly;
10
+ input.readOnly = true;
10
11
  // In modal mode, we need to know when the user has tabbed
11
12
  // off the end of the calendar, and set focus to the original
12
13
  // input. To do this, we add a special element to the DOM.
13
14
  // When the user tabs off the bottom of the calendar, they
14
15
  // will tab onto this element.
15
- dp.containerHTML += '<a href="#" class="dp-focuser">.</a>';
16
+ var destroy = dp.destroy;
17
+ dp.destroy = function () { destroy(); input.readOnly = wasReadOnly; };
16
18
  return dp;
17
19
  }
@@ -5,6 +5,7 @@ import { noop } from '../lib/fns';
5
5
  export default function PermanentMode(root: any, emit: any, opts: any): {
6
6
  el: any;
7
7
  opts: any;
8
+ destroyed: boolean;
8
9
  shouldFocusOnBlur: boolean;
9
10
  shouldFocusOnRender: boolean;
10
11
  state: {
@@ -25,5 +26,5 @@ export default function PermanentMode(root: any, emit: any, opts: any): {
25
26
  close: (becauseOfBlur?: boolean) => void;
26
27
  destroy: () => void;
27
28
  render: () => void;
28
- setState: (state: any) => void;
29
+ setState: (state: any, silent?: boolean) => void;
29
30
  };
@@ -2,7 +2,7 @@
2
2
  * @file Manages the calendar / day-picker view.
3
3
  */
4
4
  import { Key } from '../lib/dom';
5
- import { now, datesEq, shiftMonth, shiftDay } from '../lib/date-manip';
5
+ import { now, datesEq, shiftMonth, shiftDay, constrainDate } from '../lib/date-manip';
6
6
  export default {
7
7
  onKeyDown: keyDown,
8
8
  onClick: {
@@ -35,14 +35,14 @@ function render(dp) {
35
35
  var today = now().getTime();
36
36
  return ('<div class="dp-cal">' +
37
37
  '<header class="dp-cal-header">' +
38
- '<button tabindex="-1" type="button" class="dp-prev">Prev</button>' +
39
- '<button tabindex="-1" type="button" class="dp-cal-month">' +
38
+ '<button type="button" class="dp-prev" aria-label="Previous month">‹</button>' +
39
+ '<button type="button" class="dp-cal-month">' +
40
40
  lang.months[hilightedMonth] +
41
41
  '</button>' +
42
- '<button tabindex="-1" type="button" class="dp-cal-year">' +
42
+ '<button type="button" class="dp-cal-year">' +
43
43
  hilightedDate.getFullYear() +
44
44
  '</button>' +
45
- '<button tabindex="-1" type="button" class="dp-next">Next</button>' +
45
+ '<button type="button" class="dp-next" aria-label="Next month">›</button>' +
46
46
  '</header>' +
47
47
  '<div class="dp-days">' +
48
48
  dayNames.map(function (name, i) {
@@ -58,16 +58,19 @@ function render(dp) {
58
58
  className += (datesEq(date, selectedDate) ? ' dp-selected' : '');
59
59
  className += (isDisabled ? ' dp-day-disabled' : '');
60
60
  className += (isToday ? ' dp-day-today' : '');
61
- className += ' ' + opts.dateClass(date, dp);
62
- return ('<button tabindex="-1" type="button" class="' + className + '" data-date="' + date.getTime() + '">' +
61
+ className += ' ' + (opts.dateClass(date, dp) || '');
62
+ return ('<button tabindex="' + (datesEq(date, hilightedDate) && !isDisabled ? '0' : '-1') +
63
+ '" type="button" class="' + className + '" data-date="' + date.getTime() +
64
+ '" aria-label="' + date.toDateString() + '" aria-pressed="' + !!datesEq(date, selectedDate) + '"' +
65
+ (isToday ? ' aria-current="date"' : '') + (isDisabled ? ' disabled' : '') + '>' +
63
66
  date.getDate() +
64
67
  '</button>');
65
68
  }) +
66
69
  '</div>' +
67
70
  '<footer class="dp-cal-footer">' +
68
- '<button tabindex="-1" type="button" class="dp-today">' + lang.today + '</button>' +
69
- '<button tabindex="-1" type="button" class="dp-clear">' + lang.clear + '</button>' +
70
- '<button tabindex="-1" type="button" class="dp-close">' + lang.close + '</button>' +
71
+ '<button type="button" class="dp-today"' + (opts.inRange(now()) ? '' : ' disabled') + '>' + lang.today + '</button>' +
72
+ '<button type="button" class="dp-clear">' + lang.clear + '</button>' +
73
+ '<button type="button" class="dp-close">' + lang.close + '</button>' +
71
74
  '</footer>' +
72
75
  '</div>');
73
76
  }
@@ -89,8 +92,17 @@ function keyDown(e, dp) {
89
92
  }
90
93
  else if (shiftBy) {
91
94
  e.preventDefault();
95
+ var target = constrainDate(shiftDay(dp.state.hilightedDate, shiftBy), dp.opts.min, dp.opts.max);
96
+ var direction = shiftBy < 0 ? -1 : 1;
97
+ while (target && !dp.opts.inRange(target)) {
98
+ var next = shiftDay(target, direction);
99
+ if (next < dp.opts.min || next > dp.opts.max) {
100
+ return;
101
+ }
102
+ target = next;
103
+ }
92
104
  dp.setState({
93
- hilightedDate: shiftDay(dp.state.hilightedDate, shiftBy)
105
+ hilightedDate: target
94
106
  });
95
107
  }
96
108
  }
@@ -138,13 +150,10 @@ function mapDays(currentDate, dayOffset, fn) {
138
150
  var result = '';
139
151
  var iter = new Date(currentDate);
140
152
  iter.setDate(1);
141
- iter.setDate(1 - iter.getDay() + dayOffset);
153
+ iter.setDate(1 - (iter.getDay() - dayOffset + 7) % 7);
142
154
  // If we are showing monday as the 1st of the week,
143
155
  // and the monday is the 2nd of the month, the sunday won't
144
156
  // show, so we need to shift backwards
145
- if (dayOffset && iter.getDate() === dayOffset + 1) {
146
- iter.setDate(dayOffset - 6);
147
- }
148
157
  // We are going to have 6 weeks always displayed to keep a consistent
149
158
  // calendar size
150
159
  for (var day = 0; day < (6 * 7); ++day) {
@@ -32,7 +32,7 @@ function render(dp) {
32
32
  months.map(function (month, i) {
33
33
  var className = 'dp-month';
34
34
  className += (currentMonth === i ? ' dp-current' : '');
35
- return ('<button tabindex="-1" type="button" class="' + className + '" data-month="' + i + '">' +
35
+ return ('<button tabindex="' + (currentMonth === i ? '0' : '-1') + '" type="button" class="' + className + '" data-month="' + i + '">' +
36
36
  month +
37
37
  '</button>');
38
38
  }).join('') +
@@ -17,15 +17,16 @@ export default {
17
17
  * @returns {string}
18
18
  */
19
19
  function render(dp) {
20
+ var _a;
20
21
  var state = dp.state;
21
22
  var currentYear = state.hilightedDate.getFullYear();
22
- var selectedYear = state.selectedDate.getFullYear();
23
+ var selectedYear = (_a = state.selectedDate) === null || _a === void 0 ? void 0 : _a.getFullYear();
23
24
  return ('<div class="dp-years">' +
24
25
  mapYears(dp, function (year) {
25
26
  var className = 'dp-year';
26
27
  className += (year === currentYear ? ' dp-current' : '');
27
28
  className += (year === selectedYear ? ' dp-selected' : '');
28
- return ('<button tabindex="-1" type="button" class="' + className + '" data-year="' + year + '">' +
29
+ return ('<button tabindex="' + (year === currentYear ? '0' : '-1') + '" type="button" class="' + className + '" data-year="' + year + '">' +
29
30
  year +
30
31
  '</button>');
31
32
  }) +
@@ -9,6 +9,7 @@ export interface IDatePickerLangOptions {
9
9
  export interface IDatePickerOptions {
10
10
  lang?: IDatePickerLangOptions;
11
11
  mode?: 'dp-modal' | 'dp-below' | 'dp-permanent';
12
+ appendTo?: HTMLElement;
12
13
  hilightedDate?: string | Date;
13
14
  min?: string | Date;
14
15
  max?: string | Date;
@@ -48,7 +49,7 @@ export interface IDatePicker {
48
49
  selectedDate?: Date;
49
50
  view?: string;
50
51
  hilightedDate?: Date;
51
- }): void;
52
+ }, silent?: boolean): void;
52
53
  readonly state: {
53
54
  selectedDate?: Date;
54
55
  view?: string;