@nova-design-system/nova-react 3.1.0 → 3.3.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 (50) hide show
  1. package/dist/cjs/{index-Cn-oNJnW.js → index-BlWxX8x6.js} +2199 -1452
  2. package/dist/cjs/index.js +2 -1
  3. package/dist/cjs/{nv-alert.entry-BFwufSUQ.js → nv-alert.entry-BLGSitrm.js} +7 -7
  4. package/dist/cjs/{nv-avatar.entry-Do1K4s3s.js → nv-avatar.entry-CRcLMbEx.js} +7 -7
  5. package/dist/cjs/{nv-badge_2.entry-NTGHyFdg.js → nv-badge_2.entry-BtDAr7_d.js} +1 -1
  6. package/dist/cjs/{nv-breadcrumb.entry-oPVGJYlk.js → nv-breadcrumb.entry-PVDZoF9i.js} +1 -1
  7. package/dist/cjs/{nv-breadcrumbs.entry-BsOw153b.js → nv-breadcrumbs.entry-BY169s5F.js} +1 -1
  8. package/dist/cjs/{nv-button.entry-13tdBiRr.js → nv-button.entry-BpxpxFJP.js} +7 -7
  9. package/dist/cjs/{nv-calendar.entry-u9MgGb83.js → nv-calendar.entry-BobyjFdK.js} +389 -177
  10. package/dist/cjs/{nv-col.entry-DFhv-GI7.js → nv-col.entry-B4BJXJw-.js} +1 -1
  11. package/dist/cjs/{nv-datagrid.entry-BoB17gvI.js → nv-datagrid.entry-D5UVDiYl.js} +100 -108
  12. package/dist/cjs/{nv-datagridcolumn.entry-C3MYBmfS.js → nv-datagridcolumn.entry-dmpcmCIT.js} +2 -2
  13. package/dist/cjs/{nv-dialog.entry-OA3qL3Tx.js → nv-dialog.entry-BYovzkco.js} +3 -3
  14. package/dist/cjs/{nv-dialogfooter_2.entry-LAQYSiGV.js → nv-dialogfooter_2.entry-C9dhLKRM.js} +3 -3
  15. package/dist/cjs/{nv-fieldcheckbox.entry-CP7SDzVO.js → nv-fieldcheckbox.entry-BvFqY2dM.js} +1 -1
  16. package/dist/cjs/nv-fielddate.entry-CSpAcEXW.js +303 -0
  17. package/dist/cjs/nv-fielddaterange.entry-C14o96dd.js +439 -0
  18. package/dist/cjs/{nv-fielddropdown.entry-Nwric1vT.js → nv-fielddropdown.entry-C3VzNRhh.js} +84 -60
  19. package/dist/cjs/{nv-fielddropdownitem.entry-CiqSw5VL.js → nv-fielddropdownitem.entry-D4G4Ytus.js} +1 -1
  20. package/dist/cjs/{nv-fieldmultiselect.entry-QKNIBcW1.js → nv-fieldmultiselect.entry-Ci43ZvzC.js} +116 -104
  21. package/dist/cjs/nv-fieldnumber.entry-nvUi-64H.js +130 -0
  22. package/dist/cjs/nv-fieldpassword.entry-C2uqwDah.js +121 -0
  23. package/dist/cjs/{nv-fieldradio.entry-Dxc6ZCyb.js → nv-fieldradio.entry-DL2GdKqO.js} +1 -1
  24. package/dist/cjs/{nv-fieldselect.entry-Cys0KRyG.js → nv-fieldselect.entry-D4AIRE24.js} +2 -2
  25. package/dist/cjs/nv-fieldslider.entry-BNge4J69.js +665 -0
  26. package/dist/cjs/nv-fieldtext.entry-BI-fdkdX.js +123 -0
  27. package/dist/cjs/nv-fieldtextarea.entry-Ct0g9Qtb.js +198 -0
  28. package/dist/cjs/{nv-fieldtime.entry-BqxiFlLI.js → nv-fieldtime.entry-CmO96Py1.js} +67 -67
  29. package/dist/cjs/nv-icon.entry-TepdQ1jA.js +79 -0
  30. package/dist/cjs/{nv-iconbutton_2.entry-BLNrQz9Q.js → nv-iconbutton_2.entry-B7Xyut9H.js} +3 -3
  31. package/dist/cjs/{nv-menu.entry-7IDfPmZ8.js → nv-menu.entry-DHrRi_37.js} +2 -2
  32. package/dist/cjs/{nv-menuitem.entry-B9cjy7O8.js → nv-menuitem.entry-B_D1pSYa.js} +2 -2
  33. package/dist/cjs/{nv-popover.entry-ChLYZ3zY.js → nv-popover.entry-DyQPEQ4I.js} +2 -2
  34. package/dist/cjs/{nv-row.entry-DiLY8Vbc.js → nv-row.entry-CDTv7ikK.js} +2 -2
  35. package/dist/cjs/{nv-stack.entry-MpPzmg5_.js → nv-stack.entry-A78c6BVf.js} +2 -2
  36. package/dist/cjs/{nv-table.entry-cME3Zuq2.js → nv-table.entry-DkwcfdJM.js} +3 -3
  37. package/dist/cjs/{nv-tablecolumn.entry-DSctDxCS.js → nv-tablecolumn.entry-C8VNSpDf.js} +1 -1
  38. package/dist/cjs/{nv-toggle.entry-EBWm3Xy5.js → nv-toggle.entry-vxSyUDKZ.js} +3 -3
  39. package/dist/cjs/{nv-tooltip.entry-q6rJLq1C.js → nv-tooltip.entry-BQKXRp4d.js} +3 -3
  40. package/dist/generated/components.js +15 -3
  41. package/dist/types/generated/components.d.ts +8 -3
  42. package/package.json +1 -1
  43. package/dist/cjs/nv-fielddate.entry-CD7PX6yA.js +0 -269
  44. package/dist/cjs/nv-fielddaterange.entry-BVBVGmly.js +0 -353
  45. package/dist/cjs/nv-fieldnumber.entry-DfHcI-sO.js +0 -130
  46. package/dist/cjs/nv-fieldpassword.entry-b2pUmS8F.js +0 -121
  47. package/dist/cjs/nv-fieldtext.entry-DCZWLFFp.js +0 -123
  48. package/dist/cjs/nv-fieldtextarea.entry-DEeRdtZ7.js +0 -198
  49. package/dist/cjs/nv-icon.entry-CzEdUDdA.js +0 -79
  50. /package/dist/cjs/{constants-b97e736d-BzFAKCkR.js → constants-4faa1fae-BzFAKCkR.js} +0 -0
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-Cn-oNJnW.js');
4
- var constantsB97e736d = require('./constants-b97e736d-BzFAKCkR.js');
3
+ var index = require('./index-BlWxX8x6.js');
4
+ var constants4faa1fae = require('./constants-4faa1fae-BzFAKCkR.js');
5
5
  var _commonjsHelpers1789f0cf = require('./_commonjsHelpers-1789f0cf-BJu3ubxk.js');
6
6
  require('react');
7
7
 
@@ -159,9 +159,18 @@ function isSameOrAfter(date, compareDate, options) {
159
159
  * @returns {number} Week number
160
160
  */
161
161
  function getWeekNumber(date) {
162
- const startOfYear = new Date(date.getFullYear(), 0, 1);
163
- const pastDaysOfYear = (date.getTime() - startOfYear.getTime()) / 86400000;
164
- return Math.ceil((pastDaysOfYear + startOfYear.getDay() + 1) / 7);
162
+ // Create a copy of the date to avoid modifying the original
163
+ const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
164
+ // Adjust to the same week Thursday (ISO 8601)
165
+ d.setUTCDate(d.getUTCDate() + 3 - ((d.getUTCDay() + 6) % 7));
166
+ // Calculate the first Thursday of the year
167
+ const week1 = new Date(Date.UTC(d.getUTCFullYear(), 0, 4));
168
+ // Calculate the week number
169
+ return (1 +
170
+ Math.round(((d.getTime() - week1.getTime()) / 86400000 -
171
+ 3 +
172
+ ((week1.getUTCDay() + 6) % 7)) /
173
+ 7));
165
174
  }
166
175
  /**
167
176
  * Convert a date string/Date to a Date without timezone offset
@@ -235,7 +244,176 @@ function parseDate(dateInput, dateFormat) {
235
244
  return parsed.toDate();
236
245
  }
237
246
 
238
- const nvCalendarCss = "nv-calendar{display:block}.datepicker-root{display:flex;justify-content:center;align-items:flex-start;width:auto}.datepicker-container{font-family:system-ui, sans-serif;display:flex;flex-direction:column;align-items:stretch;background:var(--components-calendar-background);border-radius:var(--calendar-radius);padding:var(--calendar-padding);box-shadow:0px var(--shadow-y-axis-md-1) var(--shadow-blur-md-1) var(--shadow-spread-md, 0) var(--shadow-color-opacity-0), 0px var(--shadow-y-axis-md-2) var(--shadow-blur-md-2) var(--shadow-spread-md, 0) var(--shadow-color-opacity-2);border:1px solid var(--components-calendar-border);width:auto;max-width:100%}.datepicker-container-single{max-width:300px}.datepicker-container-single .datepicker-wrapper:has(.shortcuts-placement-left),.datepicker-container-single .datepicker-wrapper:has(.shortcuts-placement-right){max-width:410px !important}.datepicker-container-single:has(.shortcuts-placement-left),.datepicker-container-single:has(.shortcuts-placement-right){max-width:410px !important}.datepicker-wrapper{display:flex;justify-content:center;align-items:flex-start;gap:var(--calendar-gap-x);width:auto;overflow-x:hidden}.datepicker-wrapper::-webkit-scrollbar{width:6px;height:6px}.datepicker-wrapper::-webkit-scrollbar-track{background-color:var(--color-level-10-background);border-radius:9999px}.datepicker-wrapper::-webkit-scrollbar-thumb{background-color:var(--color-gray-200);border-radius:9999px}.datepicker-wrapper.single{justify-content:center}.calendar-container{display:flex;flex-direction:column;align-items:center;padding:var(--calendar-padding);width:auto;position:relative}.calendar-separator{width:1px;background:var(--components-calendar-border);height:auto;min-height:100%;margin:0 10px}.header{display:flex;justify-content:start;align-items:center;margin-bottom:var(--calendar-header-margin-bottom);width:100%}.header nv-iconbutton{width:var(--calendar-header-button-size);height:var(--calendar-header-button-size)}.nav-buttons{display:flex;gap:var(--spacing-0);margin-left:auto}.nav-left{order:-1}.date-controls{display:flex;gap:var(--spacing-1);align-items:center;min-height:34px;justify-content:center}.datepicker-container-single .date-controls{justify-content:flex-start}.datepicker-container:not(.datepicker-container-single) .date-controls{justify-content:start;flex-grow:1}.date-controls .month-select,.date-controls .year-input{background:transparent !important}.calendar-wrapper:nth-child(n+2) .datepicker-container{margin-left:42px}.calendar-grid{display:grid;grid-template-columns:auto 1fr;column-gap:var(--calendar-weeks-calendar-gap-x);position:relative}.calendar-grid.slide-left{animation:slideLeft 0.3s ease-out}.calendar-grid.slide-right{animation:slideRight 0.3s ease-out}.week-numbers{display:grid;grid-template-rows:var(--calendar-cell-size) repeat(6, var(--calendar-cell-size));background:var(--components-calendar-weeks-background);color:var(--components-calendar-weeks-text);border-radius:var(--calendar-weeks-radius);width:var(--calendar-weeks-size);row-gap:var(--calendar-grid-gap-y)}.week-numbers .clickable{cursor:pointer}.week-numbers .clickable:hover{background-color:var(--components-calendar-weeks-background-hover);color:var(--components-calendar-weeks-text-hover);border-radius:var(--calendar-radius)}.week-header,.week-number{display:grid;place-items:center;font-size:var(--calendar-cell-font-size)}.week-header{font-weight:700;color:var(--components-calendar-weeks-text)}.week-number{color:var(--components-calendar-cell-text)}.days-container{display:grid;grid-template-rows:auto 1fr;row-gap:var(--calendar-grid-gap-y)}.days-header{display:grid;grid-template-columns:repeat(7, var(--calendar-cell-size));height:var(--calendar-cell-size)}.day-header{display:grid;place-items:center;font-size:var(--calendar-cell-font-size);color:var(--components-calendar-cell-text)}.days-grid{display:grid;grid-template-columns:repeat(7, var(--calendar-cell-size));grid-template-rows:repeat(6, var(--calendar-cell-size));animation:fadeIn 0.2s ease-in;row-gap:var(--calendar-grid-gap-y);z-index:0}.day{display:grid;place-items:center;width:var(--calendar-cell-size);height:var(--calendar-cell-size);font-size:var(--calendar-cell-font-size);border-radius:var(--calendar-cell-radius);cursor:pointer;border:none;background:transparent;transition:all 0.2s ease;text-align:center;animation:scaleIn 0.2s ease-out}.day:hover:not(.disabled,.empty,.selected){background:var(--components-calendar-cell-background-hover);color:var(--components-calendar-cell-text-hover)}.day.selected,.day.selected:hover .day.is-today.selected,.day.is-today.selected:hover{background:var(--components-calendar-cell-background-selected);color:var(--components-calendar-cell-text-selected) !important}.day.disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.day.outside-month{color:var(--components-calendar-cell-text);opacity:var(--opacity-disabled)}.day.outside-month.selected{opacity:1 !important;color:var(--components-calendar-cell-text-selected)}.day.outside-month.in-range{opacity:1 !important;background-color:var(--components-calendar-cell-background-in-range);color:var(--components-calendar-cell-text-in-range)}.day.in-range{background:var(--components-calendar-cell-background-in-range);color:var(--components-calendar-cell-text-in-range);border-radius:0;position:relative}.day.range-start,.day.range-start:focus,.day.range-start:hover,.day.range-end,.day.range-end:focus,.day.range-end:hover{background-color:var(--components-calendar-cell-background-selected) !important;color:var(--components-calendar-cell-text-selected) !important}.day.range-start,.day.range-end,.day.range-start.is-today,.day.range-end.is-today{background:var(--components-calendar-cell-background-selected);color:var(--components-calendar-cell-text-selected);position:relative;border-radius:var(--radius-rounded-full)}.day.range-start:hover,.day.range-end:hover,.day.range-start.is-today:hover,.day.range-end.is-today:hover{color:var(--components-calendar-cell-text-today)}.day.range-start:before,.day.range-end:before,.day.range-start.is-today:before,.day.range-end.is-today:before{content:\"\";position:absolute;bottom:0;left:0;right:0;top:0;z-index:-1;background-color:var(--components-calendar-cell-background-in-range);border-radius:var(--radius-rounded-full);width:auto;height:auto}.day.range-start:has(~.range-end):before,.day.range-start:has(+.in-range):before{border-top-right-radius:0;border-bottom-right-radius:0}.day.range-end:before{border-top-left-radius:0 !important;border-bottom-left-radius:0 !important}.day.outside-month.range-start,.day.outside-month.range-end{background:var(--components-calendar-cell-background-selected) !important;color:var(--components-calendar-cell-text-selected);opacity:1 !important}.day.is-today{font-weight:700;position:relative;color:var(--components-calendar-cell-text-today)}.day.is-today.range-start,.day.is-today.range-end{color:var(--components-calendar-cell-text-selected)}.day.is-today.range-start:hover,.day.is-today.range-end:hover{color:var(--components-calendar-cell-text-today)}.day.is-today::after{content:\"\";position:absolute;bottom:var(--spacing-1);left:50%;transform:translateX(-50%);width:var(--calendar-cell-dot-size);height:var(--calendar-cell-dot-size);background-color:currentColor;border-radius:50%}.day.is-today.selected::after{color:var(--components-calendar-cell-text-selected)}.day.is-today.selected::after::after{background-color:var(--components-calendar-cell-dot-selected)}.calendar-footer{display:flex;gap:var(--spacing-1);justify-content:flex-start;width:100%;flex-wrap:wrap}.footer-placement-left{justify-content:flex-start}.footer-placement-right{justify-content:flex-end}.footer-placement-center{justify-content:center}.datepicker-controls{display:flex;flex-direction:column;border-top:1px solid var(--components-calendar-border);padding:var(--calendar-controls-padding-top) var(--calendar-padding) var(--calendar-padding);gap:var(--calendar-grid-gap-y);margin-top:var(--calendar-controls-margin-top)}.datepicker-actions{display:flex;justify-content:flex-end;gap:var(--spacing-1);width:100%}.datepicker-actions slot-fb{display:contents !important}.calendar-footer+.datepicker-actions{margin-top:0}.shortcuts-placement-left,.shortcuts-placement-right{display:flex;flex-direction:column;gap:var(--spacing-1);margin-top:var(--spacing-4)}.shortcuts-placement-left{align-items:flex-end}.shortcuts-placement-right{align-items:flex-start}@keyframes slideLeft{from{opacity:0;transform:translateX(20px)}to{opacity:1;transform:translateX(0)}}@keyframes slideRight{from{opacity:0;transform:translateX(-20px)}to{opacity:1;transform:translateX(0)}}@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes scaleIn{from{opacity:0;transform:scale(0.9)}to{opacity:1;transform:scale(1)}}";
247
+ /**
248
+ * Renders a single day cell in the calendar grid
249
+ * @param {DayCellProps} props - Component properties
250
+ * @returns {JSX.Element} JSX element representing a day cell
251
+ */
252
+ const DayCell = props => {
253
+ const { date, dayOfMonth, isCurrentMonth, isSelected, isInRange, isStart, isEnd, isToday, isDisabled, onClick, } = props;
254
+ // Build CSS classes for the day cell
255
+ const dayClasses = [
256
+ 'day',
257
+ isSelected ? 'selected' : '',
258
+ isStart ? 'range-start' : '',
259
+ isEnd ? 'range-end' : '',
260
+ isInRange ? 'in-range' : '',
261
+ isDisabled ? 'disabled' : '',
262
+ !isCurrentMonth ? 'outside-month' : '',
263
+ isToday ? 'is-today' : '',
264
+ ]
265
+ .filter(Boolean)
266
+ .join(' ');
267
+ const handleClick = () => {
268
+ if (!isDisabled && onClick) {
269
+ onClick(date);
270
+ }
271
+ };
272
+ return (
273
+ // eslint-disable-next-line react/jsx-no-bind
274
+ index.h("div", { class: dayClasses, onClick: handleClick, "aria-disabled": isDisabled }, dayOfMonth));
275
+ };
276
+
277
+ /**
278
+ * Renders the action buttons for the calendar (Cancel/OK)
279
+ * @param {CalendarActionsProps} props - Component properties
280
+ * @returns {JSX.Element} JSX element representing the action buttons
281
+ */
282
+ const CalendarActions = props => {
283
+ const { onReset, onConfirm, useSlot = false } = props;
284
+ return (index.h("div", { class: "datepicker-actions" }, useSlot ? (index.h("slot", { name: "actions" },
285
+ index.h("nv-button", { emphasis: "low", size: "xs", onClick: onReset }, "Cancel"),
286
+ index.h("nv-button", { size: "xs", onClick: onConfirm }, "OK"))) : (index.h("div", null,
287
+ index.h("nv-button", { emphasis: "low", size: "xs", onClick: onReset }, "Cancel"),
288
+ index.h("nv-button", { size: "xs", onClick: onConfirm }, "OK")))));
289
+ };
290
+
291
+ /**
292
+ * Renders the week numbers column for the calendar
293
+ * @param {WeekNumbersProps} props - Component properties
294
+ * @returns {JSX.Element} JSX element representing the week numbers
295
+ */
296
+ const WeekNumbers = props => {
297
+ const { weeks, localizedWeekText, selectionType, onWeekSelect, calendarIndex, } = props;
298
+ /**
299
+ * Handles click on a week number for range selection
300
+ * @param {Array<WeekData>} week - Week data
301
+ */
302
+ const handleWeekClick = (week) => {
303
+ if (selectionType === 'range') {
304
+ const dates = week.map(d => d.date);
305
+ onWeekSelect(dates, calendarIndex);
306
+ }
307
+ };
308
+ /**
309
+ * Creates a click handler for a specific week
310
+ * @param {Array<WeekData>} week - Week data
311
+ * @returns {() => void} Click handler function
312
+ */
313
+ const createWeekHandler = (week) => {
314
+ return () => handleWeekClick(week);
315
+ };
316
+ return (index.h("div", { class: "week-numbers" },
317
+ index.h("div", { class: "week-header" }, localizedWeekText),
318
+ weeks.map((week, weekIndex) => {
319
+ var _a;
320
+ const firstDayWithDate = ((_a = week.find(d => d.date)) === null || _a === void 0 ? void 0 : _a.date) || new Date();
321
+ const weekNumber = getWeekNumber(firstDayWithDate);
322
+ const isClickable = selectionType === 'range';
323
+ return (index.h("div", { class: `week-number ${isClickable ? 'clickable' : ''}`, onClick: createWeekHandler(week), key: `week-${weekIndex}`, role: isClickable ? 'button' : undefined, tabindex: isClickable ? 0 : undefined }, weekNumber));
324
+ })));
325
+ };
326
+
327
+ /**
328
+ * Renders the shortcuts for quick date selection
329
+ * @param {CalendarShortcutsProps} props - Component properties
330
+ * @returns {JSX.Element | null} JSX element representing the shortcuts or null if no shortcuts
331
+ */
332
+ const CalendarShortcuts = props => {
333
+ const { shortcuts, placement, onShortcutClick } = props;
334
+ if (!shortcuts || shortcuts.length === 0) {
335
+ return null;
336
+ }
337
+ /**
338
+ * Creates a click handler for a specific shortcut
339
+ * @param {ShortcutData} shortcut - The shortcut data
340
+ * @returns {() => void} Click handler function
341
+ */
342
+ const createShortcutHandler = (shortcut) => {
343
+ return () => onShortcutClick(shortcut);
344
+ };
345
+ return (index.h("div", { class: `shortcuts-container shortcuts-placement-${placement}` }, shortcuts.map((shortcut, index$1) => (index.h("nv-button", { key: `shortcut-${index$1}`, emphasis: "lower", size: "xs", "aria-label": shortcut.label, onClick: createShortcutHandler(shortcut) }, shortcut.label)))));
346
+ };
347
+
348
+ /**
349
+ * Renders the calendar header with navigation and date controls
350
+ * @param {CalendarHeaderProps} props - Component properties
351
+ * @returns {JSX.Element} JSX element representing the calendar header
352
+ */
353
+ const CalendarHeader = props => {
354
+ const { currentDate, months, numberOfCalendars, calendarIndex, monthOffset, onMonthChange, onMonthSelect, onYearChange, } = props;
355
+ /**
356
+ * Creates navigation handler for month change
357
+ * @param {number} direction - Direction of navigation (-1 or 1)
358
+ * @returns {() => void} Navigation handler function
359
+ */
360
+ const createNavigationHandler = (direction) => {
361
+ return () => onMonthChange(direction);
362
+ };
363
+ /**
364
+ * Creates month selection handler
365
+ * @param {number} offset - Month offset
366
+ * @returns {(event: Event) => void} Month selection handler function
367
+ */
368
+ const createMonthSelectHandler = (offset) => {
369
+ return (event) => onMonthSelect(event, offset);
370
+ };
371
+ /**
372
+ * Creates year change handler
373
+ * @param {number} offset - Month offset
374
+ * @returns {(event: Event) => void} Year change handler function
375
+ */
376
+ const createYearChangeHandler = (offset) => {
377
+ return (event) => onYearChange(event, offset);
378
+ };
379
+ const currentMonth = (currentDate.getUTCMonth() + monthOffset) % 12;
380
+ const currentYear = currentDate.getUTCFullYear() +
381
+ Math.floor((currentDate.getUTCMonth() + monthOffset) / 12);
382
+ return (index.h("div", { class: "header" },
383
+ numberOfCalendars > 1 && calendarIndex === 0 && (index.h("nv-iconbutton", { class: "nav-left", emphasis: "lower", name: "chevron-left", onClick: createNavigationHandler(-1) })),
384
+ index.h("div", { class: "date-controls" },
385
+ index.h("select", { class: "month-select mr-4", onChange: createMonthSelectHandler(monthOffset) }, months.map(month => (index.h("option", { key: month.value, value: month.value, selected: month.value === currentMonth }, month.label)))),
386
+ index.h("input", { type: "number", class: "year-input", min: "1950", max: "2100", value: currentYear, onChange: createYearChangeHandler(monthOffset) })),
387
+ numberOfCalendars === 1 && (index.h("div", { class: "nav-buttons" },
388
+ index.h("nv-iconbutton", { emphasis: "lower", name: "chevron-left", onClick: createNavigationHandler(-1) }),
389
+ index.h("nv-iconbutton", { emphasis: "lower", name: "chevron-right", onClick: createNavigationHandler(1) }))),
390
+ numberOfCalendars > 1 && calendarIndex === numberOfCalendars - 1 && (index.h("nv-iconbutton", { emphasis: "lower", name: "chevron-right", onClick: createNavigationHandler(1), class: "nav-right" }))));
391
+ };
392
+
393
+ /**
394
+ * Renders the calendar grid with day headers and day cells
395
+ * @param {CalendarGridProps} props - Component properties
396
+ * @returns {JSX.Element} JSX element representing the calendar grid
397
+ */
398
+ const CalendarGrid = props => {
399
+ const { days, dayNames, selectionType, selectedDate, startDate, endDate, isUTCMode, onDayClick, isDateInRange, isToday, } = props;
400
+ return (index.h("div", { class: "days-container" },
401
+ index.h("div", { class: "days-header" }, dayNames.map((day, index$1) => (index.h("div", { class: "day-header", key: `day-header-${index$1}` }, day)))),
402
+ index.h("div", { class: "days-grid" }, days.map(day => {
403
+ const date = day.date;
404
+ if (!date)
405
+ return null;
406
+ const isSelected = selectionType === 'single' &&
407
+ isSameDate(date, selectedDate, { isUTCMode });
408
+ const isInRange = isDateInRange(date);
409
+ const isStart = isSameDate(date, startDate, { isUTCMode });
410
+ const isEnd = isSameDate(date, endDate, { isUTCMode });
411
+ const isTodayDate = isToday(date);
412
+ return (index.h(DayCell, { date: date, dayOfMonth: day.dayOfMonth, isCurrentMonth: day.isCurrentMonth, isSelected: isSelected, isInRange: isInRange, isStart: isStart, isEnd: isEnd, isToday: isTodayDate, isDisabled: day.isDisabled, selectionType: selectionType, onClick: onDayClick }));
413
+ }))));
414
+ };
415
+
416
+ const nvCalendarCss = "nv-calendar{display:block}.datepicker-root{display:flex;justify-content:center;align-items:flex-start;width:auto}.datepicker-container{font-family:system-ui, sans-serif;display:flex;flex-direction:column;align-items:stretch;background:var(--components-calendar-background);border-radius:var(--calendar-radius);padding:var(--calendar-padding);box-shadow:0px var(--shadow-y-axis-md-1) var(--shadow-blur-md-1) var(--shadow-spread-md, 0) var(--shadow-color-opacity-0), 0px var(--shadow-y-axis-md-2) var(--shadow-blur-md-2) var(--shadow-spread-md, 0) var(--shadow-color-opacity-2);border:1px solid var(--components-calendar-border);width:auto;max-width:100%}.datepicker-container-single{max-width:300px}.datepicker-container-single .datepicker-wrapper:has(.shortcuts-placement-left),.datepicker-container-single .datepicker-wrapper:has(.shortcuts-placement-right){max-width:410px !important}.datepicker-container-single:has(.shortcuts-placement-left),.datepicker-container-single:has(.shortcuts-placement-right){max-width:410px !important}.datepicker-wrapper{display:flex;justify-content:center;align-items:flex-start;gap:var(--calendar-gap-x);width:auto;overflow-x:hidden}.datepicker-wrapper::-webkit-scrollbar{width:6px;height:6px}.datepicker-wrapper::-webkit-scrollbar-track{background-color:var(--color-level-10-background);border-radius:9999px}.datepicker-wrapper::-webkit-scrollbar-thumb{background-color:var(--color-gray-200);border-radius:9999px}.datepicker-wrapper.single{justify-content:center}.calendar-container{display:flex;flex-direction:column;align-items:center;padding:var(--calendar-padding);width:auto;position:relative}.calendar-separator{width:1px;background:var(--components-calendar-border);height:auto;min-height:100%;margin:0 10px}.header{display:flex;justify-content:start;align-items:center;margin-bottom:var(--calendar-header-margin-bottom);width:100%}.header nv-iconbutton{width:var(--calendar-header-button-size);height:var(--calendar-header-button-size)}.nav-buttons{display:flex;gap:var(--spacing-0);margin-left:auto}.nav-left{order:-1}.date-controls{display:flex;gap:var(--spacing-1);align-items:center;min-height:34px;justify-content:center}.datepicker-container-single .date-controls{justify-content:flex-start}.datepicker-container:not(.datepicker-container-single) .date-controls{justify-content:start;flex-grow:1}.date-controls .month-select,.date-controls .year-input{background:transparent !important}.calendar-wrapper:nth-child(n+2) .datepicker-container{margin-left:42px}.calendar-grid{display:grid;grid-template-columns:auto 1fr;column-gap:var(--calendar-weeks-calendar-gap-x);position:relative}.calendar-grid.slide-left{animation:slideLeft 0.3s ease-out}.calendar-grid.slide-right{animation:slideRight 0.3s ease-out}.week-numbers{display:grid;grid-template-rows:var(--calendar-cell-size) repeat(6, var(--calendar-cell-size));background:var(--components-calendar-weeks-background);color:var(--components-calendar-weeks-text);border-radius:var(--calendar-weeks-radius);width:var(--calendar-weeks-size);row-gap:var(--calendar-grid-gap-y)}.week-numbers .clickable{cursor:pointer}.week-numbers .clickable:hover{background-color:var(--components-calendar-weeks-background-hover);color:var(--components-calendar-weeks-text-hover);border-radius:var(--calendar-radius)}.week-header,.week-number{display:grid;place-items:center;font-size:var(--calendar-cell-font-size)}.week-header{font-weight:700;color:var(--components-calendar-weeks-text)}.week-number{color:var(--components-calendar-cell-text)}.days-container{display:grid;grid-template-rows:auto 1fr;row-gap:var(--calendar-grid-gap-y)}.days-header{display:grid;grid-template-columns:repeat(7, var(--calendar-cell-size));height:var(--calendar-cell-size)}.day-header{display:grid;place-items:center;font-size:var(--calendar-cell-font-size);color:var(--components-calendar-cell-text)}.days-grid{display:grid;grid-template-columns:repeat(7, var(--calendar-cell-size));grid-template-rows:repeat(6, var(--calendar-cell-size));animation:fadeIn 0.2s ease-in;row-gap:var(--calendar-grid-gap-y);z-index:0}.day{display:grid;place-items:center;width:var(--calendar-cell-size);height:var(--calendar-cell-size);font-size:var(--calendar-cell-font-size);border-radius:var(--calendar-cell-radius);cursor:pointer;border:none;background:transparent;transition:all 0.2s ease;text-align:center;animation:scaleIn 0.2s ease-out}.day:hover:not(.disabled,.empty,.selected){background:var(--components-calendar-cell-background-hover);color:var(--components-calendar-cell-text-hover)}.day.selected,.day.selected:hover .day.is-today.selected,.day.is-today.selected:hover{background:var(--components-calendar-cell-background-selected);color:var(--components-calendar-cell-text-selected) !important}.day.disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.day.outside-month{color:var(--components-calendar-cell-text);opacity:var(--opacity-disabled)}.day.outside-month.selected{opacity:1 !important;color:var(--components-calendar-cell-text-selected)}.day.outside-month.in-range{opacity:0.5 !important;background-color:var(--components-calendar-cell-background-in-range);color:var(--components-calendar-cell-text-in-range)}.day.outside-month.in-range:hover{opacity:0.7 !important;background-color:var(--components-calendar-cell-background-in-range)}.day.in-range{background:var(--components-calendar-cell-background-in-range);color:var(--components-calendar-cell-text-in-range);border-radius:0;position:relative}.day.range-start,.day.range-start:focus,.day.range-start:hover,.day.range-end,.day.range-end:focus,.day.range-end:hover{background-color:var(--components-calendar-cell-background-selected) !important;color:var(--components-calendar-cell-text-selected) !important}.day.range-start,.day.range-end,.day.range-start.is-today,.day.range-end.is-today{background:var(--components-calendar-cell-background-selected);color:var(--components-calendar-cell-text-selected);position:relative;border-radius:var(--radius-rounded-full)}.day.range-start:hover,.day.range-end:hover,.day.range-start.is-today:hover,.day.range-end.is-today:hover{color:var(--components-calendar-cell-text-today)}.day.range-start:before,.day.range-end:before,.day.range-start.is-today:before,.day.range-end.is-today:before{content:\"\";position:absolute;bottom:0;left:0;right:0;top:0;z-index:-1;background-color:var(--components-calendar-cell-background-in-range);border-radius:var(--radius-rounded-full);width:auto;height:auto}.day.range-start:has(~.range-end):before,.day.range-start:has(+.in-range):before{border-top-right-radius:0;border-bottom-right-radius:0}.day.range-end:before{border-top-left-radius:0 !important;border-bottom-left-radius:0 !important}.day.outside-month.range-start,.day.outside-month.range-end{opacity:1 !important;background:var(--components-calendar-cell-background-selected) !important;color:var(--components-calendar-cell-text-selected)}.day.is-today{font-weight:700;position:relative;color:var(--components-calendar-cell-text-today)}.day.is-today.range-start,.day.is-today.range-end{color:var(--components-calendar-cell-text-selected)}.day.is-today.range-start:hover,.day.is-today.range-end:hover{color:var(--components-calendar-cell-text-today)}.day.is-today::after{content:\"\";position:absolute;bottom:var(--spacing-1);left:50%;transform:translateX(-50%);width:var(--calendar-cell-dot-size);height:var(--calendar-cell-dot-size);background-color:currentColor;border-radius:50%}.day.is-today.selected::after{color:var(--components-calendar-cell-text-selected)}.day.is-today.selected::after::after{background-color:var(--components-calendar-cell-dot-selected)}.calendar-footer{display:flex;gap:var(--spacing-1);justify-content:flex-start;width:100%;flex-wrap:wrap}.footer-placement-left{justify-content:flex-start}.footer-placement-right{justify-content:flex-end}.footer-placement-center{justify-content:center}.datepicker-controls{display:flex;flex-direction:column;border-top:1px solid var(--components-calendar-border);padding:var(--calendar-controls-padding-top) var(--calendar-padding) var(--calendar-padding);gap:var(--calendar-grid-gap-y);margin-top:var(--calendar-controls-margin-top)}.datepicker-actions{display:flex;justify-content:flex-end;gap:var(--spacing-1);width:100%}.datepicker-actions slot-fb{display:contents !important}.calendar-footer+.datepicker-actions{margin-top:0}.shortcuts-placement-left,.shortcuts-placement-right{display:flex;flex-direction:column;gap:var(--spacing-1);margin-top:var(--spacing-4)}.shortcuts-placement-left{align-items:flex-end}.shortcuts-placement-right{align-items:flex-start}@keyframes slideLeft{from{opacity:0;transform:translateX(20px)}to{opacity:1;transform:translateX(0)}}@keyframes slideRight{from{opacity:0;transform:translateX(-20px)}to{opacity:1;transform:translateX(0)}}@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes scaleIn{from{opacity:0;transform:scale(0.9)}to{opacity:1;transform:scale(1)}}";
239
417
  const NvCalendarStyle0 = nvCalendarCss;
240
418
 
241
419
  const NvCalendar = class {
@@ -243,18 +421,28 @@ const NvCalendar = class {
243
421
  index.registerInstance(this, hostRef);
244
422
  this.singleDateChange = index.createEvent(this, "singleDateChange");
245
423
  this.rangeDateChange = index.createEvent(this, "rangeDateChange");
424
+ this.valueChanged = index.createEvent(this, "valueChanged");
246
425
  /****************************************************************************/
247
426
  //#region PROPERTIES
248
427
  /**
249
428
  * First day of the week (0 = Sunday, 1 = Monday, etc.)
250
- * @default 0
429
+ * @default 1
251
430
  */
252
- this.firstDayOfWeek = 0;
431
+ this.firstDayOfWeek = 1;
253
432
  /**
254
433
  * Number of calendars to display
255
434
  * @default 1
256
435
  */
257
436
  this.numberOfCalendars = 1;
437
+ /**
438
+ * Selected date value. For single mode: ISO date string. For range mode: comma-separated ISO date strings.
439
+ * Examples:
440
+ * - Single: "2025-03-15"
441
+ * - Range: "2025-03-15,2025-03-20"
442
+ * @default ""
443
+ */
444
+ // eslint-disable-next-line @stencil-community/strict-mutable
445
+ this.value = '';
258
446
  /**
259
447
  * Locale for date formatting
260
448
  * @default 'en-BE'
@@ -292,6 +480,75 @@ const NvCalendar = class {
292
480
  this.endDate = null;
293
481
  /** List of formatted months for the selector */
294
482
  this.months = [];
483
+ /**
484
+ * Parses the unified value prop and synchronizes with internal state
485
+ * @param {string} value - Value to parse
486
+ */
487
+ this.parseUnifiedValue = (value) => {
488
+ if (!value) {
489
+ // Reset all selections
490
+ this.selectedDate = null;
491
+ this.startDate = null;
492
+ this.endDate = null;
493
+ return;
494
+ }
495
+ const values = value
496
+ .split(',')
497
+ .map(v => v.trim())
498
+ .filter(Boolean);
499
+ if (this.selectionType === 'single' && values.length >= 1) {
500
+ const parsedDate = parseDate(values[0], this.dateFormat);
501
+ if (parsedDate) {
502
+ this.selectedDate = parsedDate;
503
+ // Only sync with legacy prop if not using actions (immediate mode)
504
+ if (!this.showActions) {
505
+ this.singleValue = values[0];
506
+ }
507
+ // Navigate to the date if not prevented
508
+ const preventNavigation = this.el.getAttribute('data-prevent-navigation') === 'true';
509
+ if (!preventNavigation) {
510
+ this.currentDate = parsedDate;
511
+ }
512
+ }
513
+ else {
514
+ // Handle malformed date gracefully - reset state
515
+ console.warn(`Invalid date format: ${values[0]}`);
516
+ this.selectedDate = null;
517
+ if (!this.showActions) {
518
+ this.singleValue = '';
519
+ }
520
+ }
521
+ }
522
+ else if (this.selectionType === 'range' && values.length >= 2) {
523
+ const startDate = parseDate(values[0], this.dateFormat);
524
+ const endDate = parseDate(values[1], this.dateFormat);
525
+ if (startDate && endDate) {
526
+ this.startDate = startDate;
527
+ this.endDate = endDate;
528
+ // Only sync with legacy prop if not using actions (immediate mode)
529
+ if (!this.showActions) {
530
+ this.rangeValue = {
531
+ start: values[0],
532
+ end: values[1],
533
+ };
534
+ }
535
+ // Navigate to start date if not prevented
536
+ const preventNavigation = this.el.getAttribute('data-prevent-navigation') === 'true';
537
+ if (!preventNavigation) {
538
+ this.currentDate = startDate;
539
+ }
540
+ }
541
+ else {
542
+ // Handle malformed dates gracefully - reset state
543
+ console.warn(`Invalid date range format: ${values[0]}, ${values[1]}`);
544
+ this.startDate = null;
545
+ this.endDate = null;
546
+ if (!this.showActions) {
547
+ this.rangeValue = { start: '', end: '' };
548
+ }
549
+ }
550
+ }
551
+ };
295
552
  /**
296
553
  * Change the displayed month
297
554
  * @param {number} offset - Month offset (-1 for previous, 1 for next)
@@ -339,7 +596,14 @@ const NvCalendar = class {
339
596
  return;
340
597
  const formattedDate = formatDate(date, { dateFormat: this.dateFormat });
341
598
  this.selectedDate = date;
342
- this.singleDateChange.emit(formattedDate);
599
+ // Update the unified value prop (like nv-fieldslider)
600
+ this.value = formattedDate;
601
+ this.valueChanged.emit(formattedDate);
602
+ // Legacy support (deprecated) - only sync props if not using actions
603
+ if (!this.showActions) {
604
+ this.singleValue = formattedDate;
605
+ this.singleDateChange.emit(formattedDate);
606
+ }
343
607
  };
344
608
  /**
345
609
  * Handles range date selection
@@ -347,18 +611,32 @@ const NvCalendar = class {
347
611
  */
348
612
  this.handleRangeSelection = (date) => {
349
613
  if (!this.startDate || (this.startDate && this.endDate)) {
614
+ // Start new range selection
350
615
  this.startDate = date;
351
616
  this.endDate = null;
352
617
  }
353
618
  else {
619
+ // Complete range selection
354
620
  this.endDate = date;
621
+ // Ensure correct order
355
622
  if (this.startDate > this.endDate) {
356
623
  [this.startDate, this.endDate] = [this.endDate, this.startDate];
357
624
  }
358
- this.rangeDateChange.emit({
359
- start: formatDate(this.startDate, { dateFormat: this.dateFormat }),
360
- end: formatDate(this.endDate, { dateFormat: this.dateFormat }),
625
+ const startFormatted = formatDate(this.startDate, {
626
+ dateFormat: this.dateFormat,
627
+ });
628
+ const endFormatted = formatDate(this.endDate, {
629
+ dateFormat: this.dateFormat,
361
630
  });
631
+ // Update the unified value prop (like nv-fieldslider)
632
+ this.value = `${startFormatted},${endFormatted}`;
633
+ this.valueChanged.emit(this.value);
634
+ // Legacy support (deprecated) - only sync props if not using actions
635
+ if (!this.showActions) {
636
+ const legacyRange = { start: startFormatted, end: endFormatted };
637
+ this.rangeDateChange.emit(legacyRange);
638
+ this.rangeValue = legacyRange;
639
+ }
362
640
  }
363
641
  };
364
642
  /**
@@ -417,23 +695,35 @@ const NvCalendar = class {
417
695
  * @returns {string[]} Array of short day names
418
696
  */
419
697
  this.getDayNames = () => {
698
+ let days;
420
699
  // If we have custom day names for this locale
421
- if (constantsB97e736d.CUSTOM_DAY_NAMES[this.locale]) {
422
- const days = [...constantsB97e736d.CUSTOM_DAY_NAMES[this.locale]];
423
- // Reorganize the days based on the first day of the week
424
- const firstDays = days.slice(0, this.firstDayOfWeek);
425
- const remainingDays = days.slice(this.firstDayOfWeek);
426
- return [...remainingDays, ...firstDays];
700
+ if (constants4faa1fae.CUSTOM_DAY_NAMES[this.locale]) {
701
+ // Custom day names are expected to start with Monday (index 0 = Monday)
702
+ days = [...constants4faa1fae.CUSTOM_DAY_NAMES[this.locale]];
703
+ }
704
+ else {
705
+ // Generate days using Intl.DateTimeFormat, starting from Monday
706
+ const formatter = new Intl.DateTimeFormat(this.locale, {
707
+ weekday: 'short',
708
+ });
709
+ // Generate days starting from Monday (2023-01-02 was a Monday)
710
+ days = [...Array(7)].map((_, i) => formatter.format(new Date(2023, 0, i + 2)).toUpperCase());
711
+ }
712
+ // Now reorganize based on firstDayOfWeek
713
+ // 0 = Sunday, 1 = Monday (default), 2 = Tuesday, etc.
714
+ if (this.firstDayOfWeek === 0) {
715
+ // If Sunday is first day, move Sunday (last element) to the beginning
716
+ return [days[6], ...days.slice(0, 6)];
717
+ }
718
+ else if (this.firstDayOfWeek === 1) {
719
+ // If Monday is first day, return as-is (since our array starts with Monday)
720
+ return days;
721
+ }
722
+ else {
723
+ // For other first days (Tuesday=2, Wednesday=3, etc.)
724
+ const offset = this.firstDayOfWeek - 1; // Convert to 0-based offset from Monday
725
+ return [...days.slice(offset), ...days.slice(0, offset)];
427
726
  }
428
- // Otherwise, use the default behavior
429
- const formatter = new Intl.DateTimeFormat(this.locale, {
430
- weekday: 'short',
431
- });
432
- const days = [...Array(7)].map((_, i) => formatter.format(new Date(2023, 0, i + 1)).toUpperCase());
433
- // Reorganize the days based on the first day of the week
434
- const firstDays = days.slice(0, this.firstDayOfWeek);
435
- const remainingDays = days.slice(this.firstDayOfWeek);
436
- return [...remainingDays, ...firstDays];
437
727
  };
438
728
  /**
439
729
  * Generates the days of the current month
@@ -493,8 +783,8 @@ const NvCalendar = class {
493
783
  /** Initializes the list of formatted months according to the locale */
494
784
  this.initializeMonths = () => {
495
785
  // If we have custom month names for this locale
496
- if (constantsB97e736d.CUSTOM_MONTH_NAMES[this.locale]) {
497
- this.months = constantsB97e736d.CUSTOM_MONTH_NAMES[this.locale].map((label, value) => ({
786
+ if (constants4faa1fae.CUSTOM_MONTH_NAMES[this.locale]) {
787
+ this.months = constants4faa1fae.CUSTOM_MONTH_NAMES[this.locale].map((label, value) => ({
498
788
  value,
499
789
  label,
500
790
  }));
@@ -512,7 +802,7 @@ const NvCalendar = class {
512
802
  * @returns {string} Localized abbreviation for "week"
513
803
  */
514
804
  this.getLocalizedWeekText = () => {
515
- return constantsB97e736d.WEEK_ABBREVIATIONS[this.locale] || 'W';
805
+ return constants4faa1fae.WEEK_ABBREVIATIONS[this.locale] || 'W';
516
806
  };
517
807
  /**
518
808
  * Handles month change in the selector
@@ -614,8 +904,15 @@ const NvCalendar = class {
614
904
  if (shortcut.singleValue) {
615
905
  const newDate = parseDate(shortcut.singleValue, this.dateFormat);
616
906
  this.selectedDate = newDate;
617
- this.singleDateChange.emit(formatDate(newDate, { dateFormat: this.dateFormat }));
618
- this.singleValue = formatDate(newDate, { dateFormat: this.dateFormat });
907
+ const formattedDate = formatDate(newDate, {
908
+ dateFormat: this.dateFormat,
909
+ });
910
+ // Update the unified value prop (like nv-fieldslider)
911
+ this.value = formattedDate;
912
+ this.valueChanged.emit(formattedDate);
913
+ // Legacy support (deprecated) - sync props
914
+ this.singleValue = formattedDate;
915
+ this.singleDateChange.emit(formattedDate);
619
916
  if (!this.showActions) {
620
917
  const event = new CustomEvent('closePopover', {
621
918
  bubbles: true,
@@ -630,14 +927,18 @@ const NvCalendar = class {
630
927
  const end = parseDate(shortcut.rangeValue.end, this.dateFormat);
631
928
  this.startDate = start;
632
929
  this.endDate = end;
633
- this.rangeDateChange.emit({
634
- start: formatDate(start, { dateFormat: this.dateFormat }),
635
- end: formatDate(end, { dateFormat: this.dateFormat }),
930
+ const startFormatted = formatDate(start, {
931
+ dateFormat: this.dateFormat,
636
932
  });
637
- this.rangeValue = {
638
- start: formatDate(start, { dateFormat: this.dateFormat }),
639
- end: formatDate(end, { dateFormat: this.dateFormat }),
640
- };
933
+ const endFormatted = formatDate(end, { dateFormat: this.dateFormat });
934
+ // Update the unified value prop (like nv-fieldslider)
935
+ this.value = `${startFormatted},${endFormatted}`;
936
+ this.valueChanged.emit(this.value);
937
+ // Legacy support (deprecated) - sync props
938
+ const legacyRange = { start: startFormatted, end: endFormatted };
939
+ this.rangeDateChange.emit(legacyRange);
940
+ // eslint-disable-next-line @stencil-community/strict-mutable
941
+ this.rangeValue = legacyRange;
641
942
  if (!this.showActions) {
642
943
  const event = new CustomEvent('closePopover', {
643
944
  bubbles: true,
@@ -645,103 +946,15 @@ const NvCalendar = class {
645
946
  });
646
947
  this.el.dispatchEvent(event);
647
948
  }
648
- this.forceCalendarUpdate(end);
949
+ this.currentDate = start;
649
950
  }
650
951
  };
651
952
  /**
652
- * Method to force the complete calendar update (and fix the persistent hover problem)
953
+ * Method to force the complete calendar update
653
954
  * @param {Date} newDate - Date to force
654
955
  */
655
956
  this.forceCalendarUpdate = newDate => {
656
957
  this.currentDate = new Date(newDate);
657
- this.currentDate = new Date(this.currentDate); // Force a re-render
658
- // Reset visually the hover/touch effect
659
- requestAnimationFrame(() => {
660
- const days = document.querySelectorAll('.day');
661
- days.forEach(el => {
662
- el.classList.remove('hover', 'active', 'touched');
663
- el.style.pointerEvents = 'none';
664
- });
665
- // Add specific touch handling (for mobile)
666
- document.body.addEventListener('touchstart', this.clearTouchState, {
667
- passive: true,
668
- });
669
- // Reset the touch state after 50ms
670
- setTimeout(() => {
671
- days.forEach(el => {
672
- el.style.pointerEvents = '';
673
- });
674
- }, 50);
675
- });
676
- };
677
- /**
678
- * Function to reset the touch effect (Mobile fix)
679
- */
680
- this.clearTouchState = () => {
681
- document.querySelectorAll('.day').forEach(el => {
682
- el.classList.remove('touched');
683
- });
684
- // Remove the listener after the first interaction
685
- document.body.removeEventListener('touchstart', this.clearTouchState);
686
- };
687
- /**
688
- * Handles month change with an offset
689
- * @param {number} direction - Direction (-1 for previous, 1 for next)
690
- * @returns {Function} Change month handler
691
- */
692
- this.getChangeMonthHandler = (direction) => {
693
- return () => this.changeMonth(direction);
694
- };
695
- /**
696
- * Handles month change from an event (ex: dropdown)
697
- * @param {number} offset - Month offset (0 by default)
698
- * @returns {Function} Change month handler
699
- */
700
- this.getHandleMonthChange = (offset) => {
701
- return (event) => this.handleMonthChange(event, offset);
702
- };
703
- /**
704
- * Handles year change from an event (ex: dropdown)
705
- * @param {number} offset - Year offset (0 by default)
706
- * @returns {Function} Change year handler
707
- */
708
- this.getHandleYearChange = (offset) => {
709
- return (event) => this.handleYearChange(event, offset);
710
- };
711
- /**
712
- * Handles day click
713
- * @param {Date} date - Date to handle
714
- * @param {boolean} isDisabled - Whether the date is disabled
715
- * @returns {Function} Day click handler
716
- */
717
- this.getDayClickHandler = (date, isDisabled) => {
718
- return isDisabled ? undefined : () => this.handleDateSelection(date);
719
- };
720
- /**
721
- * Handles shortcut selection
722
- * @param {Object} shortcut - Shortcut to handle
723
- * @param {string | Date} shortcut.singleValue - Selected date value
724
- * @param {Object} shortcut.rangeValue - Start and end date values
725
- * @param {string | Date} shortcut.rangeValue.start - Start date value
726
- * @param {string | Date} shortcut.rangeValue.end - End date value
727
- * @param {string} shortcut.label - Label
728
- * @returns {Function} Shortcut selection handler
729
- */
730
- this.getShortcutHandler = (shortcut) => {
731
- return () => this.applyShortcut(shortcut);
732
- };
733
- /**
734
- * Handles week selection
735
- * @param {Date[]} dates - Dates to handle
736
- * @param {number} index - Calendar index
737
- * @returns {Function} Week selection handler
738
- */
739
- this.getWeekSelectionHandler = (dates, index) => {
740
- return () => {
741
- if (this.selectionType === 'range') {
742
- this.handleWeekSelection(dates, index);
743
- }
744
- };
745
958
  };
746
959
  /**
747
960
  * Resets the current selection
@@ -749,14 +962,22 @@ const NvCalendar = class {
749
962
  this.resetSelection = () => {
750
963
  if (this.selectionType === 'single') {
751
964
  this.selectedDate = null;
965
+ // eslint-disable-next-line @stencil-community/strict-mutable
752
966
  this.singleValue = null;
967
+ // eslint-disable-next-line @stencil-community/strict-mutable
968
+ this.value = '';
753
969
  this.singleDateChange.emit('');
970
+ this.valueChanged.emit('');
754
971
  }
755
972
  else {
756
973
  this.startDate = null;
757
974
  this.endDate = null;
975
+ // eslint-disable-next-line @stencil-community/strict-mutable
758
976
  this.rangeValue = null;
977
+ // eslint-disable-next-line @stencil-community/strict-mutable
978
+ this.value = '';
759
979
  this.rangeDateChange.emit({ start: '', end: '' });
980
+ this.valueChanged.emit('');
760
981
  }
761
982
  };
762
983
  /**
@@ -768,6 +989,7 @@ const NvCalendar = class {
768
989
  dateFormat: this.dateFormat,
769
990
  });
770
991
  this.singleDateChange.emit(dateStr);
992
+ // eslint-disable-next-line @stencil-community/strict-mutable
771
993
  this.singleValue = dateStr;
772
994
  const event = new CustomEvent('closePopover', {
773
995
  bubbles: true,
@@ -782,6 +1004,7 @@ const NvCalendar = class {
782
1004
  start: formatDate(this.startDate, { dateFormat: this.dateFormat }),
783
1005
  end: formatDate(this.endDate, { dateFormat: this.dateFormat }),
784
1006
  });
1007
+ // eslint-disable-next-line @stencil-community/strict-mutable
785
1008
  this.rangeValue = {
786
1009
  start: formatDate(this.startDate, { dateFormat: this.dateFormat }),
787
1010
  end: formatDate(this.endDate, { dateFormat: this.dateFormat }),
@@ -804,8 +1027,7 @@ const NvCalendar = class {
804
1027
  * @description Renders the header of the calendar
805
1028
  */
806
1029
  this.renderHeader = (offset, index$1) => {
807
- return (index.h("div", { class: "header" }, this.numberOfCalendars > 1 && index$1 === 0 && (index.h("nv-iconbutton", { class: "nav-left", emphasis: "lower", name: "chevron-left", onClick: this.getChangeMonthHandler(-1) })), index.h("div", { class: "date-controls" }, index.h("select", { class: "month-select mr-4", onChange: this.getHandleMonthChange(offset) }, this.months.map(month => (index.h("option", { key: month.value, value: month.value, selected: month.value === (this.currentDate.getUTCMonth() + offset) % 12 }, month.label)))), index.h("input", { type: "number", class: "year-input", min: "1950", max: "2100", value: this.currentDate.getUTCFullYear() +
808
- Math.floor((this.currentDate.getUTCMonth() + offset) / 12), onChange: this.getHandleYearChange(offset) })), this.numberOfCalendars === 1 && (index.h("div", { class: "nav-buttons" }, index.h("nv-iconbutton", { emphasis: "lower", name: "chevron-left", onClick: this.getChangeMonthHandler(-1) }), index.h("nv-iconbutton", { emphasis: "lower", name: "chevron-right", onClick: this.getChangeMonthHandler(1) }))), this.numberOfCalendars > 1 && index$1 === this.numberOfCalendars - 1 && (index.h("nv-iconbutton", { emphasis: "lower", name: "chevron-right", onClick: this.getChangeMonthHandler(1), class: "nav-right" }))));
1030
+ return (index.h(CalendarHeader, { currentDate: this.currentDate, months: this.months, numberOfCalendars: this.numberOfCalendars, calendarIndex: index$1, monthOffset: offset, onMonthChange: this.changeMonth, onMonthSelect: this.handleMonthChange, onYearChange: this.handleYearChange }));
809
1031
  };
810
1032
  /**
811
1033
  * Renders the week numbers
@@ -819,42 +1041,7 @@ const NvCalendar = class {
819
1041
  weeks,
820
1042
  /** Calendar index */
821
1043
  index$1) => {
822
- return (index.h("div", { class: "week-numbers" }, index.h("div", { class: "week-header" }, this.getLocalizedWeekText()), weeks.map((week, weekIndex) => {
823
- var _a;
824
- const dates = week.map(d => d.date);
825
- return (index.h("div", { class: `week-number ${this.selectionType === 'range' ? 'clickable' : ''}`, onClick: this.getWeekSelectionHandler(dates, index$1), key: `week-${weekIndex}` }, getWeekNumber(((_a = week.find(d => d.date)) === null || _a === void 0 ? void 0 : _a.date) || new Date())));
826
- })));
827
- };
828
- this.renderDaysGrid = (
829
- /** Days to render */
830
- days) => {
831
- return (index.h("div", { class: "days-grid" }, days.map(day => {
832
- const date = day.date;
833
- if (!date)
834
- return null;
835
- const isSelected = this.selectionType === 'single' &&
836
- isSameDate(date, this.selectedDate, { isUTCMode: this.isUTCMode });
837
- const isInRange = this.isDateInRange(date);
838
- const isStart = isSameDate(date, this.startDate, {
839
- isUTCMode: this.isUTCMode,
840
- });
841
- const isEnd = isSameDate(date, this.endDate, {
842
- isUTCMode: this.isUTCMode,
843
- });
844
- const isToday = this.isToday(date);
845
- const isOutsideMonth = !day.isCurrentMonth;
846
- const dayClasses = [
847
- 'day',
848
- isSelected ? 'selected' : '',
849
- isStart ? 'range-start' : '',
850
- isEnd ? 'range-end' : '',
851
- isInRange ? 'in-range' : '',
852
- day.isDisabled ? 'disabled' : '',
853
- isOutsideMonth ? 'outside-month' : '',
854
- isToday ? 'is-today' : '',
855
- ];
856
- return (index.h("div", { class: dayClasses.filter(Boolean).join(' '), onClick: this.getDayClickHandler(date, day.isDisabled), "aria-disabled": day.isDisabled, key: `day-${date.toISOString()}` }, day.dayOfMonth));
857
- })));
1044
+ return (index.h(WeekNumbers, { weeks: weeks, localizedWeekText: this.getLocalizedWeekText(), selectionType: this.selectionType, onWeekSelect: this.handleWeekSelection, calendarIndex: index$1 }));
858
1045
  };
859
1046
  /**
860
1047
  * Renders the calendar
@@ -873,7 +1060,7 @@ const NvCalendar = class {
873
1060
  for (let i = 0; i < days.length; i += 7) {
874
1061
  weeks.push(days.slice(i, i + 7));
875
1062
  }
876
- return (index.h("div", { class: "calendar-wrapper" }, index.h("div", { class: "calendar-container", key: `calendar-${index$1}` }, this.renderHeader(offset, index$1), index.h("div", { class: "calendar-grid" }, this.showWeekNumbers && this.renderWeekNumbers(weeks, index$1), index.h("div", { class: "days-container" }, index.h("div", { class: "days-header" }, this.getDayNames().map(day => (index.h("div", { class: "day-header" }, day)))), this.renderDaysGrid(days)))), index$1 < this.numberOfCalendars - 1 && (index.h("div", { class: "calendar-separator" }))));
1063
+ return (index.h("div", { class: "calendar-wrapper" }, index.h("div", { class: "calendar-container", key: `calendar-${index$1}` }, this.renderHeader(offset, index$1), index.h("div", { class: "calendar-grid" }, this.showWeekNumbers && this.renderWeekNumbers(weeks, index$1), index.h(CalendarGrid, { days: days, dayNames: this.getDayNames(), selectionType: this.selectionType, selectedDate: this.selectedDate, startDate: this.startDate, endDate: this.endDate, isUTCMode: this.isUTCMode, onDayClick: this.handleDateSelection, isDateInRange: this.isDateInRange, isToday: this.isToday }))), index$1 < this.numberOfCalendars - 1 && (index.h("div", { class: "calendar-separator" }))));
877
1064
  };
878
1065
  /**
879
1066
  * Renders the shortcuts
@@ -884,7 +1071,7 @@ const NvCalendar = class {
884
1071
  if (!this.hasShortcuts) {
885
1072
  return null;
886
1073
  }
887
- return (index.h("div", { class: `shortcuts-container shortcuts-placement-${this.shortcutsPlacement}` }, this.shortcuts.map(shortcut => (index.h("nv-button", { emphasis: "lower", size: "xs", "aria-label": shortcut.label, onClick: this.getShortcutHandler(shortcut) }, shortcut.label)))));
1074
+ return (index.h(CalendarShortcuts, { shortcuts: this.shortcuts, placement: this.shortcutsPlacement, onShortcutClick: this.applyShortcut }));
888
1075
  };
889
1076
  /**
890
1077
  * Renders the actions
@@ -893,7 +1080,7 @@ const NvCalendar = class {
893
1080
  * @slot actions - Child content of the component.
894
1081
  */
895
1082
  this.renderActions = () => {
896
- return (index.h("div", { class: "datepicker-actions" }, index.h("slot", { name: "actions" }, index.h("nv-button", { emphasis: "low", size: "xs", onClick: this.resetSelection }, "Cancel"), index.h("nv-button", { size: "xs", onClick: this.confirmSelection }, "OK"))));
1083
+ return (index.h("div", { class: "datepicker-actions" }, index.h("slot", { name: "actions" }, index.h(CalendarActions, { onReset: this.resetSelection, onConfirm: this.confirmSelection, useSlot: false }))));
897
1084
  };
898
1085
  }
899
1086
  //#endregion EVENTS
@@ -921,7 +1108,11 @@ const NvCalendar = class {
921
1108
  const { startDate, endDate } = this.validateDateRange(newValue.start, newValue.end);
922
1109
  this.startDate = startDate;
923
1110
  this.endDate = endDate;
924
- this.currentDate = startDate;
1111
+ // Do not navigate to the start date if data-prevent-navigation attribute is present
1112
+ const preventNavigation = this.el.getAttribute('data-prevent-navigation') === 'true';
1113
+ if (!preventNavigation) {
1114
+ this.currentDate = startDate;
1115
+ }
925
1116
  }
926
1117
  catch (error) {
927
1118
  console.error('Invalid rangeValue:', error);
@@ -945,16 +1136,34 @@ const NvCalendar = class {
945
1136
  const parsedDate = parseDate(newValue, this.dateFormat);
946
1137
  if (parsedDate) {
947
1138
  this.selectedDate = parsedDate;
948
- this.currentDate = parsedDate;
1139
+ // Do not navigate to the selected date if data-prevent-navigation attribute is present
1140
+ const preventNavigation = this.el.getAttribute('data-prevent-navigation') === 'true';
1141
+ if (!preventNavigation) {
1142
+ this.currentDate = parsedDate;
1143
+ }
949
1144
  }
950
1145
  }
951
1146
  }
1147
+ /**
1148
+ * Watches the changes of the unified value prop
1149
+ * @param {string} newValue - New value
1150
+ * @param {string} oldValue - Old value
1151
+ */
1152
+ onValueChange(newValue, oldValue) {
1153
+ if (newValue !== oldValue) {
1154
+ this.parseUnifiedValue(newValue);
1155
+ }
1156
+ }
952
1157
  //#endregion WATCHERS
953
1158
  /****************************************************************************/
954
1159
  //#region LIFECYCLE
955
1160
  componentWillLoad() {
956
1161
  this.parseDisabledDates();
957
- if (this.selectionType === 'single' && this.singleValue) {
1162
+ // Initialize from unified value prop if provided
1163
+ if (this.value) {
1164
+ this.parseUnifiedValue(this.value);
1165
+ }
1166
+ else if (this.selectionType === 'single' && this.singleValue) {
958
1167
  this.selectedDate = parseDate(this.singleValue, this.dateFormat);
959
1168
  this.currentDate = this.selectedDate;
960
1169
  }
@@ -967,6 +1176,7 @@ const NvCalendar = class {
967
1176
  this.currentDate = startDate;
968
1177
  if (swapped) {
969
1178
  // If dates were swapped, update the rangeValue property
1179
+ // eslint-disable-next-line @stencil-community/strict-mutable
970
1180
  this.rangeValue = {
971
1181
  start: formatDate(startDate, { dateFormat: this.dateFormat }),
972
1182
  end: formatDate(endDate, { dateFormat: this.dateFormat }),
@@ -978,7 +1188,8 @@ const NvCalendar = class {
978
1188
  console.error('Invalid rangeValue:', error);
979
1189
  }
980
1190
  }
981
- else {
1191
+ // Ensure currentDate is always initialized
1192
+ if (!this.currentDate) {
982
1193
  this.currentDate = new Date();
983
1194
  }
984
1195
  this.initializeMonths();
@@ -1048,15 +1259,16 @@ const NvCalendar = class {
1048
1259
  * @slot default - Child content of the component.
1049
1260
  */
1050
1261
  render() {
1051
- return (index.h(index.Host, { key: 'd265f105851253b5aa2a40e055f8e51b5cb6b553' }, index.h("div", { key: 'c6e1ea923b17f7684243598109e4cffc767248d7', class: "datepicker-root" }, index.h("div", { key: '5fc4cfbf3f6d823c500408d0f81f5f15d3e654d7', class: `datepicker-container ${this.numberOfCalendars === 1 ? 'datepicker-container-single' : ''}` }, index.h("div", { key: '035dac25c8b8090e1a3a0ac2493865907f665da9', class: `datepicker-wrapper ${this.numberOfCalendars === 1 ? 'single' : ''}` }, this.shortcutsPlacement === 'left' && this.renderShortcuts(), Array.from({ length: this.numberOfCalendars }, (_, index) => this.renderCalendar(index, index)), this.shortcutsPlacement === 'right' && this.renderShortcuts()), ((this.hasShortcuts && this.shortcutsPlacement === 'bottom') ||
1052
- this.hasActions) && (index.h("div", { key: '91c21c945ab53acda631a8c50fb1437665fce030', class: "datepicker-controls" }, this.shortcutsPlacement === 'bottom' && this.renderShortcuts(), this.hasActions && this.renderActions())))), index.h("slot", { key: '3799c412c842e406715c235d3288022c2a734ed2' })));
1262
+ return (index.h(index.Host, { key: '43d4f3ab9199e9c5f15e853f15283fa59e4a436d' }, index.h("div", { key: 'b9956225cb2c16d997aa44266af8f8c8222ea968', class: "datepicker-root" }, index.h("div", { key: '05b63935bc5ebf500bb52d10688385f994b47fb4', class: `datepicker-container ${this.numberOfCalendars === 1 ? 'datepicker-container-single' : ''}` }, index.h("div", { key: 'd7af15b9ce051026cf841b3be361b32d8db41fc1', class: `datepicker-wrapper ${this.numberOfCalendars === 1 ? 'single' : ''}` }, this.shortcutsPlacement === 'left' && this.renderShortcuts(), Array.from({ length: this.numberOfCalendars }, (_, index) => this.renderCalendar(index, index)), this.shortcutsPlacement === 'right' && this.renderShortcuts()), ((this.hasShortcuts && this.shortcutsPlacement === 'bottom') ||
1263
+ this.hasActions) && (index.h("div", { key: '1765334bf15564bc9886b210c54bddba64c7042e', class: "datepicker-controls" }, this.shortcutsPlacement === 'bottom' && this.renderShortcuts(), this.hasActions && this.renderActions())))), index.h("slot", { key: '0ac3446394b8c23b859e5f0065370b95b6fd05d2' })));
1053
1264
  }
1054
1265
  get el() { return index.getElement(this); }
1055
1266
  static get watchers() { return {
1056
1267
  "numberOfCalendars": ["validateNumberOfCalendars"],
1057
1268
  "rangeValue": ["onRangeValueChange"],
1058
1269
  "disabledDates": ["handleDisabledDatesChange"],
1059
- "singleValue": ["onSingleValueChange"]
1270
+ "singleValue": ["onSingleValueChange"],
1271
+ "value": ["onValueChange"]
1060
1272
  }; }
1061
1273
  };
1062
1274
  NvCalendar.style = NvCalendarStyle0;