@progressive-development/pd-calendar 0.9.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/LICENSE +21 -2
  2. package/README.md +32 -57
  3. package/dist/generated/locales/be.d.ts +3 -0
  4. package/dist/generated/locales/be.d.ts.map +1 -1
  5. package/dist/generated/locales/de.d.ts +3 -0
  6. package/dist/generated/locales/de.d.ts.map +1 -1
  7. package/dist/generated/locales/en.d.ts +3 -0
  8. package/dist/generated/locales/en.d.ts.map +1 -1
  9. package/dist/index.d.ts +10 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +16 -0
  12. package/dist/locales/be.js +4 -1
  13. package/dist/locales/de.js +3 -0
  14. package/dist/locales/en.js +4 -1
  15. package/dist/pd-calendar/PdCalendar.d.ts +101 -18
  16. package/dist/pd-calendar/PdCalendar.d.ts.map +1 -1
  17. package/dist/pd-calendar/PdCalendar.js +380 -264
  18. package/dist/pd-calendar/pd-calendar-cell/PdCalendarCell.d.ts +40 -33
  19. package/dist/pd-calendar/pd-calendar-cell/PdCalendarCell.d.ts.map +1 -1
  20. package/dist/pd-calendar/pd-calendar-cell/PdCalendarCell.js +173 -113
  21. package/dist/pd-calendar/pd-calendar-day-events-panel/PdCalendarDayEventsPanel.d.ts +27 -0
  22. package/dist/pd-calendar/pd-calendar-day-events-panel/PdCalendarDayEventsPanel.d.ts.map +1 -0
  23. package/dist/pd-calendar/pd-calendar-day-events-panel/PdCalendarDayEventsPanel.js +160 -0
  24. package/dist/pd-calendar/pd-calendar-day-events-panel/pd-calendar-day-events-panel.d.ts +3 -0
  25. package/dist/pd-calendar/pd-calendar-day-events-panel/pd-calendar-day-events-panel.d.ts.map +1 -0
  26. package/dist/pd-calendar/pd-calendar-day-events-panel/pd-calendar-day-events-panel.js +8 -0
  27. package/dist/pd-calendar/pd-calendar-event-cell/PdCalendarEventCell.d.ts +55 -0
  28. package/dist/pd-calendar/pd-calendar-event-cell/PdCalendarEventCell.d.ts.map +1 -0
  29. package/dist/pd-calendar/pd-calendar-event-cell/PdCalendarEventCell.js +341 -0
  30. package/dist/pd-calendar/pd-calendar-event-cell/pd-calendar-event-cell.d.ts +3 -0
  31. package/dist/pd-calendar/pd-calendar-event-cell/pd-calendar-event-cell.d.ts.map +1 -0
  32. package/dist/pd-calendar/pd-calendar-event-cell/pd-calendar-event-cell.js +8 -0
  33. package/dist/pd-calendar/pd-calendar-event-info-panel/PdCalendarEventInfoPanel.d.ts +29 -0
  34. package/dist/pd-calendar/pd-calendar-event-info-panel/PdCalendarEventInfoPanel.d.ts.map +1 -0
  35. package/dist/pd-calendar/pd-calendar-event-info-panel/PdCalendarEventInfoPanel.js +211 -0
  36. package/dist/pd-calendar/pd-calendar-event-info-panel/pd-calendar-event-info-panel.d.ts +3 -0
  37. package/dist/pd-calendar/pd-calendar-event-info-panel/pd-calendar-event-info-panel.d.ts.map +1 -0
  38. package/dist/pd-calendar/pd-calendar-event-info-panel/pd-calendar-event-info-panel.js +8 -0
  39. package/dist/pd-calendar/pd-calendar-list-cell/PdCalendarListCell.d.ts +28 -0
  40. package/dist/pd-calendar/pd-calendar-list-cell/PdCalendarListCell.d.ts.map +1 -0
  41. package/dist/pd-calendar/pd-calendar-list-cell/PdCalendarListCell.js +252 -0
  42. package/dist/pd-calendar/pd-calendar-list-cell/pd-calendar-list-cell.d.ts +3 -0
  43. package/dist/pd-calendar/pd-calendar-list-cell/pd-calendar-list-cell.d.ts.map +1 -0
  44. package/dist/pd-calendar/pd-calendar-list-cell/pd-calendar-list-cell.js +8 -0
  45. package/dist/pd-calendar/pd-calendar-list-view/PdCalendarListView.d.ts +26 -0
  46. package/dist/pd-calendar/pd-calendar-list-view/PdCalendarListView.d.ts.map +1 -0
  47. package/dist/pd-calendar/pd-calendar-list-view/PdCalendarListView.js +165 -0
  48. package/dist/pd-calendar/pd-calendar-list-view/pd-calendar-list-view.d.ts +3 -0
  49. package/dist/pd-calendar/pd-calendar-list-view/pd-calendar-list-view.d.ts.map +1 -0
  50. package/dist/pd-calendar/pd-calendar-list-view/pd-calendar-list-view.js +8 -0
  51. package/dist/pd-calendar/pd-calendar-month-view/PdCalendarMonthView.d.ts +55 -0
  52. package/dist/pd-calendar/pd-calendar-month-view/PdCalendarMonthView.d.ts.map +1 -0
  53. package/dist/pd-calendar/pd-calendar-month-view/PdCalendarMonthView.js +461 -0
  54. package/dist/pd-calendar/pd-calendar-month-view/pd-calendar-month-view.d.ts +3 -0
  55. package/dist/pd-calendar/pd-calendar-month-view/pd-calendar-month-view.d.ts.map +1 -0
  56. package/dist/pd-calendar/pd-calendar-month-view/pd-calendar-month-view.js +8 -0
  57. package/dist/pd-calendar/pd-calendar-time-grid-view/PdCalendarTimeGridView.d.ts +32 -0
  58. package/dist/pd-calendar/pd-calendar-time-grid-view/PdCalendarTimeGridView.d.ts.map +1 -0
  59. package/dist/pd-calendar/pd-calendar-time-grid-view/PdCalendarTimeGridView.js +468 -0
  60. package/dist/pd-calendar/pd-calendar-time-grid-view/pd-calendar-time-grid-view.d.ts +3 -0
  61. package/dist/pd-calendar/pd-calendar-time-grid-view/pd-calendar-time-grid-view.d.ts.map +1 -0
  62. package/dist/pd-calendar/pd-calendar-time-grid-view/pd-calendar-time-grid-view.js +8 -0
  63. package/dist/pd-calendar/pd-calendar-week-cell/PdCalendarWeekCell.d.ts +31 -0
  64. package/dist/pd-calendar/pd-calendar-week-cell/PdCalendarWeekCell.d.ts.map +1 -0
  65. package/dist/pd-calendar/pd-calendar-week-cell/PdCalendarWeekCell.js +134 -0
  66. package/dist/pd-calendar/pd-calendar-week-cell/pd-calendar-week-cell.d.ts +3 -0
  67. package/dist/pd-calendar/pd-calendar-week-cell/pd-calendar-week-cell.d.ts.map +1 -0
  68. package/dist/pd-calendar/pd-calendar-week-cell/pd-calendar-week-cell.js +8 -0
  69. package/dist/pd-calendar/pd-calendar.stories.d.ts +79 -19
  70. package/dist/pd-calendar/pd-calendar.stories.d.ts.map +1 -1
  71. package/dist/pd-calendar/pd-year-popup/PdYearPopup.d.ts +22 -11
  72. package/dist/pd-calendar/pd-year-popup/PdYearPopup.d.ts.map +1 -1
  73. package/dist/pd-calendar/pd-year-popup/PdYearPopup.js +152 -34
  74. package/dist/pd-datepicker/PdDatepicker.d.ts +76 -7
  75. package/dist/pd-datepicker/PdDatepicker.d.ts.map +1 -1
  76. package/dist/pd-datepicker/PdDatepicker.js +257 -50
  77. package/dist/pd-datepicker/pd-date-picker.stories.d.ts +78 -20
  78. package/dist/pd-datepicker/pd-date-picker.stories.d.ts.map +1 -1
  79. package/dist/pd-slot-picker/PdSlotPicker.d.ts +102 -0
  80. package/dist/pd-slot-picker/PdSlotPicker.d.ts.map +1 -0
  81. package/dist/pd-slot-picker/PdSlotPicker.js +339 -0
  82. package/dist/pd-slot-picker/pd-slot-cell/PdSlotCell.d.ts +35 -0
  83. package/dist/pd-slot-picker/pd-slot-cell/PdSlotCell.d.ts.map +1 -0
  84. package/dist/pd-slot-picker/pd-slot-cell/PdSlotCell.js +188 -0
  85. package/dist/pd-slot-picker/pd-slot-cell/pd-slot-cell.d.ts +3 -0
  86. package/dist/pd-slot-picker/pd-slot-cell/pd-slot-cell.d.ts.map +1 -0
  87. package/dist/pd-slot-picker/pd-slot-cell/pd-slot-cell.js +8 -0
  88. package/dist/pd-slot-picker/pd-slot-picker.d.ts +3 -0
  89. package/dist/pd-slot-picker/pd-slot-picker.d.ts.map +1 -0
  90. package/dist/pd-slot-picker/pd-slot-picker.stories.d.ts +67 -0
  91. package/dist/pd-slot-picker/pd-slot-picker.stories.d.ts.map +1 -0
  92. package/dist/pd-slot-picker.d.ts +2 -0
  93. package/dist/pd-slot-picker.js +8 -0
  94. package/dist/shared/PdBaseCell.d.ts +68 -0
  95. package/dist/shared/PdBaseCell.d.ts.map +1 -0
  96. package/dist/shared/PdBaseCell.js +120 -0
  97. package/dist/shared/PdBaseView.d.ts +22 -0
  98. package/dist/shared/PdBaseView.d.ts.map +1 -0
  99. package/dist/shared/PdBaseView.js +46 -0
  100. package/dist/shared/PdCalendarPanelBase.d.ts +34 -0
  101. package/dist/shared/PdCalendarPanelBase.d.ts.map +1 -0
  102. package/dist/shared/PdCalendarPanelBase.js +169 -0
  103. package/dist/shared/calendar-button-bar/calendar-button-bar.d.ts +41 -0
  104. package/dist/shared/calendar-button-bar/calendar-button-bar.d.ts.map +1 -0
  105. package/dist/shared/calendar-button-bar/calendar-button-bar.js +435 -0
  106. package/dist/shared/calendar-locales.d.ts +9 -0
  107. package/dist/shared/calendar-locales.d.ts.map +1 -0
  108. package/dist/shared/calendar-locales.js +30 -0
  109. package/dist/shared/calendar-utils.d.ts +34 -0
  110. package/dist/shared/calendar-utils.d.ts.map +1 -0
  111. package/dist/shared/calendar-utils.js +99 -0
  112. package/dist/shared/calendar-utils.test.d.ts +2 -0
  113. package/dist/shared/calendar-utils.test.d.ts.map +1 -0
  114. package/dist/types.d.ts +102 -1
  115. package/dist/types.d.ts.map +1 -1
  116. package/package.json +10 -5
  117. package/dist/pd-calendar/pd-calendar-cell/pd-calendar-cell.stories.d.ts +0 -15
  118. package/dist/pd-calendar/pd-calendar-cell/pd-calendar-cell.stories.d.ts.map +0 -1
@@ -0,0 +1,102 @@
1
+ import { LitElement, CSSResultGroup } from 'lit';
2
+ import { CalendarData, CalendarConfig, SlotPickerValue } from '../types.js';
3
+ /**
4
+ * Slot picker component for appointment booking (Calendly-style).
5
+ *
6
+ * Combines a PdCalendar month view with a time slot list.
7
+ * Days with available slots are marked in the calendar.
8
+ * Selecting a day shows available time slots beside/below the calendar.
9
+ *
10
+ * @tagname pd-slot-picker
11
+ * @summary Appointment slot picker with calendar and time slot selection.
12
+ *
13
+ * @event change-month - Fired when navigating to a different month. Detail: `{ newDate: Date, next?: boolean, prev?: boolean }`.
14
+ * @event select-date - Fired when a date is selected. Detail: `{ dateKey: string, date: Date }`.
15
+ * @event select-slot - Fired when a time slot is selected. Detail: `{ dateKey: string, startTime: string, endTime: string, index: number }`.
16
+ *
17
+ * @cssprop --pd-slot-picker-gap - Gap between calendar and slot list. Default: `1.5rem`.
18
+ * @cssprop --pd-slot-picker-calendar-basis - Flex basis for calendar section. Default: `320px`.
19
+ * @cssprop --pd-slot-picker-calendar-min-width - Min width for calendar section. Default: `280px`.
20
+ * @cssprop --pd-slot-picker-calendar-max-width - Max width for calendar section. Default: `420px`.
21
+ * @cssprop --pd-slot-picker-slots-basis - Flex basis for slots section. Default: `280px`.
22
+ * @cssprop --pd-slot-picker-slots-min-width - Min width for slots section. Default: `240px`.
23
+ * @cssprop --pd-slot-picker-slots-max-width - Max width for slots section. Default: `400px`.
24
+ * @cssprop --pd-slot-picker-slots-max-height - Max height for slot list (scrollable). Default: `400px`.
25
+ * @cssprop --pd-slot-picker-header-size - Font size of slot list header. Default: `1rem`.
26
+ * @cssprop --pd-slot-picker-header-col - Color of slot list header. Default: `var(--pd-default-font-title-col)`.
27
+ * @cssprop --pd-slot-picker-slots-top-offset - Top padding for the slots section at wider viewports (>=624px). Default: `1.2rem`.
28
+ */
29
+ export declare class PdSlotPicker extends LitElement {
30
+ /** Calendar data with slots per date key (YYYY-MM-DD). */
31
+ data: CalendarData;
32
+ /** Calendar configuration including category definitions. */
33
+ config?: CalendarConfig;
34
+ /** Reference date for initial calendar view. */
35
+ refDate?: Date;
36
+ /** Hide Saturday and Sunday columns. */
37
+ hideWeekend: boolean;
38
+ /** Months allowed to navigate backwards (-1 = unlimited). */
39
+ prevMonthConstraint: number;
40
+ /** Months allowed to navigate forwards (-1 = unlimited). */
41
+ nextMonthConstraint: number;
42
+ /** Year values for year selection popup. Empty array disables popup. */
43
+ withYearPopup: string[];
44
+ /** Enable mouse wheel navigation between months. */
45
+ withWheelNavigation: boolean;
46
+ /** Enable touch swipe navigation between months. */
47
+ withTouchNavigation: boolean;
48
+ /** @ignore - Currently selected date key */
49
+ private _selectedDateKey;
50
+ /** @ignore - Currently selected date */
51
+ private _selectedDate?;
52
+ /** @ignore - Selected slot data */
53
+ private _selectedSlot;
54
+ /** @ignore - Internal ref date for calendar navigation (avoids mutating the refDate property) */
55
+ private _calendarRefDate?;
56
+ /** The currently selected slot, or null if no slot is selected. */
57
+ get value(): SlotPickerValue | null;
58
+ /** Set the selected slot programmatically. */
59
+ set value(val: SlotPickerValue | null);
60
+ static styles: CSSResultGroup;
61
+ render(): import('lit').TemplateResult<1>;
62
+ /**
63
+ * Renders the slot list for the selected day.
64
+ */
65
+ private _renderSlotList;
66
+ /**
67
+ * Augments the calendar data for display: days without slots get disabled,
68
+ * and info text is stripped (only day number + category color shown).
69
+ */
70
+ private _getCalendarData;
71
+ /**
72
+ * Returns the slots for the currently selected day.
73
+ */
74
+ private _getSelectedDaySlots;
75
+ /**
76
+ * Formats a header string for the selected date using pd-utils.
77
+ * Example: "Montag, 15. Januar 2026"
78
+ */
79
+ private _formatSelectedDateHeader;
80
+ /**
81
+ * Gets the category background color from config.
82
+ */
83
+ private _getCategoryColor;
84
+ /**
85
+ * Gets the category text color from config.
86
+ */
87
+ private _getCategoryTextColor;
88
+ /**
89
+ * Handles slot selection from pd-slot-cell children.
90
+ * Updates internal state and re-fires the event.
91
+ */
92
+ private _handleSlotSelect;
93
+ /**
94
+ * Handles date selection from the calendar.
95
+ */
96
+ private _handleDateSelect;
97
+ /**
98
+ * Handles month change from the calendar and re-fires it.
99
+ */
100
+ private _handleMonthChange;
101
+ }
102
+ //# sourceMappingURL=PdSlotPicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PdSlotPicker.d.ts","sourceRoot":"","sources":["../../src/pd-slot-picker/PdSlotPicker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAa,cAAc,EAAE,MAAM,KAAK,CAAC;AAK5D,OAAO,EACL,YAAY,EACZ,cAAc,EAEd,eAAe,EAChB,MAAM,aAAa,CAAC;AAErB,OAAO,+BAA+B,CAAC;AACvC,OAAO,gCAAgC,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBACa,YAAa,SAAQ,UAAU;IAC1C,0DAA0D;IAE1D,IAAI,EAAE,YAAY,CAAM;IAExB,6DAA6D;IAE7D,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB,gDAAgD;IAEhD,OAAO,CAAC,EAAE,IAAI,CAAC;IAEf,wCAAwC;IAExC,WAAW,UAAS;IAEpB,6DAA6D;IAE7D,mBAAmB,SAAM;IAEzB,4DAA4D;IAE5D,mBAAmB,SAAM;IAEzB,wEAAwE;IAExE,aAAa,EAAE,MAAM,EAAE,CAAM;IAE7B,oDAAoD;IAEpD,mBAAmB,UAAS;IAE5B,oDAAoD;IAEpD,mBAAmB,UAAS;IAE5B,4CAA4C;IAE5C,OAAO,CAAC,gBAAgB,CAAM;IAE9B,wCAAwC;IAExC,OAAO,CAAC,aAAa,CAAC,CAAO;IAE7B,mCAAmC;IAEnC,OAAO,CAAC,aAAa,CAAgC;IAErD,iGAAiG;IAEjG,OAAO,CAAC,gBAAgB,CAAC,CAAO;IAEhC,mEAAmE;IACnE,IAAI,KAAK,IAAI,eAAe,GAAG,IAAI,CAElC;IAED,8CAA8C;IAC9C,IAAI,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,EAEpC;IAED,OAAgB,MAAM,EAAE,cAAc,CA2EpC;IAEO,MAAM;IAsCf;;OAEG;IACH,OAAO,CAAC,eAAe;IA6CvB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAK5B;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAKjC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAK7B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoBzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAiB3B"}
@@ -0,0 +1,339 @@
1
+ import { css, LitElement, html } from 'lit';
2
+ import { localized, msg } from '@lit/localize';
3
+ import { property, state } from 'lit/decorators.js';
4
+ import { formatDateTime } from '@progressive-development/pd-utils';
5
+ import '../pd-calendar.js';
6
+ import './pd-slot-cell/pd-slot-cell.js';
7
+
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
10
+ var __decorateClass = (decorators, target, key, kind) => {
11
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
12
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
13
+ if (decorator = decorators[i])
14
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
15
+ if (kind && result) __defProp(target, key, result);
16
+ return result;
17
+ };
18
+ let PdSlotPicker = class extends LitElement {
19
+ constructor() {
20
+ super(...arguments);
21
+ this.data = {};
22
+ this.hideWeekend = false;
23
+ this.prevMonthConstraint = -1;
24
+ this.nextMonthConstraint = -1;
25
+ this.withYearPopup = [];
26
+ this.withWheelNavigation = false;
27
+ this.withTouchNavigation = false;
28
+ this._selectedDateKey = "";
29
+ this._selectedSlot = null;
30
+ }
31
+ /** The currently selected slot, or null if no slot is selected. */
32
+ get value() {
33
+ return this._selectedSlot;
34
+ }
35
+ /** Set the selected slot programmatically. */
36
+ set value(val) {
37
+ this._selectedSlot = val;
38
+ }
39
+ render() {
40
+ const slots = this._getSelectedDaySlots();
41
+ const hasSelectedDate = !!this._selectedDateKey;
42
+ return html`
43
+ <div class="slot-picker-layout">
44
+ <div class="calendar-section">
45
+ <pd-calendar
46
+ .data="${this._getCalendarData()}"
47
+ .config="${this.config ?? {}}"
48
+ .refDate="${this._calendarRefDate ?? this.refDate}"
49
+ ?hideWeekend="${this.hideWeekend}"
50
+ .prevMonthConstraint="${this.prevMonthConstraint}"
51
+ .nextMonthConstraint="${this.nextMonthConstraint}"
52
+ .withYearPopup="${this.withYearPopup}"
53
+ ?withWheelNavigation="${this.withWheelNavigation}"
54
+ ?withTouchNavigation="${this.withTouchNavigation}"
55
+ selectableDates
56
+ ?showSelection="${!!this._selectedDateKey}"
57
+ numberClass="center"
58
+ @select-date="${this._handleDateSelect}"
59
+ @change-month="${this._handleMonthChange}"
60
+ ></pd-calendar>
61
+ </div>
62
+
63
+ <div class="slots-section">
64
+ ${hasSelectedDate ? this._renderSlotList(slots) : html`<div class="slots-placeholder">
65
+ ${msg("Bitte wählen Sie einen Tag aus.", {
66
+ id: "pd.slotpicker.placeholder"
67
+ })}
68
+ </div>`}
69
+ </div>
70
+ </div>
71
+ `;
72
+ }
73
+ /**
74
+ * Renders the slot list for the selected day.
75
+ */
76
+ _renderSlotList(slots) {
77
+ const headerText = this._formatSelectedDateHeader();
78
+ const emptyMessage = msg("Keine verfügbaren Zeitfenster.", {
79
+ id: "pd.slotpicker.empty"
80
+ });
81
+ return html`
82
+ <div class="slots-header">${headerText}</div>
83
+ <div
84
+ class="slots-list"
85
+ role="list"
86
+ @select-slot="${this._handleSlotSelect}"
87
+ >
88
+ ${slots.length > 0 ? slots.map(
89
+ (slot, index) => html`
90
+ <pd-slot-cell
91
+ role="listitem"
92
+ tabindex="0"
93
+ key="${this._selectedDateKey}"
94
+ .startTime="${slot.startTime || ""}"
95
+ .endTime="${slot.endTime || ""}"
96
+ .title="${slot.info || ""}"
97
+ .desc="${slot.desc || ""}"
98
+ .category="${slot.category || ""}"
99
+ .categoryColor="${this._getCategoryColor(slot.category)}"
100
+ .categoryTextColor="${this._getCategoryTextColor(
101
+ slot.category
102
+ )}"
103
+ ?fullDay="${slot.fullDay ?? false}"
104
+ ?disabled="${slot.disabled || slot.capacity != null && (slot.booked ?? 0) >= slot.capacity}"
105
+ ?selected="${this._selectedSlot?.index === index}"
106
+ .capacity="${slot.capacity}"
107
+ .booked="${slot.booked}"
108
+ .index="${index}"
109
+ ></pd-slot-cell>
110
+ `
111
+ ) : html`<div class="slots-empty">${emptyMessage}</div>`}
112
+ </div>
113
+ `;
114
+ }
115
+ /**
116
+ * Augments the calendar data for display: days without slots get disabled,
117
+ * and info text is stripped (only day number + category color shown).
118
+ */
119
+ _getCalendarData() {
120
+ const ref = this._calendarRefDate ?? this.refDate ?? /* @__PURE__ */ new Date();
121
+ const year = ref.getFullYear();
122
+ const month = ref.getMonth();
123
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
124
+ const result = {};
125
+ for (let day = 1; day <= daysInMonth; day++) {
126
+ const key = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
127
+ const slots = this.data[key];
128
+ if (slots?.length) {
129
+ const allFull = slots.every(
130
+ (s) => s.disabled || s.capacity != null && (s.booked ?? 0) >= s.capacity
131
+ );
132
+ result[key] = allFull ? [{ disabled: true }] : slots.map(({ info, desc, ...rest }) => rest);
133
+ } else {
134
+ result[key] = [{ disabled: true }];
135
+ }
136
+ }
137
+ return result;
138
+ }
139
+ /**
140
+ * Returns the slots for the currently selected day.
141
+ */
142
+ _getSelectedDaySlots() {
143
+ if (!this._selectedDateKey || !this.data) return [];
144
+ return this.data[this._selectedDateKey] ?? [];
145
+ }
146
+ /**
147
+ * Formats a header string for the selected date using pd-utils.
148
+ * Example: "Montag, 15. Januar 2026"
149
+ */
150
+ _formatSelectedDateHeader() {
151
+ if (!this._selectedDate) return "";
152
+ return formatDateTime(this._selectedDate, false);
153
+ }
154
+ /**
155
+ * Gets the category background color from config.
156
+ */
157
+ _getCategoryColor(category) {
158
+ if (!category || !this.config?.categories?.[category]) return "";
159
+ return this.config.categories[category].color || "";
160
+ }
161
+ /**
162
+ * Gets the category text color from config.
163
+ */
164
+ _getCategoryTextColor(category) {
165
+ if (!category || !this.config?.categories?.[category]) return "";
166
+ return this.config.categories[category].textColor || "";
167
+ }
168
+ /**
169
+ * Handles slot selection from pd-slot-cell children.
170
+ * Updates internal state and re-fires the event.
171
+ */
172
+ _handleSlotSelect(e) {
173
+ const { dateKey, startTime, endTime, index } = e.detail;
174
+ this._selectedSlot = { dateKey, startTime, endTime, index };
175
+ this.dispatchEvent(
176
+ new CustomEvent("select-slot", {
177
+ detail: { dateKey, startTime, endTime, index },
178
+ bubbles: true,
179
+ composed: true
180
+ })
181
+ );
182
+ e.stopPropagation();
183
+ }
184
+ /**
185
+ * Handles date selection from the calendar.
186
+ */
187
+ _handleDateSelect(e) {
188
+ const { dateKey, date } = e.detail;
189
+ this._selectedDateKey = dateKey;
190
+ this._selectedDate = date;
191
+ this._selectedSlot = null;
192
+ this._calendarRefDate = date;
193
+ this.dispatchEvent(
194
+ new CustomEvent("select-date", {
195
+ detail: { dateKey, date },
196
+ bubbles: true,
197
+ composed: true
198
+ })
199
+ );
200
+ e.stopPropagation();
201
+ }
202
+ /**
203
+ * Handles month change from the calendar and re-fires it.
204
+ */
205
+ _handleMonthChange(e) {
206
+ this._calendarRefDate = e.detail.newDate;
207
+ this._selectedDateKey = "";
208
+ this._selectedDate = void 0;
209
+ this._selectedSlot = null;
210
+ this.dispatchEvent(
211
+ new CustomEvent("change-month", {
212
+ detail: e.detail,
213
+ bubbles: true,
214
+ composed: true
215
+ })
216
+ );
217
+ e.stopPropagation();
218
+ }
219
+ };
220
+ PdSlotPicker.styles = [
221
+ css`
222
+ :host {
223
+ display: block;
224
+ font-family: var(--pd-default-font-content-family);
225
+ container-type: inline-size;
226
+ }
227
+
228
+ .slot-picker-layout {
229
+ display: flex;
230
+ flex-wrap: wrap;
231
+ gap: var(--pd-slot-picker-gap, 1.5rem);
232
+ align-items: flex-start;
233
+ }
234
+
235
+ .calendar-section {
236
+ flex: 1 1 var(--pd-slot-picker-calendar-basis, 320px);
237
+ min-width: var(--pd-slot-picker-calendar-min-width, 280px);
238
+ max-width: var(--pd-slot-picker-calendar-max-width, 420px);
239
+ }
240
+
241
+ .calendar-section pd-calendar {
242
+ --pd-calendar-width: 100%;
243
+ --pd-calendar-min-width: 0;
244
+ --pd-calendar-cell-selected-bg-col: var(--pd-default-dark-col);
245
+ }
246
+
247
+ .slots-section {
248
+ flex: 1 1 var(--pd-slot-picker-slots-basis, 280px);
249
+ min-width: var(--pd-slot-picker-slots-min-width, 240px);
250
+ max-width: var(--pd-slot-picker-calendar-max-width, 420px);
251
+ display: flex;
252
+ flex-direction: column;
253
+ gap: var(--pd-spacing-sm, 0.5rem);
254
+ }
255
+
256
+ @container (min-width: 624px) {
257
+ .slots-section {
258
+ max-width: var(--pd-slot-picker-slots-max-width, 400px);
259
+ padding-top: var(--pd-slot-picker-slots-top-offset, 1.2rem);
260
+ }
261
+ }
262
+
263
+ .slots-header {
264
+ font-size: var(--pd-slot-picker-header-size, 1rem);
265
+ font-weight: 600;
266
+ color: var(
267
+ --pd-slot-picker-header-col,
268
+ var(--pd-default-font-title-col, #111827)
269
+ );
270
+ font-family: var(--pd-default-font-title-family);
271
+ padding: 0 var(--pd-spacing-xs, 0.25rem);
272
+ }
273
+
274
+ .slots-list {
275
+ display: flex;
276
+ flex-direction: column;
277
+ gap: var(--pd-spacing-xs, 0.25rem);
278
+ max-height: var(--pd-slot-picker-slots-max-height, 400px);
279
+ overflow-y: auto;
280
+ }
281
+
282
+ .slots-empty {
283
+ padding: var(--pd-spacing-lg, 1.5rem);
284
+ text-align: center;
285
+ color: var(--pd-default-font-light-col, #6b7280);
286
+ font-style: italic;
287
+ }
288
+
289
+ .slots-placeholder {
290
+ padding: var(--pd-spacing-lg, 1.5rem);
291
+ text-align: center;
292
+ color: var(--pd-default-font-light-col, #6b7280);
293
+ }
294
+ `
295
+ ];
296
+ __decorateClass([
297
+ property({ type: Object })
298
+ ], PdSlotPicker.prototype, "data", 2);
299
+ __decorateClass([
300
+ property({ type: Object })
301
+ ], PdSlotPicker.prototype, "config", 2);
302
+ __decorateClass([
303
+ property({ type: Object })
304
+ ], PdSlotPicker.prototype, "refDate", 2);
305
+ __decorateClass([
306
+ property({ type: Boolean })
307
+ ], PdSlotPicker.prototype, "hideWeekend", 2);
308
+ __decorateClass([
309
+ property({ type: Number })
310
+ ], PdSlotPicker.prototype, "prevMonthConstraint", 2);
311
+ __decorateClass([
312
+ property({ type: Number })
313
+ ], PdSlotPicker.prototype, "nextMonthConstraint", 2);
314
+ __decorateClass([
315
+ property({ type: Array })
316
+ ], PdSlotPicker.prototype, "withYearPopup", 2);
317
+ __decorateClass([
318
+ property({ type: Boolean })
319
+ ], PdSlotPicker.prototype, "withWheelNavigation", 2);
320
+ __decorateClass([
321
+ property({ type: Boolean })
322
+ ], PdSlotPicker.prototype, "withTouchNavigation", 2);
323
+ __decorateClass([
324
+ state()
325
+ ], PdSlotPicker.prototype, "_selectedDateKey", 2);
326
+ __decorateClass([
327
+ state()
328
+ ], PdSlotPicker.prototype, "_selectedDate", 2);
329
+ __decorateClass([
330
+ state()
331
+ ], PdSlotPicker.prototype, "_selectedSlot", 2);
332
+ __decorateClass([
333
+ state()
334
+ ], PdSlotPicker.prototype, "_calendarRefDate", 2);
335
+ PdSlotPicker = __decorateClass([
336
+ localized()
337
+ ], PdSlotPicker);
338
+
339
+ export { PdSlotPicker };
@@ -0,0 +1,35 @@
1
+ import { CSSResultGroup } from 'lit';
2
+ import { PdBaseCell } from '../../shared/PdBaseCell.js';
3
+ /**
4
+ * A cell component for displaying a single time slot in the slot picker.
5
+ * Shows time range, title, and optional description.
6
+ *
7
+ * @tagname pd-slot-cell
8
+ * @summary Displays a single bookable time slot.
9
+ *
10
+ * @event select-slot - Fired when slot is selected. Detail: `{ dateKey: string, startTime: string, endTime: string, index: number }`.
11
+ *
12
+ * @cssprop --pd-slot-cell-bg-col - Background color. Default: `var(--pd-default-lightest-col)`.
13
+ * @cssprop --pd-slot-cell-bg-col-hover - Hover background color. Default: `var(--pd-default-light-col)`.
14
+ * @cssprop --pd-slot-cell-selected-bg-col - Selected background color. Default: `var(--pd-default-success-light-col)`.
15
+ * @cssprop --pd-slot-cell-selected-border-col - Selected border color. Default: `var(--pd-default-success-col)`.
16
+ * @cssprop --pd-slot-cell-category-bg-col - Category background color (set via inline style).
17
+ * @cssprop --pd-slot-cell-category-text-col - Category text color (set via inline style).
18
+ * @cssprop --pd-slot-cell-time-size - Time font size. Default: `0.95rem`.
19
+ * @cssprop --pd-slot-cell-time-col - Time text color. Default: `var(--pd-default-font-col)`.
20
+ * @cssprop --pd-slot-cell-title-size - Title font size. Default: `0.875rem`.
21
+ * @cssprop --pd-slot-cell-title-col - Title text color. Default: `var(--pd-default-font-col)`.
22
+ * @cssprop --pd-slot-cell-desc-size - Description font size. Default: `0.8rem`.
23
+ * @cssprop --pd-slot-cell-desc-col - Description text color. Default: `var(--pd-default-font-light-col)`.
24
+ * @cssprop --pd-slot-cell-availability-size - Availability badge font size. Default: `0.75rem`.
25
+ * @cssprop --pd-slot-cell-availability-col - Availability badge text color. Default: `var(--pd-default-font-light-col)`.
26
+ */
27
+ export declare class PdSlotCell extends PdBaseCell {
28
+ /** Index of this slot within the day's entries. */
29
+ index: number;
30
+ static styles: CSSResultGroup;
31
+ render(): import('lit').TemplateResult<1>;
32
+ protected _handleSelect(): void;
33
+ private _handleClick;
34
+ }
35
+ //# sourceMappingURL=PdSlotCell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PdSlotCell.d.ts","sourceRoot":"","sources":["../../../src/pd-slot-picker/pd-slot-cell/PdSlotCell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,MAAM,KAAK,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBACa,UAAW,SAAQ,UAAU;IACxC,mDAAmD;IAEnD,KAAK,SAAK;IAEV,OAAgB,MAAM,EAAE,cAAc,CAmHpC;IAEO,MAAM;cAiCI,aAAa,IAAI,IAAI;IAiBxC,OAAO,CAAC,YAAY;CAGrB"}
@@ -0,0 +1,188 @@
1
+ import { css, nothing, html } from 'lit';
2
+ import { property, customElement } from 'lit/decorators.js';
3
+ import { PdBaseCell } from '../../shared/PdBaseCell.js';
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __decorateClass = (decorators, target, key, kind) => {
8
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
9
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
10
+ if (decorator = decorators[i])
11
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
12
+ if (kind && result) __defProp(target, key, result);
13
+ return result;
14
+ };
15
+ let PdSlotCell = class extends PdBaseCell {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.index = 0;
19
+ }
20
+ render() {
21
+ const timeInfo = this._formatTime();
22
+ const cellClasses = this.category ? "slot-cell categorized" : "slot-cell";
23
+ const style = this._getCategoryStyle(
24
+ "--pd-slot-cell-category-bg-col",
25
+ "--pd-slot-cell-category-text-col"
26
+ );
27
+ return html`
28
+ <div
29
+ class="${cellClasses}"
30
+ style="${style}"
31
+ data-date="${this.key}"
32
+ @click="${this._handleClick}"
33
+ @keydown="${this._handleKeyDown}"
34
+ >
35
+ ${timeInfo ? html`<span class="time">${timeInfo}</span>` : ""}
36
+ <div class="content-group">
37
+ ${this.title ? html`<span class="title">${this.title}</span>` : ""}
38
+ ${this.desc ? html`<span class="description">${this.desc}</span>` : ""}
39
+ </div>
40
+ ${this.capacity != null ? html`<span class="availability"
41
+ >${Math.max(0, this.capacity - (this.booked ?? 0))}/${this.capacity}</span
42
+ >` : nothing}
43
+ </div>
44
+ `;
45
+ }
46
+ _handleSelect() {
47
+ if (this.disabled) return;
48
+ this.dispatchEvent(
49
+ new CustomEvent("select-slot", {
50
+ detail: {
51
+ dateKey: this.key,
52
+ startTime: this.startTime,
53
+ endTime: this.endTime,
54
+ index: this.index
55
+ },
56
+ bubbles: true,
57
+ composed: true
58
+ })
59
+ );
60
+ }
61
+ _handleClick() {
62
+ this._handleSelect();
63
+ }
64
+ };
65
+ PdSlotCell.styles = [
66
+ css`
67
+ :host {
68
+ display: block;
69
+ }
70
+
71
+ .slot-cell {
72
+ display: flex;
73
+ align-items: center;
74
+ gap: var(--pd-spacing-sm, 0.5rem);
75
+ padding: var(--pd-spacing-sm, 0.5rem) var(--pd-spacing-md, 1rem);
76
+ background-color: var(
77
+ --pd-slot-cell-bg-col,
78
+ var(--pd-default-lightest-col, #f9fafb)
79
+ );
80
+ border-radius: var(--pd-radius-sm, 4px);
81
+ cursor: pointer;
82
+ transition: background-color 0.15s ease;
83
+ }
84
+
85
+ .slot-cell:hover {
86
+ background-color: var(
87
+ --pd-slot-cell-bg-col-hover,
88
+ var(--pd-default-light-col, #f3f4f6)
89
+ );
90
+ }
91
+
92
+ :host([selected]) .slot-cell {
93
+ background-color: var(
94
+ --pd-slot-cell-selected-bg-col,
95
+ var(--pd-default-success-light-col, #dcfce7)
96
+ );
97
+ border-left: 3px solid
98
+ var(
99
+ --pd-slot-cell-selected-border-col,
100
+ var(--pd-default-success-col, #22c55e)
101
+ );
102
+ }
103
+
104
+ :host([disabled]) .slot-cell {
105
+ opacity: 0.4;
106
+ cursor: not-allowed;
107
+ pointer-events: none;
108
+ }
109
+
110
+ /* Categorized cells - colors set via inline style from category config */
111
+ .slot-cell.categorized {
112
+ background-color: var(
113
+ --pd-slot-cell-category-bg-col,
114
+ var(--pd-default-success-light-col, #dcfce7)
115
+ );
116
+ }
117
+
118
+ .slot-cell.categorized .time,
119
+ .slot-cell.categorized .title,
120
+ .slot-cell.categorized .description {
121
+ color: var(--pd-slot-cell-category-text-col);
122
+ }
123
+
124
+ .time {
125
+ font-size: var(--pd-slot-cell-time-size, 0.95rem);
126
+ font-weight: 600;
127
+ color: var(
128
+ --pd-slot-cell-time-col,
129
+ var(--pd-default-font-col, #374151)
130
+ );
131
+ white-space: nowrap;
132
+ min-width: 5em;
133
+ }
134
+
135
+ .content-group {
136
+ display: flex;
137
+ flex-direction: column;
138
+ flex: 1;
139
+ min-width: 0;
140
+ gap: 2px;
141
+ }
142
+
143
+ .title {
144
+ font-size: var(--pd-slot-cell-title-size, 0.875rem);
145
+ font-weight: 500;
146
+ color: var(
147
+ --pd-slot-cell-title-col,
148
+ var(--pd-default-font-col, #111827)
149
+ );
150
+ overflow: hidden;
151
+ text-overflow: ellipsis;
152
+ white-space: nowrap;
153
+ }
154
+
155
+ .description {
156
+ font-size: var(--pd-slot-cell-desc-size, 0.8rem);
157
+ color: var(
158
+ --pd-slot-cell-desc-col,
159
+ var(--pd-default-font-light-col, #6b7280)
160
+ );
161
+ }
162
+
163
+ .availability {
164
+ font-size: var(--pd-slot-cell-availability-size, 0.75rem);
165
+ color: var(
166
+ --pd-slot-cell-availability-col,
167
+ var(--pd-default-font-light-col, #6b7280)
168
+ );
169
+ white-space: nowrap;
170
+ margin-left: auto;
171
+ }
172
+
173
+ /* Focus styles for keyboard navigation */
174
+ :host(:focus-visible) .slot-cell {
175
+ outline: 2px solid
176
+ var(--pd-focus-ring-col, var(--pd-default-info-col, #3b82f6));
177
+ outline-offset: 2px;
178
+ }
179
+ `
180
+ ];
181
+ __decorateClass([
182
+ property({ type: Number })
183
+ ], PdSlotCell.prototype, "index", 2);
184
+ PdSlotCell = __decorateClass([
185
+ customElement("pd-slot-cell")
186
+ ], PdSlotCell);
187
+
188
+ export { PdSlotCell };
@@ -0,0 +1,3 @@
1
+ import { PdSlotCell } from './PdSlotCell.js';
2
+ export { PdSlotCell };
3
+ //# sourceMappingURL=pd-slot-cell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pd-slot-cell.d.ts","sourceRoot":"","sources":["../../../src/pd-slot-picker/pd-slot-cell/pd-slot-cell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAO7C,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { PdSlotCell } from './PdSlotCell.js';
2
+
3
+ const tag = "pd-slot-cell";
4
+ if (!customElements.get(tag)) {
5
+ customElements.define(tag, PdSlotCell);
6
+ }
7
+
8
+ export { PdSlotCell };
@@ -0,0 +1,3 @@
1
+ import { PdSlotPicker } from './PdSlotPicker.js';
2
+ export { PdSlotPicker };
3
+ //# sourceMappingURL=pd-slot-picker.d.ts.map