@bimetal/calendar-svelte-components 0.29.0 → 0.32.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 (32) hide show
  1. package/dist/components/Calendar.svelte +64 -31
  2. package/dist/components/Calendar.svelte.d.ts +14 -2
  3. package/dist/components/Calendar.svelte.d.ts.map +1 -1
  4. package/dist/components/CalendarHeader.svelte +10 -10
  5. package/dist/components/CategoryFilter.svelte +2 -2
  6. package/dist/components/EventBar.svelte +16 -12
  7. package/dist/components/EventBar.svelte.d.ts.map +1 -1
  8. package/dist/components/EventDialog.svelte +50 -50
  9. package/dist/components/EventHistory.svelte +17 -21
  10. package/dist/components/EventHistory.svelte.d.ts.map +1 -1
  11. package/dist/components/ResourceFilter.svelte +2 -2
  12. package/dist/components/UndoToast.svelte +5 -5
  13. package/dist/views/agenda/AgendaEvent.svelte +14 -13
  14. package/dist/views/agenda/AgendaEvent.svelte.d.ts +2 -1
  15. package/dist/views/agenda/AgendaEvent.svelte.d.ts.map +1 -1
  16. package/dist/views/agenda/AgendaView.svelte +57 -115
  17. package/dist/views/agenda/AgendaView.svelte.d.ts +3 -2
  18. package/dist/views/agenda/AgendaView.svelte.d.ts.map +1 -1
  19. package/dist/views/day/AllDayEvent.svelte +1 -1
  20. package/dist/views/day/DayView.svelte +16 -16
  21. package/dist/views/month/MonthView.svelte +4 -4
  22. package/dist/views/month/TimedEntry.svelte +10 -4
  23. package/dist/views/month/TimedEntry.svelte.d.ts.map +1 -1
  24. package/dist/views/month/WeekRow.svelte +13 -13
  25. package/dist/views/resource/ResourceView.svelte +18 -18
  26. package/dist/views/timeline/TimelineView.svelte +13 -13
  27. package/dist/views/week/AllDayRow.svelte +3 -3
  28. package/dist/views/week/TimeEvent.svelte +18 -7
  29. package/dist/views/week/TimeEvent.svelte.d.ts.map +1 -1
  30. package/dist/views/week/WeekView.svelte +15 -15
  31. package/dist/views/year/YearView.svelte +12 -12
  32. package/package.json +9 -8
@@ -120,7 +120,7 @@
120
120
 
121
121
  <div
122
122
  bind:this={rowEl}
123
- class="week-row"
123
+ class="bm-cal__week-row"
124
124
  style="--lane-count: {lanes};"
125
125
  role="row"
126
126
  tabindex="-1"
@@ -128,7 +128,7 @@
128
128
  ondragleave={handleDragLeave}
129
129
  ondrop={handleDrop}
130
130
  >
131
- <div class="week-number">{weekNumber}</div>
131
+ <div class="bm-cal__week-number">{weekNumber}</div>
132
132
 
133
133
  {#each weekDates as date, colIdx (colIdx)}
134
134
  {@const isToday = isSameDay(date, today)}
@@ -144,8 +144,8 @@
144
144
  {@const overflow = timedEvents.length - maxVisible}
145
145
 
146
146
  <div
147
- class="day-cell"
148
- class:outside-month={!inMonth}
147
+ class="bm-cal__day"
148
+ class:bm-cal__day--outside={!inMonth}
149
149
  style="grid-column: {colIdx + 2}; grid-row: 1 / -1; --lane-count: {cellLanes};"
150
150
  role="gridcell"
151
151
  tabindex="0"
@@ -154,14 +154,14 @@
154
154
  onclick={(e) => handleDayCellClick(e, date)}
155
155
  ondblclick={(e) => handleDayCellDoubleClick(e, date)}
156
156
  >
157
- <div class="day-number-container">
158
- <span class="day-number" class:today={isToday}>
157
+ <div class="bm-cal__day-number-container">
158
+ <span class="bm-cal__day-number" class:bm-cal__today={isToday}>
159
159
  {formatDayLabel(date, config.locale.code)}
160
160
  </span>
161
161
  </div>
162
162
 
163
163
  {#if timedEvents.length > 0}
164
- <div class="day-cell__timed">
164
+ <div class="bm-cal__day-timed">
165
165
  {#each showEvents as ev (ev.id)}
166
166
  <TimedEntry
167
167
  {ev}
@@ -173,7 +173,7 @@
173
173
  {/each}
174
174
  {#if !isExpanded && hasOverflow}
175
175
  <div
176
- class="timed-overflow"
176
+ class="bm-cal__timed-overflow"
177
177
  role="button"
178
178
  tabindex="0"
179
179
  onkeydown={(e) => { if (e.key === 'Enter' || e.key === ' ') ctx.onExpandMonthCell(dayMs); }}
@@ -186,12 +186,12 @@
186
186
 
187
187
  {#if isExpanded && hasOverflow}
188
188
  <div
189
- class="day-cell__expand-overlay"
189
+ class="bm-cal__day-expand-overlay"
190
190
  role="tooltip"
191
191
  onmouseleave={() => ctx.onCollapseMonthCell()}
192
192
  >
193
- <div class="day-number-container">
194
- <span class="day-number" class:today={isToday}>{dayNum}</span>
193
+ <div class="bm-cal__day-number-container">
194
+ <span class="bm-cal__day-number" class:bm-cal__today={isToday}>{dayNum}</span>
195
195
  </div>
196
196
  {#each timedEvents as ev (ev.id)}
197
197
  <TimedEntry
@@ -209,8 +209,8 @@
209
209
  {/each}
210
210
 
211
211
  <!-- Events overlay -->
212
- <div class="events-overlay">
213
- <div class="events-grid">
212
+ <div class="bm-cal__events-overlay">
213
+ <div class="bm-cal__events-grid">
214
214
  {#each items as layoutItem, idx (`${layoutItem.segment.event.id}-${idx}`)}
215
215
  {@const isDragged = ctx.previewEvent?.id === layoutItem.segment.event.id}
216
216
  <EventBar
@@ -120,7 +120,7 @@
120
120
 
121
121
  function handleColumnClick(e: MouseEvent) {
122
122
  if (!click.accept(config.clickThresholdMs)) return;
123
- if ((e.target as HTMLElement).closest('.time-event')) return;
123
+ if ((e.target as HTMLElement).closest('.bm-cal-time-event')) return;
124
124
  // Single click deselects; create-dialog moves to dblclick.
125
125
  if (ctx.selectedEventId !== null) ctx.onClearSelection();
126
126
  }
@@ -128,7 +128,7 @@
128
128
  function handleColumnDoubleClick(e: MouseEvent, resourceId: string) {
129
129
  if (!click.accept(config.clickThresholdMs)) return;
130
130
  if (!gridInnerEl) return;
131
- if ((e.target as HTMLElement).closest('.time-event')) return;
131
+ if ((e.target as HTMLElement).closest('.bm-cal-time-event')) return;
132
132
  const time = getTimeFromMouseY(e.clientY, gridInnerEl);
133
133
  const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
134
134
  onResourceCellClick(currentDate, time, resourceId, rect);
@@ -136,28 +136,28 @@
136
136
  </script>
137
137
 
138
138
  {#if visibleResources.length === 0}
139
- <div class="resource-view resource-view--empty">{config.locale.unassigned ?? 'No resource selected'}</div>
139
+ <div class="bm-cal-resource bm-cal-resource--empty">{config.locale.unassigned}</div>
140
140
  {:else}
141
- <div class="resource-view">
142
- <div class="resource-view__header">
143
- <div class="resource-view__day-name">{dayName}</div>
144
- <div class="resource-view__resources">
145
- <div class="resource-view__time-spacer" style:width={`${DEFAULT_TIME_LABEL_WIDTH_DAY}px`}></div>
141
+ <div class="bm-cal-resource">
142
+ <div class="bm-cal-resource__header">
143
+ <div class="bm-cal-resource__day-name">{dayName}</div>
144
+ <div class="bm-cal-resource__resources">
145
+ <div class="bm-cal-resource__time-spacer" style:width={`${DEFAULT_TIME_LABEL_WIDTH_DAY}px`}></div>
146
146
  {#each visibleResources as r (r.id)}
147
- <div class="resource-view__resource-header" style="flex: 1 1 0; min-width: 0;">
147
+ <div class="bm-cal-resource__resource-header" style="flex: 1 1 0; min-width: 0;">
148
148
  {#if r.color}
149
- <span class="resource-view__resource-dot" style:background-color={r.color}></span>
149
+ <span class="bm-cal-resource__resource-dot" style:background-color={r.color}></span>
150
150
  {/if}
151
- <span class="resource-view__resource-name">{r.name}</span>
151
+ <span class="bm-cal-resource__resource-name">{r.name}</span>
152
152
  </div>
153
153
  {/each}
154
154
  </div>
155
155
  </div>
156
156
 
157
- <div class="resource-view__time-grid" bind:this={timeGridEl}>
157
+ <div class="bm-cal-resource__time-grid" bind:this={timeGridEl}>
158
158
  <!-- svelte-ignore a11y_no_static_element_interactions -->
159
159
  <div
160
- class="resource-view__time-grid-inner"
160
+ class="bm-cal-resource__time-grid-inner"
161
161
  bind:this={gridInnerEl}
162
162
  style:height={`${24 * DEFAULT_HOUR_HEIGHT}px`}
163
163
  ondragover={handleGridDragOver}
@@ -168,11 +168,11 @@
168
168
  {@const wh = config.core.workingHours}
169
169
  {@const isOff = wh ? (hr < wh.start || hr >= wh.end) : false}
170
170
  <div
171
- class="resource-view__hour-row{isOff ? ' hour-slot--off' : ''}"
171
+ class="bm-cal-resource__hour-row{isOff ? ' bm-cal__hour-slot--off' : ''}"
172
172
  style:top={`${hr * DEFAULT_HOUR_HEIGHT}px`}
173
173
  style:height={`${DEFAULT_HOUR_HEIGHT}px`}
174
174
  >
175
- <div class="resource-view__hour-label">
175
+ <div class="bm-cal-resource__hour-label">
176
176
  {hr > 0 ? `${String(hr).padStart(2, '0')}:00` : ''}
177
177
  </div>
178
178
  </div>
@@ -181,7 +181,7 @@
181
181
  {#each visibleResources as r, idx (`col-${r.id}`)}
182
182
  <!-- svelte-ignore a11y_click_events_have_key_events -->
183
183
  <div
184
- class="resource-view__resource-col"
184
+ class="bm-cal-resource__resource-col"
185
185
  role="gridcell"
186
186
  tabindex="-1"
187
187
  style:left={`calc(${DEFAULT_TIME_LABEL_WIDTH_DAY}px + ${idx} * ${colWidth})`}
@@ -214,11 +214,11 @@
214
214
 
215
215
  {#if isToday}
216
216
  <div
217
- class="resource-view__now-line"
217
+ class="bm-cal-resource__now-line"
218
218
  style:top={`${nowHours * DEFAULT_HOUR_HEIGHT}px`}
219
219
  style:left={`${DEFAULT_TIME_LABEL_WIDTH_DAY}px`}
220
220
  >
221
- <div class="resource-view__now-dot"></div>
221
+ <div class="bm-cal-resource__now-dot"></div>
222
222
  </div>
223
223
  {/if}
224
224
  </div>
@@ -113,35 +113,35 @@
113
113
  </script>
114
114
 
115
115
  {#if visibleResources.length === 0}
116
- <div class="timeline-view timeline-view--empty">
117
- {config.locale.unassigned ?? 'No resource selected'}
116
+ <div class="bm-cal-timeline bm-cal-timeline--empty">
117
+ {config.locale.unassigned}
118
118
  </div>
119
119
  {:else}
120
- <div class="timeline-view">
121
- <div class="timeline-view__header" style:grid-template-columns={colTemplate}>
122
- <div class="timeline-view__corner"></div>
120
+ <div class="bm-cal-timeline">
121
+ <div class="bm-cal-timeline__header" style:grid-template-columns={colTemplate}>
122
+ <div class="bm-cal-timeline__corner"></div>
123
123
  {#each dates as d (d.epochMs)}
124
124
  {@const isToday = isSameDay(d, today)}
125
- <div class="timeline-view__date-header{isToday ? ' timeline-view__date-header--today' : ''}">
125
+ <div class="bm-cal-timeline__date-header{isToday ? ' bm-cal-timeline__date-header--today' : ''}">
126
126
  {dateFmt.format(new Date(d.epochMs))}
127
127
  </div>
128
128
  {/each}
129
129
  </div>
130
130
 
131
- <div class="timeline-view__body">
131
+ <div class="bm-cal-timeline__body">
132
132
  {#each visibleResources as r (r.id)}
133
133
  {@const items = lanesByResource.get(r.id) ?? []}
134
134
  {@const lanes = Math.max(1, maxLanes(items))}
135
- <div class="timeline-view__lane">
136
- <div class="timeline-view__resource-label" style:width={`${DEFAULT_RESOURCE_LABEL_WIDTH}px`}>
135
+ <div class="bm-cal-timeline__lane">
136
+ <div class="bm-cal-timeline__resource-label" style:width={`${DEFAULT_RESOURCE_LABEL_WIDTH}px`}>
137
137
  {#if r.color}
138
- <span class="timeline-view__resource-dot" style:background-color={r.color}></span>
138
+ <span class="bm-cal-timeline__resource-dot" style:background-color={r.color}></span>
139
139
  {/if}
140
- <span class="timeline-view__resource-name">{r.name}</span>
140
+ <span class="bm-cal-timeline__resource-name">{r.name}</span>
141
141
  </div>
142
142
  <!-- svelte-ignore a11y_no_static_element_interactions -->
143
143
  <div
144
- class="timeline-view__lane-content"
144
+ class="bm-cal-timeline__lane-content"
145
145
  style:display="grid"
146
146
  style:grid-template-columns={`repeat(${days}, 1fr)`}
147
147
  style:grid-auto-rows="32px"
@@ -154,7 +154,7 @@
154
154
  {@const isToday = isSameDay(d, today)}
155
155
  <button
156
156
  type="button"
157
- class="timeline-view__cell{isToday ? ' timeline-view__cell--today' : ''}"
157
+ class="bm-cal-timeline__cell{isToday ? ' bm-cal-timeline__cell--today' : ''}"
158
158
  style:grid-column={i + 1}
159
159
  style:grid-row="1 / -1"
160
160
  aria-label="{r.name}, {dateFmt.format(new Date(d.epochMs))}"
@@ -53,14 +53,14 @@
53
53
  {#if items.length > 0}
54
54
  <div
55
55
  bind:this={rowEl}
56
- class="week-view__allday"
56
+ class="bm-cal-week__allday"
57
57
  role="application"
58
58
  ondragover={handleDragOver}
59
59
  ondrop={handleDrop}
60
60
  ondragleave={handleDragLeave}
61
61
  >
62
- <div class="week-view__allday-label">{config.locale.allDayLabel}</div>
63
- <div class="week-view__allday-grid" style="--lane-count: {lanes};">
62
+ <div class="bm-cal-week__allday-label">{config.locale.allDayLabel}</div>
63
+ <div class="bm-cal-week__allday-grid" style="--lane-count: {lanes};">
64
64
  {#each items as layoutItem, idx (`${layoutItem.segment.event.id}-${idx}`)}
65
65
  {@const isDragged = ctx.previewEvent?.id === layoutItem.segment.event.id}
66
66
  <EventBar
@@ -4,6 +4,7 @@
4
4
  import { getCalendarContext, getCalendarConfig, toTimeStr, buildDragInfo, getEventSlots } from '../../binding/index.js';
5
5
  import type { DragInfo } from '../../binding/index.js';
6
6
  import { createClickIntent, writeCalendarDragData, installTransparentDragImage } from '@bimetal/calendar-headless';
7
+ import { probeRender } from '@bimetal/svelte';
7
8
 
8
9
  /**
9
10
  * Layout-Position eines Termins (Pilot-Direktive 2026-06-21). Zwei
@@ -132,10 +133,22 @@
132
133
  ? Object.entries(slots.style).map(([k, v]) => `${k.replace(/[A-Z]/g, m => '-' + m.toLowerCase())}: ${v}`).join('; ')
133
134
  : '');
134
135
  const style = $derived(slotStyleStr ? `${baseStyle} ${slotStyleStr}` : baseStyle);
136
+
137
+ // The week timed-layout rebuilds its `item`/`event` wrappers every snapshot, so the raw `event`
138
+ // prop ref churns even for unchanged events. Route the id through an equality-gated `$derived` so
139
+ // the probe below tracks the STABLE id string, not the churning prop ref (the DOM-driving
140
+ // deriveds `style`/`renderedTitle`/… already gate the same churn to their stable values).
141
+ const eventId = $derived(event.id);
142
+
143
+ // v0.30 Slice 3 perf probe: re-runs (post-DOM) ONLY when this event's DOM-driving deriveds
144
+ // change. `style` folds in all `layout` geometry (top/height/left/width fractions), and
145
+ // `isSelected` is equality-gated — so a selection or geometry change elsewhere does NOT
146
+ // re-run unchanged events, proving fine-grained reactivity even with the context selection read.
147
+ $effect(() => { void style; void isSelected; void renderedTitle; void timeLabel; void duration; probeRender(eventId); });
135
148
  </script>
136
149
 
137
150
  <div
138
- class="time-event{ghost ? ' time-event--ghost' : ''}{isSelected ? ' time-event--selected' : ''}{extraClass}"
151
+ class="bm-cal-time-event{ghost ? ' bm-cal-time-event--ghost' : ''}{isSelected ? ' bm-cal-time-event--selected' : ''}{extraClass}"
139
152
  {style}
140
153
  draggable={!ghost}
141
154
  role="button"
@@ -155,9 +168,8 @@
155
168
  {#if isFirstDay && !ghost}
156
169
  <!-- svelte-ignore a11y_no_noninteractive_element_interactions a11y_no_noninteractive_tabindex a11y_no_static_element_interactions -->
157
170
  <div
158
- class="time-event__resize time-event__resize--top"
171
+ class="bm-cal-time-event__resize bm-cal-time-event__resize--top"
159
172
  role="separator"
160
- aria-label="Resize start"
161
173
  draggable={true}
162
174
  ondragstart={(e) => handleResizeDragStart(e, 'start')}
163
175
  ondragend={ctx.onDragEnd}
@@ -168,9 +180,9 @@
168
180
  {#if slots.content}
169
181
  {#if typeof slots.content === 'string'}{slots.content}{:else}{@render slots.content()}{/if}
170
182
  {:else}
171
- <div class="time-event__title">{renderedTitle}</div>
183
+ <div class="bm-cal-time-event__title">{renderedTitle}</div>
172
184
  {#if duration >= 0.75 && timeLabel}
173
- <div class="time-event__time">{timeLabel}</div>
185
+ <div class="bm-cal-time-event__time">{timeLabel}</div>
174
186
  {/if}
175
187
  {/if}
176
188
  {#if slots.badges}
@@ -180,9 +192,8 @@
180
192
  {#if isLastDay && !ghost}
181
193
  <!-- svelte-ignore a11y_no_noninteractive_element_interactions a11y_no_noninteractive_tabindex a11y_no_static_element_interactions -->
182
194
  <div
183
- class="time-event__resize time-event__resize--bottom"
195
+ class="bm-cal-time-event__resize bm-cal-time-event__resize--bottom"
184
196
  role="separator"
185
- aria-label="Resize end"
186
197
  draggable={true}
187
198
  ondragstart={(e) => handleResizeDragStart(e, 'end')}
188
199
  ondragend={ctx.onDragEnd}
@@ -1 +1 @@
1
- {"version":3,"file":"TimeEvent.svelte.d.ts","sourceRoot":"","sources":["../../../src/views/week/TimeEvent.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAO5E;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AACF,KAAK,gBAAgB,GAAI;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAgJJ,QAAA,MAAM,SAAS,sDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"TimeEvent.svelte.d.ts","sourceRoot":"","sources":["../../../src/views/week/TimeEvent.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAQ5E;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AACF,KAAK,gBAAgB,GAAI;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AA6JJ,QAAA,MAAM,SAAS,sDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -120,14 +120,14 @@
120
120
 
121
121
  function handleGridClick(e: MouseEvent) {
122
122
  if (!click.accept(config.clickThresholdMs)) return;
123
- if ((e.target as HTMLElement).closest('.time-event')) return;
123
+ if ((e.target as HTMLElement).closest('.bm-cal-time-event')) return;
124
124
  // Single click on empty grid deselects; create-dialog moves to dblclick.
125
125
  if (ctx.selectedEventId !== null) ctx.onClearSelection();
126
126
  }
127
127
 
128
128
  function handleGridDoubleClick(e: MouseEvent) {
129
129
  if (!click.accept(config.clickThresholdMs)) return;
130
- if ((e.target as HTMLElement).closest('.time-event')) return;
130
+ if ((e.target as HTMLElement).closest('.bm-cal-time-event')) return;
131
131
  if (!gridInnerEl) return;
132
132
  const gridRect = gridInnerEl.getBoundingClientRect();
133
133
  const hit = timeGridHit({ x: e.clientX, y: e.clientY }, gridRect, { labelWidth: DEFAULT_TIME_LABEL_WIDTH_WEEK, hourHeight: DEFAULT_HOUR_HEIGHT, snapMinutes: timeSnapMinutes });
@@ -139,15 +139,15 @@
139
139
  }
140
140
  </script>
141
141
 
142
- <div class="week-view">
142
+ <div class="bm-cal-week">
143
143
  <!-- Header -->
144
- <div class="week-view__header">
145
- <div class="week-view__corner">{config.locale.calendarWeek} {weekNumber}</div>
144
+ <div class="bm-cal-week__header">
145
+ <div class="bm-cal-week__corner">{config.locale.calendarWeek} {weekNumber}</div>
146
146
  {#each weekDates as date, i (i)}
147
147
  {@const isToday = isSameDay(date, currentNow)}
148
- <div class="week-view__day-header{isToday ? ' week-view__day-header--today' : ''}">
149
- <span class="week-view__day-name">{config.locale.dayNamesShort[i]}</span>
150
- <span class="week-view__day-number{isToday ? ' week-view__day-number--today' : ''}">
148
+ <div class="bm-cal-week__day-header{isToday ? ' bm-cal-week__day-header--today' : ''}">
149
+ <span class="bm-cal-week__day-name">{config.locale.dayNamesShort[i]}</span>
150
+ <span class="bm-cal-week__day-number{isToday ? ' bm-cal-week__day-number--today' : ''}">
151
151
  {getDayOfMonth(date)}
152
152
  </span>
153
153
  </div>
@@ -160,7 +160,7 @@
160
160
  <!-- Time grid -->
161
161
  <div
162
162
  bind:this={timeGridEl}
163
- class="week-view__time-grid"
163
+ class="bm-cal-week__time-grid"
164
164
  role="grid"
165
165
  tabindex="0"
166
166
  ondragover={handleGridDragOver}
@@ -173,7 +173,7 @@
173
173
  >
174
174
  <div
175
175
  bind:this={gridInnerEl}
176
- class="week-view__time-grid-inner"
176
+ class="bm-cal-week__time-grid-inner"
177
177
  style="height: {24 * DEFAULT_HOUR_HEIGHT}px;"
178
178
  >
179
179
  <!-- Hour rows -->
@@ -181,10 +181,10 @@
181
181
  {@const wh = config.core.workingHours}
182
182
  {@const isOff = wh ? (hr < wh.start || hr >= wh.end) : false}
183
183
  <div
184
- class="week-view__hour-row{isOff ? ' hour-slot--off' : ''}"
184
+ class="bm-cal-week__hour-row{isOff ? ' bm-cal__hour-slot--off' : ''}"
185
185
  style="top: {hr * DEFAULT_HOUR_HEIGHT}px; height: {DEFAULT_HOUR_HEIGHT}px;"
186
186
  >
187
- <div class="week-view__hour-label">
187
+ <div class="bm-cal-week__hour-label">
188
188
  {hr > 0 ? `${String(hr).padStart(2, '0')}:00` : ''}
189
189
  </div>
190
190
  </div>
@@ -193,7 +193,7 @@
193
193
  <!-- Day columns -->
194
194
  {#each weekDates as _, col (col)}
195
195
  <div
196
- class="week-view__day-col"
196
+ class="bm-cal-week__day-col"
197
197
  style="left: calc({DEFAULT_TIME_LABEL_WIDTH_WEEK}px + {col} * (100% - {DEFAULT_TIME_LABEL_WIDTH_WEEK}px) / 7); width: calc((100% - {DEFAULT_TIME_LABEL_WIDTH_WEEK}px) / 7);"
198
198
  ></div>
199
199
  {/each}
@@ -221,10 +221,10 @@
221
221
  <!-- Now line -->
222
222
  {#if nowCol >= 0}
223
223
  <div
224
- class="week-view__now-line"
224
+ class="bm-cal-week__now-line"
225
225
  style="top: {nowHours * DEFAULT_HOUR_HEIGHT}px; left: calc({DEFAULT_TIME_LABEL_WIDTH_WEEK}px + {nowCol} * (100% - {DEFAULT_TIME_LABEL_WIDTH_WEEK}px) / 7); width: calc((100% - {DEFAULT_TIME_LABEL_WIDTH_WEEK}px) / 7);"
226
226
  >
227
- <div class="week-view__now-dot"></div>
227
+ <div class="bm-cal-week__now-dot"></div>
228
228
  </div>
229
229
  {/if}
230
230
  </div>
@@ -51,22 +51,22 @@
51
51
  }
52
52
  </script>
53
53
 
54
- <div class="year-grid">
54
+ <div class="bm-cal-year">
55
55
  {#each months as { month, label, weeks } (month)}
56
- <div class="year-month">
56
+ <div class="bm-cal-year-month">
57
57
  {#if onMonthClick}
58
- <button type="button" class="year-month__header" onclick={() => onMonthClick?.(year, month)}>
58
+ <button type="button" class="bm-cal-year-month__header" onclick={() => onMonthClick?.(year, month)}>
59
59
  {label}
60
60
  </button>
61
61
  {:else}
62
- <div class="year-month__header">{label}</div>
62
+ <div class="bm-cal-year-month__header">{label}</div>
63
63
  {/if}
64
- <div class="year-month__day-headers">
64
+ <div class="bm-cal-year-month__day-headers">
65
65
  {#each config.locale.dayNamesShort as n (n)}
66
- <div class="year-month__day-header">{n[0]}</div>
66
+ <div class="bm-cal-year-month__day-header">{n[0]}</div>
67
67
  {/each}
68
68
  </div>
69
- <div class="year-month__days">
69
+ <div class="bm-cal-year-month__days">
70
70
  {#each weeks as week, wIdx (wIdx)}
71
71
  {#each week as date (date.epochMs)}
72
72
  {@const inMonth = getMonth(date) === month}
@@ -75,14 +75,14 @@
75
75
  <button
76
76
  type="button"
77
77
  class={
78
- 'year-month__day'
79
- + (inMonth ? '' : ' year-month__day--outside')
80
- + (isToday ? ' year-month__day--today' : '')
81
- + (hasEvents ? ' year-month__day--has-events' : '')
78
+ 'bm-cal-year-month__day'
79
+ + (inMonth ? '' : ' bm-cal-year-month__day--outside')
80
+ + (isToday ? ' bm-cal-year-month__day--today' : '')
81
+ + (hasEvents ? ' bm-cal-year-month__day--has-events' : '')
82
82
  }
83
83
  onclick={(e) => dayClick(e, date)}
84
84
  >
85
- <span class="year-month__day-num">{getDayOfMonth(date)}</span>
85
+ <span class="bm-cal-year-month__day-num">{getDayOfMonth(date)}</span>
86
86
  </button>
87
87
  {/each}
88
88
  {/each}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bimetal/calendar-svelte-components",
3
- "version": "0.29.0",
3
+ "version": "0.32.0",
4
4
  "description": "Default Svelte 5 calendar UI components",
5
5
  "type": "module",
6
6
  "svelte": "./dist/index.js",
@@ -27,13 +27,14 @@
27
27
  "prepublishOnly": "npm run build"
28
28
  },
29
29
  "dependencies": {
30
- "@bimetal/svelte": "^0.29.0",
31
- "@bimetal/core": "^0.29.0",
32
- "@bimetal/calendar-core": "^0.29.0",
33
- "@bimetal/calendar-data": "^0.29.0",
34
- "@bimetal/calendar-headless": "^0.29.0",
35
- "@bimetal/calendar-rules": "^0.29.0",
36
- "@bimetal/calendar-themes": "^0.29.0"
30
+ "@bimetal/svelte": "^0.32.0",
31
+ "@bimetal/core": "^0.32.0",
32
+ "@bimetal/calendar-core": "^0.32.0",
33
+ "@bimetal/calendar-data": "^0.32.0",
34
+ "@bimetal/calendar-headless": "^0.32.0",
35
+ "@bimetal/a11y-dom": "^0.32.0",
36
+ "@bimetal/calendar-rules": "^0.32.0",
37
+ "@bimetal/calendar-themes": "^0.32.0"
37
38
  },
38
39
  "peerDependencies": {
39
40
  "svelte": "^5.46.4"