inviton-powerduck 0.0.179 → 0.0.181

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.
@@ -2,6 +2,7 @@ import { Modal as BootstrapModal } from 'bootstrap';
2
2
  import { globalState } from '../app/global-state';
3
3
  import PowerduckState from '../app/powerduck-state';
4
4
  import { ButtonLayout } from '../components/button/button-layout';
5
+ import { ModalUtils } from '../components/modal/modal-utils';
5
6
  import { DialogIcons } from './enums/dialog-icons';
6
7
  import { isNullOrEmpty } from './utils/is-null-or-empty';
7
8
  import { PortalUtils } from './utils/utils';
@@ -54,6 +55,7 @@ export interface AppDialogButton {
54
55
  export interface AppDialogArgs {
55
56
  title: string;
56
57
  message: string;
58
+ mobileMode?: 'default' | 'bottom-sheet' | 'fullscreen';
57
59
  icon?: DialogIcons;
58
60
  autoHide?: boolean;
59
61
  boxColor?: string;
@@ -123,10 +125,11 @@ class DialogBuilder {
123
125
  this.builder
124
126
  += `<div id="${this.id}" key="${this.id
125
127
  }" tabindex="-1" role="dialog" aria-labelledby="${this.labelId
126
- }" data-bs-backdrop="true" data-bs-keyboard="true" class="modal fade${args.cssClass ? ` ${args.cssClass}` : ''
128
+ }" data-bs-backdrop="true" data-bs-keyboard="true" class="modal fade modal-bottom-sheet${args.cssClass ? ` ${args.cssClass}` : ''
127
129
  }">`;
128
130
  this.builder += ` <div role="document" class="modal-dialog${args.size != null ? ` ${args.size}` : ''}">`;
129
131
  this.builder += ' <div class="modal-content">';
132
+ this.builder += ' <div class="drag-handle text-center"><div class="handle-bar"></div></div>';
130
133
 
131
134
  this.builder += this._getHeader();
132
135
  this.builder += this._getBody();
@@ -240,6 +243,11 @@ export class DialogUtils {
240
243
  }, 50);
241
244
  });
242
245
 
246
+ if (args.mobileMode == null || args.mobileMode == 'bottom-sheet') {
247
+ const modal = document.getElementById(builder.id);
248
+ ModalUtils.bindModalBottomSheetHandle(() => modal, () => ModalUtils.hideModal(modalContext));
249
+ }
250
+
243
251
  const ensureIconAnimation = function (
244
252
  selector: string,
245
253
  icon: DialogIcons,
@@ -0,0 +1,3 @@
1
+ .pd-modal-mobile-input .modal-content {
2
+ padding-bottom: 0;
3
+ }
@@ -5,6 +5,7 @@ import { Prop, toNative } from 'vue-facing-decorator';
5
5
  import { globalState } from '../../app/global-state';
6
6
  import PowerduckState from '../../app/powerduck-state';
7
7
  import TsxComponent, { Component } from '../../app/vuetsx';
8
+ import { DialogUtils } from '../../common/dialog-utils';
8
9
  import { utcEpochMilliseconds } from '../../common/extensions/temporal-extensions';
9
10
  import DateUtils from '../../common/utils/date-utils';
10
11
  import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
@@ -13,6 +14,7 @@ import { PortalUtils } from '../../common/utils/utils';
13
14
  import FormItemWrapper from '../form/form-item-wrapper';
14
15
  import DateInputHelper from './ts/dateInputHelper';
15
16
  import './plugins/daterangepicker/jquery.daterangepicker';
17
+ import './../_common/css/modal-mobile-control.css';
16
18
  import './css/daterange-picker.css';
17
19
 
18
20
  export interface DaterangePickerArgsCustomCellRenderArgs {
@@ -31,6 +33,8 @@ export interface DaterangePickerArgsCustomCellRenderDay {
31
33
  valid: boolean;
32
34
  }
33
35
 
36
+ type CalendarPlacement = 'body' | 'inline' | 'input-container-leftalign' | 'input-container-rightalign';
37
+
34
38
  interface DaterangePickerArgs extends FormItemWrapperArgs {
35
39
  disabled?: boolean;
36
40
  value?: DaterangeChangedArgs;
@@ -48,7 +52,7 @@ interface DaterangePickerArgs extends FormItemWrapperArgs {
48
52
  nextIcon?: string;
49
53
  hideYearInMonthName?: boolean;
50
54
  singleMonth?: boolean;
51
- calendarPlacement?: 'body' | 'inline' | 'input-container-leftalign' | 'input-container-rightalign';
55
+ calendarPlacement?: CalendarPlacement;
52
56
  ensureMonthContinuity?: boolean;
53
57
  monthSelect?: boolean;
54
58
  yearSelect?: boolean;
@@ -107,7 +111,7 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
107
111
  @Prop() prependIconClicked: () => void;
108
112
  @Prop() appendIconClicked: () => void;
109
113
  @Prop() marginType?: MarginType;
110
- @Prop() calendarPlacement?: 'body' | 'inline' | 'input-container-leftalign' | 'input-container-rightalign';
114
+ @Prop() calendarPlacement?: CalendarPlacement;
111
115
  @Prop() changed: (newValue: DaterangeChangedArgs) => void;
112
116
  @Prop() format?: string;
113
117
  @Prop() showClearValueButton!: boolean;
@@ -155,6 +159,10 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
155
159
  }
156
160
 
157
161
  beforeUnmount() {
162
+ this.tryDestroyPickerInstance();
163
+ }
164
+
165
+ tryDestroyPickerInstance() {
158
166
  try {
159
167
  this.getInputElement().data('dateRangePicker').destroy();
160
168
  } catch (error) { }
@@ -165,13 +173,71 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
165
173
  return;
166
174
  }
167
175
 
168
- const self = this;
169
176
  const $elem = this.getInputElement();
177
+ if (!this.useModalMode()) {
178
+ this.bindDateRangePicker(
179
+ $elem,
180
+ this.calendarPlacement,
181
+ this.singleMonth,
182
+ this.alwaysOpen,
183
+ () => this.raiseChangedEvent(),
184
+ (this.calendarPlacement == null || this.calendarPlacement == 'body') ? 'body' : $elem.parent(),
185
+ );
186
+ } else {
187
+ this.getInputElement().parent().on('click', async () => {
188
+ const uuid = `drp-modal-${PortalUtils.randomString(6)}`;
189
+ const handle = await DialogUtils.showDialogEx({
190
+ title: this.label || '',
191
+ cssClass: 'daterangepicker-modal pd-modal-mobile-input',
192
+ message: `<div><div id="${uuid}"></div></div>`,
193
+ buttons: [],
194
+ onHidden: () => {
195
+ this.tryDestroyPickerInstance();
196
+ },
197
+ });
198
+
199
+ const $modalRoot = $(document.getElementById(uuid));
200
+ this.bindDateRangePicker(
201
+ $elem,
202
+ 'inline',
203
+ true,
204
+ true,
205
+ () => {
206
+ this.raiseChangedEvent();
207
+ handle.hideModal();
208
+ },
209
+ $modalRoot,
210
+ );
211
+ });
212
+ }
213
+ }
214
+
215
+ beforeUpdate() {
216
+ if (!globalState.windowExists) {
217
+ return;
218
+ }
219
+
220
+ this.handleModelValueChange();
221
+ }
222
+
223
+ useModalMode(): boolean {
224
+ return PortalUtils.treatAsMobileDevice();
225
+ }
226
+
227
+ bindDateRangePicker(
228
+ $elem: JQuery<HTMLElement>,
229
+ calendarPlacement: CalendarPlacement,
230
+ singleMonth: boolean,
231
+ alwaysOpen: boolean,
232
+ raiseChangedEvent: () => void,
233
+ container: JQuery<HTMLElement> | string,
234
+ ) {
235
+ const self = this;
170
236
  const now = Temporal.Now.plainDateTimeISO();
171
237
 
172
238
  ($elem as any).dateRangePicker({
173
- singleMonth: this.singleMonth == true,
174
- alwaysOpen: this.alwaysOpen == true,
239
+ singleMonth: singleMonth == true,
240
+ alwaysOpen: alwaysOpen == true,
175
241
  singleDate: this.singleDate == true,
176
242
  startOfWeek: DateInputHelper.getStartOfWeek() == 0 ? 'sunday' : 'monday',
177
243
  separator: self.getSeparator(),
@@ -185,13 +251,9 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
185
251
  yearSelect: this.yearSelect != false,
186
252
  getCellHtml: this.getCellHtml,
187
253
  maxDaysTooltip: this.maxDaysTooltip,
188
- calendarPlacement: this.calendarPlacement,
189
- container: (this.calendarPlacement == null || this.calendarPlacement == 'body') ? 'body' : $elem.parent(),
254
+ calendarPlacement,
255
+ container,
190
256
  displayMode: () => {
191
- if (PortalUtils.treatAsMobileDevice() && this.alwaysOpen != true) {
192
- return 'modal';
193
- }
194
-
195
257
  return 'below-input';
196
258
  },
197
259
  leftOffset: () => {
@@ -244,8 +306,8 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
244
306
  self._endDate = obj.date2 || obj.date1;
245
307
  self._changed = true;
246
308
 
247
- if (this.alwaysOpen) {
248
- self.raiseChangedEvent();
309
+ if (alwaysOpen) {
310
+ raiseChangedEvent();
249
311
  }
250
312
  }).bind('datepicker-closed', () => {
251
313
  const val = $elem.val() as string;
@@ -262,18 +324,10 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
262
324
  }
263
325
 
264
326
  self._opened = false;
265
- self.raiseChangedEvent();
327
+ raiseChangedEvent();
266
328
  });
267
329
  }
268
330
 
269
- beforeUpdate() {
270
- if (!globalState.windowExists) {
271
- return;
272
- }
273
-
274
- this.handleModelValueChange();
275
- }
276
-
277
331
  handleModelValueChange() {
278
332
  if (this.value?.endTime && this.value?.startTime) {
279
333
  if (this.enableTime) {
@@ -525,9 +579,6 @@ class DaterangePickerComponent extends TsxComponent<DaterangePickerArgs> impleme
525
579
  render(h) {
526
580
  return (
527
581
  <FormItemWrapper label={this.label} cssClass={this.getCssClass()} mandatory={this.mandatory} wrap={this.wrap} appendIcon={this.appendIcon} prependIcon={this.prependIcon} hint={this.hint} marginType={this.marginType} appendClicked={this.appendClicked} prependClicked={this.prependClicked} prependIconClicked={this.prependIconClicked} appendIconClicked={this.appendIconClicked} validationState={this.validationState} labelButtons={this.labelButtons} subtitle={this.subtitle}>
528
- {this.shouldAddModalClick()
529
- && <div class="pd-daterange-picker-modalclick" onClick={(e) => { this.handleModalOpenClick(e); }}></div>}
530
-
531
582
  <div style="position: relative; display: flex; align-items: center; flex-grow:1">
532
583
  {' '}
533
584
  {/* Added a wrapper for input and clear button */}
@@ -91,6 +91,10 @@
91
91
  pointer-events: none;
92
92
  }
93
93
 
94
+ .date-range-picker-root.inline-wrapper.drpc-inline {
95
+ position: static;
96
+ }
97
+
94
98
  .date-range-picker-root.inline-wrapper.drpc-input-container-leftalign,
95
99
  .date-range-picker-root.inline-wrapper.drpc-input-container-rightalign {
96
100
  top: 100%;
@@ -165,7 +169,7 @@
165
169
  height: 20px;
166
170
  }
167
171
 
168
- .date-range-picker-wrapper .month-wrapper > table {
172
+ .date-range-picker-wrapper .month-wrapper>table {
169
173
  padding-top: 15px;
170
174
  }
171
175
 
@@ -264,15 +268,6 @@
264
268
  background-color: rgb(112, 204, 213);
265
269
  }
266
270
 
267
- .date-range-picker-wrapper table .caption {
268
- height: 40px;
269
- color: #393562;
270
- height: 36px;
271
- font-size: 18px;
272
- font-weight: 500;
273
- font-family: sans-serif;
274
- }
275
-
276
271
  .date-range-picker-wrapper table .caption .next,
277
272
  .date-range-picker-wrapper table .caption .prev {
278
273
  padding: 0 5px;
@@ -562,7 +557,7 @@
562
557
  border-right: 0.667px solid #dfe3f1;
563
558
  }
564
559
 
565
- .date-range-picker-wrapper .month-wrapper table td > div {
560
+ .date-range-picker-wrapper .month-wrapper table td>div {
566
561
  background-color: inherit !important;
567
562
  line-height: 1.9;
568
563
  margin-left: 5px;
@@ -619,9 +614,83 @@
619
614
  background-color: #b94c4c;
620
615
  }
621
616
 
617
+ .date-range-picker-root .select-wrapper-selected-month {
618
+ display: none;
619
+ }
620
+
622
621
  .drp-date-switch.month-name {
623
622
  border: 0;
624
623
  appearance: none;
625
624
  -webkit-appearance: none;
626
625
  -moz-appearance: none;
627
626
  }
627
+
628
+
629
+ .date-range-picker-wrapper table .caption,
630
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th>span.select-wrapper,
631
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th>span.select-wrapper select {
632
+ height: 40px;
633
+ color: #393562;
634
+ height: 36px;
635
+ font-size: 18px;
636
+ font-weight: 400;
637
+ font-family: sans-serif;
638
+ background: white;
639
+ }
640
+
641
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline {
642
+ border: 0;
643
+ background: transparent;
644
+ box-shadow: none;
645
+ }
646
+
647
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper {
648
+ padding-left: 0;
649
+ padding-right: 0;
650
+ border: 0;
651
+ width: 100% !important;
652
+ padding: 0;
653
+ vertical-align: top;
654
+ }
655
+
656
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common {}
657
+
658
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table {
659
+ width: 100%;
660
+ }
661
+
662
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table td,
663
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th {
664
+ width: 99999px;
665
+ text-align: center;
666
+ font-weight: 400;
667
+ }
668
+
669
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table td>div,
670
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th>div,
671
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table td>span,
672
+ .daterangepicker-modal .date-range-picker-root.inline-wrapper.drpc-inline .month-wrapper .month-wrapper-inner-common table th>span {
673
+ margin: 0;
674
+ margin: auto;
675
+ font-size: 14px;
676
+ font-weight: 400;
677
+ }
678
+
679
+ .daterangepicker-modal .date-range-picker-root .select-wrapper {
680
+ position: relative;
681
+ }
682
+
683
+
684
+ .daterangepicker-modal .date-range-picker-root .select-wrapper-selected-month {
685
+ display: inline-block;
686
+ }
687
+
688
+ .daterangepicker-modal .date-range-picker-root select {
689
+ position: absolute;
690
+ top: 0;
691
+ left: 0;
692
+ right: 0;
693
+ bottom: 0;
694
+ height: auto !important;
695
+ opacity: 0.001;
696
+ }
@@ -260,6 +260,16 @@ import { globalState } from '../../../../app/global-state';
260
260
  },
261
261
  };
262
262
 
263
+ const MS_PER_DAY = 86_400_000;
264
+
265
+ // 1970 01 01 bol štvrtok. Pre weekday v rozsahu 0..6 kde 0 nedeľa:
266
+ const weekdayFromEpochDay = (epochDay: number) => (epochDay + 4) % 7; // 0 št 1 pia 2 so 3 ne 4 po 5 ut 6 st
267
+ // ak chceš 0 nedeľa:
268
+ const weekdaySun0 = (epochDay: number) => (epochDay + 4 + 3) % 7; // posun na nedeľu
269
+
270
+ const toEpochDayUTC = (msUTC: number) => Math.floor(msUTC / MS_PER_DAY);
271
+ const fromEpochDayUTC = (epochDay: number) => epochDay * MS_PER_DAY;
272
+
263
273
  const dateNow = () => Temporal.Now.plainDateTimeISO();
264
274
  const ensureTemporal = (date: Temporal.PlainDateTime | number | string): Temporal.PlainDateTime => {
265
275
  if (date == null) {
@@ -441,7 +451,21 @@ import { globalState } from '../../../../app/global-state';
441
451
  opt = {} as any
442
452
  }
443
453
 
454
+ const getStartMs = () => {
455
+ if (opt.start) {
456
+ return opt.start[utcEpochMilliseconds]();
457
+ }
444
458
 
459
+ return 0;
460
+ }
461
+
462
+ const getEndMs = () => {
463
+ if (opt.end) {
464
+ return opt.end[utcEpochMilliseconds]();
465
+ }
466
+
467
+ return 0;
468
+ }
445
469
 
446
470
  opt = $.extend(
447
471
  true,
@@ -509,7 +533,7 @@ import { globalState } from '../../../../app/global-state';
509
533
  customArrowNextSymbol: null,
510
534
  monthSelect: false,
511
535
  yearSelect: false,
512
- enableSwipeDebug: false, // Enable mouse dragging to simulate touch swipe (for debugging)
536
+ enableSwipeDebug: location.href.includes('localhost'), // Enable mouse dragging to simulate touch swipe (for debugging)
513
537
  },
514
538
  opt,
515
539
  );
@@ -533,9 +557,9 @@ import { globalState } from '../../../../app/global-state';
533
557
  singleMonth = ($(window).width() < 480) as any;
534
558
  }
535
559
 
536
- if (($(window).width() < 480)) {
537
- singleMonth = true;
538
- }
560
+ if (($(window).width() < 480)) {
561
+ singleMonth = true;
562
+ }
539
563
 
540
564
  if (singleMonth) {
541
565
  opt.stickyMonths = false;
@@ -579,22 +603,6 @@ import { globalState } from '../../../../app/global-state';
579
603
  open(0);
580
604
  }
581
605
 
582
- const getStartMs = () => {
583
- if (opt.start) {
584
- return opt.start[utcEpochMilliseconds]();
585
- }
586
-
587
- return 0;
588
- }
589
-
590
- const getEndMs = () => {
591
- if (opt.end) {
592
- return opt.end[utcEpochMilliseconds]();
593
- }
594
-
595
- return 0;
596
- }
597
-
598
606
  // expose some api
599
607
  $(this).data('dateRangePicker', {
600
608
  setStart(d1) {
@@ -658,7 +666,7 @@ import { globalState } from '../../../../app/global-state';
658
666
  return this;
659
667
 
660
668
  function isModalDisplayMode() {
661
- return (box != null && box.hasClass('date-range-picker-modalmode')) || $(window).width() <= 992;
669
+ return (box != null && box.hasClass('date-range-picker-modalmode'))
662
670
  }
663
671
 
664
672
  function IsOwnDatePickerClicked(evt, selfObj) {
@@ -1303,12 +1311,7 @@ import { globalState } from '../../../../app/global-state';
1303
1311
 
1304
1312
  const winWidth = $(window).width();
1305
1313
  const timeEnabled = opt.time.enabled == true;
1306
-
1307
- if (winWidth <= 992 && opt.alwaysOpen != true) {
1308
- setModalDisplayMode();
1309
- } else {
1310
- setDisplayMode();
1311
- }
1314
+ setDisplayMode();
1312
1315
 
1313
1316
  if ($(window).height() < 550 && winWidth < DaterangePickerConfig.calendarsOneColThreshold && !timeEnabled) {
1314
1317
  singleMonth = true;
@@ -1818,6 +1821,76 @@ import { globalState } from '../../../../app/global-state';
1818
1821
  return true;
1819
1822
  }
1820
1823
 
1824
+ function isValidTimeDate(date: Date) {
1825
+ // --- lokálne inliny bez sub-metód ---
1826
+ // prevod PlainDate na epochDay (UTC) bez časovej zóny
1827
+ const epochDay = (y, m, d) => Math.floor(Date.UTC(y, m - 1, d) / MS_PER_DAY);
1828
+
1829
+ // pomocné vyčítanie čísla dňa z Temporal.PlainDateTime-like objektu
1830
+ const d_epoch = epochDay(date.getFullYear(), date.getMonth() + 1, date.getDate());
1831
+
1832
+ // hranice
1833
+ const hasStartDate = !!opt.startDate;
1834
+ const hasEndDate = !!opt.endDate;
1835
+ const startDate_epoch = hasStartDate ? epochDay(opt.startDate.year, opt.startDate.month, opt.startDate.day) : 0;
1836
+ const endDate_epoch = hasEndDate ? epochDay(opt.endDate.year, opt.endDate.month, opt.endDate.day) : 0;
1837
+
1838
+ // 1) mimo absolútnych hraníc
1839
+ if (hasStartDate && d_epoch < startDate_epoch) return false;
1840
+ if (hasEndDate && d_epoch > endDate_epoch) return false;
1841
+
1842
+ // Ak ešte nie je zvolený koniec a nie je singleDate, platia ďalšie pravidlá
1843
+ if (opt.start && !opt.end && !opt.singleDate) {
1844
+ const s = opt.start;
1845
+ const s_epoch = epochDay(s.year, s.month, s.day);
1846
+
1847
+ // 2) minDays / maxDays (počítané ako rozdiel v celých dňoch)
1848
+ if (opt.maxDays > 0) {
1849
+ const diff = Math.abs(d_epoch - s_epoch);
1850
+ if (diff > opt.maxDays) return false;
1851
+ }
1852
+ if (opt.minDays > 0) {
1853
+ const diff = Math.abs(d_epoch - s_epoch);
1854
+ if (diff < opt.minDays) return false;
1855
+ }
1856
+
1857
+ // 3) forward / backward
1858
+ if (opt.selectForward && d_epoch < s_epoch) return false;
1859
+ if (opt.selectBackward && d_epoch > s_epoch) return false;
1860
+
1861
+ // 4) disabled days cez beforeShowDay medzi start a date
1862
+ // Prechádzame smerom k start po 1 dni, ale bez volania ak je to zbytočné.
1863
+ if (opt.beforeShowDay && typeof opt.beforeShowDay === 'function') {
1864
+ // krok +1 alebo -1 podľa smeru
1865
+ const step = d_epoch === s_epoch ? 0 : (d_epoch > s_epoch ? -1 : +1);
1866
+ if (step !== 0) {
1867
+ let cur = d_epoch;
1868
+ // pôvodná logika mala while (countDays(...) > 1):
1869
+ // tu to čítaj ako "kým je medzi nimi aspoň 2-dňová vzdialenosť"
1870
+ while (Math.abs(cur - s_epoch) > 1) {
1871
+ cur += step;
1872
+
1873
+ // z cur vyrobíme PlainDateTime len vtedy keď ho naozaj voláme
1874
+ // inferuj rok-mesiac-deň cez dočasný Date, bez extra helperov
1875
+ const ms = cur * MS_PER_DAY;
1876
+ const tmp = new Date(ms);
1877
+ const y = tmp.getUTCFullYear();
1878
+ const m = tmp.getUTCMonth() + 1;
1879
+ const d = tmp.getUTCDate();
1880
+
1881
+ // PlainDateTime s nulovým časom pre kompatibilitu s existujúcim hookom
1882
+ const pdt = Temporal.PlainDateTime.from({ year: y, month: m, day: d, hour: 0, minute: 0, second: 0, millisecond: 0 });
1883
+
1884
+ const arr: any = opt.beforeShowDay(pdt);
1885
+ if (arr && arr[0] === false) return false;
1886
+ }
1887
+ }
1888
+ }
1889
+ }
1890
+
1891
+ return true;
1892
+ }
1893
+
1821
1894
  function updateSelectableRange() {
1822
1895
  box.find('.day.invalid.tmp').removeClass('tmp invalid').addClass('valid');
1823
1896
  if (opt.start && !opt.end) {
@@ -2137,54 +2210,69 @@ import { globalState } from '../../../../app/global-state';
2137
2210
  }
2138
2211
 
2139
2212
  function showSelectedDays() {
2140
- if (!opt.start && !opt.end) { return; }
2141
-
2142
- box.find('.day').each(function (this: any) {
2143
- let time = parseInt($(this).attr('time'));
2144
- let start = opt.start;
2145
- let end = opt.end;
2146
- if (opt.time.enabled) {
2147
- time = startOfDay(time)[utcEpochMilliseconds]();
2148
- start = startOfDay(start);
2149
- end = startOfDay(end);
2150
- }
2151
-
2152
- if (
2153
- (opt.start && opt.end && end[utcEpochMilliseconds]() >= time && start[utcEpochMilliseconds]() <= time)
2154
- || (opt.start && !opt.end && DateUtils.formatDate(start, 'yyyyMMdd') == DateUtils.formatDate(time, 'yyyyMMdd'))
2155
- ) {
2156
- $(this).addClass('checked');
2213
+ const tz = 'UTC';
2214
+ const toStartOfDayMs = (dt: Temporal.PlainDateTime) =>
2215
+ dt.with({ hour: 0, minute: 0, second: 0, millisecond: 0 })
2216
+ .toZonedDateTime(tz).epochMilliseconds;
2217
+
2218
+ const toEndOfDayMs = (dt: Temporal.PlainDateTime) =>
2219
+ dt.with({ hour: 23, minute: 59, second: 59, millisecond: 999 })
2220
+ .toZonedDateTime(tz).epochMilliseconds;
2221
+
2222
+ const hasStart = !!opt.start;
2223
+ const hasEnd = !!opt.end;
2224
+ const startDayStartMs = hasStart ? toStartOfDayMs(opt.start) : NaN;
2225
+ const startDayEndMs = hasStart ? toEndOfDayMs(opt.start) : NaN;
2226
+ const endDayStartMs = hasEnd ? toStartOfDayMs(opt.end) : NaN;
2227
+ const endDayEndMs = hasEnd ? toEndOfDayMs(opt.end) : NaN;
2228
+
2229
+ const rangeStartMs = hasStart ? startDayStartMs : NaN;
2230
+ const rangeEndMs = hasEnd ? endDayEndMs : startDayEndMs; // ak nie je end, berie sa len deň start
2231
+
2232
+ const $days = box.find('.day');
2233
+ for (let i = 0; i < $days.length; i++) {
2234
+ const el = $days[i];
2235
+ const timeAttr = (el as HTMLElement).getAttribute('time');
2236
+ if (!timeAttr) continue;
2237
+
2238
+ const timeMs = Number(timeAttr); // očakáva sa epoch ms
2239
+
2240
+ const isInRange =
2241
+ hasStart && hasEnd
2242
+ ? (timeMs >= rangeStartMs && timeMs <= rangeEndMs)
2243
+ : hasStart
2244
+ ? (timeMs >= startDayStartMs && timeMs <= startDayEndMs)
2245
+ : false;
2246
+
2247
+ const isStartDay = hasStart && timeMs >= startDayStartMs && timeMs <= startDayEndMs;
2248
+ const isEndDay = hasEnd && timeMs >= endDayStartMs && timeMs <= endDayEndMs;
2249
+
2250
+ const $el = $(el);
2251
+ $el.toggleClass('checked', isInRange || isStartDay || isEndDay);
2252
+ $el.toggleClass('first-date-selected', isStartDay);
2253
+ $el.toggleClass('last-date-selected', isEndDay);
2254
+ }
2255
+
2256
+ // ——— výpočet pre .week-number ———
2257
+ const startWeekNum = Number(opt.startWeek);
2258
+ const $weeks = box.find('.week-number');
2259
+ for (let i = 0; i < $weeks.length; i++) {
2260
+ const el = $weeks[i];
2261
+ const w = Number((el as HTMLElement).getAttribute('data-start-time'));
2262
+ if (w === startWeekNum) {
2263
+ $(el).addClass('week-number-selected');
2157
2264
  } else {
2158
- $(this).removeClass('checked');
2265
+ $(el).removeClass('week-number-selected');
2159
2266
  }
2160
-
2161
- // add first-date-selected class name to the first date selected
2162
- if (opt.start && DateUtils.formatDate(start, 'yyyyMMdd') == DateUtils.formatDate(time, 'yyyyMMdd')) {
2163
- $(this).addClass('first-date-selected');
2164
- } else {
2165
- $(this).removeClass('first-date-selected');
2166
- }
2167
-
2168
- // add last-date-selected
2169
- if (opt.end && DateUtils.formatDate(end, 'yyyyMMdd') == DateUtils.formatDate(time, 'yyyyMMdd')) {
2170
- $(this).addClass('last-date-selected');
2171
- } else {
2172
- $(this).removeClass('last-date-selected');
2173
- }
2174
- });
2175
-
2176
- box.find('.week-number').each(function (this: any) {
2177
- if ($(this).attr('data-start-time') == opt.startWeek) {
2178
- $(this).addClass('week-number-selected');
2179
- }
2180
- });
2267
+ }
2181
2268
  }
2182
2269
 
2183
2270
  function showMonth(date: Temporal.PlainDateTime, month: 'month1' | 'month2') {
2184
2271
  const monthName = nameMonth(date.month);
2185
2272
  var selectableMonthElement = generateSelectableMonthElement(date, month);
2186
2273
  var selectableYearElement = generateSelectableYearElement(date, month);
2187
- box.find(`.${month} .month-name`).html(`${opt.monthSelect ? selectableMonthElement : monthName}${opt.hideYearInMonthName ? '' : ` ${opt.yearSelect ? selectableYearElement : date.year}`}`);
2274
+ const html = `${opt.monthSelect ? selectableMonthElement : monthName}${opt.hideYearInMonthName ? '' : ` ${opt.yearSelect ? selectableYearElement : date.year}`}`;
2275
+ box.find(`.${month} .month-name`).first().html(html);
2188
2276
  box.find(`.${month} tbody`).html(createMonthHTML(date));
2189
2277
  opt[month] = date;
2190
2278
  updateSelectableRange();
@@ -2284,7 +2372,8 @@ import { globalState } from '../../../../app/global-state';
2284
2372
  return data;
2285
2373
  }
2286
2374
  function generateSelect(name: string, data: Array<{ value: number, text: string | number, selected: boolean, disabled: boolean }>): string {
2287
- var select = '<span class="select-wrapper"><select class="drp-date-switch month-name ' + name + '" name="' + name + '">';
2375
+ const selectedItem = data.find(p => p.selected == true);
2376
+ var select = '<span class="select-wrapper">' + (selectedItem != null ? '<span class="select-wrapper-selected-month">' + selectedItem.text + '</span>' : '') + '<select class="drp-date-switch month-name ' + name + '" name="' + name + '">';
2288
2377
  var current: string | number = '';
2289
2378
 
2290
2379
  for (var i = 0, l = data.length; i < l; i++) {
@@ -2747,98 +2836,148 @@ import { globalState } from '../../../../app/global-state';
2747
2836
  }
2748
2837
 
2749
2838
  function createMonthHTML(d: Temporal.PlainDateTime) {
2750
- const days: DaterangePickerArgsCustomCellRenderDay[] = [];
2751
- d = d.with({ day: 1 });
2752
- const lastMonth = d.subtract({ days: 1 });
2753
- const now = dateNow();
2754
-
2755
- let dayOfWeek = getJsDateDay(d);
2756
- if ((dayOfWeek === 0) && (opt.startOfWeek === 'monday')) {
2757
- // add one week
2758
- dayOfWeek = 7;
2759
- }
2760
-
2761
- if (dayOfWeek > 0) {
2762
- for (let i: number = dayOfWeek; i > 0; i--) {
2763
- let day = d.subtract({ milliseconds: 86400000 * i });
2764
- let valid = isValidTime(day);
2765
- if (opt.startDate && compare_day(day, opt.startDate) < 0) {
2766
- valid = false;
2767
- } else if (opt.endDate && compare_day(day, opt.endDate) > 0) {
2768
- valid = false;
2769
- }
2839
+ // vstup prevedieme len raz na UTC Date bez časovej zóny
2840
+ // beriem prvý deň v mesiaci
2841
+ const y = d.year, m = d.month; // 1..12
2842
+ const firstMs = Date.UTC(y, m - 1, 1);
2843
+ const firstEpochDay = toEpochDayUTC(firstMs);
2844
+
2845
+ // start týždňa
2846
+ const weekStartsMonday = opt.startOfWeek === 'monday';
2847
+ const dowSun0 = weekdaySun0(firstEpochDay); // 0 nedeľa 1 pondelok ...
2848
+ const backDays = weekStartsMonday ? ((dowSun0 + 6) % 7) : dowSun0;
2849
+ const gridStartEpochDay = firstEpochDay - backDays;
2850
+
2851
+ // hranice iba ako čísla dní
2852
+ const hasStart = !!opt.startDate;
2853
+ const hasEnd = !!opt.endDate;
2854
+ const startEpochDay = hasStart ? toEpochDayUTC(Date.UTC(opt.startDate.year, opt.startDate.month - 1, opt.startDate.day)) : 0;
2855
+ const endEpochDay = hasEnd ? toEpochDayUTC(Date.UTC(opt.endDate.year, opt.endDate.month - 1, opt.endDate.day)) : 0;
2856
+
2857
+ // dnes
2858
+ const now = dateNow(); // očakávam Temporal.PlainDateTime
2859
+ const nowEpochDay = toEpochDayUTC(Date.UTC(now.year, now.month - 1, now.day));
2860
+
2861
+ // pomocná mutovateľná Date v UTC. Nepoužívaj ju na porovnávanie. Iba ak potrebuješ time alebo hooky
2862
+ const tmp = new Date(firstMs);
2863
+
2864
+ // zisti mesiac pre typ bunky rýchlo
2865
+ // posledný deň mesiaca
2866
+ const nextMonthMs = Date.UTC(y, m, 1);
2867
+ const thisMonthEndEpochDay = toEpochDayUTC(nextMonthMs - 1); // posledný deň
2868
+
2869
+ let sawToMonth = false;
2870
+ let weekCount = 0;
2871
+ const html: string[] = [];
2770
2872
 
2771
- days.push({
2772
- date: day,
2773
- type: 'lastMonth',
2774
- day: day.day,
2775
- time: day[utcEpochMilliseconds](),
2776
- valid,
2777
- });
2778
- }
2779
- }
2873
+ for (let week = 0; week < 6; week++) {
2874
+ const rowStart = gridStartEpochDay + week * 7;
2780
2875
 
2781
- const toMonth = d.month;
2782
- for (let i: number = 0; i < 40; i++) {
2783
- let today = d.add({ milliseconds: (86400000 * i) });
2784
- let valid = isValidTime(today);
2785
- if (opt.startDate && compare_day(today, opt.startDate) < 0) {
2786
- valid = false;
2787
- } else if (opt.endDate && compare_day(today, opt.endDate) > 0) {
2788
- valid = false;
2789
- }
2876
+ // ak prvá bunka riadku je po mesiaci a už sme mali toMonth ukonči
2877
+ if (week > 0 && rowStart > thisMonthEndEpochDay && sawToMonth) break;
2790
2878
 
2791
- days.push({
2792
- date: today,
2793
- type: today.month == toMonth ? 'toMonth' : 'nextMonth',
2794
- day: today.day,
2795
- time: today[utcEpochMilliseconds](),
2796
- valid,
2797
- });
2798
- }
2879
+ html.push('<tr>');
2799
2880
 
2800
- const html = [];
2801
- for (let week = 0; week < 6; week++) {
2802
- if (days[week * 7].type == 'nextMonth') {
2803
- break;
2804
- }
2881
+ for (let wd = 0; wd < 7; wd++) {
2882
+ const epochDay = rowStart + wd;
2805
2883
 
2806
- html.push('<tr>');
2884
+ // čísla na rýchle rozhodnutia
2885
+ const inMonth = epochDay >= firstEpochDay && epochDay <= thisMonthEndEpochDay;
2886
+ if (inMonth) sawToMonth = true;
2887
+
2888
+ const type = inMonth ? 'toMonth' : (epochDay < firstEpochDay ? 'lastMonth' : 'nextMonth');
2807
2889
 
2808
- for (var day: any = 0; day < 7; day++) {
2809
- const _day: any = (opt.startOfWeek == 'monday') ? day + 1 : day;
2810
- const today = days[week * 7 + _day];
2811
- const highlightToday = (Temporal.PlainDateTime.compare(today.date.toPlainDate(), now.toPlainDate()) == 0);
2812
- today.extraClass = '';
2813
- today.tooltip = '';
2814
-
2815
- if (today.valid && opt.beforeShowDay && typeof opt.beforeShowDay == 'function') {
2816
- const _r = opt.beforeShowDay(today.date);
2817
- today.valid = _r[0];
2818
- today.extraClass = _r[1] || '';
2819
- today.tooltip = _r[2] || '';
2820
- if (today.tooltip !== '') { today.extraClass += ' has-tooltip '; }
2890
+ // validácia bez Temporal
2891
+ let valid = true;
2892
+ if (hasStart && epochDay < startEpochDay) valid = false;
2893
+ if (valid && hasEnd && epochDay > endEpochDay) valid = false;
2894
+ if (valid) {
2895
+ // pre isValidTime potrebujeme skutočný čas. Použijeme tmp iba raz
2896
+ tmp.setTime(fromEpochDayUTC(epochDay));
2897
+ // ak vieš spraviť rýchlu vetvu pre isValidTime z čísel, urob to. Inak toto:
2898
+ valid = isValidTimeDate(tmp);
2821
2899
  }
2822
2900
 
2823
- const todayDivAttr = {
2824
- 'time': today.time,
2825
- 'data-tooltip': today.tooltip,
2826
- 'class': `day ${today.type} ${today.extraClass} ${today.valid ? 'valid' : 'invalid'} ${highlightToday ? 'real-today' : ''}`,
2827
- };
2901
+ // week number bunku vlož ešte pred TD dňa
2902
+ if (wd === 0 && opt.showWeekNumbers) {
2903
+ tmp.setTime(fromEpochDayUTC(epochDay));
2904
+ const wn = opt.getWeekNumber ? opt.getWeekNumber(Temporal.PlainDate.from({
2905
+ year: tmp.getUTCFullYear(),
2906
+ month: tmp.getUTCMonth() + 1,
2907
+ day: tmp.getUTCDate()
2908
+ }) as any) : '';
2909
+ html.push('<td><div class="week-number" data-start-time="', String(tmp.getTime()), '">', String(wn), '</div></td>');
2910
+ }
2828
2911
 
2829
- if (day === 0 && opt.showWeekNumbers) {
2830
- html.push(`<td><div class="week-number" data-start-time="${today.time}">${opt.getWeekNumber(today.date)}</div></td>`);
2912
+ // hook beforeShowDay len ak valid
2913
+ let extraClass = '';
2914
+ let tooltip = '';
2915
+ if (valid && opt.beforeShowDay) {
2916
+ // vytvor Temporal iba tu kde to naozaj treba
2917
+ const tpd = Temporal.PlainDate.from(epochDayToYMD(epochDay));
2918
+ const tdt = Temporal.PlainDateTime.from({ ...tpd, hour: 0, minute: 0, second: 0, millisecond: 0 });
2919
+ const _r = opt.beforeShowDay(tdt);
2920
+ valid = !!_r[0];
2921
+ if (_r[1]) extraClass = _r[1];
2922
+ if (_r[2]) tooltip = _r[2];
2831
2923
  }
2924
+ if (tooltip !== '') extraClass += ' has-tooltip';
2925
+
2926
+ const isToday = epochDay === nowEpochDay;
2927
+
2928
+ // priprava údajov pre TD a vnútro
2929
+ // tmp nastavíme na koniec dňa aby bol time konzistentný ak to tak používaš
2930
+ tmp.setTime(fromEpochDayUTC(epochDay));
2931
+ const ms = tmp.getTime();
2932
+ const dayNumber = utcDayOfMonth(tmp);
2933
+
2934
+ const divClass =
2935
+ 'day ' + type +
2936
+ (extraClass ? ' ' + extraClass : '') +
2937
+ (valid ? ' valid' : ' invalid') +
2938
+ (isToday ? ' real-today' : '');
2939
+
2940
+ const tdAttrs = attributesCallbacks({}, opt.dayTdAttrs, {
2941
+ date: null, // ak front nepotrebuje Temporal ušetríš. Inak si sem vieš dohnať PlainDate len na klikanie
2942
+ type,
2943
+ day: dayNumber,
2944
+ time: ms,
2945
+ valid,
2946
+ extraClass,
2947
+ tooltip
2948
+ } as any);
2832
2949
 
2833
- html.push(`<td ${attributesCallbacks(
2834
- {},
2835
- opt.dayTdAttrs,
2836
- today,
2837
- )}>${getInnerDayHtml(todayDivAttr, today)}</td>`);
2950
+ const inner = getInnerDayHtml(
2951
+ { 'time': String(ms), 'data-tooltip': tooltip, 'class': divClass },
2952
+ { day: dayNumber, type, time: ms, valid } as any
2953
+ );
2954
+
2955
+ html.push('<td ', tdAttrs, '>', inner, '</td>');
2838
2956
  }
2957
+
2958
+ weekCount += 1;
2839
2959
  html.push('</tr>');
2840
2960
  }
2961
+
2962
+ while (weekCount < 6) {
2963
+ html.push('<tr><td colspan="7"><div color="transparent" class="day daterangepicker-dummy-row-item" time="-1" style="visibility:hidden;">42</div></td></tr>');
2964
+ weekCount += 1;
2965
+ }
2966
+
2841
2967
  return html.join('');
2968
+
2969
+ // pomôcky
2970
+ function utcDayOfMonth(dt: Date) { return dt.getUTCDate(); }
2971
+
2972
+ function epochDayToYMD(epochDay: number) {
2973
+ const ms = fromEpochDayUTC(epochDay);
2974
+ tmp.setTime(ms);
2975
+ return {
2976
+ year: tmp.getUTCFullYear(),
2977
+ month: tmp.getUTCMonth() + 1,
2978
+ day: tmp.getUTCDate()
2979
+ };
2980
+ }
2842
2981
  }
2843
2982
 
2844
2983
  function getInnerDayHtml(attributes: any, today: any) {
@@ -136,6 +136,100 @@ export class ModalUtils {
136
136
  }
137
137
  }
138
138
 
139
+ static bindModalBottomSheetHandle(getModal: () => HTMLElement, hideModal: () => void) {
140
+ if ((getModal() as any)?._dragBound) {
141
+ return;
142
+ }
143
+
144
+ setTimeout(() => {
145
+ const modal = getModal() as HTMLElement;
146
+ const modalDialog = modal.querySelector('.modal-dialog') as HTMLElement;
147
+ const dragHandle = modal.querySelector('.drag-handle');
148
+
149
+ let startY = 0;
150
+ let currentY = 0;
151
+ let isDragging = false;
152
+ const threshold = 100;
153
+ const cancelDragging = () => {
154
+ isDragging = false;
155
+ modal.classList.remove('modal-is-dragging');
156
+ };
157
+
158
+ const startDragging = () => {
159
+ isDragging = true;
160
+ modal.classList.add('modal-is-dragging');
161
+ };
162
+
163
+ const onMove = (y) => {
164
+ const translateY = Math.max(y - startY, 0);
165
+ modalDialog.style.transform = `translateY(${translateY}px)`;
166
+ };
167
+
168
+ const endDrag = () => {
169
+ cancelDragging();
170
+ const dragDistance = currentY - startY;
171
+
172
+ if (dragDistance > threshold) {
173
+ hideModal();
174
+ } else {
175
+ modalDialog.style.transform = 'translateY(0)';
176
+ }
177
+ };
178
+
179
+ // Touch events
180
+ dragHandle.addEventListener('touchstart', (e) => {
181
+ startY = (e as TouchEvent).touches[0].clientY;
182
+ startDragging();
183
+ });
184
+
185
+ dragHandle.addEventListener('touchmove', (e) => {
186
+ if (!isDragging) {
187
+ return;
188
+ }
189
+
190
+ currentY = (e as TouchEvent).touches[0].clientY;
191
+ onMove(currentY);
192
+ });
193
+
194
+ dragHandle.addEventListener('touchend', endDrag);
195
+
196
+ // Mouse events
197
+ dragHandle.addEventListener('mousedown', (e) => {
198
+ startY = (e as MouseEvent).clientY;
199
+ startDragging();
200
+
201
+ const onMouseMove = (e) => {
202
+ if (!isDragging) {
203
+ return;
204
+ }
205
+
206
+ currentY = e.clientY;
207
+ onMove(currentY);
208
+ e.preventDefault();
209
+ e.stopPropagation();
210
+ e.stopImmediatePropagation();
211
+ };
212
+
213
+ const onMouseUp = () => {
214
+ endDrag();
215
+ globalState.removeEventListener('mousemove', onMouseMove);
216
+ globalState.removeEventListener('mouseup', onMouseUp);
217
+ };
218
+
219
+ globalState.addEventListener('mousemove', onMouseMove);
220
+ globalState.addEventListener('mouseup', onMouseUp);
221
+ });
222
+
223
+ // Reset on modal hide
224
+ modal.addEventListener('hidden.bs.modal', () => {
225
+ cancelDragging();
226
+ modalDialog.style.transform = '';
227
+ });
228
+
229
+ (modal as any)._dragBound = true;
230
+ }, 100);
231
+ }
232
+
139
233
  private static _getModalJquery(modalElem: Element | IVue): JQuery {
140
234
  return globalState.jQuery(modalElem as any);
141
235
  }
@@ -122,98 +122,10 @@ class ModalComponent extends TsxComponent<ModalArgs> implements ModalArgs {
122
122
  return;
123
123
  }
124
124
 
125
- const modal = this.$refs.modalRoot as HTMLElement;
126
- if ((modal as any)?._dragBound) {
127
- return;
128
- }
129
-
130
- setTimeout(() => {
131
- const modal = this.$refs.modalRoot as HTMLElement;
132
- const modalDialog = modal.querySelector('.modal-dialog') as HTMLElement;
133
- const dragHandle = modal.querySelector('.drag-handle');
134
-
135
- let startY = 0;
136
- let currentY = 0;
137
- let isDragging = false;
138
- const threshold = 100;
139
- const cancelDragging = () => {
140
- isDragging = false;
141
- modal.classList.remove('modal-is-dragging');
142
- };
143
-
144
- const startDragging = () => {
145
- isDragging = true;
146
- modal.classList.add('modal-is-dragging');
147
- };
148
-
149
- const onMove = (y) => {
150
- const translateY = Math.max(y - startY, 0);
151
- modalDialog.style.transform = `translateY(${translateY}px)`;
152
- };
153
-
154
- const endDrag = () => {
155
- cancelDragging();
156
- const dragDistance = currentY - startY;
157
-
158
- if (dragDistance > threshold) {
159
- this.hide();
160
- } else {
161
- modalDialog.style.transform = 'translateY(0)';
162
- }
163
- };
164
-
165
- // Touch events
166
- dragHandle.addEventListener('touchstart', (e) => {
167
- startY = (e as TouchEvent).touches[0].clientY;
168
- startDragging();
169
- });
170
-
171
- dragHandle.addEventListener('touchmove', (e) => {
172
- if (!isDragging) {
173
- return;
174
- }
175
-
176
- currentY = (e as TouchEvent).touches[0].clientY;
177
- onMove(currentY);
178
- });
179
-
180
- dragHandle.addEventListener('touchend', endDrag);
181
-
182
- // Mouse events
183
- dragHandle.addEventListener('mousedown', (e) => {
184
- startY = (e as MouseEvent).clientY;
185
- startDragging();
186
-
187
- const onMouseMove = (e) => {
188
- if (!isDragging) {
189
- return;
190
- }
191
-
192
- currentY = e.clientY;
193
- onMove(currentY);
194
- e.preventDefault();
195
- e.stopPropagation();
196
- e.stopImmediatePropagation();
197
- };
198
-
199
- const onMouseUp = () => {
200
- endDrag();
201
- globalState.removeEventListener('mousemove', onMouseMove);
202
- globalState.removeEventListener('mouseup', onMouseUp);
203
- };
204
-
205
- globalState.addEventListener('mousemove', onMouseMove);
206
- globalState.addEventListener('mouseup', onMouseUp);
207
- });
208
-
209
- // Reset on modal hide
210
- modal.addEventListener('hidden.bs.modal', () => {
211
- cancelDragging();
212
- modalDialog.style.transform = '';
213
- });
214
-
215
- (modal as any)._dragBound = true;
216
- }, 100);
125
+ ModalUtils.bindModalBottomSheetHandle(
126
+ () => this.$refs.modalRoot as HTMLElement,
127
+ () => this.hide()
128
+ )
217
129
  }
218
130
 
219
131
  treatMobileAsBottomSheet(): boolean {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "inviton-powerduck",
3
3
  "type": "module",
4
- "version": "0.0.179",
4
+ "version": "0.0.181",
5
5
  "files": [
6
6
  "app/",
7
7
  "common/",