@radix-ng/primitives 0.33.1 → 0.34.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 (35) hide show
  1. package/calendar/README.md +1 -0
  2. package/calendar/index.d.ts +30 -0
  3. package/calendar/src/calendar-cell-trigger.directive.d.ts +54 -0
  4. package/calendar/src/calendar-cell.directive.d.ts +11 -0
  5. package/calendar/src/calendar-grid-body.directive.d.ts +5 -0
  6. package/calendar/src/calendar-grid-head.directive.d.ts +5 -0
  7. package/calendar/src/calendar-grid-row.directive.d.ts +5 -0
  8. package/calendar/src/calendar-grid.directive.d.ts +8 -0
  9. package/calendar/src/calendar-head-cell.directive.d.ts +5 -0
  10. package/calendar/src/calendar-header.directive.d.ts +5 -0
  11. package/calendar/src/calendar-heading.directive.d.ts +7 -0
  12. package/calendar/src/calendar-next.directive.d.ts +16 -0
  13. package/calendar/src/calendar-prev.directive.d.ts +16 -0
  14. package/calendar/src/calendar-root.directive.d.ts +148 -0
  15. package/calendar/src/calendar.d.ts +44 -0
  16. package/calendar/src//321/201alendar-/321/201ontext.token.d.ts +24 -0
  17. package/core/index.d.ts +2 -0
  18. package/core/src/chunk.d.ts +12 -0
  19. package/core/src/date-time/calendar.d.ts +33 -0
  20. package/core/src/date-time/comparators.d.ts +92 -0
  21. package/core/src/date-time/formatter.d.ts +30 -0
  22. package/core/src/date-time/index.d.ts +6 -0
  23. package/core/src/date-time/placeholders.d.ts +8 -0
  24. package/core/src/date-time/types.d.ts +28 -0
  25. package/core/src/date-time/utils.d.ts +1 -0
  26. package/core/src/kbd-constants.d.ts +1 -0
  27. package/core/src/watch.d.ts +41 -0
  28. package/fesm2022/radix-ng-primitives-calendar.mjs +941 -0
  29. package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -0
  30. package/fesm2022/radix-ng-primitives-core.mjs +544 -2
  31. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  32. package/hover-card/src/hover-card-root.directive.d.ts +4 -4
  33. package/package.json +5 -1
  34. package/popover/src/popover-root.directive.d.ts +4 -4
  35. package/tooltip/src/tooltip-root.directive.d.ts +4 -4
@@ -1,8 +1,9 @@
1
1
  import { NG_VALUE_ACCESSOR, NgControl, FormControlDirective, FormControlName, NgModel } from '@angular/forms';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, ElementRef, NgZone, booleanAttribute, Input, Directive, APP_ID, Injectable, InjectionToken } from '@angular/core';
3
+ import { inject, ElementRef, NgZone, booleanAttribute, Input, Directive, APP_ID, Injectable, InjectionToken, effect, untracked } from '@angular/core';
4
4
  import { DOCUMENT } from '@angular/common';
5
5
  import { Platform } from '@angular/cdk/platform';
6
+ import { getLocalTimeZone, CalendarDateTime, ZonedDateTime, getDayOfWeek, DateFormatter, createCalendar, toCalendar, CalendarDate, startOfMonth, endOfMonth, today } from '@internationalized/date';
6
7
 
7
8
  /**
8
9
  * Include in the providers section of a component which utilizes ControlValueAccessor to redundant code.
@@ -236,6 +237,7 @@ const p = 'p';
236
237
  const n = 'n';
237
238
  const j = 'j';
238
239
  const k = 'k';
240
+ const SPACE_CODE = 'Space';
239
241
 
240
242
  const WINDOW = new InjectionToken('An abstraction over global window object', {
241
243
  factory: () => {
@@ -250,6 +252,509 @@ function injectWindow() {
250
252
  return inject(WINDOW);
251
253
  }
252
254
 
255
+ /**
256
+ * Splits an array into chunks of a given size.
257
+ * @param arr The array to split.
258
+ * @param size The size of each chunk.
259
+ * @returns An array of arrays, where each sub-array has `size` elements from the original array.
260
+ * @example ```ts
261
+ * const arr = [1, 2, 3, 4, 5, 6, 7, 8];
262
+ * const chunks = chunk(arr, 3);
263
+ * // chunks = [[1, 2, 3], [4, 5, 6], [7, 8]]
264
+ * ```
265
+ */
266
+ function chunk(arr, size) {
267
+ const result = [];
268
+ for (let i = 0; i < arr.length; i += size)
269
+ result.push(arr.slice(i, i + size));
270
+ return result;
271
+ }
272
+
273
+ /**
274
+ * Given a `DateValue` object, convert it to a native `Date` object.
275
+ * If a timezone is provided, the date will be converted to that timezone.
276
+ * If no timezone is provided, the date will be converted to the local timezone.
277
+ */
278
+ function toDate(dateValue, tz = getLocalTimeZone()) {
279
+ if (isZonedDateTime(dateValue))
280
+ return dateValue.toDate();
281
+ else
282
+ return dateValue.toDate(tz);
283
+ }
284
+ function isCalendarDateTime(dateValue) {
285
+ return dateValue instanceof CalendarDateTime;
286
+ }
287
+ function isZonedDateTime(dateValue) {
288
+ return dateValue instanceof ZonedDateTime;
289
+ }
290
+ function hasTime(dateValue) {
291
+ return isCalendarDateTime(dateValue) || isZonedDateTime(dateValue);
292
+ }
293
+ /**
294
+ * Given a date, return the number of days in the month.
295
+ */
296
+ function getDaysInMonth(date) {
297
+ if (date instanceof Date) {
298
+ const year = date.getFullYear();
299
+ const month = date.getMonth() + 1;
300
+ /**
301
+ * By using zero as the day, we get the
302
+ * last day of the previous month, which
303
+ * is the month we originally passed in.
304
+ */
305
+ return new Date(year, month, 0).getDate();
306
+ }
307
+ else {
308
+ return date.set({ day: 100 }).day;
309
+ }
310
+ }
311
+ /**
312
+ * Determine if a date is before the reference date.
313
+ * @param dateToCompare - is this date before the `referenceDate`
314
+ * @param referenceDate - is the `dateToCompare` before this date
315
+ *
316
+ * @see {@link isBeforeOrSame} for inclusive
317
+ */
318
+ function isBefore(dateToCompare, referenceDate) {
319
+ return dateToCompare.compare(referenceDate) < 0;
320
+ }
321
+ /**
322
+ * Determine if a date is after the reference date.
323
+ * @param dateToCompare - is this date after the `referenceDate`
324
+ * @param referenceDate - is the `dateToCompare` after this date
325
+ *
326
+ * @see {@link isAfterOrSame} for inclusive
327
+ */
328
+ function isAfter(dateToCompare, referenceDate) {
329
+ return dateToCompare.compare(referenceDate) > 0;
330
+ }
331
+ /**
332
+ * Determine if a date is before or the same as the reference date.
333
+ *
334
+ * @param dateToCompare - the date to compare
335
+ * @param referenceDate - the reference date to make the comparison against
336
+ *
337
+ * @see {@link isBefore} for non-inclusive
338
+ */
339
+ function isBeforeOrSame(dateToCompare, referenceDate) {
340
+ return dateToCompare.compare(referenceDate) <= 0;
341
+ }
342
+ /**
343
+ * Determine if a date is after or the same as the reference date.
344
+ *
345
+ * @param dateToCompare - is this date after or the same as the `referenceDate`
346
+ * @param referenceDate - is the `dateToCompare` after or the same as this date
347
+ *
348
+ * @see {@link isAfter} for non-inclusive
349
+ */
350
+ function isAfterOrSame(dateToCompare, referenceDate) {
351
+ return dateToCompare.compare(referenceDate) >= 0;
352
+ }
353
+ /**
354
+ * Determine if a date is inclusively between a start and end reference date.
355
+ *
356
+ * @param date - is this date inclusively between the `start` and `end` dates
357
+ * @param start - the start reference date to make the comparison against
358
+ * @param end - the end reference date to make the comparison against
359
+ *
360
+ * @see {@link isBetween} for non-inclusive
361
+ */
362
+ function isBetweenInclusive(date, start, end) {
363
+ return isAfterOrSame(date, start) && isBeforeOrSame(date, end);
364
+ }
365
+ /**
366
+ * Determine if a date is between a start and end reference date.
367
+ *
368
+ * @param date - is this date between the `start` and `end` dates
369
+ * @param start - the start reference date to make the comparison against
370
+ * @param end - the end reference date to make the comparison against
371
+ *
372
+ * @see {@link isBetweenInclusive} for inclusive
373
+ */
374
+ function isBetween(date, start, end) {
375
+ return isAfter(date, start) && isBefore(date, end);
376
+ }
377
+ function getLastFirstDayOfWeek(date, firstDayOfWeek, locale) {
378
+ const day = getDayOfWeek(date, locale);
379
+ if (firstDayOfWeek > day)
380
+ return date.subtract({ days: day + 7 - firstDayOfWeek });
381
+ if (firstDayOfWeek === day)
382
+ return date;
383
+ return date.subtract({ days: day - firstDayOfWeek });
384
+ }
385
+ function getNextLastDayOfWeek(date, firstDayOfWeek, locale) {
386
+ const day = getDayOfWeek(date, locale);
387
+ const lastDayOfWeek = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1;
388
+ if (day === lastDayOfWeek)
389
+ return date;
390
+ if (day > lastDayOfWeek)
391
+ return date.add({ days: 7 - day + lastDayOfWeek });
392
+ return date.add({ days: lastDayOfWeek - day });
393
+ }
394
+ function areAllDaysBetweenValid(start, end, isUnavailable, isDisabled) {
395
+ if (isUnavailable === undefined && isDisabled === undefined)
396
+ return true;
397
+ let dCurrent = start.add({ days: 1 });
398
+ if (isDisabled?.(dCurrent) || isUnavailable?.(dCurrent))
399
+ return false;
400
+ const dEnd = end;
401
+ while (dCurrent.compare(dEnd) < 0) {
402
+ dCurrent = dCurrent.add({ days: 1 });
403
+ if (isDisabled?.(dCurrent) || isUnavailable?.(dCurrent))
404
+ return false;
405
+ }
406
+ return true;
407
+ }
408
+ /**
409
+ * A helper function used throughout the various date builders
410
+ * to generate a default `DateValue` using the `defaultValue`,
411
+ * `defaultPlaceholder`, and `granularity` props.
412
+ *
413
+ * It's important to match the `DateValue` type being used
414
+ * elsewhere in the builder, so they behave according to the
415
+ * behavior the user expects based on the props they've provided.
416
+ *
417
+ */
418
+ function getDefaultDate(props) {
419
+ const { defaultValue, defaultPlaceholder, granularity = 'day', locale = 'en' } = props;
420
+ if (Array.isArray(defaultValue) && defaultValue.length)
421
+ return defaultValue[defaultValue.length - 1].copy();
422
+ if (defaultValue && !Array.isArray(defaultValue))
423
+ return defaultValue.copy();
424
+ if (defaultPlaceholder)
425
+ return defaultPlaceholder.copy();
426
+ const date = new Date();
427
+ const year = date.getFullYear();
428
+ const month = date.getMonth() + 1;
429
+ const day = date.getDate();
430
+ const calendarDateTimeGranularities = ['hour', 'minute', 'second'];
431
+ const defaultFormatter = new DateFormatter(locale);
432
+ const calendar = createCalendar(defaultFormatter.resolvedOptions().calendar);
433
+ if (calendarDateTimeGranularities.includes(granularity ?? 'day'))
434
+ return toCalendar(new CalendarDateTime(year, month, day, 0, 0, 0), calendar);
435
+ return toCalendar(new CalendarDate(year, month, day), calendar);
436
+ }
437
+
438
+ /**
439
+ * Retrieves an array of date values representing the days between
440
+ * the provided start and end dates.
441
+ */
442
+ function getDaysBetween(start, end) {
443
+ const days = [];
444
+ let dCurrent = start.add({ days: 1 });
445
+ const dEnd = end;
446
+ while (dCurrent.compare(dEnd) < 0) {
447
+ days.push(dCurrent);
448
+ dCurrent = dCurrent.add({ days: 1 });
449
+ }
450
+ return days;
451
+ }
452
+ function createMonth(props) {
453
+ const { dateObj, weekStartsOn, fixedWeeks, locale } = props;
454
+ const daysInMonth = getDaysInMonth(dateObj);
455
+ const datesArray = Array.from({ length: daysInMonth }, (_, i) => dateObj.set({ day: i + 1 }));
456
+ const firstDayOfMonth = startOfMonth(dateObj);
457
+ const lastDayOfMonth = endOfMonth(dateObj);
458
+ const lastSunday = getLastFirstDayOfWeek(firstDayOfMonth, weekStartsOn, locale);
459
+ const nextSaturday = getNextLastDayOfWeek(lastDayOfMonth, weekStartsOn, locale);
460
+ const lastMonthDays = getDaysBetween(lastSunday.subtract({ days: 1 }), firstDayOfMonth);
461
+ const nextMonthDays = getDaysBetween(lastDayOfMonth, nextSaturday.add({ days: 1 }));
462
+ const totalDays = lastMonthDays.length + datesArray.length + nextMonthDays.length;
463
+ if (fixedWeeks && totalDays < 42) {
464
+ const extraDays = 42 - totalDays;
465
+ let startFrom = nextMonthDays[nextMonthDays.length - 1];
466
+ if (!startFrom)
467
+ startFrom = endOfMonth(dateObj);
468
+ const extraDaysArray = Array.from({ length: extraDays }, (_, i) => {
469
+ const incr = i + 1;
470
+ return startFrom.add({ days: incr });
471
+ });
472
+ nextMonthDays.push(...extraDaysArray);
473
+ }
474
+ const allDays = lastMonthDays.concat(datesArray, nextMonthDays);
475
+ const weeks = chunk(allDays, 7);
476
+ return {
477
+ value: dateObj,
478
+ dates: allDays,
479
+ weeks: weeks
480
+ };
481
+ }
482
+ function createMonths(props) {
483
+ const { numberOfMonths, dateObj, ...monthProps } = props;
484
+ const months = [];
485
+ if (!numberOfMonths || numberOfMonths === 1) {
486
+ months.push(createMonth({
487
+ ...monthProps,
488
+ dateObj
489
+ }));
490
+ return months;
491
+ }
492
+ months.push(createMonth({
493
+ ...monthProps,
494
+ dateObj
495
+ }));
496
+ // Create all the months, starting with the current month
497
+ for (let i = 1; i < numberOfMonths; i++) {
498
+ const nextMonth = dateObj.add({ months: i });
499
+ months.push(createMonth({
500
+ ...monthProps,
501
+ dateObj: nextMonth
502
+ }));
503
+ }
504
+ return months;
505
+ }
506
+
507
+ const defaultPartOptions = {
508
+ year: 'numeric',
509
+ month: 'numeric',
510
+ day: 'numeric',
511
+ hour: 'numeric',
512
+ minute: 'numeric',
513
+ second: 'numeric'
514
+ };
515
+ /**
516
+ * Creates a wrapper around the `DateFormatter`, which is
517
+ * an improved version of the {@link Intl.DateTimeFormat} API,
518
+ * that is used internally by the various date builders to
519
+ * easily format dates in a consistent way.
520
+ *
521
+ * @see [DateFormatter](https://react-spectrum.adobe.com/internationalized/date/DateFormatter.html)
522
+ */
523
+ function createFormatter(initialLocale) {
524
+ let locale = initialLocale;
525
+ function setLocale(newLocale) {
526
+ locale = newLocale;
527
+ }
528
+ function getLocale() {
529
+ return locale;
530
+ }
531
+ function custom(date, options) {
532
+ return new DateFormatter(locale, options).format(date);
533
+ }
534
+ function selectedDate(date, includeTime = true) {
535
+ if (hasTime(date) && includeTime) {
536
+ return custom(toDate(date), {
537
+ dateStyle: 'long',
538
+ timeStyle: 'long'
539
+ });
540
+ }
541
+ else {
542
+ return custom(toDate(date), {
543
+ dateStyle: 'long'
544
+ });
545
+ }
546
+ }
547
+ function fullMonthAndYear(date) {
548
+ return new DateFormatter(locale, { month: 'long', year: 'numeric' }).format(date);
549
+ }
550
+ function fullMonth(date) {
551
+ return new DateFormatter(locale, { month: 'long' }).format(date);
552
+ }
553
+ function fullYear(date) {
554
+ return new DateFormatter(locale, { year: 'numeric' }).format(date);
555
+ }
556
+ function toParts(date, options) {
557
+ if (isZonedDateTime(date)) {
558
+ return new DateFormatter(locale, {
559
+ ...options,
560
+ timeZone: date.timeZone
561
+ }).formatToParts(toDate(date));
562
+ }
563
+ else {
564
+ return new DateFormatter(locale, options).formatToParts(toDate(date));
565
+ }
566
+ }
567
+ function dayOfWeek(date, length = 'narrow') {
568
+ return new DateFormatter(locale, { weekday: length }).format(date);
569
+ }
570
+ function dayPeriod(date, hourCycle = undefined) {
571
+ const parts = new DateFormatter(locale, {
572
+ hour: 'numeric',
573
+ minute: 'numeric',
574
+ hourCycle: hourCycle === 24 ? 'h23' : undefined
575
+ }).formatToParts(date);
576
+ const value = parts.find((p) => p.type === 'dayPeriod')?.value;
577
+ if (value === 'PM') {
578
+ return 'PM';
579
+ }
580
+ return 'AM';
581
+ }
582
+ function part(dateObj, type, options = {}) {
583
+ const opts = { ...defaultPartOptions, ...options };
584
+ const parts = toParts(dateObj, opts);
585
+ const part = parts.find((p) => p.type === type);
586
+ return part ? part.value : '';
587
+ }
588
+ function getMonths() {
589
+ const defaultDate = today(getLocalTimeZone());
590
+ const months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
591
+ return months.map((item) => ({ label: fullMonth(toDate(defaultDate.set({ month: item }))), value: item }));
592
+ }
593
+ return {
594
+ setLocale,
595
+ getLocale,
596
+ fullMonth,
597
+ fullYear,
598
+ fullMonthAndYear,
599
+ toParts,
600
+ custom,
601
+ part,
602
+ dayPeriod,
603
+ selectedDate,
604
+ dayOfWeek,
605
+ getMonths
606
+ };
607
+ }
608
+
609
+ /*
610
+ * Implementation ported from from from https://github.com/melt-ui/melt-ui/blob/develop/src/lib/internal/helpers/date/placeholders.ts
611
+ */
612
+ // prettier-ignore
613
+ const supportedLocales = [
614
+ 'ach', 'af', 'am', 'an', 'ar', 'ast', 'az', 'be', 'bg', 'bn', 'br', 'bs',
615
+ 'ca', 'cak', 'ckb', 'cs', 'cy', 'da', 'de', 'dsb', 'el', 'en', 'eo', 'es',
616
+ 'et', 'eu', 'fa', 'ff', 'fi', 'fr', 'fy', 'ga', 'gd', 'gl', 'he', 'hr',
617
+ 'hsb', 'hu', 'ia', 'id', 'it', 'ja', 'ka', 'kk', 'kn', 'ko', 'lb', 'lo',
618
+ 'lt', 'lv', 'meh', 'ml', 'ms', 'nl', 'nn', 'no', 'oc', 'pl', 'pt', 'rm',
619
+ 'ro', 'ru', 'sc', 'scn', 'sk', 'sl', 'sr', 'sv', 'szl', 'tg', 'th', 'tr',
620
+ 'uk', 'zh-CN', 'zh-TW',
621
+ ];
622
+ const placeholderFields = ['year', 'month', 'day'];
623
+ const placeholders = {
624
+ ach: { year: 'mwaka', month: 'dwe', day: 'nino' },
625
+ af: { year: 'jjjj', month: 'mm', day: 'dd' },
626
+ am: { year: 'ዓዓዓዓ', month: 'ሚሜ', day: 'ቀቀ' },
627
+ an: { year: 'aaaa', month: 'mm', day: 'dd' },
628
+ ar: { year: 'سنة', month: 'شهر', day: 'يوم' },
629
+ ast: { year: 'aaaa', month: 'mm', day: 'dd' },
630
+ az: { year: 'iiii', month: 'aa', day: 'gg' },
631
+ be: { year: 'гггг', month: 'мм', day: 'дд' },
632
+ bg: { year: 'гггг', month: 'мм', day: 'дд' },
633
+ bn: { year: 'yyyy', month: 'মিমি', day: 'dd' },
634
+ br: { year: 'bbbb', month: 'mm', day: 'dd' },
635
+ bs: { year: 'gggg', month: 'mm', day: 'dd' },
636
+ ca: { year: 'aaaa', month: 'mm', day: 'dd' },
637
+ cak: { year: 'jjjj', month: 'ii', day: "q'q'" },
638
+ ckb: { year: 'ساڵ', month: 'مانگ', day: 'ڕۆژ' },
639
+ cs: { year: 'rrrr', month: 'mm', day: 'dd' },
640
+ cy: { year: 'bbbb', month: 'mm', day: 'dd' },
641
+ da: { year: 'åååå', month: 'mm', day: 'dd' },
642
+ de: { year: 'jjjj', month: 'mm', day: 'tt' },
643
+ dsb: { year: 'llll', month: 'mm', day: 'źź' },
644
+ el: { year: 'εεεε', month: 'μμ', day: 'ηη' },
645
+ en: { year: 'yyyy', month: 'mm', day: 'dd' },
646
+ eo: { year: 'jjjj', month: 'mm', day: 'tt' },
647
+ es: { year: 'aaaa', month: 'mm', day: 'dd' },
648
+ et: { year: 'aaaa', month: 'kk', day: 'pp' },
649
+ eu: { year: 'uuuu', month: 'hh', day: 'ee' },
650
+ fa: { year: 'سال', month: 'ماه', day: 'روز' },
651
+ ff: { year: 'hhhh', month: 'll', day: 'ññ' },
652
+ fi: { year: 'vvvv', month: 'kk', day: 'pp' },
653
+ fr: { year: 'aaaa', month: 'mm', day: 'jj' },
654
+ fy: { year: 'jjjj', month: 'mm', day: 'dd' },
655
+ ga: { year: 'bbbb', month: 'mm', day: 'll' },
656
+ gd: { year: 'bbbb', month: 'mm', day: 'll' },
657
+ gl: { year: 'aaaa', month: 'mm', day: 'dd' },
658
+ he: { year: 'שנה', month: 'חודש', day: 'יום' },
659
+ hr: { year: 'gggg', month: 'mm', day: 'dd' },
660
+ hsb: { year: 'llll', month: 'mm', day: 'dd' },
661
+ hu: { year: 'éééé', month: 'hh', day: 'nn' },
662
+ ia: { year: 'aaaa', month: 'mm', day: 'dd' },
663
+ id: { year: 'tttt', month: 'bb', day: 'hh' },
664
+ it: { year: 'aaaa', month: 'mm', day: 'gg' },
665
+ ja: { year: ' 年 ', month: '月', day: '日' },
666
+ ka: { year: 'წწწწ', month: 'თთ', day: 'რრ' },
667
+ kk: { year: 'жжжж', month: 'аа', day: 'кк' },
668
+ kn: { year: 'ವವವವ', month: 'ಮಿಮೀ', day: 'ದಿದಿ' },
669
+ ko: { year: '연도', month: '월', day: '일' },
670
+ lb: { year: 'jjjj', month: 'mm', day: 'dd' },
671
+ lo: { year: 'ປປປປ', month: 'ດດ', day: 'ວວ' },
672
+ lt: { year: 'mmmm', month: 'mm', day: 'dd' },
673
+ lv: { year: 'gggg', month: 'mm', day: 'dd' },
674
+ meh: { year: 'aaaa', month: 'mm', day: 'dd' },
675
+ ml: { year: 'വർഷം', month: 'മാസം', day: 'തീയതി' },
676
+ ms: { year: 'tttt', month: 'mm', day: 'hh' },
677
+ nl: { year: 'jjjj', month: 'mm', day: 'dd' },
678
+ nn: { year: 'åååå', month: 'mm', day: 'dd' },
679
+ no: { year: 'åååå', month: 'mm', day: 'dd' },
680
+ oc: { year: 'aaaa', month: 'mm', day: 'jj' },
681
+ pl: { year: 'rrrr', month: 'mm', day: 'dd' },
682
+ pt: { year: 'aaaa', month: 'mm', day: 'dd' },
683
+ rm: { year: 'oooo', month: 'mm', day: 'dd' },
684
+ ro: { year: 'aaaa', month: 'll', day: 'zz' },
685
+ ru: { year: 'гггг', month: 'мм', day: 'дд' },
686
+ sc: { year: 'aaaa', month: 'mm', day: 'dd' },
687
+ scn: { year: 'aaaa', month: 'mm', day: 'jj' },
688
+ sk: { year: 'rrrr', month: 'mm', day: 'dd' },
689
+ sl: { year: 'llll', month: 'mm', day: 'dd' },
690
+ sr: { year: 'гггг', month: 'мм', day: 'дд' },
691
+ sv: { year: 'åååå', month: 'mm', day: 'dd' },
692
+ szl: { year: 'rrrr', month: 'mm', day: 'dd' },
693
+ tg: { year: 'сссс', month: 'мм', day: 'рр' },
694
+ th: { year: 'ปปปป', month: 'ดด', day: 'วว' },
695
+ tr: { year: 'yyyy', month: 'aa', day: 'gg' },
696
+ uk: { year: 'рррр', month: 'мм', day: 'дд' },
697
+ 'zh-CN': { year: '年', month: '月', day: '日' },
698
+ 'zh-TW': { year: '年', month: '月', day: '日' }
699
+ };
700
+ function getPlaceholderObj(locale) {
701
+ if (!isSupportedLocale(locale)) {
702
+ const localeLanguage = getLocaleLanguage(locale);
703
+ if (!isSupportedLocale(localeLanguage)) {
704
+ return placeholders.en;
705
+ }
706
+ else {
707
+ return placeholders[localeLanguage];
708
+ }
709
+ }
710
+ else {
711
+ return placeholders[locale];
712
+ }
713
+ }
714
+ function getPlaceholder(field, value, locale) {
715
+ if (isPlaceholderField(field))
716
+ return getPlaceholderObj(locale)[field];
717
+ if (isDefaultField(field))
718
+ return value;
719
+ if (isTimeField(field))
720
+ return '––';
721
+ return '';
722
+ }
723
+ function isSupportedLocale(locale) {
724
+ return supportedLocales.includes(locale);
725
+ }
726
+ function isPlaceholderField(field) {
727
+ return placeholderFields.includes(field);
728
+ }
729
+ function isTimeField(field) {
730
+ return field === 'hour' || field === 'minute' || field === 'second';
731
+ }
732
+ function isDefaultField(field) {
733
+ return field === 'era' || field === 'dayPeriod';
734
+ }
735
+ function getLocaleLanguage(locale) {
736
+ if (Intl.Locale) {
737
+ return new Intl.Locale(locale).language;
738
+ }
739
+ return locale.split('-')[0];
740
+ }
741
+
742
+ /*
743
+ * Implementation ported from https://github.com/melt-ui/melt-ui/blob/develop/src/lib/internal/helpers/date/types.ts
744
+ */
745
+
746
+ function handleCalendarInitialFocus(calendar) {
747
+ const selectedDay = calendar.querySelector('[data-selected]');
748
+ if (selectedDay)
749
+ return selectedDay.focus();
750
+ const today = calendar.querySelector('[data-today]');
751
+ if (today)
752
+ return today.focus();
753
+ const firstDay = calendar.querySelector('[data-rdx-calendar-day]');
754
+ if (firstDay)
755
+ return firstDay.focus();
756
+ }
757
+
253
758
  var RdxPositionSide;
254
759
  (function (RdxPositionSide) {
255
760
  RdxPositionSide["Top"] = "top";
@@ -465,9 +970,46 @@ function getArrowPositionParams(sideAndAlign, arrowWidthAndHeight, triggerWidthA
465
970
  return posParams;
466
971
  }
467
972
 
973
+ // https://ngxtension.netlify.app/utilities/signals/explicit-effect/
974
+ /**
975
+ * This explicit effect function will take the dependencies and the function to run when the dependencies change.
976
+ *
977
+ * @example
978
+ * ```typescript
979
+ * import { watch } from 'radix-ng/primitives/core';
980
+ *
981
+ * const count = signal(0);
982
+ * const state = signal('idle');
983
+ *
984
+ * watch([count, state], ([count, state], cleanup) => {
985
+ * console.log('count updated', count, state);
986
+ *
987
+ * cleanup(() => {
988
+ * console.log('cleanup');
989
+ * });
990
+ * });
991
+ * ```
992
+ *
993
+ * @param deps - The dependencies that the effect will run on
994
+ * @param fn - The function to run when the dependencies change
995
+ * @param options - The options for the effect with the addition of defer (it allows the computation to run on first change, not immediately)
996
+ */
997
+ function watch(deps, fn, options) {
998
+ let defer = options && options.defer;
999
+ return effect((onCleanup) => {
1000
+ const depValues = deps.map((s) => s());
1001
+ untracked(() => {
1002
+ if (!defer) {
1003
+ fn(depValues, onCleanup);
1004
+ }
1005
+ defer = false;
1006
+ });
1007
+ }, options);
1008
+ }
1009
+
468
1010
  /**
469
1011
  * Generated bundle index. Do not edit.
470
1012
  */
471
1013
 
472
- export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RDX_POSITIONING_DEFAULTS, RDX_POSITIONS, RdxAutoFocusDirective, RdxFocusInitialDirective, RdxPositionAlign, RdxPositionSide, SHIFT, SPACE, TAB, WINDOW, _IdGenerator, a, getAllPossibleConnectedPositions, getArrowPositionParams, getContentPosition, getSideAndAlignFromAllPossibleConnectedPositions, injectDocument, injectIsClient, injectNgControl, injectWindow, isInsideForm, isNullish, isNumber, j, k, n, p, provideValueAccessor };
1014
+ export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RDX_POSITIONING_DEFAULTS, RDX_POSITIONS, RdxAutoFocusDirective, RdxFocusInitialDirective, RdxPositionAlign, RdxPositionSide, SHIFT, SPACE, SPACE_CODE, TAB, WINDOW, _IdGenerator, a, areAllDaysBetweenValid, createFormatter, createMonth, createMonths, getAllPossibleConnectedPositions, getArrowPositionParams, getContentPosition, getDaysBetween, getDaysInMonth, getDefaultDate, getLastFirstDayOfWeek, getNextLastDayOfWeek, getPlaceholder, getSideAndAlignFromAllPossibleConnectedPositions, handleCalendarInitialFocus, hasTime, injectDocument, injectIsClient, injectNgControl, injectWindow, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isInsideForm, isNullish, isNumber, isZonedDateTime, j, k, n, p, provideValueAccessor, toDate, watch };
473
1015
  //# sourceMappingURL=radix-ng-primitives-core.mjs.map