@forcecalendar/interface 1.0.44 → 1.0.45
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.
- package/dist/force-calendar-interface.esm.js +557 -554
- package/dist/force-calendar-interface.esm.js.map +1 -1
- package/dist/force-calendar-interface.umd.js +12 -12
- package/dist/force-calendar-interface.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ForceCalendar.js +17 -2
- package/src/core/StateManager.js +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"force-calendar-interface.umd.js","sources":["../src/core/BaseComponent.js","../src/core/EventBus.js","../src/core/StateManager.js","../src/utils/DateUtils.js","../src/utils/DOMUtils.js","../src/utils/StyleUtils.js","../src/renderers/BaseViewRenderer.js","../src/renderers/MonthViewRenderer.js","../src/renderers/WeekViewRenderer.js","../src/renderers/DayViewRenderer.js","../src/components/EventForm.js","../src/components/ForceCalendar.js"],"sourcesContent":["/**\n * BaseComponent - Foundation for all Force Calendar Web Components\n *\n * Provides common functionality:\n * - Shadow DOM setup\n * - Event handling\n * - State management integration\n * - Lifecycle management\n * - Style management\n */\n\nexport class BaseComponent extends HTMLElement {\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n this._listeners = [];\n this._state = null;\n this._props = new Map();\n this._initialized = false;\n }\n\n // Lifecycle methods\n connectedCallback() {\n if (!this._initialized) {\n this.initialize();\n this._initialized = true;\n }\n this.mount();\n }\n\n disconnectedCallback() {\n this.unmount();\n this.cleanup();\n }\n\n // To be overridden by child classes\n initialize() {\n // Setup component-specific initialization\n }\n\n mount() {\n // Component mounted to DOM\n this.render();\n }\n\n unmount() {\n // Component removed from DOM\n }\n\n cleanup() {\n // Clean up event listeners\n this._listeners.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler);\n });\n this._listeners = [];\n }\n\n // State management\n setState(newState) {\n const oldState = this._state;\n this._state = { ...this._state, ...newState };\n this.stateChanged(oldState, this._state);\n this.render();\n }\n\n getState() {\n return this._state;\n }\n\n stateChanged(_oldState, _newState) {\n // Override in child classes to handle state changes\n }\n\n // Props management\n setProp(key, value) {\n const oldValue = this._props.get(key);\n this._props.set(key, value);\n this.propChanged(key, oldValue, value);\n }\n\n getProp(key) {\n return this._props.get(key);\n }\n\n propChanged(_key, _oldValue, _newValue) {\n // Override in child classes to handle prop changes\n }\n\n // Event handling\n addListener(element, event, handler) {\n if (!element || !event || !handler) {\n console.warn('addListener called with invalid parameters', { element, event, handler });\n return;\n }\n const boundHandler = handler.bind(this);\n element.addEventListener(event, boundHandler);\n this._listeners.push({ element, event, handler: boundHandler });\n }\n\n emit(eventName, detail = {}) {\n this.dispatchEvent(\n new CustomEvent(eventName, {\n detail,\n bubbles: true,\n composed: true\n })\n );\n }\n\n // Style management\n getStyles() {\n // Override in child classes to provide component styles\n return '';\n }\n\n getBaseStyles() {\n return `\n :host {\n display: block;\n box-sizing: border-box;\n }\n\n *, *::before, *::after {\n box-sizing: inherit;\n }\n `;\n }\n\n // Template rendering\n render() {\n // Clean up existing listeners before replacing DOM\n this.cleanup();\n\n const styles = `\n <style>\n ${this.getBaseStyles()}\n ${this.getStyles()}\n </style>\n `;\n\n const template = this.template();\n this.shadowRoot.innerHTML = styles + template;\n this.afterRender();\n }\n\n template() {\n // Override in child classes to provide component template\n return '';\n }\n\n afterRender() {\n // Override in child classes for post-render operations\n }\n\n // Utility methods\n $(selector) {\n return this.shadowRoot.querySelector(selector);\n }\n\n $$(selector) {\n return this.shadowRoot.querySelectorAll(selector);\n }\n\n // Attribute observation\n static get observedAttributes() {\n return [];\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n this.setProp(name, newValue);\n if (this._initialized) {\n this.render();\n }\n }\n}\n","/**\n * EventBus - Central event communication system\n *\n * Enables decoupled communication between components\n * Supports event namespacing and wildcard subscriptions\n */\n\nclass EventBus {\n constructor() {\n this.events = new Map();\n this.wildcardHandlers = new Set();\n }\n\n /**\n * Subscribe to an event\n * @param {string} eventName - Event name or pattern (supports wildcards)\n * @param {Function} handler - Event handler function\n * @param {Object} options - Subscription options\n * @returns {Function} Unsubscribe function\n */\n on(eventName, handler, options = {}) {\n const { once = false, priority = 0 } = options;\n\n // Handle wildcard subscriptions\n if (eventName.includes('*')) {\n const subscription = { pattern: eventName, handler, once, priority };\n this.wildcardHandlers.add(subscription);\n return () => this.wildcardHandlers.delete(subscription);\n }\n\n // Regular event subscription\n if (!this.events.has(eventName)) {\n this.events.set(eventName, []);\n }\n\n const subscription = { handler, once, priority };\n const handlers = this.events.get(eventName);\n handlers.push(subscription);\n handlers.sort((a, b) => b.priority - a.priority);\n\n // Return unsubscribe function\n return () => {\n const index = handlers.indexOf(subscription);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n };\n }\n\n /**\n * Subscribe to an event that fires only once\n */\n once(eventName, handler, options = {}) {\n return this.on(eventName, handler, { ...options, once: true });\n }\n\n /**\n * Unsubscribe from an event\n */\n off(eventName, handler) {\n // Handle wildcard pattern removal\n if (eventName.includes('*')) {\n for (const sub of this.wildcardHandlers) {\n if (sub.pattern === eventName && sub.handler === handler) {\n this.wildcardHandlers.delete(sub);\n return;\n }\n }\n return;\n }\n\n if (!this.events.has(eventName)) return;\n\n const handlers = this.events.get(eventName);\n const index = handlers.findIndex(sub => sub.handler === handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n\n if (handlers.length === 0) {\n this.events.delete(eventName);\n }\n }\n\n /**\n * Remove all wildcard handlers matching a pattern\n * @param {string} pattern - Pattern to match (e.g., 'event:*')\n */\n offWildcard(pattern) {\n for (const sub of [...this.wildcardHandlers]) {\n if (sub.pattern === pattern) {\n this.wildcardHandlers.delete(sub);\n }\n }\n }\n\n /**\n * Remove all handlers (regular and wildcard) for a specific handler function\n * Useful for cleanup when a component is destroyed\n * @param {Function} handler - Handler function to remove\n */\n offAll(handler) {\n // Remove from regular events\n for (const [eventName, handlers] of this.events) {\n const index = handlers.findIndex(sub => sub.handler === handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n if (handlers.length === 0) {\n this.events.delete(eventName);\n }\n }\n\n // Remove from wildcard handlers\n for (const sub of [...this.wildcardHandlers]) {\n if (sub.handler === handler) {\n this.wildcardHandlers.delete(sub);\n }\n }\n }\n\n /**\n * Emit an event synchronously\n * @param {string} eventName - Event name\n * @param {*} data - Event data\n */\n emit(eventName, data) {\n // Handle direct subscriptions\n if (this.events.has(eventName)) {\n const handlers = [...this.events.get(eventName)];\n\n for (const subscription of handlers) {\n const { handler, once } = subscription;\n\n if (once) {\n this.off(eventName, handler);\n }\n\n try {\n handler(data, eventName);\n } catch (error) {\n console.error(`Error in event handler for ${eventName}:`, error);\n }\n }\n }\n\n // Handle wildcard subscriptions (copy Set to avoid mutation during iteration)\n const toRemove = [];\n for (const subscription of [...this.wildcardHandlers]) {\n if (this.matchesPattern(eventName, subscription.pattern)) {\n const { handler, once } = subscription;\n\n if (once) {\n toRemove.push(subscription);\n }\n\n try {\n handler(data, eventName);\n } catch (error) {\n console.error(`Error in wildcard handler for ${eventName}:`, error);\n }\n }\n }\n // Remove one-time handlers after iteration\n toRemove.forEach(sub => this.wildcardHandlers.delete(sub));\n }\n\n /**\n * Check if event name matches a pattern\n */\n matchesPattern(eventName, pattern) {\n const regex = new RegExp('^' + pattern.replace(/\\*/g, '.*') + '$');\n return regex.test(eventName);\n }\n\n /**\n * Clear all event subscriptions\n */\n clear() {\n this.events.clear();\n this.wildcardHandlers.clear();\n }\n\n /**\n * Get all registered event names\n */\n getEventNames() {\n return Array.from(this.events.keys());\n }\n\n /**\n * Get handler count for an event\n */\n getHandlerCount(eventName) {\n return this.events.has(eventName) ? this.events.get(eventName).length : 0;\n }\n\n /**\n * Get wildcard handler count\n */\n getWildcardHandlerCount() {\n return this.wildcardHandlers.size;\n }\n\n /**\n * Get total handler count (for debugging/monitoring)\n */\n getTotalHandlerCount() {\n let count = this.wildcardHandlers.size;\n for (const handlers of this.events.values()) {\n count += handlers.length;\n }\n return count;\n }\n}\n\n// Create singleton instance\nconst eventBus = new EventBus();\n\n// Export both the class and singleton\nexport { EventBus, eventBus as default };\n","/**\n * StateManager - Centralized state management for Force Calendar\n *\n * Wraps the @forcecalendar/core Calendar instance\n * Provides reactive state updates and component synchronization\n */\n\nimport { Calendar } from '@forcecalendar/core';\nimport { EventBus } from './EventBus.js';\n\nclass StateManager {\n constructor(config = {}) {\n // Each StateManager gets its own EventBus to prevent cross-instance\n // contamination when multiple calendars exist on the same page.\n this.eventBus = new EventBus();\n\n // Initialize Core Calendar instance\n this.calendar = new Calendar({\n view: config.view || 'month',\n date: config.date || new Date(),\n weekStartsOn: config.weekStartsOn ?? 0,\n locale: config.locale || 'en-US',\n timeZone: config.timeZone || Intl.DateTimeFormat().resolvedOptions().timeZone,\n ...config\n });\n\n // Internal state\n this.state = {\n view: this.calendar.getView(),\n currentDate: this.calendar.getCurrentDate(),\n events: [],\n selectedEvent: null,\n selectedDate: null,\n loading: false,\n error: null,\n config: { ...config }\n };\n\n // State change subscribers\n this.subscribers = new Set();\n\n // Bind methods\n this.subscribe = this.subscribe.bind(this);\n this.unsubscribe = this.unsubscribe.bind(this);\n this.setState = this.setState.bind(this);\n\n // Initial sync of events from Core (in case events were pre-loaded)\n this._syncEventsFromCore({ silent: true });\n }\n\n /**\n * Sync state.events from Core calendar (single source of truth)\n * This ensures state.events always matches Core's event store.\n *\n * @param {object} options\n * @param {boolean} options.silent - suppress subscriber notifications\n * @param {boolean} options.force - always update even when IDs match\n * (required after updateEvent where IDs\n * are unchanged but content has changed)\n */\n _syncEventsFromCore(options = {}) {\n const { force = false } = options;\n const coreEvents = this.calendar.getEvents() || [];\n // Skip the update when nothing changed, unless the caller forces a sync\n // (e.g. after updateEvent where IDs are the same but content differs)\n if (\n force ||\n this.state.events.length !== coreEvents.length ||\n !this._eventsMatch(this.state.events, coreEvents)\n ) {\n this.setState({ events: [...coreEvents] }, options);\n }\n return coreEvents;\n }\n\n /**\n * Check if two event arrays have the same events by id.\n * Only used for add/delete guards — updateEvent must pass force:true\n * to bypass this check because IDs are unchanged after an update.\n */\n _eventsMatch(arr1, arr2) {\n if (arr1.length !== arr2.length) return false;\n const ids1 = new Set(arr1.map(e => e.id));\n return arr2.every(e => ids1.has(e.id));\n }\n\n // State management\n getState() {\n return {\n ...this.state,\n config: { ...this.state.config },\n events: [...this.state.events]\n };\n }\n\n setState(updates, options = {}) {\n const { silent = false } = options;\n const oldState = { ...this.state };\n this.state = { ...this.state, ...updates };\n\n if (!silent) {\n this.notifySubscribers(oldState, this.state);\n this.emitStateChange(oldState, this.state);\n }\n\n return this.state;\n }\n\n subscribe(callback, subscriberId = null) {\n this.subscribers.add(callback);\n\n // Track subscriber ID for debugging/cleanup\n if (subscriberId) {\n if (!this._subscriberIds) {\n this._subscriberIds = new Map();\n }\n this._subscriberIds.set(subscriberId, callback);\n }\n\n return () => this.unsubscribe(callback, subscriberId);\n }\n\n unsubscribe(callback, subscriberId = null) {\n this.subscribers.delete(callback);\n\n // Clean up ID tracking\n if (subscriberId && this._subscriberIds) {\n this._subscriberIds.delete(subscriberId);\n }\n }\n\n /**\n * Unsubscribe by subscriber ID\n * @param {string} subscriberId - ID used when subscribing\n */\n unsubscribeById(subscriberId) {\n if (!this._subscriberIds) return false;\n\n const callback = this._subscriberIds.get(subscriberId);\n if (callback) {\n this.subscribers.delete(callback);\n this._subscriberIds.delete(subscriberId);\n return true;\n }\n return false;\n }\n\n /**\n * Get subscriber count (for debugging/monitoring)\n */\n getSubscriberCount() {\n return this.subscribers.size;\n }\n\n notifySubscribers(oldState, newState) {\n this.subscribers.forEach(callback => {\n try {\n callback(newState, oldState);\n } catch (error) {\n console.error('Error in state subscriber:', error);\n }\n });\n }\n\n emitStateChange(oldState, newState) {\n const changedKeys = Object.keys(newState).filter(key => oldState[key] !== newState[key]);\n\n changedKeys.forEach(key => {\n this.eventBus.emit(`state:${key}:changed`, {\n oldValue: oldState[key],\n newValue: newState[key],\n state: newState\n });\n });\n\n if (changedKeys.length > 0) {\n this.eventBus.emit('state:changed', { oldState, newState, changedKeys });\n }\n }\n\n // Calendar operations\n setView(view) {\n this.calendar.setView(view);\n this.setState({ view });\n this.eventBus.emit('view:changed', { view });\n }\n\n getView() {\n return this.state.view;\n }\n\n setDate(date) {\n this.calendar.goToDate(date);\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('date:changed', { date: this.state.currentDate });\n }\n\n getCurrentDate() {\n return this.state.currentDate;\n }\n\n // Navigation\n next() {\n this.calendar.next();\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('navigation:next', { date: this.state.currentDate });\n }\n\n previous() {\n this.calendar.previous();\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('navigation:previous', { date: this.state.currentDate });\n }\n\n today() {\n this.calendar.today();\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('navigation:today', { date: this.state.currentDate });\n }\n\n goToDate(date) {\n this.calendar.goToDate(date);\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('navigation:goto', { date: this.state.currentDate });\n }\n\n // Event management\n addEvent(event) {\n const addedEvent = this.calendar.addEvent(event);\n if (!addedEvent) {\n console.error('Failed to add event to calendar');\n this.eventBus.emit('event:error', { action: 'add', event, error: 'Failed to add event' });\n return null;\n }\n // Sync from Core to ensure consistency (single source of truth)\n this._syncEventsFromCore();\n this.eventBus.emit('event:add', { event: addedEvent });\n this.eventBus.emit('event:added', { event: addedEvent });\n return addedEvent;\n }\n\n updateEvent(eventId, updates) {\n // First, ensure state is in sync with Core (recover from any prior desync)\n this._syncEventsFromCore({ silent: true });\n\n const event = this.calendar.updateEvent(eventId, updates);\n if (!event) {\n console.error(`Failed to update event: ${eventId}`);\n this.eventBus.emit('event:error', {\n action: 'update',\n eventId,\n updates,\n error: 'Event not found in calendar'\n });\n return null;\n }\n\n // Force sync from Core — IDs are unchanged after an update so the\n // ID-only guard in _eventsMatch would otherwise skip the state update\n this._syncEventsFromCore({ force: true });\n this.eventBus.emit('event:update', { event });\n this.eventBus.emit('event:updated', { event });\n return event;\n }\n\n deleteEvent(eventId) {\n // First, ensure state is in sync with Core (recover from any prior desync)\n this._syncEventsFromCore({ silent: true });\n\n const deleted = this.calendar.removeEvent(eventId);\n if (!deleted) {\n console.error(`Failed to delete event: ${eventId}`);\n this.eventBus.emit('event:error', { action: 'delete', eventId, error: 'Event not found' });\n return false;\n }\n // Sync from Core to ensure consistency (single source of truth)\n this._syncEventsFromCore();\n this.eventBus.emit('event:remove', { eventId });\n this.eventBus.emit('event:deleted', { eventId });\n return true;\n }\n\n getEvents() {\n // Return from Core (source of truth)\n return this.calendar.getEvents() || [];\n }\n\n /**\n * Force sync state.events from Core calendar\n * Use this if you've modified events directly on the Core calendar\n */\n syncEvents() {\n return this._syncEventsFromCore();\n }\n\n getEventsForDate(date) {\n return this.calendar.getEventsForDate(date);\n }\n\n getEventsInRange(start, end) {\n return this.calendar.getEventsInRange(start, end);\n }\n\n // View data\n getViewData() {\n const viewData = this.calendar.getViewData();\n return this.enrichViewData(viewData);\n }\n\n enrichViewData(viewData) {\n // Shallow-copy the top-level object so we never mutate what Core returned.\n // Core may cache and reuse the same reference across calls; mutating it\n // in-place would corrupt its internal state.\n const enriched = { ...viewData };\n const selectedDateString = this.state.selectedDate?.toDateString();\n\n // Strategy 1: Multi-week structure (Month view)\n if (enriched.weeks) {\n enriched.weeks = enriched.weeks.map(week => ({\n ...week,\n days: week.days.map(day => {\n const dayDate = new Date(day.date);\n return {\n ...day,\n isSelected: dayDate.toDateString() === selectedDateString,\n events: day.events || this.getEventsForDate(dayDate)\n };\n })\n }));\n }\n\n // Strategy 2: Flat days structure (Week view or list view)\n if (enriched.days) {\n enriched.days = enriched.days.map(day => {\n const dayDate = new Date(day.date);\n return {\n ...day,\n isSelected: dayDate.toDateString() === selectedDateString,\n events: day.events || this.getEventsForDate(dayDate)\n };\n });\n }\n\n // Strategy 3: Single day structure (Day view)\n if (enriched.date && !enriched.days && !enriched.weeks) {\n const dayDate = new Date(enriched.date);\n enriched.isSelected = dayDate.toDateString() === selectedDateString;\n enriched.events = enriched.events || this.getEventsForDate(dayDate);\n }\n\n return enriched;\n }\n\n // Selection management\n selectEvent(event) {\n this.setState({ selectedEvent: event });\n this.eventBus.emit('event:selected', { event });\n }\n\n selectEventById(eventId) {\n const event = this.state.events.find(e => e.id === eventId);\n if (event) {\n this.selectEvent(event);\n }\n }\n\n deselectEvent() {\n this.setState({ selectedEvent: null });\n this.eventBus.emit('event:deselected', {});\n }\n\n selectDate(date) {\n this.setState({ selectedDate: date });\n this.eventBus.emit('date:selected', { date });\n }\n\n deselectDate() {\n this.setState({ selectedDate: null });\n this.eventBus.emit('date:deselected', {});\n }\n\n // Utility methods\n isToday(date) {\n const today = new Date();\n return date.toDateString() === today.toDateString();\n }\n\n isSelectedDate(date) {\n return (\n this.state.selectedDate && date.toDateString() === this.state.selectedDate.toDateString()\n );\n }\n\n isWeekend(date) {\n const day = date.getDay();\n return day === 0 || day === 6;\n }\n\n // Loading state\n setLoading(loading) {\n this.setState({ loading });\n }\n\n // Error handling\n setError(error) {\n this.setState({ error });\n if (error) {\n this.eventBus.emit('error', { error });\n }\n }\n\n clearError() {\n this.setState({ error: null });\n }\n\n // Configuration\n updateConfig(config) {\n this.setState({ config: { ...this.state.config, ...config } });\n\n // Update calendar configuration if needed\n if (config.weekStartsOn !== undefined) {\n this.calendar.setWeekStartsOn(config.weekStartsOn);\n }\n if (config.locale !== undefined) {\n this.calendar.setLocale(config.locale);\n }\n if (config.timeZone !== undefined) {\n this.calendar.setTimezone(config.timeZone);\n }\n }\n\n // Destroy\n destroy() {\n this.subscribers.clear();\n if (this._subscriberIds) {\n this._subscriberIds.clear();\n this._subscriberIds = null;\n }\n this.state = null;\n this.calendar = null;\n }\n}\n\n// Export StateManager\nexport default StateManager;\n","/**\n * DateUtils - Date formatting and manipulation utilities\n *\n * Extends Core DateUtils with UI-specific formatting\n */\n\nimport { DateUtils as CoreDateUtils } from '@forcecalendar/core';\n\nexport class DateUtils extends CoreDateUtils {\n /**\n * Format date for display\n */\n static formatDate(date, format = 'default', locale = 'en-US') {\n if (!date) return '';\n\n const formats = {\n default: { year: 'numeric', month: 'long', day: 'numeric' },\n short: { year: 'numeric', month: 'short', day: 'numeric' },\n long: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' },\n month: { year: 'numeric', month: 'long' },\n monthShort: { year: 'numeric', month: 'short' },\n day: { weekday: 'long', day: 'numeric' },\n dayShort: { weekday: 'short', day: 'numeric' },\n time: { hour: 'numeric', minute: '2-digit' },\n timeShort: { hour: 'numeric' },\n datetime: {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n }\n };\n\n const options = formats[format] || formats.default;\n return new Intl.DateTimeFormat(locale, options).format(date);\n }\n\n /**\n * Format time for display\n */\n static formatTime(date, showMinutes = true, use24Hour = false, locale = 'en-US') {\n if (!date) return '';\n\n const options = {\n hour: 'numeric',\n minute: showMinutes ? '2-digit' : undefined,\n hour12: !use24Hour\n };\n\n return new Intl.DateTimeFormat(locale, options).format(date);\n }\n\n /**\n * Format date range for display\n */\n static formatDateRange(start, end, locale = 'en-US') {\n if (!start) return '';\n if (!end || this.isSameDay(start, end)) {\n return this.formatDate(start, 'default', locale);\n }\n\n const startFormat = this.isSameYear(start, end) ? 'short' : 'default';\n return `${this.formatDate(start, startFormat, locale)} - ${this.formatDate(end, 'default', locale)}`;\n }\n\n /**\n * Format time range for display\n */\n static formatTimeRange(start, end, locale = 'en-US') {\n if (!start) return '';\n\n const startTime = this.formatTime(start, true, false, locale);\n if (!end) return startTime;\n\n const endTime = this.formatTime(end, true, false, locale);\n return `${startTime} - ${endTime}`;\n }\n\n /**\n * Get relative time string (e.g., \"2 hours ago\", \"in 3 days\")\n */\n static getRelativeTime(date, baseDate = new Date(), locale = 'en-US') {\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });\n const diff = date - baseDate;\n const diffInSeconds = Math.floor(diff / 1000);\n const diffInMinutes = Math.floor(diffInSeconds / 60);\n const diffInHours = Math.floor(diffInMinutes / 60);\n const diffInDays = Math.floor(diffInHours / 24);\n const diffInWeeks = Math.floor(diffInDays / 7);\n const diffInMonths = Math.floor(diffInDays / 30);\n const diffInYears = Math.floor(diffInDays / 365);\n\n if (Math.abs(diffInSeconds) < 60) {\n return rtf.format(diffInSeconds, 'second');\n } else if (Math.abs(diffInMinutes) < 60) {\n return rtf.format(diffInMinutes, 'minute');\n } else if (Math.abs(diffInHours) < 24) {\n return rtf.format(diffInHours, 'hour');\n } else if (Math.abs(diffInDays) < 7) {\n return rtf.format(diffInDays, 'day');\n } else if (Math.abs(diffInWeeks) < 4) {\n return rtf.format(diffInWeeks, 'week');\n } else if (Math.abs(diffInMonths) < 12) {\n return rtf.format(diffInMonths, 'month');\n } else {\n return rtf.format(diffInYears, 'year');\n }\n }\n\n /**\n * Check if date is today\n */\n static isToday(date) {\n const today = new Date();\n return this.isSameDay(date, today);\n }\n\n /**\n * Check if date is in the past\n */\n static isPast(date) {\n return date < new Date();\n }\n\n /**\n * Check if date is in the future\n */\n static isFuture(date) {\n return date > new Date();\n }\n\n /**\n * Get calendar week number\n */\n static getWeekNumber(date) {\n const firstDayOfYear = new Date(date.getFullYear(), 0, 1);\n const pastDaysOfYear = (date - firstDayOfYear) / 86400000;\n return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);\n }\n\n /**\n * Get day abbreviation\n */\n static getDayAbbreviation(dayIndex, locale = 'en-US') {\n const date = new Date(2024, 0, 7 + dayIndex); // Jan 7, 2024 is a Sunday\n return new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(date);\n }\n\n /**\n * Get month name\n */\n static getMonthName(monthIndex, format = 'long', locale = 'en-US') {\n const date = new Date(2024, monthIndex, 1);\n return new Intl.DateTimeFormat(locale, { month: format }).format(date);\n }\n\n /**\n * Parse time string (e.g., \"14:30\" or \"2:30 PM\")\n */\n static parseTimeString(timeStr, baseDate = new Date()) {\n const date = new Date(baseDate);\n const [time, period] = timeStr.split(/\\s+/);\n const [hours, minutes] = time.split(':').map(Number);\n\n let adjustedHours = hours;\n if (period) {\n if (period.toLowerCase() === 'pm' && hours < 12) {\n adjustedHours = hours + 12;\n } else if (period.toLowerCase() === 'am' && hours === 12) {\n adjustedHours = 0;\n }\n }\n\n date.setHours(adjustedHours, minutes || 0, 0, 0);\n return date;\n }\n}\n\nexport default DateUtils;\n","/**\n * DOMUtils - DOM manipulation and event utilities\n */\n\nexport class DOMUtils {\n /**\n * Create element with attributes and children\n */\n static createElement(tag, attributes = {}, children = []) {\n const element = document.createElement(tag);\n\n // Set attributes\n Object.entries(attributes).forEach(([key, value]) => {\n if (key === 'className') {\n element.className = value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(element.style, value);\n } else if (key.startsWith('data-')) {\n element.setAttribute(key, value);\n } else if (key.startsWith('on') && typeof value === 'function') {\n const eventName = key.slice(2).toLowerCase();\n element.addEventListener(eventName, value);\n } else {\n element[key] = value;\n }\n });\n\n // Add children\n children.forEach(child => {\n if (typeof child === 'string') {\n element.appendChild(document.createTextNode(child));\n } else if (child instanceof Node) {\n element.appendChild(child);\n }\n });\n\n return element;\n }\n\n /**\n * Add multiple event listeners\n */\n static addEventListeners(element, events) {\n Object.entries(events).forEach(([event, handler]) => {\n element.addEventListener(event, handler);\n });\n\n // Return cleanup function\n return () => {\n Object.entries(events).forEach(([event, handler]) => {\n element.removeEventListener(event, handler);\n });\n };\n }\n\n /**\n * Delegate event handling\n */\n static delegate(element, selector, event, handler) {\n const delegatedHandler = e => {\n const target = e.target.closest(selector);\n if (target && element.contains(target)) {\n handler.call(target, e);\n }\n };\n\n element.addEventListener(event, delegatedHandler);\n return () => element.removeEventListener(event, delegatedHandler);\n }\n\n /**\n * Get element position relative to viewport\n */\n static getPosition(element) {\n const rect = element.getBoundingClientRect();\n return {\n top: rect.top + window.scrollY,\n left: rect.left + window.scrollX,\n bottom: rect.bottom + window.scrollY,\n right: rect.right + window.scrollX,\n width: rect.width,\n height: rect.height\n };\n }\n\n /**\n * Check if element is in viewport\n */\n static isInViewport(element, threshold = 0) {\n const rect = element.getBoundingClientRect();\n return (\n rect.top >= -threshold &&\n rect.left >= -threshold &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) + threshold &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth) + threshold\n );\n }\n\n /**\n * Smooth scroll to element\n */\n static scrollToElement(element, options = {}) {\n const { behavior = 'smooth', block = 'start', inline = 'nearest' } = options;\n element.scrollIntoView({ behavior, block, inline });\n }\n\n /**\n * Get computed style value\n */\n static getStyle(element, property) {\n return window.getComputedStyle(element).getPropertyValue(property);\n }\n\n /**\n * Set multiple styles\n */\n static setStyles(element, styles) {\n Object.assign(element.style, styles);\n }\n\n /**\n * Add/remove classes with animation support\n */\n static async animateClass(element, className, duration = 300) {\n element.classList.add(className);\n await this.wait(duration);\n element.classList.remove(className);\n }\n\n /**\n * Wait for animation/transition to complete\n */\n static waitForAnimation(element, eventType = 'animationend') {\n return new Promise(resolve => {\n const handler = () => {\n element.removeEventListener(eventType, handler);\n resolve();\n };\n element.addEventListener(eventType, handler);\n });\n }\n\n /**\n * Utility wait function\n */\n static wait(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n /**\n * Parse HTML string safely\n */\n static parseHTML(htmlString) {\n const template = document.createElement('template');\n template.innerHTML = htmlString.trim();\n return template.content.firstChild;\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n static escapeHTML(str) {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n\n /**\n * Debounce function calls\n */\n static debounce(func, wait = 250) {\n let timeout;\n return function executedFunction(...args) {\n const later = () => {\n clearTimeout(timeout);\n func(...args);\n };\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n };\n }\n\n /**\n * Throttle function calls\n */\n static throttle(func, limit = 250) {\n let inThrottle;\n return function (...args) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n }\n\n /**\n * Get closest parent matching selector\n */\n static closest(element, selector) {\n return element.closest(selector);\n }\n\n /**\n * Get all parents matching selector\n */\n static parents(element, selector) {\n const parents = [];\n let parent = element.parentElement;\n\n while (parent) {\n if (parent.matches(selector)) {\n parents.push(parent);\n }\n parent = parent.parentElement;\n }\n\n return parents;\n }\n\n /**\n * Measure element dimensions including margins\n */\n static getOuterDimensions(element) {\n const styles = window.getComputedStyle(element);\n const margin = {\n top: parseInt(styles.marginTop),\n right: parseInt(styles.marginRight),\n bottom: parseInt(styles.marginBottom),\n left: parseInt(styles.marginLeft)\n };\n\n return {\n width: element.offsetWidth + margin.left + margin.right,\n height: element.offsetHeight + margin.top + margin.bottom,\n margin\n };\n }\n\n /**\n * Clone element with event listeners\n */\n static cloneWithEvents(element, deep = true) {\n const clone = element.cloneNode(deep);\n\n // Copy event listeners (Note: This is a simplified version)\n // In production, you'd need a more robust event copying mechanism\n return clone;\n }\n\n /**\n * Focus trap for modals/dialogs\n */\n static trapFocus(container) {\n const focusableElements = container.querySelectorAll(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n );\n\n // Handle case where there are no focusable elements\n if (focusableElements.length === 0) {\n // Make container focusable as fallback\n container.setAttribute('tabindex', '-1');\n container.focus();\n return () => container.removeAttribute('tabindex');\n }\n\n const firstFocusable = focusableElements[0];\n const lastFocusable = focusableElements[focusableElements.length - 1];\n\n const handleKeyDown = e => {\n if (e.key !== 'Tab') return;\n\n if (e.shiftKey) {\n if (document.activeElement === firstFocusable) {\n lastFocusable?.focus();\n e.preventDefault();\n }\n } else {\n if (document.activeElement === lastFocusable) {\n firstFocusable?.focus();\n e.preventDefault();\n }\n }\n };\n\n container.addEventListener('keydown', handleKeyDown);\n firstFocusable?.focus();\n\n return () => container.removeEventListener('keydown', handleKeyDown);\n }\n}\n\nexport default DOMUtils;\n","/**\n * StyleUtils - Styling utilities and theme management\n */\n\nexport class StyleUtils {\n /**\n * Default theme colors\n */\n static colors = {\n primary: '#3B82F6', // Modern Blue\n secondary: '#64748B', // Slate\n accent: '#F59E0B', // Amber\n danger: '#EF4444', // Red\n warning: '#F97316', // Orange\n info: '#06B6D4', // Cyan\n success: '#22C55E', // Green\n light: '#F8FAFC',\n dark: '#0F172A',\n white: '#FFFFFF',\n gray: {\n 50: '#F8FAFC',\n 100: '#F1F5F9',\n 200: '#E2E8F0',\n 300: '#CBD5E1',\n 400: '#94A3B8',\n 500: '#64748B',\n 600: '#475569',\n 700: '#334155',\n 800: '#1E293B',\n 900: '#0F172A'\n }\n };\n\n /**\n * Common CSS variables\n */\n static cssVariables = {\n // \"Pro\" Palette - Functional & Sharp\n '--fc-primary-color': '#2563EB', // International Blue (Focus)\n '--fc-primary-hover': '#1D4ED8',\n '--fc-primary-light': '#EFF6FF',\n\n // Neutral Scale (Slate/Gray for structure)\n '--fc-text-color': '#111827', // Almost Black\n '--fc-text-secondary': '#6B7280', // Cool Gray\n '--fc-text-light': '#9CA3AF',\n\n '--fc-border-color': '#E5E7EB', // Crisp Light Gray\n '--fc-border-color-hover': '#D1D5DB',\n\n '--fc-background': '#FFFFFF',\n '--fc-background-alt': '#FAFAFA', // Very subtle off-white\n '--fc-background-hover': '#F3F4F6',\n '--fc-background-active': '#E5E7EB',\n\n // Semantic Colors\n '--fc-accent-color': '#F59E0B',\n '--fc-danger-color': '#EF4444',\n '--fc-success-color': '#10B981',\n\n // Typography - optimized for UI density\n '--fc-font-family': 'Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n '--fc-font-size-xs': '11px',\n '--fc-font-size-sm': '12px',\n '--fc-font-size-base': '13px', // Slightly smaller for density\n '--fc-font-size-lg': '15px',\n '--fc-font-size-xl': '18px',\n '--fc-font-size-2xl': '24px',\n '--fc-line-height': '1.4',\n '--fc-font-weight-normal': '400',\n '--fc-font-weight-medium': '500',\n '--fc-font-weight-semibold': '600',\n '--fc-font-weight-bold': '700',\n\n // Spacing - Tighter\n '--fc-spacing-xs': '2px',\n '--fc-spacing-sm': '6px',\n '--fc-spacing-md': '10px',\n '--fc-spacing-lg': '14px',\n '--fc-spacing-xl': '20px',\n '--fc-spacing-2xl': '28px',\n\n // Border\n '--fc-border-width': '1px',\n '--fc-border-radius-sm': '3px', // Micro rounding\n '--fc-border-radius': '5px',\n '--fc-border-radius-lg': '8px',\n '--fc-border-radius-full': '9999px',\n\n // Shadows - Minimal/Functional\n '--fc-shadow-sm': '0 1px 1px rgba(0,0,0,0.05)',\n '--fc-shadow': '0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06)',\n '--fc-shadow-md': '0 4px 6px -1px rgba(0, 0, 0, 0.1)',\n '--fc-shadow-lg': '0 10px 15px -3px rgba(0, 0, 0, 0.1)',\n\n // Transitions - Snappy\n '--fc-transition-fast': '100ms ease-out',\n '--fc-transition': '150ms ease-out',\n '--fc-transition-slow': '250ms ease-out',\n\n // Z-index\n '--fc-z-dropdown': '1000',\n '--fc-z-modal': '2000',\n '--fc-z-tooltip': '3000'\n };\n\n /**\n * Get CSS variable value\n */\n static getCSSVariable(name, element = document.documentElement) {\n return getComputedStyle(element).getPropertyValue(name).trim();\n }\n\n /**\n * Set CSS variables\n */\n static setCSSVariables(variables, element = document.documentElement) {\n Object.entries(variables).forEach(([key, value]) => {\n element.style.setProperty(key, value);\n });\n }\n\n /**\n * Generate base styles\n */\n static getBaseStyles() {\n return `\n :host {\n /* Apply CSS variables */\n ${Object.entries(this.cssVariables)\n .map(([key, value]) => `${key}: ${value};`)\n .join('\\n ')}\n\n /* Base styles */\n display: block;\n box-sizing: border-box;\n font-family: var(--fc-font-family);\n font-size: var(--fc-font-size-base);\n line-height: var(--fc-line-height);\n color: var(--fc-text-color);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n\n *, *::before, *::after {\n box-sizing: inherit;\n }\n\n /* Reset styles */\n h1, h2, h3, h4, h5, h6, p {\n margin: 0;\n font-weight: normal;\n }\n\n button {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n margin: 0;\n }\n\n /* Accessibility */\n .visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* Focus styles */\n :focus-visible {\n outline: 2px solid var(--fc-primary-color);\n outline-offset: 2px;\n }\n `;\n }\n\n /**\n * Generate button styles\n */\n static getButtonStyles() {\n return `\n .fc-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 8px 16px;\n font-size: var(--fc-font-size-sm);\n font-weight: var(--fc-font-weight-medium);\n line-height: 1.25rem;\n border-radius: var(--fc-border-radius);\n border: 1px solid transparent;\n cursor: pointer;\n transition: all var(--fc-transition-fast);\n outline: none;\n user-select: none;\n gap: var(--fc-spacing-sm);\n white-space: nowrap;\n }\n\n .fc-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .fc-btn-primary {\n background: var(--fc-primary-color);\n color: white;\n box-shadow: var(--fc-shadow-sm);\n }\n\n .fc-btn-primary:hover:not(:disabled) {\n background: var(--fc-primary-hover);\n box-shadow: var(--fc-shadow);\n }\n\n .fc-btn-secondary {\n background: white;\n border-color: var(--fc-border-color);\n color: var(--fc-text-color);\n box-shadow: var(--fc-shadow-sm);\n }\n\n .fc-btn-secondary:hover:not(:disabled) {\n background: var(--fc-background-hover);\n border-color: var(--fc-border-color-hover);\n }\n\n .fc-btn-outline {\n background: transparent;\n border-color: var(--fc-border-color);\n color: var(--fc-text-secondary);\n }\n\n .fc-btn-outline:hover:not(:disabled) {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n border-color: var(--fc-border-color-hover);\n }\n\n .fc-btn-ghost {\n background: transparent;\n color: var(--fc-text-secondary);\n }\n\n .fc-btn-ghost:hover:not(:disabled) {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n }\n\n .fc-btn-sm {\n padding: 6px 12px;\n font-size: var(--fc-font-size-xs);\n }\n\n .fc-btn-lg {\n padding: 10px 20px;\n font-size: var(--fc-font-size-base);\n }\n\n .fc-btn-icon {\n width: 32px;\n height: 32px;\n padding: 0;\n border-radius: var(--fc-border-radius-full);\n }\n `;\n }\n\n /**\n * Darken color by percentage\n */\n static darken(color, percent) {\n const num = parseInt(color.replace('#', ''), 16);\n const amt = Math.round(2.55 * percent);\n const R = (num >> 16) - amt;\n const G = ((num >> 8) & 0x00ff) - amt;\n const B = (num & 0x0000ff) - amt;\n return (\n '#' +\n (\n 0x1000000 +\n (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +\n (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +\n (B < 255 ? (B < 1 ? 0 : B) : 255)\n )\n .toString(16)\n .slice(1)\n );\n }\n\n /**\n * Lighten color by percentage\n */\n static lighten(color, percent) {\n const num = parseInt(color.replace('#', ''), 16);\n const amt = Math.round(2.55 * percent);\n const R = (num >> 16) + amt;\n const G = ((num >> 8) & 0x00ff) + amt;\n const B = (num & 0x0000ff) + amt;\n return (\n '#' +\n (\n 0x1000000 +\n (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +\n (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +\n (B < 255 ? (B < 1 ? 0 : B) : 255)\n )\n .toString(16)\n .slice(1)\n );\n }\n\n /**\n * Get contrast color (black or white) for background\n */\n static getContrastColor(bgColor) {\n const color = bgColor.replace('#', '');\n const r = parseInt(color.substr(0, 2), 16);\n const g = parseInt(color.substr(2, 2), 16);\n const b = parseInt(color.substr(4, 2), 16);\n const yiq = (r * 299 + g * 587 + b * 114) / 1000;\n return yiq >= 128 ? '#000000' : '#FFFFFF';\n }\n\n /**\n * Sanitize color value to prevent CSS injection\n * Returns the color if valid, or a fallback color if invalid\n */\n static sanitizeColor(color, fallback = 'var(--fc-primary-color)') {\n if (!color || typeof color !== 'string') {\n return fallback;\n }\n\n // Trim and check for dangerous characters that could break out of CSS\n const trimmed = color.trim();\n if (/[;{}()<>\\\"\\'\\\\]/.test(trimmed)) {\n return fallback;\n }\n\n // Allow hex colors (#RGB, #RRGGBB, #RRGGBBAA)\n if (/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(trimmed)) {\n return trimmed;\n }\n\n // Allow CSS variables\n if (/^var\\(--[a-zA-Z0-9-]+\\)$/.test(trimmed)) {\n return trimmed;\n }\n\n // Allow rgb/rgba with numbers only\n if (/^rgba?\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*(,\\s*(0|1|0?\\.\\d+))?\\s*\\)$/.test(trimmed)) {\n return trimmed;\n }\n\n // Allow safe CSS color keywords\n const safeKeywords = [\n 'transparent',\n 'currentColor',\n 'inherit',\n 'black',\n 'white',\n 'red',\n 'green',\n 'blue',\n 'yellow',\n 'orange',\n 'purple',\n 'pink',\n 'brown',\n 'gray',\n 'grey',\n 'cyan',\n 'magenta',\n 'lime',\n 'navy',\n 'teal',\n 'aqua',\n 'maroon',\n 'olive',\n 'silver',\n 'fuchsia'\n ];\n if (safeKeywords.includes(trimmed.toLowerCase())) {\n return trimmed;\n }\n\n return fallback;\n }\n\n /**\n * Convert hex to rgba\n */\n static hexToRgba(hex, alpha = 1) {\n const color = hex.replace('#', '');\n const r = parseInt(color.substr(0, 2), 16);\n const g = parseInt(color.substr(2, 2), 16);\n const b = parseInt(color.substr(4, 2), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n /**\n * Generate grid styles\n */\n static getGridStyles() {\n return `\n .fc-grid {\n display: grid;\n gap: 1px;\n background: var(--fc-border-color);\n border: 1px solid var(--fc-border-color);\n border-radius: var(--fc-border-radius);\n overflow: hidden;\n }\n\n .fc-grid-cell {\n background: var(--fc-background);\n padding: var(--fc-spacing-sm);\n min-height: 100px;\n position: relative;\n }\n\n .fc-grid-cell:hover {\n background: var(--fc-background-hover);\n }\n\n .fc-grid-header {\n background: var(--fc-background-alt);\n padding: var(--fc-spacing-sm);\n font-weight: var(--fc-font-weight-semibold);\n text-align: center;\n color: var(--fc-text-secondary);\n font-size: var(--fc-font-size-xs);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n `;\n }\n\n /**\n * Get responsive breakpoints\n */\n static breakpoints = {\n xs: '320px',\n sm: '576px',\n md: '768px',\n lg: '992px',\n xl: '1200px',\n '2xl': '1400px'\n };\n\n /**\n * Generate media query\n */\n static mediaQuery(breakpoint, styles) {\n const size = this.breakpoints[breakpoint];\n if (!size) return '';\n return `@media (min-width: ${size}) { ${styles} }`;\n }\n\n /**\n * Animation keyframes\n */\n static getAnimations() {\n return `\n @keyframes fc-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes fc-slide-in-up {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n @keyframes fc-slide-in-down {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n @keyframes fc-scale-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n @keyframes fc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n .fc-fade-in {\n animation: fc-fade-in var(--fc-transition);\n }\n\n .fc-slide-in-up {\n animation: fc-slide-in-up var(--fc-transition);\n }\n\n .fc-scale-in {\n animation: fc-scale-in var(--fc-transition);\n }\n `;\n }\n}\n\nexport default StyleUtils;\n","/**\n * BaseViewRenderer - Foundation for all view renderers\n *\n * Pure JavaScript class (no Web Components) for Salesforce Locker Service compatibility.\n * Provides common functionality for rendering calendar views.\n */\n\nimport { DOMUtils } from '../utils/DOMUtils.js';\nimport { StyleUtils } from '../utils/StyleUtils.js';\n\nexport class BaseViewRenderer {\n /**\n * @param {HTMLElement} container - The DOM element to render into\n * @param {StateManager} stateManager - The state manager instance\n */\n constructor(container, stateManager) {\n this.container = container;\n this.stateManager = stateManager;\n this._listeners = [];\n this._scrolled = false;\n }\n\n /**\n * Render the view into the container\n * Must be implemented by subclasses\n */\n render() {\n throw new Error('render() must be implemented by subclass');\n }\n\n /**\n * Clean up event listeners\n */\n cleanup() {\n this._listeners.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler);\n });\n this._listeners = [];\n }\n\n /**\n * Add an event listener with automatic cleanup tracking\n * @param {HTMLElement} element\n * @param {string} event\n * @param {Function} handler\n */\n addListener(element, event, handler) {\n const boundHandler = handler.bind(this);\n element.addEventListener(event, boundHandler);\n this._listeners.push({ element, event, handler: boundHandler });\n }\n\n /**\n * Escape HTML to prevent XSS\n * @param {string} str\n * @returns {string}\n */\n escapeHTML(str) {\n if (str === null || str === undefined) return '';\n return DOMUtils.escapeHTML(String(str));\n }\n\n /**\n * Check if a date is today\n * @param {Date} date\n * @returns {boolean}\n */\n isToday(date) {\n const today = new Date();\n return (\n date.getDate() === today.getDate() &&\n date.getMonth() === today.getMonth() &&\n date.getFullYear() === today.getFullYear()\n );\n }\n\n /**\n * Check if two dates are the same day\n * @param {Date} date1\n * @param {Date} date2\n * @returns {boolean}\n */\n isSameDay(date1, date2) {\n return (\n date1.getDate() === date2.getDate() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getFullYear() === date2.getFullYear()\n );\n }\n\n /**\n * Format hour for display (e.g., \"9 AM\", \"2 PM\")\n * @param {number} hour - Hour in 24-hour format (0-23)\n * @returns {string}\n */\n formatHour(hour) {\n const period = hour >= 12 ? 'PM' : 'AM';\n const displayHour = hour % 12 || 12;\n return `${displayHour} ${period}`;\n }\n\n /**\n * Format time for display (e.g., \"9 AM\", \"2:30 PM\")\n * @param {Date} date\n * @returns {string}\n */\n formatTime(date) {\n const hours = date.getHours();\n const minutes = date.getMinutes();\n const period = hours >= 12 ? 'PM' : 'AM';\n const displayHour = hours % 12 || 12;\n return minutes === 0\n ? `${displayHour} ${period}`\n : `${displayHour}:${minutes.toString().padStart(2, '0')} ${period}`;\n }\n\n /**\n * Get contrasting text color for a background color\n * Uses WCAG luminance formula\n * @param {string} bgColor - Hex color string\n * @returns {string} 'black' or 'white'\n */\n getContrastingTextColor(bgColor) {\n if (!bgColor || typeof bgColor !== 'string') return 'white';\n\n const color = bgColor.charAt(0) === '#' ? bgColor.substring(1) : bgColor;\n\n if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(color)) {\n return 'white';\n }\n\n const fullColor =\n color.length === 3 ? color[0] + color[0] + color[1] + color[1] + color[2] + color[2] : color;\n\n const r = parseInt(fullColor.substring(0, 2), 16);\n const g = parseInt(fullColor.substring(2, 4), 16);\n const b = parseInt(fullColor.substring(4, 6), 16);\n\n if (isNaN(r) || isNaN(g) || isNaN(b)) {\n return 'white';\n }\n\n const uicolors = [r / 255, g / 255, b / 255];\n const c = uicolors.map(col => {\n if (col <= 0.03928) {\n return col / 12.92;\n }\n return Math.pow((col + 0.055) / 1.055, 2.4);\n });\n const L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];\n return L > 0.179 ? 'black' : 'white';\n }\n\n /**\n * Render the \"now\" indicator line for time-based views\n * @returns {string} HTML string\n */\n renderNowIndicator() {\n const now = new Date();\n const minutes = now.getHours() * 60 + now.getMinutes();\n return `<div class=\"fc-now-indicator\" style=\"position: absolute; left: 0; right: 0; top: ${minutes}px; height: 2px; background: #dc2626; z-index: 15; pointer-events: none;\"></div>`;\n }\n\n /**\n * Compute overlap layout columns for a list of timed events.\n * Returns a Map of event.id -> { column, totalColumns }.\n * Uses a greedy left-to-right column packing algorithm.\n * @param {Array} events - Array of event objects with start/end dates\n * @returns {Map<string, {column: number, totalColumns: number}>}\n */\n computeOverlapLayout(events) {\n if (!events || events.length === 0) return new Map();\n\n // Convert to sortable entries with minute ranges\n const entries = events.map(evt => {\n const start = new Date(evt.start);\n const end = new Date(evt.end);\n const startMin = start.getHours() * 60 + start.getMinutes();\n const endMin = Math.max(startMin + 1, end.getHours() * 60 + end.getMinutes());\n return { id: evt.id, startMin, endMin };\n });\n\n // Sort by start time, then by longer duration first\n entries.sort((a, b) => a.startMin - b.startMin || (b.endMin - b.startMin) - (a.endMin - a.startMin));\n\n // Assign columns greedily\n const columns = []; // each column tracks the end time of its last event\n const layout = new Map();\n\n for (const entry of entries) {\n let placed = false;\n for (let col = 0; col < columns.length; col++) {\n if (columns[col] <= entry.startMin) {\n columns[col] = entry.endMin;\n layout.set(entry.id, { column: col, totalColumns: 0 });\n placed = true;\n break;\n }\n }\n if (!placed) {\n layout.set(entry.id, { column: columns.length, totalColumns: 0 });\n columns.push(entry.endMin);\n }\n }\n\n // Determine the max overlapping columns for each cluster of overlapping events\n // Walk through entries and find connected groups\n const groups = [];\n let currentGroup = [];\n let groupEnd = 0;\n\n for (const entry of entries) {\n if (currentGroup.length === 0 || entry.startMin < groupEnd) {\n currentGroup.push(entry);\n groupEnd = Math.max(groupEnd, entry.endMin);\n } else {\n groups.push(currentGroup);\n currentGroup = [entry];\n groupEnd = entry.endMin;\n }\n }\n if (currentGroup.length > 0) groups.push(currentGroup);\n\n for (const group of groups) {\n const maxCol = Math.max(...group.map(e => layout.get(e.id).column)) + 1;\n for (const entry of group) {\n layout.get(entry.id).totalColumns = maxCol;\n }\n }\n\n return layout;\n }\n\n /**\n * Render a timed event block\n * @param {Object} event - Event object\n * @param {Object} options - Rendering options\n * @param {Object} options.compact - Use compact layout\n * @param {Object} options.overlapLayout - Map from computeOverlapLayout()\n * @returns {string} HTML string\n */\n renderTimedEvent(event, options = {}) {\n const { compact = true, overlapLayout = null } = options;\n const start = new Date(event.start);\n const end = new Date(event.end);\n const startMinutes = start.getHours() * 60 + start.getMinutes();\n const durationMinutes = Math.max((end - start) / (1000 * 60), compact ? 20 : 30);\n const color = this.getEventColor(event);\n\n const padding = compact ? '4px 8px' : '8px 12px';\n const fontSize = compact ? '11px' : '13px';\n const baseMargin = compact ? 2 : 12;\n const rightPad = compact ? 2 : 24;\n const borderRadius = compact ? '4px' : '6px';\n\n // Compute left/width based on overlap columns\n let leftPx, widthCalc;\n if (overlapLayout && overlapLayout.has(event.id)) {\n const { column, totalColumns } = overlapLayout.get(event.id);\n const colWidth = `(100% - ${baseMargin + rightPad}px)`;\n leftPx = `calc(${baseMargin}px + ${column} * ${colWidth} / ${totalColumns})`;\n widthCalc = `calc(${colWidth} / ${totalColumns})`;\n } else {\n leftPx = `${baseMargin}px`;\n widthCalc = `calc(100% - ${baseMargin + rightPad}px)`;\n }\n\n return `\n <div class=\"fc-event fc-timed-event\" data-event-id=\"${this.escapeHTML(event.id)}\"\n style=\"position: absolute; top: ${startMinutes}px; height: ${durationMinutes}px;\n left: ${leftPx}; width: ${widthCalc};\n background-color: ${color}; border-radius: ${borderRadius};\n padding: ${padding}; font-size: ${fontSize};\n font-weight: 500; color: white; overflow: hidden;\n box-shadow: 0 1px 2px rgba(0,0,0,0.1);\n cursor: pointer; z-index: 5;\">\n <div style=\"white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\">\n ${this.escapeHTML(event.title)}\n </div>\n <div style=\"font-size: ${compact ? '10px' : '11px'}; opacity: 0.9;\">\n ${this.formatTime(start)}${compact ? '' : ' - ' + this.formatTime(end)}\n </div>\n </div>\n `;\n }\n\n /**\n * Get a safe, sanitized event color value.\n * @param {Object} event\n * @returns {string}\n */\n getEventColor(event) {\n return StyleUtils.sanitizeColor(event?.backgroundColor, '#2563eb');\n }\n\n /**\n * Attach common event handlers for day/event clicks\n */\n attachCommonEventHandlers() {\n // Delegate event clicks at container level to avoid rebinding per event node.\n this.addListener(this.container, 'click', e => {\n const eventEl = e.target.closest('.fc-event');\n if (!eventEl || !this.container.contains(eventEl)) return;\n\n e.stopPropagation();\n const eventId = eventEl.dataset.eventId;\n const event = this.stateManager.getEvents().find(ev => ev.id === eventId);\n if (event) {\n this.stateManager.selectEvent(event);\n }\n });\n }\n}\n\nexport default BaseViewRenderer;\n","/**\n * MonthViewRenderer - Renders month calendar grid\n *\n * Pure JavaScript renderer for month view, compatible with Salesforce Locker Service.\n */\n\nimport { BaseViewRenderer } from './BaseViewRenderer.js';\n\nexport class MonthViewRenderer extends BaseViewRenderer {\n constructor(container, stateManager) {\n super(container, stateManager);\n this.maxEventsToShow = 3;\n }\n\n render() {\n if (!this.container || !this.stateManager) return;\n\n const viewData = this.stateManager.getViewData();\n if (!viewData || !viewData.weeks) {\n this.container.innerHTML =\n '<div style=\"padding: 20px; text-align: center; color: #666;\">No data available for month view.</div>';\n return;\n }\n\n this.cleanup();\n const config = this.stateManager.getState().config;\n const html = this._renderMonthView(viewData, config);\n this.container.innerHTML = html;\n this._attachEventHandlers();\n }\n\n _renderMonthView(viewData, config) {\n const weekStartsOn = config.weekStartsOn || 0;\n const dayNames = this._getDayNames(weekStartsOn);\n\n let html = `\n <div class=\"fc-month-view\" style=\"display: flex; flex-direction: column; height: 100%; min-height: 400px; background: #fff; border: 1px solid #e5e7eb;\">\n <div class=\"fc-month-header\" style=\"display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid #e5e7eb; background: #f9fafb;\">\n ${dayNames.map(d => `<div class=\"fc-month-header-cell\" style=\"padding: 12px 8px; text-align: center; font-size: 11px; font-weight: 600; color: #6b7280; text-transform: uppercase;\">${d}</div>`).join('')}\n </div>\n <div class=\"fc-month-body\" style=\"display: flex; flex-direction: column; flex: 1;\">\n `;\n\n viewData.weeks.forEach(week => {\n html += this._renderWeek(week);\n });\n\n html += '</div></div>';\n return html;\n }\n\n _getDayNames(weekStartsOn) {\n const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n const dayNames = [];\n for (let i = 0; i < 7; i++) {\n const dayIndex = (weekStartsOn + i) % 7;\n dayNames.push(days[dayIndex]);\n }\n return dayNames;\n }\n\n _renderWeek(week) {\n let html =\n '<div class=\"fc-month-week\" style=\"display: grid; grid-template-columns: repeat(7, 1fr); flex: 1; min-height: 80px;\">';\n\n week.days.forEach(day => {\n html += this._renderDay(day);\n });\n\n html += '</div>';\n return html;\n }\n\n _renderDay(day) {\n const isOtherMonth = !day.isCurrentMonth;\n const isToday = day.isToday;\n\n const dayBg = isOtherMonth ? '#f3f4f6' : '#fff';\n const dayNumColor = isOtherMonth ? '#9ca3af' : '#111827';\n const todayStyle = isToday\n ? 'background: #2563eb; color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;'\n : '';\n\n const events = day.events || [];\n const visibleEvents = events.slice(0, this.maxEventsToShow);\n const moreCount = events.length - this.maxEventsToShow;\n\n return `\n <div class=\"fc-month-day\" data-date=\"${day.date}\"\n style=\"background: ${dayBg}; border-right: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; padding: 4px; min-height: 80px; cursor: pointer; display: flex; flex-direction: column;\">\n <div class=\"fc-day-number\" style=\"font-size: 13px; font-weight: 500; color: ${dayNumColor}; padding: 2px 4px; margin-bottom: 4px; ${todayStyle}\">\n ${day.dayOfMonth}\n </div>\n <div class=\"fc-day-events\" style=\"display: flex; flex-direction: column; gap: 2px; flex: 1; overflow: hidden;\">\n ${visibleEvents.map(evt => this._renderEvent(evt)).join('')}\n ${moreCount > 0 ? `<div class=\"fc-more-events\" style=\"font-size: 10px; color: #6b7280; padding: 2px 4px; font-weight: 500;\">+${moreCount} more</div>` : ''}\n </div>\n </div>\n `;\n }\n\n _renderEvent(event) {\n const color = this.getEventColor(event);\n return `\n <div class=\"fc-event\" data-event-id=\"${this.escapeHTML(event.id)}\"\n style=\"background-color: ${color}; font-size: 11px; padding: 2px 6px; border-radius: 3px; color: white; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;\">\n ${this.escapeHTML(event.title)}\n </div>\n `;\n }\n\n _attachEventHandlers() {\n this.addListener(this.container, 'click', e => {\n const dayEl = e.target.closest('.fc-month-day');\n if (!dayEl || !this.container.contains(dayEl)) return;\n if (e.target.closest('.fc-event')) return;\n\n const date = new Date(dayEl.dataset.date);\n this.stateManager.selectDate(date);\n });\n\n // Common event handlers (event clicks)\n this.attachCommonEventHandlers();\n }\n}\n\nexport default MonthViewRenderer;\n","/**\n * WeekViewRenderer - Renders week calendar view\n *\n * Pure JavaScript renderer for week view, compatible with Salesforce Locker Service.\n */\n\nimport { BaseViewRenderer } from './BaseViewRenderer.js';\n\nexport class WeekViewRenderer extends BaseViewRenderer {\n constructor(container, stateManager) {\n super(container, stateManager);\n this.hourHeight = 60; // pixels per hour\n this.totalHeight = 24 * this.hourHeight; // 1440px for 24 hours\n }\n\n render() {\n if (!this.container || !this.stateManager) return;\n\n const viewData = this.stateManager.getViewData();\n if (!viewData || !viewData.days || viewData.days.length === 0) {\n this.container.innerHTML =\n '<div style=\"padding: 20px; text-align: center; color: #666;\">No data available for week view.</div>';\n return;\n }\n\n this.cleanup();\n this._scrolled = false;\n const config = this.stateManager.getState().config;\n const html = this._renderWeekView(viewData, config);\n this.container.innerHTML = html;\n this._attachEventHandlers();\n this._scrollToCurrentTime();\n }\n\n _renderWeekView(viewData, _config) {\n const days = viewData.days;\n const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n const hours = Array.from({ length: 24 }, (_, i) => i);\n\n // Process days to categorize events\n const processedDays = days.map(day => {\n const dayDate = new Date(day.date);\n const events = day.events || [];\n return {\n ...day,\n date: dayDate,\n dayName: dayNames[dayDate.getDay()],\n dayOfMonth: dayDate.getDate(),\n isToday: this.isToday(dayDate),\n timedEvents: events.filter(e => !e.allDay),\n allDayEvents: events.filter(e => e.allDay)\n };\n });\n\n return `\n <div class=\"fc-week-view\" style=\"display: flex; flex-direction: column; height: 100%; background: #fff; overflow: hidden;\">\n ${this._renderHeader(processedDays)}\n ${this._renderAllDayRow(processedDays)}\n ${this._renderTimeGrid(processedDays, hours)}\n </div>\n `;\n }\n\n _renderHeader(days) {\n return `\n <div class=\"fc-week-header\" style=\"display: grid; grid-template-columns: 60px repeat(7, 1fr); border-bottom: 1px solid #e5e7eb; background: #f9fafb; flex-shrink: 0;\">\n <div style=\"border-right: 1px solid #e5e7eb;\"></div>\n ${days\n .map(\n day => `\n <div style=\"padding: 12px 8px; text-align: center; border-right: 1px solid #e5e7eb;\">\n <div style=\"font-size: 10px; font-weight: 700; color: #6b7280; text-transform: uppercase; letter-spacing: 0.1em;\">\n ${day.dayName}\n </div>\n <div style=\"font-size: 16px; font-weight: 500; margin-top: 4px; ${day.isToday ? 'background: #dc2626; color: white; border-radius: 50%; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;' : 'color: #111827;'}\">\n ${day.dayOfMonth}\n </div>\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n _renderAllDayRow(days) {\n return `\n <div class=\"fc-all-day-row\" style=\"display: grid; grid-template-columns: 60px repeat(7, 1fr); border-bottom: 1px solid #e5e7eb; background: #fafafa; min-height: 32px; flex-shrink: 0;\">\n <div style=\"font-size: 9px; color: #6b7280; display: flex; align-items: center; justify-content: center; border-right: 1px solid #e5e7eb; text-transform: uppercase; font-weight: 700;\">\n All day\n </div>\n ${days\n .map(\n day => `\n <div class=\"fc-all-day-cell\" data-date=\"${day.date.toISOString()}\" style=\"border-right: 1px solid #e5e7eb; padding: 4px; display: flex; flex-direction: column; gap: 2px;\">\n ${day.allDayEvents\n .map(\n evt => `\n <div class=\"fc-event fc-all-day-event\" data-event-id=\"${this.escapeHTML(evt.id)}\"\n style=\"background-color: ${this.getEventColor(evt)}; font-size: 10px; padding: 2px 4px; border-radius: 2px; color: white; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\">\n ${this.escapeHTML(evt.title)}\n </div>\n `\n )\n .join('')}\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n _renderTimeGrid(days, hours) {\n return `\n <div id=\"week-scroll-container\" class=\"fc-time-grid-container\" style=\"flex: 1; overflow-y: auto; overflow-x: hidden; position: relative;\">\n <div class=\"fc-time-grid\" style=\"display: grid; grid-template-columns: 60px repeat(7, 1fr); position: relative; height: ${this.totalHeight}px;\">\n ${this._renderTimeGutter(hours)}\n ${days.map(day => this._renderDayColumn(day, hours)).join('')}\n </div>\n </div>\n `;\n }\n\n _renderTimeGutter(hours) {\n return `\n <div class=\"fc-time-gutter\" style=\"border-right: 1px solid #e5e7eb; background: #fafafa;\">\n ${hours\n .map(\n h => `\n <div style=\"height: ${this.hourHeight}px; font-size: 10px; color: #6b7280; text-align: right; padding-right: 8px; font-weight: 500;\">\n ${h === 0 ? '' : this.formatHour(h)}\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n _renderDayColumn(day, hours) {\n return `\n <div class=\"fc-week-day-column\" data-date=\"${day.date.toISOString()}\" style=\"border-right: 1px solid #e5e7eb; position: relative; cursor: pointer;\">\n <!-- Hour grid lines -->\n ${hours.map(() => `<div style=\"height: ${this.hourHeight}px; border-bottom: 1px solid #f3f4f6;\"></div>`).join('')}\n\n <!-- Now indicator for today -->\n ${day.isToday ? this.renderNowIndicator() : ''}\n\n <!-- Timed events -->\n ${(() => {\n const layout = this.computeOverlapLayout(day.timedEvents);\n return day.timedEvents.map(evt => this.renderTimedEvent(evt, { compact: true, overlapLayout: layout })).join('');\n })()}\n </div>\n `;\n }\n\n _attachEventHandlers() {\n this.addListener(this.container, 'click', e => {\n const dayEl = e.target.closest('.fc-week-day-column');\n if (!dayEl || !this.container.contains(dayEl)) return;\n if (e.target.closest('.fc-event')) return;\n\n const date = new Date(dayEl.dataset.date);\n const scrollContainer = this.container.querySelector('#week-scroll-container');\n const gridTop = dayEl.offsetTop;\n const y = e.clientY - dayEl.getBoundingClientRect().top + (scrollContainer ? scrollContainer.scrollTop : 0) - gridTop;\n\n // Calculate time from click position within the 1440px time grid\n const clampedY = Math.max(0, Math.min(y + gridTop, this.totalHeight));\n date.setHours(\n Math.floor(clampedY / this.hourHeight),\n Math.floor((clampedY % this.hourHeight) / (this.hourHeight / 60)),\n 0,\n 0\n );\n this.stateManager.selectDate(date);\n });\n\n // Common event handlers (event clicks)\n this.attachCommonEventHandlers();\n }\n\n _scrollToCurrentTime() {\n if (this._scrolled) return;\n\n const scrollContainer = this.container.querySelector('#week-scroll-container');\n if (scrollContainer) {\n // Scroll to 8 AM, minus some offset for visibility\n scrollContainer.scrollTop = 8 * this.hourHeight - 50;\n this._scrolled = true;\n }\n }\n}\n\nexport default WeekViewRenderer;\n","/**\n * DayViewRenderer - Renders single day calendar view\n *\n * Pure JavaScript renderer for day view, compatible with Salesforce Locker Service.\n */\n\nimport { BaseViewRenderer } from './BaseViewRenderer.js';\n\nexport class DayViewRenderer extends BaseViewRenderer {\n constructor(container, stateManager) {\n super(container, stateManager);\n this.hourHeight = 60; // pixels per hour\n this.totalHeight = 24 * this.hourHeight; // 1440px for 24 hours\n }\n\n render() {\n if (!this.container || !this.stateManager) return;\n\n const viewData = this.stateManager.getViewData();\n if (!viewData) {\n this.container.innerHTML =\n '<div style=\"padding: 20px; text-align: center; color: #666;\">No data available for day view.</div>';\n return;\n }\n\n this.cleanup();\n this._scrolled = false;\n const config = this.stateManager.getState().config;\n const html = this._renderDayView(viewData, config);\n this.container.innerHTML = html;\n this._attachEventHandlers();\n this._scrollToCurrentTime();\n }\n\n _renderDayView(viewData, _config) {\n const currentDate = this.stateManager?.getState()?.currentDate || new Date();\n const dayData = this._extractDayData(viewData, currentDate);\n\n if (!dayData) {\n return '<div style=\"padding: 20px; text-align: center; color: #666;\">No data available for day view.</div>';\n }\n\n const { dayDate, dayName, isToday, allDayEvents, timedEvents } = dayData;\n const hours = Array.from({ length: 24 }, (_, i) => i);\n\n return `\n <div class=\"fc-day-view\" style=\"display: flex; flex-direction: column; height: 100%; background: #fff; overflow: hidden;\">\n ${this._renderHeader(dayDate, dayName, isToday)}\n ${this._renderAllDayRow(allDayEvents, dayDate)}\n ${this._renderTimeGrid(timedEvents, isToday, dayDate, hours)}\n </div>\n `;\n }\n\n _extractDayData(viewData, currentDate) {\n let dayDate, dayName, isToday, allDayEvents, timedEvents;\n const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n\n if (viewData.type === 'day' && viewData.date) {\n // Core day view structure\n dayDate = new Date(viewData.date);\n dayName = viewData.dayName || dayNames[dayDate.getDay()];\n isToday = viewData.isToday !== undefined ? viewData.isToday : this.isToday(dayDate);\n allDayEvents = viewData.allDayEvents || [];\n\n // Extract timed events from hours array\n if (viewData.hours && Array.isArray(viewData.hours)) {\n const eventMap = new Map();\n viewData.hours.forEach(hour => {\n (hour.events || []).forEach(evt => {\n if (!eventMap.has(evt.id)) {\n eventMap.set(evt.id, evt);\n }\n });\n });\n timedEvents = Array.from(eventMap.values());\n } else {\n timedEvents = [];\n }\n } else if (viewData.days && viewData.days.length > 0) {\n // Enriched structure with days array\n const dayDataItem =\n viewData.days.find(d => this.isSameDay(new Date(d.date), currentDate)) || viewData.days[0];\n dayDate = new Date(dayDataItem.date);\n dayName = dayNames[dayDate.getDay()];\n isToday = this.isToday(dayDate);\n const events = dayDataItem.events || [];\n allDayEvents = events.filter(e => e.allDay);\n timedEvents = events.filter(e => !e.allDay);\n } else {\n return null;\n }\n\n return { dayDate, dayName, isToday, allDayEvents, timedEvents };\n }\n\n _renderHeader(dayDate, dayName, isToday) {\n return `\n <div class=\"fc-day-header\" style=\"display: grid; grid-template-columns: 60px 1fr; border-bottom: 1px solid #e5e7eb; background: #f9fafb; flex-shrink: 0;\">\n <div style=\"border-right: 1px solid #e5e7eb;\"></div>\n <div style=\"padding: 16px 24px;\">\n <div style=\"font-size: 12px; font-weight: 700; color: #6b7280; text-transform: uppercase; letter-spacing: 0.1em;\">\n ${dayName}\n </div>\n <div style=\"font-size: 24px; font-weight: 600; margin-top: 4px; ${isToday ? 'color: #dc2626;' : 'color: #111827;'}\">\n ${dayDate.getDate()}\n </div>\n </div>\n </div>\n `;\n }\n\n _renderAllDayRow(allDayEvents, dayDate) {\n return `\n <div class=\"fc-all-day-row\" style=\"display: grid; grid-template-columns: 60px 1fr; border-bottom: 1px solid #e5e7eb; background: #fafafa; min-height: 36px; flex-shrink: 0;\">\n <div style=\"font-size: 9px; color: #6b7280; display: flex; align-items: center; justify-content: center; border-right: 1px solid #e5e7eb; text-transform: uppercase; font-weight: 700;\">\n All day\n </div>\n <div class=\"fc-all-day-cell\" data-date=\"${dayDate.toISOString()}\" style=\"padding: 6px 12px; display: flex; flex-wrap: wrap; gap: 4px;\">\n ${allDayEvents\n .map(\n evt => `\n <div class=\"fc-event fc-all-day-event\" data-event-id=\"${this.escapeHTML(evt.id)}\"\n style=\"background-color: ${this.getEventColor(evt)}; font-size: 12px; padding: 4px 8px; border-radius: 4px; color: white; cursor: pointer; font-weight: 500;\">\n ${this.escapeHTML(evt.title)}\n </div>\n `\n )\n .join('')}\n </div>\n </div>\n `;\n }\n\n _renderTimeGrid(timedEvents, isToday, dayDate, hours) {\n return `\n <div id=\"day-scroll-container\" class=\"fc-time-grid-container\" style=\"flex: 1; overflow-y: auto; overflow-x: hidden; position: relative;\">\n <div class=\"fc-time-grid\" style=\"display: grid; grid-template-columns: 60px 1fr; position: relative; height: ${this.totalHeight}px;\">\n ${this._renderTimeGutter(hours)}\n ${this._renderDayColumn(timedEvents, isToday, dayDate, hours)}\n </div>\n </div>\n `;\n }\n\n _renderTimeGutter(hours) {\n return `\n <div class=\"fc-time-gutter\" style=\"border-right: 1px solid #e5e7eb; background: #fafafa;\">\n ${hours\n .map(\n h => `\n <div style=\"height: ${this.hourHeight}px; font-size: 11px; color: #6b7280; text-align: right; padding-right: 12px; font-weight: 500;\">\n ${h === 0 ? '' : this.formatHour(h)}\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n _renderDayColumn(timedEvents, isToday, dayDate, hours) {\n return `\n <div class=\"fc-day-column\" data-date=\"${dayDate.toISOString()}\" style=\"position: relative; cursor: pointer;\">\n <!-- Hour grid lines -->\n ${hours.map(() => `<div style=\"height: ${this.hourHeight}px; border-bottom: 1px solid #f3f4f6;\"></div>`).join('')}\n\n <!-- Now indicator for today -->\n ${isToday ? this.renderNowIndicator() : ''}\n\n <!-- Timed events -->\n ${(() => {\n const layout = this.computeOverlapLayout(timedEvents);\n return timedEvents.map(evt => this.renderTimedEvent(evt, { compact: false, overlapLayout: layout })).join('');\n })()}\n </div>\n `;\n }\n\n _attachEventHandlers() {\n this.addListener(this.container, 'click', e => {\n const dayEl = e.target.closest('.fc-day-column');\n if (!dayEl || !this.container.contains(dayEl)) return;\n if (e.target.closest('.fc-event')) return;\n\n const date = new Date(dayEl.dataset.date);\n const scrollContainer = this.container.querySelector('#day-scroll-container');\n const gridTop = dayEl.offsetTop;\n const y = e.clientY - dayEl.getBoundingClientRect().top + (scrollContainer ? scrollContainer.scrollTop : 0) - gridTop;\n\n // Calculate time from click position within the 1440px time grid\n const clampedY = Math.max(0, Math.min(y + gridTop, this.totalHeight));\n date.setHours(\n Math.floor(clampedY / this.hourHeight),\n Math.floor((clampedY % this.hourHeight) / (this.hourHeight / 60)),\n 0,\n 0\n );\n this.stateManager.selectDate(date);\n });\n\n // Common event handlers (event clicks)\n this.attachCommonEventHandlers();\n }\n\n _scrollToCurrentTime() {\n if (this._scrolled) return;\n\n const scrollContainer = this.container.querySelector('#day-scroll-container');\n if (scrollContainer) {\n // Scroll to 8 AM, minus some offset for visibility\n scrollContainer.scrollTop = 8 * this.hourHeight - 50;\n this._scrolled = true;\n }\n }\n}\n\nexport default DayViewRenderer;\n","import { BaseComponent } from '../core/BaseComponent.js';\nimport { StyleUtils } from '../utils/StyleUtils.js';\nimport { DOMUtils } from '../utils/DOMUtils.js';\n\nexport class EventForm extends BaseComponent {\n constructor() {\n super();\n this._isVisible = false;\n this._cleanupFocusTrap = null;\n this.config = {\n title: 'New Event',\n defaultDuration: 60, // minutes\n colors: [\n { color: '#2563EB', label: 'Blue' },\n { color: '#10B981', label: 'Green' },\n { color: '#F59E0B', label: 'Amber' },\n { color: '#EF4444', label: 'Red' },\n { color: '#8B5CF6', label: 'Purple' },\n { color: '#6B7280', label: 'Gray' }\n ]\n };\n this._formData = {\n title: '',\n start: new Date(),\n end: new Date(),\n allDay: false,\n color: this.config.colors[0].color\n };\n }\n\n static get observedAttributes() {\n return ['open'];\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n if (name === 'open') {\n if (newValue !== null) {\n this.open();\n } else {\n this.close();\n }\n }\n }\n\n getStyles() {\n return `\n ${StyleUtils.getBaseStyles()}\n ${StyleUtils.getButtonStyles()}\n\n :host {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: var(--fc-z-modal);\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(2px);\n }\n\n :host([open]) {\n display: flex;\n }\n\n .modal-content {\n background: var(--fc-background);\n width: 400px;\n max-width: 90vw;\n border-radius: var(--fc-border-radius-lg);\n box-shadow: var(--fc-shadow-lg);\n border: 1px solid var(--fc-border-color);\n display: flex;\n flex-direction: column;\n animation: fc-scale-in var(--fc-transition);\n }\n\n .modal-header {\n padding: var(--fc-spacing-lg);\n border-bottom: 1px solid var(--fc-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .modal-title {\n font-size: var(--fc-font-size-lg);\n font-weight: var(--fc-font-weight-semibold);\n color: var(--fc-text-color);\n }\n\n .close-btn {\n background: transparent;\n border: none;\n color: var(--fc-text-secondary);\n cursor: pointer;\n padding: 4px;\n border-radius: var(--fc-border-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .close-btn:hover {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n }\n\n .modal-body {\n padding: var(--fc-spacing-lg);\n display: flex;\n flex-direction: column;\n gap: var(--fc-spacing-md);\n }\n\n .form-group {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n label {\n font-size: var(--fc-font-size-sm);\n font-weight: var(--fc-font-weight-medium);\n color: var(--fc-text-secondary);\n }\n\n input[type=\"text\"],\n input[type=\"datetime-local\"],\n select {\n padding: 8px 12px;\n border: 1px solid var(--fc-border-color);\n border-radius: var(--fc-border-radius);\n font-family: var(--fc-font-family);\n font-size: var(--fc-font-size-base);\n color: var(--fc-text-color);\n background: var(--fc-background);\n transition: border-color var(--fc-transition-fast);\n }\n\n input:focus,\n select:focus {\n outline: none;\n border-color: var(--fc-primary-color);\n box-shadow: 0 0 0 2px var(--fc-primary-light);\n }\n\n .row {\n display: flex;\n gap: var(--fc-spacing-md);\n }\n \n .row .form-group {\n flex: 1;\n }\n\n .modal-footer {\n padding: var(--fc-spacing-lg);\n border-top: 1px solid var(--fc-border-color);\n display: flex;\n justify-content: flex-end;\n gap: var(--fc-spacing-md);\n background: var(--fc-background-alt);\n border-bottom-left-radius: var(--fc-border-radius-lg);\n border-bottom-right-radius: var(--fc-border-radius-lg);\n }\n\n /* Color picker style */\n .color-options {\n display: flex;\n gap: 8px;\n margin-top: 4px;\n }\n\n .color-btn {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n cursor: pointer;\n border: 2px solid transparent;\n transition: transform var(--fc-transition-fast), border-color var(--fc-transition-fast);\n padding: 0;\n position: relative;\n }\n\n .color-btn:hover {\n transform: scale(1.1);\n }\n\n .color-btn.selected {\n border-color: var(--fc-text-color);\n box-shadow: 0 0 0 2px var(--fc-background), 0 0 0 4px var(--fc-primary-color);\n }\n\n .color-btn:focus {\n outline: none;\n box-shadow: 0 0 0 2px var(--fc-background), 0 0 0 4px var(--fc-primary-color);\n }\n\n .error-message {\n color: var(--fc-danger-color);\n font-size: 11px;\n margin-top: 2px;\n display: none;\n }\n\n .form-group.has-error .error-message {\n display: block;\n }\n\n .form-group.has-error input {\n border-color: var(--fc-danger-color);\n }\n `;\n }\n\n template() {\n return `\n <div class=\"modal-content\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"modal-title\">\n <header class=\"modal-header\">\n <h3 class=\"modal-title\" id=\"modal-title\">${this.config.title}</h3>\n <button class=\"close-btn\" id=\"close-x\" aria-label=\"Close modal\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M18 6L6 18M6 6l12 12\"></path>\n </svg>\n </button>\n </header>\n \n <div class=\"modal-body\">\n <div class=\"form-group\" id=\"title-group\">\n <label for=\"event-title\">Title</label>\n <input type=\"text\" id=\"event-title\" placeholder=\"Event name\" autofocus required>\n <span class=\"error-message\">Title is required</span>\n </div>\n\n <div class=\"row\">\n <div class=\"form-group\" id=\"start-group\">\n <label for=\"event-start\">Start</label>\n <input type=\"datetime-local\" id=\"event-start\" required>\n </div>\n <div class=\"form-group\" id=\"end-group\">\n <label for=\"event-end\">End</label>\n <input type=\"datetime-local\" id=\"event-end\" required>\n <span class=\"error-message\">End time must be after start time</span>\n </div>\n </div>\n\n <div class=\"form-group\">\n <label id=\"color-label\">Color</label>\n <div class=\"color-options\" id=\"color-picker\" role=\"radiogroup\" aria-labelledby=\"color-label\">\n ${this.config.colors\n .map(\n c => `\n <button type=\"button\" \n class=\"color-btn ${c.color === this._formData.color ? 'selected' : ''}\" \n style=\"background-color: ${c.color}\" \n data-color=\"${c.color}\"\n title=\"${c.label}\"\n aria-label=\"${c.label}\"\n aria-checked=\"${c.color === this._formData.color ? 'true' : 'false'}\"\n role=\"radio\"></button>\n `\n )\n .join('')}\n </div>\n </div>\n </div>\n\n <footer class=\"modal-footer\">\n <button class=\"fc-btn fc-btn-secondary\" id=\"cancel-btn\">Cancel</button>\n <button class=\"fc-btn fc-btn-primary\" id=\"save-btn\">Save Event</button>\n </footer>\n </div>\n `;\n }\n\n afterRender() {\n // Bind elements\n this.modalContent = this.$('.modal-content');\n this.titleInput = this.$('#event-title');\n this.startInput = this.$('#event-start');\n this.endInput = this.$('#event-end');\n this.colorContainer = this.$('#color-picker');\n\n this.titleGroup = this.$('#title-group');\n this.endGroup = this.$('#end-group');\n\n // Event Listeners using addListener for automatic cleanup\n this.addListener(this.$('#close-x'), 'click', () => this.close());\n this.addListener(this.$('#cancel-btn'), 'click', () => this.close());\n this.addListener(this.$('#save-btn'), 'click', () => this.save());\n\n this.colorContainer.querySelectorAll('.color-btn').forEach(btn => {\n this.addListener(btn, 'click', e => {\n this._formData.color = e.currentTarget.dataset.color;\n this.updateColorSelection();\n });\n });\n\n // Close on backdrop click\n this.addListener(this, 'click', e => {\n if (e.target === this) this.close();\n });\n\n // Close on Escape key - only add once to prevent memory leaks\n if (!this._keydownListenerAdded) {\n this._handleKeyDown = e => {\n if (e.key === 'Escape' && this.hasAttribute('open')) {\n this.close();\n }\n };\n window.addEventListener('keydown', this._handleKeyDown);\n this._keydownListenerAdded = true;\n }\n }\n\n updateColorSelection() {\n const buttons = this.colorContainer.querySelectorAll('.color-btn');\n buttons.forEach(btn => {\n const isSelected = btn.dataset.color === this._formData.color;\n btn.classList.toggle('selected', isSelected);\n btn.setAttribute('aria-checked', isSelected ? 'true' : 'false');\n });\n }\n\n open(initialDate = new Date()) {\n if (!this.hasAttribute('open')) {\n this.setAttribute('open', '');\n }\n\n // Reset errors\n this.titleGroup.classList.remove('has-error');\n this.endGroup.classList.remove('has-error');\n\n // Initialize form data\n this._formData.start = initialDate;\n this._formData.end = new Date(initialDate.getTime() + this.config.defaultDuration * 60 * 1000);\n this._formData.title = '';\n this._formData.color = this.config.colors[0].color;\n\n // Update inputs\n if (this.startInput) {\n this.titleInput.value = '';\n this.startInput.value = this.formatDateForInput(this._formData.start);\n this.endInput.value = this.formatDateForInput(this._formData.end);\n this.updateColorSelection();\n\n // Clean up previous focus trap before creating a new one\n if (this._cleanupFocusTrap) {\n this._cleanupFocusTrap();\n }\n this._cleanupFocusTrap = DOMUtils.trapFocus(this.modalContent);\n }\n }\n\n close() {\n this.removeAttribute('open');\n if (this._cleanupFocusTrap) {\n this._cleanupFocusTrap();\n this._cleanupFocusTrap = null;\n }\n }\n\n validate() {\n let isValid = true;\n\n // Reset errors\n this.titleGroup.classList.remove('has-error');\n this.endGroup.classList.remove('has-error');\n\n // Check title\n if (!this.titleInput.value.trim()) {\n this.titleGroup.classList.add('has-error');\n isValid = false;\n }\n\n // Check date range\n const start = new Date(this.startInput.value);\n const end = new Date(this.endInput.value);\n if (end <= start) {\n this.endGroup.classList.add('has-error');\n isValid = false;\n }\n\n return isValid;\n }\n\n save() {\n if (!this.validate()) return;\n\n const event = {\n title: this.titleInput.value.trim(),\n start: new Date(this.startInput.value),\n end: new Date(this.endInput.value),\n backgroundColor: this._formData.color\n };\n\n this.emit('save', event);\n this.close();\n }\n\n formatDateForInput(date) {\n // Handle local date string for datetime-local input\n const pad = num => String(num).padStart(2, '0');\n const year = date.getFullYear();\n const month = pad(date.getMonth() + 1);\n const day = pad(date.getDate());\n const hours = pad(date.getHours());\n const minutes = pad(date.getMinutes());\n\n return `${year}-${month}-${day}T${hours}:${minutes}`;\n }\n\n unmount() {\n if (this._cleanupFocusTrap) {\n this._cleanupFocusTrap();\n }\n // Clean up window listener\n if (this._handleKeyDown) {\n window.removeEventListener('keydown', this._handleKeyDown);\n this._handleKeyDown = null;\n this._keydownListenerAdded = false;\n }\n }\n}\n\nif (!customElements.get('forcecal-event-form')) {\n customElements.define('forcecal-event-form', EventForm);\n}\n","/**\n * ForceCalendar - Main calendar component\n *\n * The primary interface component that integrates all views and features\n */\n\nimport { BaseComponent } from '../core/BaseComponent.js';\nimport StateManager from '../core/StateManager.js';\nimport { StyleUtils } from '../utils/StyleUtils.js';\nimport { DateUtils } from '../utils/DateUtils.js';\nimport { DOMUtils } from '../utils/DOMUtils.js';\n\n// Import view renderers (pure JS classes, Locker Service compatible)\nimport { MonthViewRenderer } from '../renderers/MonthViewRenderer.js';\nimport { WeekViewRenderer } from '../renderers/WeekViewRenderer.js';\nimport { DayViewRenderer } from '../renderers/DayViewRenderer.js';\n\n// Import EventForm component (registers custom element as side effect)\nimport './EventForm.js';\n\nexport class ForceCalendar extends BaseComponent {\n static RENDERERS = {\n month: MonthViewRenderer,\n week: WeekViewRenderer,\n day: DayViewRenderer\n };\n\n static get observedAttributes() {\n return ['view', 'date', 'locale', 'timezone', 'week-starts-on', 'height'];\n }\n\n constructor() {\n super();\n this.stateManager = null;\n this.currentView = null;\n this._hasRendered = false; // Track if initial render is complete\n this._cachedStyles = null; // Cache styles to avoid recreation\n this._busUnsubscribers = [];\n }\n\n initialize() {\n // Initialize state manager with config from attributes\n const config = {\n view: this.getAttribute('view') || 'month',\n date: this.getAttribute('date') ? new Date(this.getAttribute('date')) : new Date(),\n locale: this.getAttribute('locale') || 'en-US',\n timeZone: this.getAttribute('timezone') || Intl.DateTimeFormat().resolvedOptions().timeZone,\n weekStartsOn: parseInt(this.getAttribute('week-starts-on') || '0')\n };\n\n this.stateManager = new StateManager(config);\n\n // Subscribe to state changes\n this.stateManager.subscribe(this.handleStateChange.bind(this));\n\n // Listen for events\n this.setupEventListeners();\n }\n\n setupEventListeners() {\n // Clean up any existing subscriptions before re-subscribing\n this._busUnsubscribers.forEach(unsub => unsub());\n this._busUnsubscribers = [];\n\n const bus = this.stateManager.eventBus;\n\n // Navigation events\n this._busUnsubscribers.push(\n bus.on('navigation:*', (data, event) => {\n this.emit('calendar-navigate', { action: event.split(':')[1], ...data });\n })\n );\n\n // View change events\n this._busUnsubscribers.push(\n bus.on('view:changed', data => {\n this.emit('calendar-view-change', data);\n })\n );\n\n const forwardEventAction = (action, data) => {\n this.emit(`calendar-event-${action}`, data);\n };\n\n // Event management events (canonical + backward-compatible aliases)\n this._busUnsubscribers.push(\n bus.on('event:add', data => {\n forwardEventAction('add', data);\n })\n );\n this._busUnsubscribers.push(\n bus.on('event:update', data => {\n forwardEventAction('update', data);\n })\n );\n this._busUnsubscribers.push(\n bus.on('event:remove', data => {\n forwardEventAction('remove', data);\n })\n );\n // Specific lifecycle events — do NOT call forwardEventAction here; the\n // canonical event:add/update/remove handlers above already forward the\n // generic CustomEvent. These handlers emit only the specific variant so\n // consumers that care about the distinction can subscribe to it without\n // receiving the generic event a second time.\n this._busUnsubscribers.push(\n bus.on('event:added', data => {\n this.emit('calendar-event-added', data);\n })\n );\n this._busUnsubscribers.push(\n bus.on('event:updated', data => {\n this.emit('calendar-event-updated', data);\n })\n );\n this._busUnsubscribers.push(\n bus.on('event:deleted', data => {\n this.emit('calendar-event-deleted', data);\n })\n );\n\n // Date selection events\n this._busUnsubscribers.push(\n bus.on('date:selected', data => {\n this.emit('calendar-date-select', data);\n })\n );\n }\n\n handleStateChange(newState, oldState) {\n // If not yet rendered, do nothing (mount will handle initial render)\n if (!this._hasRendered) {\n return;\n }\n\n // Check what changed\n const viewChanged = newState.view !== oldState?.view;\n const dateChanged = newState.currentDate?.getTime() !== oldState?.currentDate?.getTime();\n const eventsChanged = newState.events !== oldState?.events;\n const loadingChanged = newState.loading !== oldState?.loading;\n const errorChanged = newState.error !== oldState?.error;\n\n // For loading/error state changes, do full re-render (rare)\n if (errorChanged) {\n this.render();\n return;\n }\n if (loadingChanged) {\n this._updateLoadingState(newState.loading);\n return;\n }\n\n // Update local view reference if needed\n if (viewChanged) {\n this.currentView = newState.view;\n }\n\n // Targeted updates based on what changed\n if (viewChanged) {\n // View changed: update title, buttons, and switch view\n this._updateTitle();\n this._updateViewButtons();\n this._switchView();\n } else if (dateChanged) {\n // Date changed: update title and re-render view\n this._updateTitle();\n this._updateViewContent();\n } else if (eventsChanged) {\n // Events changed: only re-render view content\n this._updateViewContent();\n }\n // Selection changes are handled by the view internally, no action needed here\n }\n\n /**\n * Update only the title text (no DOM recreation)\n */\n _updateTitle() {\n const titleEl = this.$('.fc-title');\n if (titleEl) {\n const state = this.stateManager.getState();\n titleEl.textContent = this.getTitle(state.currentDate, state.view);\n }\n }\n\n /**\n * Update view button active states (no DOM recreation)\n */\n _updateViewButtons() {\n const state = this.stateManager.getState();\n this.$$('[data-view]').forEach(button => {\n const isActive = button.dataset.view === state.view;\n button.classList.toggle('active', isActive);\n });\n }\n\n /**\n * Switch to a different view type\n */\n _switchView() {\n const container = this.$('#calendar-view-container');\n if (!container) return;\n\n // Clean up previous view\n if (this._currentViewInstance) {\n if (this._currentViewInstance.cleanup) {\n this._currentViewInstance.cleanup();\n }\n }\n\n // Create new view using renderer classes\n try {\n const RendererClass = ForceCalendar.RENDERERS[this.currentView] || MonthViewRenderer;\n const viewRenderer = new RendererClass(container, this.stateManager);\n viewRenderer._viewType = this.currentView;\n this._currentViewInstance = viewRenderer;\n viewRenderer.render();\n // Note: No subscription - handleStateChange manages all view updates\n } catch (err) {\n console.error('[ForceCalendar] Error switching view:', err);\n }\n }\n\n /**\n * Re-render only the view content (not header)\n */\n _updateViewContent() {\n if (this._currentViewInstance && this._currentViewInstance.render) {\n this._currentViewInstance.render();\n }\n }\n\n /**\n * Toggle loading overlay without rebuilding the component tree.\n */\n _updateLoadingState(isLoading) {\n const loadingEl = this.$('.fc-loading');\n const viewContainer = this.$('.fc-view-container');\n if (loadingEl) {\n loadingEl.style.display = isLoading ? 'flex' : 'none';\n }\n if (viewContainer) {\n viewContainer.style.display = isLoading ? 'none' : 'flex';\n }\n }\n\n mount() {\n this.currentView = this.stateManager.getView();\n super.mount();\n }\n\n loadView(viewType) {\n if (!viewType || this.currentView === viewType) return;\n this.currentView = viewType;\n this._switchView();\n this._updateViewButtons();\n this._updateTitle();\n }\n\n getStyles() {\n const height = this.getAttribute('height') || '800px';\n\n return `\n ${StyleUtils.getBaseStyles()}\n ${StyleUtils.getButtonStyles()}\n ${StyleUtils.getGridStyles()}\n ${StyleUtils.getAnimations()}\n\n :host {\n --calendar-height: ${height};\n display: block;\n font-family: var(--fc-font-family);\n }\n\n .force-calendar {\n display: flex;\n flex-direction: column;\n height: var(--calendar-height);\n background: var(--fc-background);\n border: 1px solid var(--fc-border-color);\n border-radius: var(--fc-border-radius-lg);\n overflow: hidden;\n box-shadow: var(--fc-shadow);\n }\n\n .fc-header {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: center;\n padding: var(--fc-spacing-md) var(--fc-spacing-lg);\n background: rgba(255, 255, 255, 0.95);\n -webkit-backdrop-filter: blur(8px); /* Safari support */\n backdrop-filter: blur(8px);\n border-bottom: 1px solid var(--fc-border-color);\n z-index: 10;\n position: sticky;\n top: 0;\n }\n\n .fc-header-left {\n display: flex;\n align-items: center;\n gap: var(--fc-spacing-md);\n justify-self: start;\n flex-basis: 0; /* Force Safari to distribute space */\n }\n\n .fc-header-center {\n display: flex;\n align-items: center;\n gap: var(--fc-spacing-lg);\n justify-self: center;\n }\n\n .fc-header-right {\n display: flex;\n align-items: center;\n gap: var(--fc-spacing-md);\n justify-self: end;\n flex-basis: 0; /* Force Safari to distribute space */\n }\n\n .fc-title {\n font-size: 14px;\n font-weight: var(--fc-font-weight-semibold);\n color: var(--fc-text-color);\n white-space: nowrap;\n letter-spacing: -0.01em;\n min-width: 140px;\n text-align: center;\n }\n\n .fc-btn-today {\n border-radius: var(--fc-border-radius-sm);\n padding: 0 12px;\n font-size: 12px;\n font-weight: var(--fc-font-weight-medium);\n border: 1px solid var(--fc-border-color);\n background: var(--fc-background);\n color: var(--fc-text-color);\n height: 28px;\n transition: all var(--fc-transition-fast);\n cursor: pointer;\n display: flex;\n align-items: center;\n }\n\n .fc-btn-today:hover {\n background: var(--fc-background-hover);\n border-color: var(--fc-border-color-hover);\n }\n\n .fc-nav-arrow {\n border: 1px solid var(--fc-border-color);\n background: var(--fc-background);\n height: 28px;\n width: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--fc-border-radius-sm);\n color: var(--fc-text-secondary);\n cursor: pointer;\n transition: all var(--fc-transition-fast);\n padding: 0;\n }\n\n .fc-nav-arrow:hover {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n border-color: var(--fc-border-color-hover);\n }\n\n /* View Switcher - Fused Button Group */\n .fc-view-buttons {\n display: flex;\n border: 1px solid var(--fc-border-color);\n border-radius: var(--fc-border-radius-sm);\n overflow: hidden;\n }\n\n .fc-view-button {\n background: var(--fc-background);\n border: none;\n border-right: 1px solid var(--fc-border-color);\n color: var(--fc-text-secondary);\n padding: 0 12px;\n font-size: var(--fc-font-size-sm);\n font-weight: var(--fc-font-weight-medium);\n transition: background-color var(--fc-transition-fast);\n cursor: pointer;\n height: 28px;\n display: flex;\n align-items: center;\n }\n \n .fc-view-button:last-child {\n border-right: none;\n }\n\n .fc-view-button:hover:not(.active) {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n }\n\n .fc-view-button.active {\n background: var(--fc-background-alt);\n color: var(--fc-text-color);\n font-weight: var(--fc-font-weight-semibold);\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.02);\n }\n\n .fc-body {\n flex: 1;\n position: relative;\n background: var(--fc-background);\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n\n .fc-view-container {\n flex: 1;\n position: relative;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n\n /* Ensure view container has proper dimensions */\n #calendar-view-container {\n display: block;\n width: 100%;\n height: 100%;\n flex: 1;\n }\n\n #calendar-view-container > * {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n /* Loading state */\n .fc-loading {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--fc-spacing-md);\n color: var(--fc-text-secondary);\n }\n\n .fc-spinner {\n width: 24px;\n height: 24px;\n border: 3px solid var(--fc-border-color);\n border-top-color: var(--fc-primary-color);\n border-radius: 50%;\n animation: fc-spin 1s linear infinite;\n }\n\n /* Error state */\n .fc-error {\n padding: var(--fc-spacing-xl);\n text-align: center;\n color: var(--fc-danger-color);\n background: #FEF2F2;\n border-radius: var(--fc-border-radius);\n margin: var(--fc-spacing-xl);\n }\n\n /* Icons */\n .fc-icon {\n width: 18px;\n height: 18px;\n fill: currentColor;\n }\n\n /* Responsive Adjustments */\n @media (max-width: 850px) {\n .fc-header {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--fc-spacing-md);\n height: auto;\n position: static;\n padding: var(--fc-spacing-md);\n }\n\n .fc-header-center {\n order: -1;\n text-align: center;\n width: 100%;\n padding: var(--fc-spacing-xs) 0;\n }\n\n .fc-header-left,\n .fc-header-right {\n justify-content: space-between;\n width: 100%;\n }\n\n #create-event-btn {\n flex: 1;\n }\n }\n\n /* Month View Styles (inline rendering for Locker Service compatibility) */\n .fc-month-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--fc-background);\n }\n\n .fc-month-header {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n border-bottom: 1px solid var(--fc-border-color);\n background: var(--fc-background-alt);\n }\n\n .fc-month-header-cell {\n padding: 12px 8px;\n text-align: center;\n font-size: 11px;\n font-weight: 600;\n color: var(--fc-text-light);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .fc-month-body {\n display: flex;\n flex-direction: column;\n flex: 1;\n }\n\n .fc-month-week {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n flex: 1;\n min-height: 100px;\n }\n\n .fc-month-day {\n background: var(--fc-background);\n border-right: 1px solid var(--fc-border-color);\n border-bottom: 1px solid var(--fc-border-color);\n padding: 4px;\n min-height: 80px;\n cursor: pointer;\n transition: background-color 0.15s ease;\n display: flex;\n flex-direction: column;\n }\n\n .fc-month-day:hover {\n background: var(--fc-background-hover);\n }\n\n .fc-month-day:last-child {\n border-right: none;\n }\n\n .fc-month-day.other-month {\n background: var(--fc-background-alt);\n }\n\n .fc-month-day.other-month .fc-day-number {\n color: var(--fc-text-light);\n }\n\n .fc-month-day.today {\n background: rgba(37, 99, 235, 0.05);\n }\n\n .fc-month-day.today .fc-day-number {\n background: var(--fc-primary-color);\n color: white;\n border-radius: 50%;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .fc-day-number {\n font-size: 13px;\n font-weight: 500;\n color: var(--fc-text-color);\n padding: 2px 4px;\n margin-bottom: 4px;\n }\n\n .fc-day-events {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex: 1;\n overflow: hidden;\n }\n\n .fc-event {\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 3px;\n color: white;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: pointer;\n transition: transform 0.1s ease;\n }\n\n .fc-event:hover {\n transform: scale(1.02);\n }\n\n .fc-more-events {\n font-size: 10px;\n color: var(--fc-text-light);\n padding: 2px 4px;\n font-weight: 500;\n }\n\n /* Week View Styles (inline rendering for Locker Service compatibility) */\n .fc-week-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--fc-background);\n }\n\n /* Day View Styles (inline rendering for Locker Service compatibility) */\n .fc-day-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--fc-background);\n }\n `;\n }\n\n template() {\n const state = this.stateManager.getState();\n const { currentDate, view, loading, error } = state;\n\n if (error) {\n return `\n <div class=\"force-calendar\">\n <div class=\"fc-error\">\n <p><strong>Error:</strong> ${DOMUtils.escapeHTML(error.message || 'An error occurred')}</p>\n </div>\n </div>\n `;\n }\n\n const title = this.getTitle(currentDate, view);\n\n return `\n <div class=\"force-calendar\">\n <header class=\"fc-header\">\n <div class=\"fc-header-left\">\n <button class=\"fc-btn-today\" data-action=\"today\">\n Today\n </button>\n </div>\n\n <div class=\"fc-header-center\">\n <button class=\"fc-nav-arrow\" data-action=\"previous\" title=\"Previous\">\n ${this.getIcon('chevron-left')}\n </button>\n <h2 class=\"fc-title\">${title}</h2>\n <button class=\"fc-nav-arrow\" data-action=\"next\" title=\"Next\">\n ${this.getIcon('chevron-right')}\n </button>\n </div>\n\n <div class=\"fc-header-right\">\n <button class=\"fc-btn fc-btn-primary\" id=\"create-event-btn\" style=\"height: 28px; padding: 0 12px; font-size: 12px;\">\n + New Event\n </button>\n <div class=\"fc-view-buttons\" role=\"group\">\n <button class=\"fc-view-button ${view === 'month' ? 'active' : ''}\"\n data-view=\"month\">Month</button>\n <button class=\"fc-view-button ${view === 'week' ? 'active' : ''}\"\n data-view=\"week\">Week</button>\n <button class=\"fc-view-button ${view === 'day' ? 'active' : ''}\"\n data-view=\"day\">Day</button>\n </div>\n </div>\n </header>\n\n <div class=\"fc-body\">\n <div class=\"fc-loading\" style=\"display: ${loading ? 'flex' : 'none'};\">\n <div class=\"fc-spinner\"></div>\n <span>Loading...</span>\n </div>\n <div class=\"fc-view-container\" style=\"display: ${loading ? 'none' : 'flex'};\">\n ${this.renderView()}\n </div>\n </div>\n \n <forcecal-event-form id=\"event-modal\"></forcecal-event-form>\n </div>\n `;\n }\n\n renderView() {\n // Use a plain div container - we'll manually instantiate view classes\n // This bypasses Locker Service's custom element restrictions\n return '<div id=\"calendar-view-container\"></div>';\n }\n\n afterRender() {\n // Manually instantiate and mount view renderer (bypasses Locker Service)\n const container = this.$('#calendar-view-container');\n\n // Only create view once per view type change\n if (container && this.stateManager && this.currentView) {\n // Check if container actually has content (render() clears shadow DOM)\n if (\n this._currentViewInstance &&\n this._currentViewInstance._viewType === this.currentView &&\n container.children.length > 0\n ) {\n return;\n }\n\n // Clean up previous view if exists\n if (this._currentViewInstance) {\n if (this._currentViewInstance.cleanup) {\n this._currentViewInstance.cleanup();\n }\n if (this._viewUnsubscribe) {\n this._viewUnsubscribe();\n this._viewUnsubscribe = null;\n }\n }\n\n // Create view renderer using the appropriate renderer class\n try {\n const RendererClass = ForceCalendar.RENDERERS[this.currentView] || MonthViewRenderer;\n const viewRenderer = new RendererClass(container, this.stateManager);\n viewRenderer._viewType = this.currentView;\n this._currentViewInstance = viewRenderer;\n viewRenderer.render();\n // Note: No subscription here - handleStateChange manages all view updates\n // via _updateViewContent(), _switchView(), or full re-render\n } catch (err) {\n console.error('[ForceCalendar] Error creating/rendering view:', err);\n }\n }\n\n // Add event listeners for buttons using tracked addListener\n this.$$('[data-action]').forEach(button => {\n this.addListener(button, 'click', this.handleNavigation);\n });\n\n this.$$('[data-view]').forEach(button => {\n this.addListener(button, 'click', this.handleViewChange);\n });\n\n // Event Modal Handling\n const modal = this.$('#event-modal');\n const createBtn = this.$('#create-event-btn');\n\n if (createBtn && modal) {\n this.addListener(createBtn, 'click', () => {\n modal.open(new Date());\n });\n }\n\n // Listen for day clicks from the view\n this.addListener(this.shadowRoot, 'day-click', e => {\n if (modal) {\n modal.open(e.detail.date);\n }\n });\n\n // Handle event saving\n if (modal) {\n this.addListener(modal, 'save', e => {\n const eventData = e.detail;\n // Robust Safari support check for randomUUID\n const id =\n window.crypto && typeof window.crypto.randomUUID === 'function'\n ? window.crypto.randomUUID()\n : Math.random().toString(36).substring(2, 15);\n\n this.stateManager.addEvent({\n id,\n ...eventData\n });\n });\n }\n\n // Mark initial render as complete for targeted updates\n this._hasRendered = true;\n }\n\n handleNavigation(event) {\n const action = event.currentTarget.dataset.action;\n switch (action) {\n case 'today':\n this.stateManager.today();\n break;\n case 'previous':\n this.stateManager.previous();\n break;\n case 'next':\n this.stateManager.next();\n break;\n }\n }\n\n handleViewChange(event) {\n const view = event.currentTarget.dataset.view;\n this.stateManager.setView(view);\n }\n\n getTitle(date, view) {\n const locale = this.stateManager.state.config.locale;\n\n switch (view) {\n case 'month':\n return DateUtils.formatDate(date, 'month', locale);\n case 'week': {\n const weekStart = DateUtils.startOfWeek(date);\n const weekEnd = DateUtils.endOfWeek(date);\n return DateUtils.formatDateRange(weekStart, weekEnd, locale);\n }\n case 'day':\n return DateUtils.formatDate(date, 'long', locale);\n default:\n return DateUtils.formatDate(date, 'month', locale);\n }\n }\n\n getIcon(name) {\n const icons = {\n 'chevron-left': `\n <svg class=\"fc-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"/>\n </svg>\n `,\n 'chevron-right': `\n <svg class=\"fc-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z\"/>\n </svg>\n `,\n calendar: `\n <svg class=\"fc-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"/>\n </svg>\n `\n };\n\n return icons[name] || '';\n }\n\n // Public API methods\n addEvent(event) {\n return this.stateManager.addEvent(event);\n }\n\n updateEvent(eventId, updates) {\n return this.stateManager.updateEvent(eventId, updates);\n }\n\n deleteEvent(eventId) {\n return this.stateManager.deleteEvent(eventId);\n }\n\n getEvents() {\n return this.stateManager.getEvents();\n }\n\n setView(view) {\n this.stateManager.setView(view);\n }\n\n setDate(date) {\n this.stateManager.setDate(date);\n }\n\n next() {\n this.stateManager.next();\n }\n\n previous() {\n this.stateManager.previous();\n }\n\n today() {\n this.stateManager.today();\n }\n\n destroy() {\n this._busUnsubscribers.forEach(unsub => unsub());\n this._busUnsubscribers = [];\n\n if (this.stateManager) {\n this.stateManager.destroy();\n }\n super.cleanup();\n }\n}\n\n// Register component\nif (!customElements.get('forcecal-main')) {\n customElements.define('forcecal-main', ForceCalendar);\n}\n"],"names":["BaseComponent","element","event","handler","newState","oldState","_oldState","_newState","key","value","oldValue","_key","_oldValue","_newValue","boundHandler","eventName","detail","styles","template","selector","name","newValue","EventBus","options","once","priority","subscription","handlers","b","index","sub","pattern","data","error","toRemove","count","eventBus","StateManager","config","Calendar","force","coreEvents","arr1","arr2","ids1","e","updates","silent","callback","subscriberId","changedKeys","view","date","addedEvent","eventId","start","end","viewData","enriched","selectedDateString","_a","week","day","dayDate","today","loading","DateUtils","CoreDateUtils","format","locale","formats","showMinutes","use24Hour","startFormat","startTime","endTime","baseDate","rtf","diff","diffInSeconds","diffInMinutes","diffInHours","diffInDays","diffInWeeks","diffInMonths","diffInYears","firstDayOfYear","pastDaysOfYear","dayIndex","monthIndex","timeStr","time","period","hours","minutes","adjustedHours","DOMUtils","tag","attributes","children","child","events","delegatedHandler","target","rect","threshold","behavior","block","inline","property","className","duration","eventType","resolve","ms","htmlString","str","div","func","wait","timeout","args","later","limit","inThrottle","parents","parent","margin","deep","container","focusableElements","firstFocusable","lastFocusable","handleKeyDown","StyleUtils","variables","color","percent","num","amt","R","G","B","bgColor","g","fallback","trimmed","hex","alpha","r","breakpoint","size","__publicField","BaseViewRenderer","stateManager","date1","date2","hour","displayHour","fullColor","c","col","now","entries","evt","startMin","endMin","columns","layout","entry","placed","groups","currentGroup","groupEnd","group","maxCol","compact","overlapLayout","startMinutes","durationMinutes","padding","fontSize","baseMargin","rightPad","borderRadius","leftPx","widthCalc","column","totalColumns","colWidth","eventEl","ev","MonthViewRenderer","html","weekStartsOn","d","days","dayNames","isOtherMonth","isToday","dayBg","dayNumColor","todayStyle","visibleEvents","moreCount","dayEl","WeekViewRenderer","_config","_","i","processedDays","h","scrollContainer","gridTop","y","clampedY","DayViewRenderer","currentDate","_b","dayData","dayName","allDayEvents","timedEvents","eventMap","dayDataItem","EventForm","btn","isSelected","initialDate","isValid","pad","year","month","_ForceCalendar","unsub","bus","forwardEventAction","action","viewChanged","dateChanged","eventsChanged","loadingChanged","titleEl","state","button","isActive","RendererClass","viewRenderer","err","isLoading","loadingEl","viewContainer","viewType","height","title","modal","createBtn","eventData","id","weekStart","weekEnd","ForceCalendar"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"force-calendar-interface.umd.js","sources":["../src/core/BaseComponent.js","../src/core/EventBus.js","../src/core/StateManager.js","../src/utils/DateUtils.js","../src/utils/DOMUtils.js","../src/utils/StyleUtils.js","../src/renderers/BaseViewRenderer.js","../src/renderers/MonthViewRenderer.js","../src/renderers/WeekViewRenderer.js","../src/renderers/DayViewRenderer.js","../src/components/EventForm.js","../src/components/ForceCalendar.js"],"sourcesContent":["/**\n * BaseComponent - Foundation for all Force Calendar Web Components\n *\n * Provides common functionality:\n * - Shadow DOM setup\n * - Event handling\n * - State management integration\n * - Lifecycle management\n * - Style management\n */\n\nexport class BaseComponent extends HTMLElement {\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n this._listeners = [];\n this._state = null;\n this._props = new Map();\n this._initialized = false;\n }\n\n // Lifecycle methods\n connectedCallback() {\n if (!this._initialized) {\n this.initialize();\n this._initialized = true;\n }\n this.mount();\n }\n\n disconnectedCallback() {\n this.unmount();\n this.cleanup();\n }\n\n // To be overridden by child classes\n initialize() {\n // Setup component-specific initialization\n }\n\n mount() {\n // Component mounted to DOM\n this.render();\n }\n\n unmount() {\n // Component removed from DOM\n }\n\n cleanup() {\n // Clean up event listeners\n this._listeners.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler);\n });\n this._listeners = [];\n }\n\n // State management\n setState(newState) {\n const oldState = this._state;\n this._state = { ...this._state, ...newState };\n this.stateChanged(oldState, this._state);\n this.render();\n }\n\n getState() {\n return this._state;\n }\n\n stateChanged(_oldState, _newState) {\n // Override in child classes to handle state changes\n }\n\n // Props management\n setProp(key, value) {\n const oldValue = this._props.get(key);\n this._props.set(key, value);\n this.propChanged(key, oldValue, value);\n }\n\n getProp(key) {\n return this._props.get(key);\n }\n\n propChanged(_key, _oldValue, _newValue) {\n // Override in child classes to handle prop changes\n }\n\n // Event handling\n addListener(element, event, handler) {\n if (!element || !event || !handler) {\n console.warn('addListener called with invalid parameters', { element, event, handler });\n return;\n }\n const boundHandler = handler.bind(this);\n element.addEventListener(event, boundHandler);\n this._listeners.push({ element, event, handler: boundHandler });\n }\n\n emit(eventName, detail = {}) {\n this.dispatchEvent(\n new CustomEvent(eventName, {\n detail,\n bubbles: true,\n composed: true\n })\n );\n }\n\n // Style management\n getStyles() {\n // Override in child classes to provide component styles\n return '';\n }\n\n getBaseStyles() {\n return `\n :host {\n display: block;\n box-sizing: border-box;\n }\n\n *, *::before, *::after {\n box-sizing: inherit;\n }\n `;\n }\n\n // Template rendering\n render() {\n // Clean up existing listeners before replacing DOM\n this.cleanup();\n\n const styles = `\n <style>\n ${this.getBaseStyles()}\n ${this.getStyles()}\n </style>\n `;\n\n const template = this.template();\n this.shadowRoot.innerHTML = styles + template;\n this.afterRender();\n }\n\n template() {\n // Override in child classes to provide component template\n return '';\n }\n\n afterRender() {\n // Override in child classes for post-render operations\n }\n\n // Utility methods\n $(selector) {\n return this.shadowRoot.querySelector(selector);\n }\n\n $$(selector) {\n return this.shadowRoot.querySelectorAll(selector);\n }\n\n // Attribute observation\n static get observedAttributes() {\n return [];\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n this.setProp(name, newValue);\n if (this._initialized) {\n this.render();\n }\n }\n}\n","/**\n * EventBus - Central event communication system\n *\n * Enables decoupled communication between components\n * Supports event namespacing and wildcard subscriptions\n */\n\nclass EventBus {\n constructor() {\n this.events = new Map();\n this.wildcardHandlers = new Set();\n }\n\n /**\n * Subscribe to an event\n * @param {string} eventName - Event name or pattern (supports wildcards)\n * @param {Function} handler - Event handler function\n * @param {Object} options - Subscription options\n * @returns {Function} Unsubscribe function\n */\n on(eventName, handler, options = {}) {\n const { once = false, priority = 0 } = options;\n\n // Handle wildcard subscriptions\n if (eventName.includes('*')) {\n const subscription = { pattern: eventName, handler, once, priority };\n this.wildcardHandlers.add(subscription);\n return () => this.wildcardHandlers.delete(subscription);\n }\n\n // Regular event subscription\n if (!this.events.has(eventName)) {\n this.events.set(eventName, []);\n }\n\n const subscription = { handler, once, priority };\n const handlers = this.events.get(eventName);\n handlers.push(subscription);\n handlers.sort((a, b) => b.priority - a.priority);\n\n // Return unsubscribe function\n return () => {\n const index = handlers.indexOf(subscription);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n };\n }\n\n /**\n * Subscribe to an event that fires only once\n */\n once(eventName, handler, options = {}) {\n return this.on(eventName, handler, { ...options, once: true });\n }\n\n /**\n * Unsubscribe from an event\n */\n off(eventName, handler) {\n // Handle wildcard pattern removal\n if (eventName.includes('*')) {\n for (const sub of this.wildcardHandlers) {\n if (sub.pattern === eventName && sub.handler === handler) {\n this.wildcardHandlers.delete(sub);\n return;\n }\n }\n return;\n }\n\n if (!this.events.has(eventName)) return;\n\n const handlers = this.events.get(eventName);\n const index = handlers.findIndex(sub => sub.handler === handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n\n if (handlers.length === 0) {\n this.events.delete(eventName);\n }\n }\n\n /**\n * Remove all wildcard handlers matching a pattern\n * @param {string} pattern - Pattern to match (e.g., 'event:*')\n */\n offWildcard(pattern) {\n for (const sub of [...this.wildcardHandlers]) {\n if (sub.pattern === pattern) {\n this.wildcardHandlers.delete(sub);\n }\n }\n }\n\n /**\n * Remove all handlers (regular and wildcard) for a specific handler function\n * Useful for cleanup when a component is destroyed\n * @param {Function} handler - Handler function to remove\n */\n offAll(handler) {\n // Remove from regular events\n for (const [eventName, handlers] of this.events) {\n const index = handlers.findIndex(sub => sub.handler === handler);\n if (index > -1) {\n handlers.splice(index, 1);\n }\n if (handlers.length === 0) {\n this.events.delete(eventName);\n }\n }\n\n // Remove from wildcard handlers\n for (const sub of [...this.wildcardHandlers]) {\n if (sub.handler === handler) {\n this.wildcardHandlers.delete(sub);\n }\n }\n }\n\n /**\n * Emit an event synchronously\n * @param {string} eventName - Event name\n * @param {*} data - Event data\n */\n emit(eventName, data) {\n // Handle direct subscriptions\n if (this.events.has(eventName)) {\n const handlers = [...this.events.get(eventName)];\n\n for (const subscription of handlers) {\n const { handler, once } = subscription;\n\n if (once) {\n this.off(eventName, handler);\n }\n\n try {\n handler(data, eventName);\n } catch (error) {\n console.error(`Error in event handler for ${eventName}:`, error);\n }\n }\n }\n\n // Handle wildcard subscriptions (copy Set to avoid mutation during iteration)\n const toRemove = [];\n for (const subscription of [...this.wildcardHandlers]) {\n if (this.matchesPattern(eventName, subscription.pattern)) {\n const { handler, once } = subscription;\n\n if (once) {\n toRemove.push(subscription);\n }\n\n try {\n handler(data, eventName);\n } catch (error) {\n console.error(`Error in wildcard handler for ${eventName}:`, error);\n }\n }\n }\n // Remove one-time handlers after iteration\n toRemove.forEach(sub => this.wildcardHandlers.delete(sub));\n }\n\n /**\n * Check if event name matches a pattern\n */\n matchesPattern(eventName, pattern) {\n const regex = new RegExp('^' + pattern.replace(/\\*/g, '.*') + '$');\n return regex.test(eventName);\n }\n\n /**\n * Clear all event subscriptions\n */\n clear() {\n this.events.clear();\n this.wildcardHandlers.clear();\n }\n\n /**\n * Get all registered event names\n */\n getEventNames() {\n return Array.from(this.events.keys());\n }\n\n /**\n * Get handler count for an event\n */\n getHandlerCount(eventName) {\n return this.events.has(eventName) ? this.events.get(eventName).length : 0;\n }\n\n /**\n * Get wildcard handler count\n */\n getWildcardHandlerCount() {\n return this.wildcardHandlers.size;\n }\n\n /**\n * Get total handler count (for debugging/monitoring)\n */\n getTotalHandlerCount() {\n let count = this.wildcardHandlers.size;\n for (const handlers of this.events.values()) {\n count += handlers.length;\n }\n return count;\n }\n}\n\n// Create singleton instance\nconst eventBus = new EventBus();\n\n// Export both the class and singleton\nexport { EventBus, eventBus as default };\n","/**\n * StateManager - Centralized state management for Force Calendar\n *\n * Wraps the @forcecalendar/core Calendar instance\n * Provides reactive state updates and component synchronization\n */\n\nimport { Calendar } from '@forcecalendar/core';\nimport { EventBus } from './EventBus.js';\n\nclass StateManager {\n constructor(config = {}) {\n // Each StateManager gets its own EventBus to prevent cross-instance\n // contamination when multiple calendars exist on the same page.\n this.eventBus = new EventBus();\n\n // Initialize Core Calendar instance\n this.calendar = new Calendar({\n view: config.view || 'month',\n date: config.date || new Date(),\n weekStartsOn: config.weekStartsOn ?? 0,\n locale: config.locale || 'en-US',\n timeZone: config.timeZone || Intl.DateTimeFormat().resolvedOptions().timeZone,\n ...config\n });\n\n // Internal state\n this.state = {\n view: this.calendar.getView(),\n currentDate: this.calendar.getCurrentDate(),\n events: [],\n selectedEvent: null,\n selectedDate: null,\n loading: false,\n error: null,\n config: { ...config }\n };\n\n // State change subscribers\n this.subscribers = new Set();\n\n // Bind methods\n this.subscribe = this.subscribe.bind(this);\n this.unsubscribe = this.unsubscribe.bind(this);\n this.setState = this.setState.bind(this);\n\n // Initial sync of events from Core (in case events were pre-loaded)\n this._syncEventsFromCore({ silent: true });\n }\n\n /**\n * Sync state.events from Core calendar (single source of truth)\n * This ensures state.events always matches Core's event store.\n *\n * @param {object} options\n * @param {boolean} options.silent - suppress subscriber notifications\n * @param {boolean} options.force - always update even when IDs match\n * (required after updateEvent where IDs\n * are unchanged but content has changed)\n */\n _syncEventsFromCore(options = {}) {\n const { force = false } = options;\n const coreEvents = this.calendar.getEvents() || [];\n // Skip the update when nothing changed, unless the caller forces a sync\n // (e.g. after updateEvent where IDs are the same but content differs)\n if (\n force ||\n this.state.events.length !== coreEvents.length ||\n !this._eventsMatch(this.state.events, coreEvents)\n ) {\n this.setState({ events: [...coreEvents] }, options);\n }\n return coreEvents;\n }\n\n /**\n * Check if two event arrays have the same events by id.\n * Only used for add/delete guards — updateEvent must pass force:true\n * to bypass this check because IDs are unchanged after an update.\n */\n _eventsMatch(arr1, arr2) {\n if (arr1.length !== arr2.length) return false;\n const ids1 = new Set(arr1.map(e => e.id));\n return arr2.every(e => ids1.has(e.id));\n }\n\n // State management\n getState() {\n return {\n ...this.state,\n config: { ...this.state.config },\n events: [...this.state.events]\n };\n }\n\n setState(updates, options = {}) {\n const { silent = false } = options;\n const oldState = { ...this.state };\n this.state = { ...this.state, ...updates };\n\n if (!silent) {\n this.notifySubscribers(oldState, this.state);\n this.emitStateChange(oldState, this.state);\n }\n\n return this.state;\n }\n\n subscribe(callback, subscriberId = null) {\n this.subscribers.add(callback);\n\n // Track subscriber ID for debugging/cleanup\n if (subscriberId) {\n if (!this._subscriberIds) {\n this._subscriberIds = new Map();\n }\n this._subscriberIds.set(subscriberId, callback);\n }\n\n return () => this.unsubscribe(callback, subscriberId);\n }\n\n unsubscribe(callback, subscriberId = null) {\n this.subscribers.delete(callback);\n\n // Clean up ID tracking\n if (subscriberId && this._subscriberIds) {\n this._subscriberIds.delete(subscriberId);\n }\n }\n\n /**\n * Unsubscribe by subscriber ID\n * @param {string} subscriberId - ID used when subscribing\n */\n unsubscribeById(subscriberId) {\n if (!this._subscriberIds) return false;\n\n const callback = this._subscriberIds.get(subscriberId);\n if (callback) {\n this.subscribers.delete(callback);\n this._subscriberIds.delete(subscriberId);\n return true;\n }\n return false;\n }\n\n /**\n * Get subscriber count (for debugging/monitoring)\n */\n getSubscriberCount() {\n return this.subscribers.size;\n }\n\n notifySubscribers(oldState, newState) {\n this.subscribers.forEach(callback => {\n try {\n callback(newState, oldState);\n } catch (error) {\n console.error('Error in state subscriber:', error);\n }\n });\n }\n\n emitStateChange(oldState, newState) {\n const changedKeys = Object.keys(newState).filter(key => oldState[key] !== newState[key]);\n\n changedKeys.forEach(key => {\n this.eventBus.emit(`state:${key}:changed`, {\n oldValue: oldState[key],\n newValue: newState[key],\n state: newState\n });\n });\n\n if (changedKeys.length > 0) {\n this.eventBus.emit('state:changed', { oldState, newState, changedKeys });\n }\n }\n\n // Calendar operations\n setView(view) {\n this.calendar.setView(view);\n this.setState({ view });\n this.eventBus.emit('view:changed', { view });\n }\n\n getView() {\n return this.state.view;\n }\n\n setDate(date) {\n this.calendar.goToDate(date);\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('date:changed', { date: this.state.currentDate });\n }\n\n getCurrentDate() {\n return this.state.currentDate;\n }\n\n // Navigation\n next() {\n this.calendar.next();\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('navigation:next', { date: this.state.currentDate });\n }\n\n previous() {\n this.calendar.previous();\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('navigation:previous', { date: this.state.currentDate });\n }\n\n today() {\n this.calendar.today();\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('navigation:today', { date: this.state.currentDate });\n }\n\n goToDate(date) {\n this.calendar.goToDate(date);\n this.setState({ currentDate: this.calendar.getCurrentDate() });\n this.eventBus.emit('navigation:goto', { date: this.state.currentDate });\n }\n\n // Event management\n addEvent(event) {\n const addedEvent = this.calendar.addEvent(event);\n if (!addedEvent) {\n console.error('Failed to add event to calendar');\n this.eventBus.emit('event:error', { action: 'add', event, error: 'Failed to add event' });\n return null;\n }\n // Sync from Core to ensure consistency (single source of truth)\n this._syncEventsFromCore();\n this.eventBus.emit('event:add', { event: addedEvent });\n this.eventBus.emit('event:added', { event: addedEvent });\n return addedEvent;\n }\n\n updateEvent(eventId, updates) {\n // First, ensure state is in sync with Core (recover from any prior desync)\n this._syncEventsFromCore({ silent: true });\n\n const event = this.calendar.updateEvent(eventId, updates);\n if (!event) {\n console.error(`Failed to update event: ${eventId}`);\n this.eventBus.emit('event:error', {\n action: 'update',\n eventId,\n updates,\n error: 'Event not found in calendar'\n });\n return null;\n }\n\n // Force sync from Core — IDs are unchanged after an update so the\n // ID-only guard in _eventsMatch would otherwise skip the state update\n this._syncEventsFromCore({ force: true });\n this.eventBus.emit('event:update', { event });\n this.eventBus.emit('event:updated', { event });\n return event;\n }\n\n deleteEvent(eventId) {\n // First, ensure state is in sync with Core (recover from any prior desync)\n this._syncEventsFromCore({ silent: true });\n\n const deleted = this.calendar.removeEvent(eventId);\n if (!deleted) {\n console.error(`Failed to delete event: ${eventId}`);\n this.eventBus.emit('event:error', { action: 'delete', eventId, error: 'Event not found' });\n return false;\n }\n // Sync from Core to ensure consistency (single source of truth)\n this._syncEventsFromCore();\n this.eventBus.emit('event:remove', { eventId });\n this.eventBus.emit('event:deleted', { eventId });\n return true;\n }\n\n getEvents() {\n // Return from Core (source of truth)\n return this.calendar.getEvents() || [];\n }\n\n /**\n * Force sync state.events from Core calendar\n * Use this if you've modified events directly on the Core calendar\n */\n syncEvents() {\n return this._syncEventsFromCore();\n }\n\n getEventsForDate(date) {\n return this.calendar.getEventsForDate(date);\n }\n\n getEventsInRange(start, end) {\n return this.calendar.getEventsInRange(start, end);\n }\n\n // View data\n getViewData() {\n const viewData = this.calendar.getViewData();\n return this.enrichViewData(viewData);\n }\n\n enrichViewData(viewData) {\n // Shallow-copy the top-level object so we never mutate what Core returned.\n // Core may cache and reuse the same reference across calls; mutating it\n // in-place would corrupt its internal state.\n const enriched = { ...viewData };\n const selectedDateString = this.state.selectedDate?.toDateString();\n\n // Strategy 1: Multi-week structure (Month view)\n if (enriched.weeks) {\n enriched.weeks = enriched.weeks.map(week => ({\n ...week,\n days: week.days.map(day => {\n const dayDate = new Date(day.date);\n return {\n ...day,\n isSelected: dayDate.toDateString() === selectedDateString,\n events: day.events || this.getEventsForDate(dayDate)\n };\n })\n }));\n }\n\n // Strategy 2: Flat days structure (Week view or list view)\n if (enriched.days) {\n enriched.days = enriched.days.map(day => {\n const dayDate = new Date(day.date);\n return {\n ...day,\n isSelected: dayDate.toDateString() === selectedDateString,\n events: day.events || this.getEventsForDate(dayDate)\n };\n });\n }\n\n // Strategy 3: Single day structure (Day view)\n if (enriched.date && !enriched.days && !enriched.weeks) {\n const dayDate = new Date(enriched.date);\n enriched.isSelected = dayDate.toDateString() === selectedDateString;\n enriched.events = enriched.events || this.getEventsForDate(dayDate);\n }\n\n return enriched;\n }\n\n // Selection management\n selectEvent(event) {\n this.setState({ selectedEvent: event });\n this.eventBus.emit('event:selected', { event });\n }\n\n selectEventById(eventId) {\n const event = this.state.events.find(e => e.id === eventId);\n if (event) {\n this.selectEvent(event);\n }\n }\n\n deselectEvent() {\n this.setState({ selectedEvent: null });\n this.eventBus.emit('event:deselected', {});\n }\n\n selectDate(date) {\n this.setState({ selectedDate: date });\n this.eventBus.emit('date:selected', { date });\n }\n\n deselectDate() {\n this.setState({ selectedDate: null });\n this.eventBus.emit('date:deselected', {});\n }\n\n // Utility methods\n isToday(date) {\n const today = new Date();\n return date.toDateString() === today.toDateString();\n }\n\n isSelectedDate(date) {\n return (\n this.state.selectedDate && date.toDateString() === this.state.selectedDate.toDateString()\n );\n }\n\n isWeekend(date) {\n const day = date.getDay();\n return day === 0 || day === 6;\n }\n\n // Loading state\n setLoading(loading) {\n this.setState({ loading });\n }\n\n // Error handling\n setError(error) {\n this.setState({ error });\n if (error) {\n this.eventBus.emit('error', { error });\n }\n }\n\n clearError() {\n this.setState({ error: null });\n }\n\n // Configuration\n updateConfig(config) {\n this.setState({ config: { ...this.state.config, ...config } });\n\n // Update calendar configuration if needed\n if (config.weekStartsOn !== undefined) {\n this.calendar.setWeekStartsOn(config.weekStartsOn);\n }\n if (config.locale !== undefined) {\n this.calendar.setLocale(config.locale);\n }\n if (config.timeZone !== undefined) {\n this.calendar.setTimezone(config.timeZone);\n }\n }\n\n // Destroy\n destroy() {\n this.subscribers.clear();\n if (this._subscriberIds) {\n this._subscriberIds.clear();\n this._subscriberIds = null;\n }\n if (this.eventBus) {\n this.eventBus.clear();\n this.eventBus = null;\n }\n this.state = null;\n this.calendar = null;\n }\n}\n\n// Export StateManager\nexport default StateManager;\n","/**\n * DateUtils - Date formatting and manipulation utilities\n *\n * Extends Core DateUtils with UI-specific formatting\n */\n\nimport { DateUtils as CoreDateUtils } from '@forcecalendar/core';\n\nexport class DateUtils extends CoreDateUtils {\n /**\n * Format date for display\n */\n static formatDate(date, format = 'default', locale = 'en-US') {\n if (!date) return '';\n\n const formats = {\n default: { year: 'numeric', month: 'long', day: 'numeric' },\n short: { year: 'numeric', month: 'short', day: 'numeric' },\n long: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' },\n month: { year: 'numeric', month: 'long' },\n monthShort: { year: 'numeric', month: 'short' },\n day: { weekday: 'long', day: 'numeric' },\n dayShort: { weekday: 'short', day: 'numeric' },\n time: { hour: 'numeric', minute: '2-digit' },\n timeShort: { hour: 'numeric' },\n datetime: {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit'\n }\n };\n\n const options = formats[format] || formats.default;\n return new Intl.DateTimeFormat(locale, options).format(date);\n }\n\n /**\n * Format time for display\n */\n static formatTime(date, showMinutes = true, use24Hour = false, locale = 'en-US') {\n if (!date) return '';\n\n const options = {\n hour: 'numeric',\n minute: showMinutes ? '2-digit' : undefined,\n hour12: !use24Hour\n };\n\n return new Intl.DateTimeFormat(locale, options).format(date);\n }\n\n /**\n * Format date range for display\n */\n static formatDateRange(start, end, locale = 'en-US') {\n if (!start) return '';\n if (!end || this.isSameDay(start, end)) {\n return this.formatDate(start, 'default', locale);\n }\n\n const startFormat = this.isSameYear(start, end) ? 'short' : 'default';\n return `${this.formatDate(start, startFormat, locale)} - ${this.formatDate(end, 'default', locale)}`;\n }\n\n /**\n * Format time range for display\n */\n static formatTimeRange(start, end, locale = 'en-US') {\n if (!start) return '';\n\n const startTime = this.formatTime(start, true, false, locale);\n if (!end) return startTime;\n\n const endTime = this.formatTime(end, true, false, locale);\n return `${startTime} - ${endTime}`;\n }\n\n /**\n * Get relative time string (e.g., \"2 hours ago\", \"in 3 days\")\n */\n static getRelativeTime(date, baseDate = new Date(), locale = 'en-US') {\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });\n const diff = date - baseDate;\n const diffInSeconds = Math.floor(diff / 1000);\n const diffInMinutes = Math.floor(diffInSeconds / 60);\n const diffInHours = Math.floor(diffInMinutes / 60);\n const diffInDays = Math.floor(diffInHours / 24);\n const diffInWeeks = Math.floor(diffInDays / 7);\n const diffInMonths = Math.floor(diffInDays / 30);\n const diffInYears = Math.floor(diffInDays / 365);\n\n if (Math.abs(diffInSeconds) < 60) {\n return rtf.format(diffInSeconds, 'second');\n } else if (Math.abs(diffInMinutes) < 60) {\n return rtf.format(diffInMinutes, 'minute');\n } else if (Math.abs(diffInHours) < 24) {\n return rtf.format(diffInHours, 'hour');\n } else if (Math.abs(diffInDays) < 7) {\n return rtf.format(diffInDays, 'day');\n } else if (Math.abs(diffInWeeks) < 4) {\n return rtf.format(diffInWeeks, 'week');\n } else if (Math.abs(diffInMonths) < 12) {\n return rtf.format(diffInMonths, 'month');\n } else {\n return rtf.format(diffInYears, 'year');\n }\n }\n\n /**\n * Check if date is today\n */\n static isToday(date) {\n const today = new Date();\n return this.isSameDay(date, today);\n }\n\n /**\n * Check if date is in the past\n */\n static isPast(date) {\n return date < new Date();\n }\n\n /**\n * Check if date is in the future\n */\n static isFuture(date) {\n return date > new Date();\n }\n\n /**\n * Get calendar week number\n */\n static getWeekNumber(date) {\n const firstDayOfYear = new Date(date.getFullYear(), 0, 1);\n const pastDaysOfYear = (date - firstDayOfYear) / 86400000;\n return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);\n }\n\n /**\n * Get day abbreviation\n */\n static getDayAbbreviation(dayIndex, locale = 'en-US') {\n const date = new Date(2024, 0, 7 + dayIndex); // Jan 7, 2024 is a Sunday\n return new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(date);\n }\n\n /**\n * Get month name\n */\n static getMonthName(monthIndex, format = 'long', locale = 'en-US') {\n const date = new Date(2024, monthIndex, 1);\n return new Intl.DateTimeFormat(locale, { month: format }).format(date);\n }\n\n /**\n * Parse time string (e.g., \"14:30\" or \"2:30 PM\")\n */\n static parseTimeString(timeStr, baseDate = new Date()) {\n const date = new Date(baseDate);\n const [time, period] = timeStr.split(/\\s+/);\n const [hours, minutes] = time.split(':').map(Number);\n\n let adjustedHours = hours;\n if (period) {\n if (period.toLowerCase() === 'pm' && hours < 12) {\n adjustedHours = hours + 12;\n } else if (period.toLowerCase() === 'am' && hours === 12) {\n adjustedHours = 0;\n }\n }\n\n date.setHours(adjustedHours, minutes || 0, 0, 0);\n return date;\n }\n}\n\nexport default DateUtils;\n","/**\n * DOMUtils - DOM manipulation and event utilities\n */\n\nexport class DOMUtils {\n /**\n * Create element with attributes and children\n */\n static createElement(tag, attributes = {}, children = []) {\n const element = document.createElement(tag);\n\n // Set attributes\n Object.entries(attributes).forEach(([key, value]) => {\n if (key === 'className') {\n element.className = value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(element.style, value);\n } else if (key.startsWith('data-')) {\n element.setAttribute(key, value);\n } else if (key.startsWith('on') && typeof value === 'function') {\n const eventName = key.slice(2).toLowerCase();\n element.addEventListener(eventName, value);\n } else {\n element[key] = value;\n }\n });\n\n // Add children\n children.forEach(child => {\n if (typeof child === 'string') {\n element.appendChild(document.createTextNode(child));\n } else if (child instanceof Node) {\n element.appendChild(child);\n }\n });\n\n return element;\n }\n\n /**\n * Add multiple event listeners\n */\n static addEventListeners(element, events) {\n Object.entries(events).forEach(([event, handler]) => {\n element.addEventListener(event, handler);\n });\n\n // Return cleanup function\n return () => {\n Object.entries(events).forEach(([event, handler]) => {\n element.removeEventListener(event, handler);\n });\n };\n }\n\n /**\n * Delegate event handling\n */\n static delegate(element, selector, event, handler) {\n const delegatedHandler = e => {\n const target = e.target.closest(selector);\n if (target && element.contains(target)) {\n handler.call(target, e);\n }\n };\n\n element.addEventListener(event, delegatedHandler);\n return () => element.removeEventListener(event, delegatedHandler);\n }\n\n /**\n * Get element position relative to viewport\n */\n static getPosition(element) {\n const rect = element.getBoundingClientRect();\n return {\n top: rect.top + window.scrollY,\n left: rect.left + window.scrollX,\n bottom: rect.bottom + window.scrollY,\n right: rect.right + window.scrollX,\n width: rect.width,\n height: rect.height\n };\n }\n\n /**\n * Check if element is in viewport\n */\n static isInViewport(element, threshold = 0) {\n const rect = element.getBoundingClientRect();\n return (\n rect.top >= -threshold &&\n rect.left >= -threshold &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) + threshold &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth) + threshold\n );\n }\n\n /**\n * Smooth scroll to element\n */\n static scrollToElement(element, options = {}) {\n const { behavior = 'smooth', block = 'start', inline = 'nearest' } = options;\n element.scrollIntoView({ behavior, block, inline });\n }\n\n /**\n * Get computed style value\n */\n static getStyle(element, property) {\n return window.getComputedStyle(element).getPropertyValue(property);\n }\n\n /**\n * Set multiple styles\n */\n static setStyles(element, styles) {\n Object.assign(element.style, styles);\n }\n\n /**\n * Add/remove classes with animation support\n */\n static async animateClass(element, className, duration = 300) {\n element.classList.add(className);\n await this.wait(duration);\n element.classList.remove(className);\n }\n\n /**\n * Wait for animation/transition to complete\n */\n static waitForAnimation(element, eventType = 'animationend') {\n return new Promise(resolve => {\n const handler = () => {\n element.removeEventListener(eventType, handler);\n resolve();\n };\n element.addEventListener(eventType, handler);\n });\n }\n\n /**\n * Utility wait function\n */\n static wait(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n /**\n * Parse HTML string safely\n */\n static parseHTML(htmlString) {\n const template = document.createElement('template');\n template.innerHTML = htmlString.trim();\n return template.content.firstChild;\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n static escapeHTML(str) {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n\n /**\n * Debounce function calls\n */\n static debounce(func, wait = 250) {\n let timeout;\n return function executedFunction(...args) {\n const later = () => {\n clearTimeout(timeout);\n func(...args);\n };\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n };\n }\n\n /**\n * Throttle function calls\n */\n static throttle(func, limit = 250) {\n let inThrottle;\n return function (...args) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n }\n\n /**\n * Get closest parent matching selector\n */\n static closest(element, selector) {\n return element.closest(selector);\n }\n\n /**\n * Get all parents matching selector\n */\n static parents(element, selector) {\n const parents = [];\n let parent = element.parentElement;\n\n while (parent) {\n if (parent.matches(selector)) {\n parents.push(parent);\n }\n parent = parent.parentElement;\n }\n\n return parents;\n }\n\n /**\n * Measure element dimensions including margins\n */\n static getOuterDimensions(element) {\n const styles = window.getComputedStyle(element);\n const margin = {\n top: parseInt(styles.marginTop),\n right: parseInt(styles.marginRight),\n bottom: parseInt(styles.marginBottom),\n left: parseInt(styles.marginLeft)\n };\n\n return {\n width: element.offsetWidth + margin.left + margin.right,\n height: element.offsetHeight + margin.top + margin.bottom,\n margin\n };\n }\n\n /**\n * Clone element with event listeners\n */\n static cloneWithEvents(element, deep = true) {\n const clone = element.cloneNode(deep);\n\n // Copy event listeners (Note: This is a simplified version)\n // In production, you'd need a more robust event copying mechanism\n return clone;\n }\n\n /**\n * Focus trap for modals/dialogs\n */\n static trapFocus(container) {\n const focusableElements = container.querySelectorAll(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n );\n\n // Handle case where there are no focusable elements\n if (focusableElements.length === 0) {\n // Make container focusable as fallback\n container.setAttribute('tabindex', '-1');\n container.focus();\n return () => container.removeAttribute('tabindex');\n }\n\n const firstFocusable = focusableElements[0];\n const lastFocusable = focusableElements[focusableElements.length - 1];\n\n const handleKeyDown = e => {\n if (e.key !== 'Tab') return;\n\n if (e.shiftKey) {\n if (document.activeElement === firstFocusable) {\n lastFocusable?.focus();\n e.preventDefault();\n }\n } else {\n if (document.activeElement === lastFocusable) {\n firstFocusable?.focus();\n e.preventDefault();\n }\n }\n };\n\n container.addEventListener('keydown', handleKeyDown);\n firstFocusable?.focus();\n\n return () => container.removeEventListener('keydown', handleKeyDown);\n }\n}\n\nexport default DOMUtils;\n","/**\n * StyleUtils - Styling utilities and theme management\n */\n\nexport class StyleUtils {\n /**\n * Default theme colors\n */\n static colors = {\n primary: '#3B82F6', // Modern Blue\n secondary: '#64748B', // Slate\n accent: '#F59E0B', // Amber\n danger: '#EF4444', // Red\n warning: '#F97316', // Orange\n info: '#06B6D4', // Cyan\n success: '#22C55E', // Green\n light: '#F8FAFC',\n dark: '#0F172A',\n white: '#FFFFFF',\n gray: {\n 50: '#F8FAFC',\n 100: '#F1F5F9',\n 200: '#E2E8F0',\n 300: '#CBD5E1',\n 400: '#94A3B8',\n 500: '#64748B',\n 600: '#475569',\n 700: '#334155',\n 800: '#1E293B',\n 900: '#0F172A'\n }\n };\n\n /**\n * Common CSS variables\n */\n static cssVariables = {\n // \"Pro\" Palette - Functional & Sharp\n '--fc-primary-color': '#2563EB', // International Blue (Focus)\n '--fc-primary-hover': '#1D4ED8',\n '--fc-primary-light': '#EFF6FF',\n\n // Neutral Scale (Slate/Gray for structure)\n '--fc-text-color': '#111827', // Almost Black\n '--fc-text-secondary': '#6B7280', // Cool Gray\n '--fc-text-light': '#9CA3AF',\n\n '--fc-border-color': '#E5E7EB', // Crisp Light Gray\n '--fc-border-color-hover': '#D1D5DB',\n\n '--fc-background': '#FFFFFF',\n '--fc-background-alt': '#FAFAFA', // Very subtle off-white\n '--fc-background-hover': '#F3F4F6',\n '--fc-background-active': '#E5E7EB',\n\n // Semantic Colors\n '--fc-accent-color': '#F59E0B',\n '--fc-danger-color': '#EF4444',\n '--fc-success-color': '#10B981',\n\n // Typography - optimized for UI density\n '--fc-font-family': 'Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n '--fc-font-size-xs': '11px',\n '--fc-font-size-sm': '12px',\n '--fc-font-size-base': '13px', // Slightly smaller for density\n '--fc-font-size-lg': '15px',\n '--fc-font-size-xl': '18px',\n '--fc-font-size-2xl': '24px',\n '--fc-line-height': '1.4',\n '--fc-font-weight-normal': '400',\n '--fc-font-weight-medium': '500',\n '--fc-font-weight-semibold': '600',\n '--fc-font-weight-bold': '700',\n\n // Spacing - Tighter\n '--fc-spacing-xs': '2px',\n '--fc-spacing-sm': '6px',\n '--fc-spacing-md': '10px',\n '--fc-spacing-lg': '14px',\n '--fc-spacing-xl': '20px',\n '--fc-spacing-2xl': '28px',\n\n // Border\n '--fc-border-width': '1px',\n '--fc-border-radius-sm': '3px', // Micro rounding\n '--fc-border-radius': '5px',\n '--fc-border-radius-lg': '8px',\n '--fc-border-radius-full': '9999px',\n\n // Shadows - Minimal/Functional\n '--fc-shadow-sm': '0 1px 1px rgba(0,0,0,0.05)',\n '--fc-shadow': '0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06)',\n '--fc-shadow-md': '0 4px 6px -1px rgba(0, 0, 0, 0.1)',\n '--fc-shadow-lg': '0 10px 15px -3px rgba(0, 0, 0, 0.1)',\n\n // Transitions - Snappy\n '--fc-transition-fast': '100ms ease-out',\n '--fc-transition': '150ms ease-out',\n '--fc-transition-slow': '250ms ease-out',\n\n // Z-index\n '--fc-z-dropdown': '1000',\n '--fc-z-modal': '2000',\n '--fc-z-tooltip': '3000'\n };\n\n /**\n * Get CSS variable value\n */\n static getCSSVariable(name, element = document.documentElement) {\n return getComputedStyle(element).getPropertyValue(name).trim();\n }\n\n /**\n * Set CSS variables\n */\n static setCSSVariables(variables, element = document.documentElement) {\n Object.entries(variables).forEach(([key, value]) => {\n element.style.setProperty(key, value);\n });\n }\n\n /**\n * Generate base styles\n */\n static getBaseStyles() {\n return `\n :host {\n /* Apply CSS variables */\n ${Object.entries(this.cssVariables)\n .map(([key, value]) => `${key}: ${value};`)\n .join('\\n ')}\n\n /* Base styles */\n display: block;\n box-sizing: border-box;\n font-family: var(--fc-font-family);\n font-size: var(--fc-font-size-base);\n line-height: var(--fc-line-height);\n color: var(--fc-text-color);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n\n *, *::before, *::after {\n box-sizing: inherit;\n }\n\n /* Reset styles */\n h1, h2, h3, h4, h5, h6, p {\n margin: 0;\n font-weight: normal;\n }\n\n button {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n margin: 0;\n }\n\n /* Accessibility */\n .visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* Focus styles */\n :focus-visible {\n outline: 2px solid var(--fc-primary-color);\n outline-offset: 2px;\n }\n `;\n }\n\n /**\n * Generate button styles\n */\n static getButtonStyles() {\n return `\n .fc-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 8px 16px;\n font-size: var(--fc-font-size-sm);\n font-weight: var(--fc-font-weight-medium);\n line-height: 1.25rem;\n border-radius: var(--fc-border-radius);\n border: 1px solid transparent;\n cursor: pointer;\n transition: all var(--fc-transition-fast);\n outline: none;\n user-select: none;\n gap: var(--fc-spacing-sm);\n white-space: nowrap;\n }\n\n .fc-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .fc-btn-primary {\n background: var(--fc-primary-color);\n color: white;\n box-shadow: var(--fc-shadow-sm);\n }\n\n .fc-btn-primary:hover:not(:disabled) {\n background: var(--fc-primary-hover);\n box-shadow: var(--fc-shadow);\n }\n\n .fc-btn-secondary {\n background: white;\n border-color: var(--fc-border-color);\n color: var(--fc-text-color);\n box-shadow: var(--fc-shadow-sm);\n }\n\n .fc-btn-secondary:hover:not(:disabled) {\n background: var(--fc-background-hover);\n border-color: var(--fc-border-color-hover);\n }\n\n .fc-btn-outline {\n background: transparent;\n border-color: var(--fc-border-color);\n color: var(--fc-text-secondary);\n }\n\n .fc-btn-outline:hover:not(:disabled) {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n border-color: var(--fc-border-color-hover);\n }\n\n .fc-btn-ghost {\n background: transparent;\n color: var(--fc-text-secondary);\n }\n\n .fc-btn-ghost:hover:not(:disabled) {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n }\n\n .fc-btn-sm {\n padding: 6px 12px;\n font-size: var(--fc-font-size-xs);\n }\n\n .fc-btn-lg {\n padding: 10px 20px;\n font-size: var(--fc-font-size-base);\n }\n\n .fc-btn-icon {\n width: 32px;\n height: 32px;\n padding: 0;\n border-radius: var(--fc-border-radius-full);\n }\n `;\n }\n\n /**\n * Darken color by percentage\n */\n static darken(color, percent) {\n const num = parseInt(color.replace('#', ''), 16);\n const amt = Math.round(2.55 * percent);\n const R = (num >> 16) - amt;\n const G = ((num >> 8) & 0x00ff) - amt;\n const B = (num & 0x0000ff) - amt;\n return (\n '#' +\n (\n 0x1000000 +\n (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +\n (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +\n (B < 255 ? (B < 1 ? 0 : B) : 255)\n )\n .toString(16)\n .slice(1)\n );\n }\n\n /**\n * Lighten color by percentage\n */\n static lighten(color, percent) {\n const num = parseInt(color.replace('#', ''), 16);\n const amt = Math.round(2.55 * percent);\n const R = (num >> 16) + amt;\n const G = ((num >> 8) & 0x00ff) + amt;\n const B = (num & 0x0000ff) + amt;\n return (\n '#' +\n (\n 0x1000000 +\n (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +\n (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +\n (B < 255 ? (B < 1 ? 0 : B) : 255)\n )\n .toString(16)\n .slice(1)\n );\n }\n\n /**\n * Get contrast color (black or white) for background\n */\n static getContrastColor(bgColor) {\n const color = bgColor.replace('#', '');\n const r = parseInt(color.substr(0, 2), 16);\n const g = parseInt(color.substr(2, 2), 16);\n const b = parseInt(color.substr(4, 2), 16);\n const yiq = (r * 299 + g * 587 + b * 114) / 1000;\n return yiq >= 128 ? '#000000' : '#FFFFFF';\n }\n\n /**\n * Sanitize color value to prevent CSS injection\n * Returns the color if valid, or a fallback color if invalid\n */\n static sanitizeColor(color, fallback = 'var(--fc-primary-color)') {\n if (!color || typeof color !== 'string') {\n return fallback;\n }\n\n // Trim and check for dangerous characters that could break out of CSS\n const trimmed = color.trim();\n if (/[;{}()<>\\\"\\'\\\\]/.test(trimmed)) {\n return fallback;\n }\n\n // Allow hex colors (#RGB, #RRGGBB, #RRGGBBAA)\n if (/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(trimmed)) {\n return trimmed;\n }\n\n // Allow CSS variables\n if (/^var\\(--[a-zA-Z0-9-]+\\)$/.test(trimmed)) {\n return trimmed;\n }\n\n // Allow rgb/rgba with numbers only\n if (/^rgba?\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*(,\\s*(0|1|0?\\.\\d+))?\\s*\\)$/.test(trimmed)) {\n return trimmed;\n }\n\n // Allow safe CSS color keywords\n const safeKeywords = [\n 'transparent',\n 'currentColor',\n 'inherit',\n 'black',\n 'white',\n 'red',\n 'green',\n 'blue',\n 'yellow',\n 'orange',\n 'purple',\n 'pink',\n 'brown',\n 'gray',\n 'grey',\n 'cyan',\n 'magenta',\n 'lime',\n 'navy',\n 'teal',\n 'aqua',\n 'maroon',\n 'olive',\n 'silver',\n 'fuchsia'\n ];\n if (safeKeywords.includes(trimmed.toLowerCase())) {\n return trimmed;\n }\n\n return fallback;\n }\n\n /**\n * Convert hex to rgba\n */\n static hexToRgba(hex, alpha = 1) {\n const color = hex.replace('#', '');\n const r = parseInt(color.substr(0, 2), 16);\n const g = parseInt(color.substr(2, 2), 16);\n const b = parseInt(color.substr(4, 2), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n /**\n * Generate grid styles\n */\n static getGridStyles() {\n return `\n .fc-grid {\n display: grid;\n gap: 1px;\n background: var(--fc-border-color);\n border: 1px solid var(--fc-border-color);\n border-radius: var(--fc-border-radius);\n overflow: hidden;\n }\n\n .fc-grid-cell {\n background: var(--fc-background);\n padding: var(--fc-spacing-sm);\n min-height: 100px;\n position: relative;\n }\n\n .fc-grid-cell:hover {\n background: var(--fc-background-hover);\n }\n\n .fc-grid-header {\n background: var(--fc-background-alt);\n padding: var(--fc-spacing-sm);\n font-weight: var(--fc-font-weight-semibold);\n text-align: center;\n color: var(--fc-text-secondary);\n font-size: var(--fc-font-size-xs);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n `;\n }\n\n /**\n * Get responsive breakpoints\n */\n static breakpoints = {\n xs: '320px',\n sm: '576px',\n md: '768px',\n lg: '992px',\n xl: '1200px',\n '2xl': '1400px'\n };\n\n /**\n * Generate media query\n */\n static mediaQuery(breakpoint, styles) {\n const size = this.breakpoints[breakpoint];\n if (!size) return '';\n return `@media (min-width: ${size}) { ${styles} }`;\n }\n\n /**\n * Animation keyframes\n */\n static getAnimations() {\n return `\n @keyframes fc-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes fc-slide-in-up {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n @keyframes fc-slide-in-down {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n @keyframes fc-scale-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n @keyframes fc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n .fc-fade-in {\n animation: fc-fade-in var(--fc-transition);\n }\n\n .fc-slide-in-up {\n animation: fc-slide-in-up var(--fc-transition);\n }\n\n .fc-scale-in {\n animation: fc-scale-in var(--fc-transition);\n }\n `;\n }\n}\n\nexport default StyleUtils;\n","/**\n * BaseViewRenderer - Foundation for all view renderers\n *\n * Pure JavaScript class (no Web Components) for Salesforce Locker Service compatibility.\n * Provides common functionality for rendering calendar views.\n */\n\nimport { DOMUtils } from '../utils/DOMUtils.js';\nimport { StyleUtils } from '../utils/StyleUtils.js';\n\nexport class BaseViewRenderer {\n /**\n * @param {HTMLElement} container - The DOM element to render into\n * @param {StateManager} stateManager - The state manager instance\n */\n constructor(container, stateManager) {\n this.container = container;\n this.stateManager = stateManager;\n this._listeners = [];\n this._scrolled = false;\n }\n\n /**\n * Render the view into the container\n * Must be implemented by subclasses\n */\n render() {\n throw new Error('render() must be implemented by subclass');\n }\n\n /**\n * Clean up event listeners\n */\n cleanup() {\n this._listeners.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler);\n });\n this._listeners = [];\n }\n\n /**\n * Add an event listener with automatic cleanup tracking\n * @param {HTMLElement} element\n * @param {string} event\n * @param {Function} handler\n */\n addListener(element, event, handler) {\n const boundHandler = handler.bind(this);\n element.addEventListener(event, boundHandler);\n this._listeners.push({ element, event, handler: boundHandler });\n }\n\n /**\n * Escape HTML to prevent XSS\n * @param {string} str\n * @returns {string}\n */\n escapeHTML(str) {\n if (str === null || str === undefined) return '';\n return DOMUtils.escapeHTML(String(str));\n }\n\n /**\n * Check if a date is today\n * @param {Date} date\n * @returns {boolean}\n */\n isToday(date) {\n const today = new Date();\n return (\n date.getDate() === today.getDate() &&\n date.getMonth() === today.getMonth() &&\n date.getFullYear() === today.getFullYear()\n );\n }\n\n /**\n * Check if two dates are the same day\n * @param {Date} date1\n * @param {Date} date2\n * @returns {boolean}\n */\n isSameDay(date1, date2) {\n return (\n date1.getDate() === date2.getDate() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getFullYear() === date2.getFullYear()\n );\n }\n\n /**\n * Format hour for display (e.g., \"9 AM\", \"2 PM\")\n * @param {number} hour - Hour in 24-hour format (0-23)\n * @returns {string}\n */\n formatHour(hour) {\n const period = hour >= 12 ? 'PM' : 'AM';\n const displayHour = hour % 12 || 12;\n return `${displayHour} ${period}`;\n }\n\n /**\n * Format time for display (e.g., \"9 AM\", \"2:30 PM\")\n * @param {Date} date\n * @returns {string}\n */\n formatTime(date) {\n const hours = date.getHours();\n const minutes = date.getMinutes();\n const period = hours >= 12 ? 'PM' : 'AM';\n const displayHour = hours % 12 || 12;\n return minutes === 0\n ? `${displayHour} ${period}`\n : `${displayHour}:${minutes.toString().padStart(2, '0')} ${period}`;\n }\n\n /**\n * Get contrasting text color for a background color\n * Uses WCAG luminance formula\n * @param {string} bgColor - Hex color string\n * @returns {string} 'black' or 'white'\n */\n getContrastingTextColor(bgColor) {\n if (!bgColor || typeof bgColor !== 'string') return 'white';\n\n const color = bgColor.charAt(0) === '#' ? bgColor.substring(1) : bgColor;\n\n if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(color)) {\n return 'white';\n }\n\n const fullColor =\n color.length === 3 ? color[0] + color[0] + color[1] + color[1] + color[2] + color[2] : color;\n\n const r = parseInt(fullColor.substring(0, 2), 16);\n const g = parseInt(fullColor.substring(2, 4), 16);\n const b = parseInt(fullColor.substring(4, 6), 16);\n\n if (isNaN(r) || isNaN(g) || isNaN(b)) {\n return 'white';\n }\n\n const uicolors = [r / 255, g / 255, b / 255];\n const c = uicolors.map(col => {\n if (col <= 0.03928) {\n return col / 12.92;\n }\n return Math.pow((col + 0.055) / 1.055, 2.4);\n });\n const L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];\n return L > 0.179 ? 'black' : 'white';\n }\n\n /**\n * Render the \"now\" indicator line for time-based views\n * @returns {string} HTML string\n */\n renderNowIndicator() {\n const now = new Date();\n const minutes = now.getHours() * 60 + now.getMinutes();\n return `<div class=\"fc-now-indicator\" style=\"position: absolute; left: 0; right: 0; top: ${minutes}px; height: 2px; background: #dc2626; z-index: 15; pointer-events: none;\"></div>`;\n }\n\n /**\n * Compute overlap layout columns for a list of timed events.\n * Returns a Map of event.id -> { column, totalColumns }.\n * Uses a greedy left-to-right column packing algorithm.\n * @param {Array} events - Array of event objects with start/end dates\n * @returns {Map<string, {column: number, totalColumns: number}>}\n */\n computeOverlapLayout(events) {\n if (!events || events.length === 0) return new Map();\n\n // Convert to sortable entries with minute ranges\n const entries = events.map(evt => {\n const start = new Date(evt.start);\n const end = new Date(evt.end);\n const startMin = start.getHours() * 60 + start.getMinutes();\n const endMin = Math.max(startMin + 1, end.getHours() * 60 + end.getMinutes());\n return { id: evt.id, startMin, endMin };\n });\n\n // Sort by start time, then by longer duration first\n entries.sort((a, b) => a.startMin - b.startMin || (b.endMin - b.startMin) - (a.endMin - a.startMin));\n\n // Assign columns greedily\n const columns = []; // each column tracks the end time of its last event\n const layout = new Map();\n\n for (const entry of entries) {\n let placed = false;\n for (let col = 0; col < columns.length; col++) {\n if (columns[col] <= entry.startMin) {\n columns[col] = entry.endMin;\n layout.set(entry.id, { column: col, totalColumns: 0 });\n placed = true;\n break;\n }\n }\n if (!placed) {\n layout.set(entry.id, { column: columns.length, totalColumns: 0 });\n columns.push(entry.endMin);\n }\n }\n\n // Determine the max overlapping columns for each cluster of overlapping events\n // Walk through entries and find connected groups\n const groups = [];\n let currentGroup = [];\n let groupEnd = 0;\n\n for (const entry of entries) {\n if (currentGroup.length === 0 || entry.startMin < groupEnd) {\n currentGroup.push(entry);\n groupEnd = Math.max(groupEnd, entry.endMin);\n } else {\n groups.push(currentGroup);\n currentGroup = [entry];\n groupEnd = entry.endMin;\n }\n }\n if (currentGroup.length > 0) groups.push(currentGroup);\n\n for (const group of groups) {\n const maxCol = Math.max(...group.map(e => layout.get(e.id).column)) + 1;\n for (const entry of group) {\n layout.get(entry.id).totalColumns = maxCol;\n }\n }\n\n return layout;\n }\n\n /**\n * Render a timed event block\n * @param {Object} event - Event object\n * @param {Object} options - Rendering options\n * @param {Object} options.compact - Use compact layout\n * @param {Object} options.overlapLayout - Map from computeOverlapLayout()\n * @returns {string} HTML string\n */\n renderTimedEvent(event, options = {}) {\n const { compact = true, overlapLayout = null } = options;\n const start = new Date(event.start);\n const end = new Date(event.end);\n const startMinutes = start.getHours() * 60 + start.getMinutes();\n const durationMinutes = Math.max((end - start) / (1000 * 60), compact ? 20 : 30);\n const color = this.getEventColor(event);\n\n const padding = compact ? '4px 8px' : '8px 12px';\n const fontSize = compact ? '11px' : '13px';\n const baseMargin = compact ? 2 : 12;\n const rightPad = compact ? 2 : 24;\n const borderRadius = compact ? '4px' : '6px';\n\n // Compute left/width based on overlap columns\n let leftPx, widthCalc;\n if (overlapLayout && overlapLayout.has(event.id)) {\n const { column, totalColumns } = overlapLayout.get(event.id);\n const colWidth = `(100% - ${baseMargin + rightPad}px)`;\n leftPx = `calc(${baseMargin}px + ${column} * ${colWidth} / ${totalColumns})`;\n widthCalc = `calc(${colWidth} / ${totalColumns})`;\n } else {\n leftPx = `${baseMargin}px`;\n widthCalc = `calc(100% - ${baseMargin + rightPad}px)`;\n }\n\n return `\n <div class=\"fc-event fc-timed-event\" data-event-id=\"${this.escapeHTML(event.id)}\"\n style=\"position: absolute; top: ${startMinutes}px; height: ${durationMinutes}px;\n left: ${leftPx}; width: ${widthCalc};\n background-color: ${color}; border-radius: ${borderRadius};\n padding: ${padding}; font-size: ${fontSize};\n font-weight: 500; color: white; overflow: hidden;\n box-shadow: 0 1px 2px rgba(0,0,0,0.1);\n cursor: pointer; z-index: 5;\">\n <div style=\"white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\">\n ${this.escapeHTML(event.title)}\n </div>\n <div style=\"font-size: ${compact ? '10px' : '11px'}; opacity: 0.9;\">\n ${this.formatTime(start)}${compact ? '' : ' - ' + this.formatTime(end)}\n </div>\n </div>\n `;\n }\n\n /**\n * Get a safe, sanitized event color value.\n * @param {Object} event\n * @returns {string}\n */\n getEventColor(event) {\n return StyleUtils.sanitizeColor(event?.backgroundColor, '#2563eb');\n }\n\n /**\n * Attach common event handlers for day/event clicks\n */\n attachCommonEventHandlers() {\n // Delegate event clicks at container level to avoid rebinding per event node.\n this.addListener(this.container, 'click', e => {\n const eventEl = e.target.closest('.fc-event');\n if (!eventEl || !this.container.contains(eventEl)) return;\n\n e.stopPropagation();\n const eventId = eventEl.dataset.eventId;\n const event = this.stateManager.getEvents().find(ev => ev.id === eventId);\n if (event) {\n this.stateManager.selectEvent(event);\n }\n });\n }\n}\n\nexport default BaseViewRenderer;\n","/**\n * MonthViewRenderer - Renders month calendar grid\n *\n * Pure JavaScript renderer for month view, compatible with Salesforce Locker Service.\n */\n\nimport { BaseViewRenderer } from './BaseViewRenderer.js';\n\nexport class MonthViewRenderer extends BaseViewRenderer {\n constructor(container, stateManager) {\n super(container, stateManager);\n this.maxEventsToShow = 3;\n }\n\n render() {\n if (!this.container || !this.stateManager) return;\n\n const viewData = this.stateManager.getViewData();\n if (!viewData || !viewData.weeks) {\n this.container.innerHTML =\n '<div style=\"padding: 20px; text-align: center; color: #666;\">No data available for month view.</div>';\n return;\n }\n\n this.cleanup();\n const config = this.stateManager.getState().config;\n const html = this._renderMonthView(viewData, config);\n this.container.innerHTML = html;\n this._attachEventHandlers();\n }\n\n _renderMonthView(viewData, config) {\n const weekStartsOn = config.weekStartsOn || 0;\n const dayNames = this._getDayNames(weekStartsOn);\n\n let html = `\n <div class=\"fc-month-view\" style=\"display: flex; flex-direction: column; height: 100%; min-height: 400px; background: #fff; border: 1px solid #e5e7eb;\">\n <div class=\"fc-month-header\" style=\"display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid #e5e7eb; background: #f9fafb;\">\n ${dayNames.map(d => `<div class=\"fc-month-header-cell\" style=\"padding: 12px 8px; text-align: center; font-size: 11px; font-weight: 600; color: #6b7280; text-transform: uppercase;\">${d}</div>`).join('')}\n </div>\n <div class=\"fc-month-body\" style=\"display: flex; flex-direction: column; flex: 1;\">\n `;\n\n viewData.weeks.forEach(week => {\n html += this._renderWeek(week);\n });\n\n html += '</div></div>';\n return html;\n }\n\n _getDayNames(weekStartsOn) {\n const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n const dayNames = [];\n for (let i = 0; i < 7; i++) {\n const dayIndex = (weekStartsOn + i) % 7;\n dayNames.push(days[dayIndex]);\n }\n return dayNames;\n }\n\n _renderWeek(week) {\n let html =\n '<div class=\"fc-month-week\" style=\"display: grid; grid-template-columns: repeat(7, 1fr); flex: 1; min-height: 80px;\">';\n\n week.days.forEach(day => {\n html += this._renderDay(day);\n });\n\n html += '</div>';\n return html;\n }\n\n _renderDay(day) {\n const isOtherMonth = !day.isCurrentMonth;\n const isToday = day.isToday;\n\n const dayBg = isOtherMonth ? '#f3f4f6' : '#fff';\n const dayNumColor = isOtherMonth ? '#9ca3af' : '#111827';\n const todayStyle = isToday\n ? 'background: #2563eb; color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;'\n : '';\n\n const events = day.events || [];\n const visibleEvents = events.slice(0, this.maxEventsToShow);\n const moreCount = events.length - this.maxEventsToShow;\n\n return `\n <div class=\"fc-month-day\" data-date=\"${day.date}\"\n style=\"background: ${dayBg}; border-right: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; padding: 4px; min-height: 80px; cursor: pointer; display: flex; flex-direction: column;\">\n <div class=\"fc-day-number\" style=\"font-size: 13px; font-weight: 500; color: ${dayNumColor}; padding: 2px 4px; margin-bottom: 4px; ${todayStyle}\">\n ${day.dayOfMonth}\n </div>\n <div class=\"fc-day-events\" style=\"display: flex; flex-direction: column; gap: 2px; flex: 1; overflow: hidden;\">\n ${visibleEvents.map(evt => this._renderEvent(evt)).join('')}\n ${moreCount > 0 ? `<div class=\"fc-more-events\" style=\"font-size: 10px; color: #6b7280; padding: 2px 4px; font-weight: 500;\">+${moreCount} more</div>` : ''}\n </div>\n </div>\n `;\n }\n\n _renderEvent(event) {\n const color = this.getEventColor(event);\n return `\n <div class=\"fc-event\" data-event-id=\"${this.escapeHTML(event.id)}\"\n style=\"background-color: ${color}; font-size: 11px; padding: 2px 6px; border-radius: 3px; color: white; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;\">\n ${this.escapeHTML(event.title)}\n </div>\n `;\n }\n\n _attachEventHandlers() {\n this.addListener(this.container, 'click', e => {\n const dayEl = e.target.closest('.fc-month-day');\n if (!dayEl || !this.container.contains(dayEl)) return;\n if (e.target.closest('.fc-event')) return;\n\n const date = new Date(dayEl.dataset.date);\n this.stateManager.selectDate(date);\n });\n\n // Common event handlers (event clicks)\n this.attachCommonEventHandlers();\n }\n}\n\nexport default MonthViewRenderer;\n","/**\n * WeekViewRenderer - Renders week calendar view\n *\n * Pure JavaScript renderer for week view, compatible with Salesforce Locker Service.\n */\n\nimport { BaseViewRenderer } from './BaseViewRenderer.js';\n\nexport class WeekViewRenderer extends BaseViewRenderer {\n constructor(container, stateManager) {\n super(container, stateManager);\n this.hourHeight = 60; // pixels per hour\n this.totalHeight = 24 * this.hourHeight; // 1440px for 24 hours\n }\n\n render() {\n if (!this.container || !this.stateManager) return;\n\n const viewData = this.stateManager.getViewData();\n if (!viewData || !viewData.days || viewData.days.length === 0) {\n this.container.innerHTML =\n '<div style=\"padding: 20px; text-align: center; color: #666;\">No data available for week view.</div>';\n return;\n }\n\n this.cleanup();\n this._scrolled = false;\n const config = this.stateManager.getState().config;\n const html = this._renderWeekView(viewData, config);\n this.container.innerHTML = html;\n this._attachEventHandlers();\n this._scrollToCurrentTime();\n }\n\n _renderWeekView(viewData, _config) {\n const days = viewData.days;\n const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n const hours = Array.from({ length: 24 }, (_, i) => i);\n\n // Process days to categorize events\n const processedDays = days.map(day => {\n const dayDate = new Date(day.date);\n const events = day.events || [];\n return {\n ...day,\n date: dayDate,\n dayName: dayNames[dayDate.getDay()],\n dayOfMonth: dayDate.getDate(),\n isToday: this.isToday(dayDate),\n timedEvents: events.filter(e => !e.allDay),\n allDayEvents: events.filter(e => e.allDay)\n };\n });\n\n return `\n <div class=\"fc-week-view\" style=\"display: flex; flex-direction: column; height: 100%; background: #fff; overflow: hidden;\">\n ${this._renderHeader(processedDays)}\n ${this._renderAllDayRow(processedDays)}\n ${this._renderTimeGrid(processedDays, hours)}\n </div>\n `;\n }\n\n _renderHeader(days) {\n return `\n <div class=\"fc-week-header\" style=\"display: grid; grid-template-columns: 60px repeat(7, 1fr); border-bottom: 1px solid #e5e7eb; background: #f9fafb; flex-shrink: 0;\">\n <div style=\"border-right: 1px solid #e5e7eb;\"></div>\n ${days\n .map(\n day => `\n <div style=\"padding: 12px 8px; text-align: center; border-right: 1px solid #e5e7eb;\">\n <div style=\"font-size: 10px; font-weight: 700; color: #6b7280; text-transform: uppercase; letter-spacing: 0.1em;\">\n ${day.dayName}\n </div>\n <div style=\"font-size: 16px; font-weight: 500; margin-top: 4px; ${day.isToday ? 'background: #dc2626; color: white; border-radius: 50%; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;' : 'color: #111827;'}\">\n ${day.dayOfMonth}\n </div>\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n _renderAllDayRow(days) {\n return `\n <div class=\"fc-all-day-row\" style=\"display: grid; grid-template-columns: 60px repeat(7, 1fr); border-bottom: 1px solid #e5e7eb; background: #fafafa; min-height: 32px; flex-shrink: 0;\">\n <div style=\"font-size: 9px; color: #6b7280; display: flex; align-items: center; justify-content: center; border-right: 1px solid #e5e7eb; text-transform: uppercase; font-weight: 700;\">\n All day\n </div>\n ${days\n .map(\n day => `\n <div class=\"fc-all-day-cell\" data-date=\"${day.date.toISOString()}\" style=\"border-right: 1px solid #e5e7eb; padding: 4px; display: flex; flex-direction: column; gap: 2px;\">\n ${day.allDayEvents\n .map(\n evt => `\n <div class=\"fc-event fc-all-day-event\" data-event-id=\"${this.escapeHTML(evt.id)}\"\n style=\"background-color: ${this.getEventColor(evt)}; font-size: 10px; padding: 2px 4px; border-radius: 2px; color: white; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\">\n ${this.escapeHTML(evt.title)}\n </div>\n `\n )\n .join('')}\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n _renderTimeGrid(days, hours) {\n return `\n <div id=\"week-scroll-container\" class=\"fc-time-grid-container\" style=\"flex: 1; overflow-y: auto; overflow-x: hidden; position: relative;\">\n <div class=\"fc-time-grid\" style=\"display: grid; grid-template-columns: 60px repeat(7, 1fr); position: relative; height: ${this.totalHeight}px;\">\n ${this._renderTimeGutter(hours)}\n ${days.map(day => this._renderDayColumn(day, hours)).join('')}\n </div>\n </div>\n `;\n }\n\n _renderTimeGutter(hours) {\n return `\n <div class=\"fc-time-gutter\" style=\"border-right: 1px solid #e5e7eb; background: #fafafa;\">\n ${hours\n .map(\n h => `\n <div style=\"height: ${this.hourHeight}px; font-size: 10px; color: #6b7280; text-align: right; padding-right: 8px; font-weight: 500;\">\n ${h === 0 ? '' : this.formatHour(h)}\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n _renderDayColumn(day, hours) {\n return `\n <div class=\"fc-week-day-column\" data-date=\"${day.date.toISOString()}\" style=\"border-right: 1px solid #e5e7eb; position: relative; cursor: pointer;\">\n <!-- Hour grid lines -->\n ${hours.map(() => `<div style=\"height: ${this.hourHeight}px; border-bottom: 1px solid #f3f4f6;\"></div>`).join('')}\n\n <!-- Now indicator for today -->\n ${day.isToday ? this.renderNowIndicator() : ''}\n\n <!-- Timed events -->\n ${(() => {\n const layout = this.computeOverlapLayout(day.timedEvents);\n return day.timedEvents.map(evt => this.renderTimedEvent(evt, { compact: true, overlapLayout: layout })).join('');\n })()}\n </div>\n `;\n }\n\n _attachEventHandlers() {\n this.addListener(this.container, 'click', e => {\n const dayEl = e.target.closest('.fc-week-day-column');\n if (!dayEl || !this.container.contains(dayEl)) return;\n if (e.target.closest('.fc-event')) return;\n\n const date = new Date(dayEl.dataset.date);\n const scrollContainer = this.container.querySelector('#week-scroll-container');\n const gridTop = dayEl.offsetTop;\n const y = e.clientY - dayEl.getBoundingClientRect().top + (scrollContainer ? scrollContainer.scrollTop : 0) - gridTop;\n\n // Calculate time from click position within the 1440px time grid\n const clampedY = Math.max(0, Math.min(y + gridTop, this.totalHeight));\n date.setHours(\n Math.floor(clampedY / this.hourHeight),\n Math.floor((clampedY % this.hourHeight) / (this.hourHeight / 60)),\n 0,\n 0\n );\n this.stateManager.selectDate(date);\n });\n\n // Common event handlers (event clicks)\n this.attachCommonEventHandlers();\n }\n\n _scrollToCurrentTime() {\n if (this._scrolled) return;\n\n const scrollContainer = this.container.querySelector('#week-scroll-container');\n if (scrollContainer) {\n // Scroll to 8 AM, minus some offset for visibility\n scrollContainer.scrollTop = 8 * this.hourHeight - 50;\n this._scrolled = true;\n }\n }\n}\n\nexport default WeekViewRenderer;\n","/**\n * DayViewRenderer - Renders single day calendar view\n *\n * Pure JavaScript renderer for day view, compatible with Salesforce Locker Service.\n */\n\nimport { BaseViewRenderer } from './BaseViewRenderer.js';\n\nexport class DayViewRenderer extends BaseViewRenderer {\n constructor(container, stateManager) {\n super(container, stateManager);\n this.hourHeight = 60; // pixels per hour\n this.totalHeight = 24 * this.hourHeight; // 1440px for 24 hours\n }\n\n render() {\n if (!this.container || !this.stateManager) return;\n\n const viewData = this.stateManager.getViewData();\n if (!viewData) {\n this.container.innerHTML =\n '<div style=\"padding: 20px; text-align: center; color: #666;\">No data available for day view.</div>';\n return;\n }\n\n this.cleanup();\n this._scrolled = false;\n const config = this.stateManager.getState().config;\n const html = this._renderDayView(viewData, config);\n this.container.innerHTML = html;\n this._attachEventHandlers();\n this._scrollToCurrentTime();\n }\n\n _renderDayView(viewData, _config) {\n const currentDate = this.stateManager?.getState()?.currentDate || new Date();\n const dayData = this._extractDayData(viewData, currentDate);\n\n if (!dayData) {\n return '<div style=\"padding: 20px; text-align: center; color: #666;\">No data available for day view.</div>';\n }\n\n const { dayDate, dayName, isToday, allDayEvents, timedEvents } = dayData;\n const hours = Array.from({ length: 24 }, (_, i) => i);\n\n return `\n <div class=\"fc-day-view\" style=\"display: flex; flex-direction: column; height: 100%; background: #fff; overflow: hidden;\">\n ${this._renderHeader(dayDate, dayName, isToday)}\n ${this._renderAllDayRow(allDayEvents, dayDate)}\n ${this._renderTimeGrid(timedEvents, isToday, dayDate, hours)}\n </div>\n `;\n }\n\n _extractDayData(viewData, currentDate) {\n let dayDate, dayName, isToday, allDayEvents, timedEvents;\n const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n\n if (viewData.type === 'day' && viewData.date) {\n // Core day view structure\n dayDate = new Date(viewData.date);\n dayName = viewData.dayName || dayNames[dayDate.getDay()];\n isToday = viewData.isToday !== undefined ? viewData.isToday : this.isToday(dayDate);\n allDayEvents = viewData.allDayEvents || [];\n\n // Extract timed events from hours array\n if (viewData.hours && Array.isArray(viewData.hours)) {\n const eventMap = new Map();\n viewData.hours.forEach(hour => {\n (hour.events || []).forEach(evt => {\n if (!eventMap.has(evt.id)) {\n eventMap.set(evt.id, evt);\n }\n });\n });\n timedEvents = Array.from(eventMap.values());\n } else {\n timedEvents = [];\n }\n } else if (viewData.days && viewData.days.length > 0) {\n // Enriched structure with days array\n const dayDataItem =\n viewData.days.find(d => this.isSameDay(new Date(d.date), currentDate)) || viewData.days[0];\n dayDate = new Date(dayDataItem.date);\n dayName = dayNames[dayDate.getDay()];\n isToday = this.isToday(dayDate);\n const events = dayDataItem.events || [];\n allDayEvents = events.filter(e => e.allDay);\n timedEvents = events.filter(e => !e.allDay);\n } else {\n return null;\n }\n\n return { dayDate, dayName, isToday, allDayEvents, timedEvents };\n }\n\n _renderHeader(dayDate, dayName, isToday) {\n return `\n <div class=\"fc-day-header\" style=\"display: grid; grid-template-columns: 60px 1fr; border-bottom: 1px solid #e5e7eb; background: #f9fafb; flex-shrink: 0;\">\n <div style=\"border-right: 1px solid #e5e7eb;\"></div>\n <div style=\"padding: 16px 24px;\">\n <div style=\"font-size: 12px; font-weight: 700; color: #6b7280; text-transform: uppercase; letter-spacing: 0.1em;\">\n ${dayName}\n </div>\n <div style=\"font-size: 24px; font-weight: 600; margin-top: 4px; ${isToday ? 'color: #dc2626;' : 'color: #111827;'}\">\n ${dayDate.getDate()}\n </div>\n </div>\n </div>\n `;\n }\n\n _renderAllDayRow(allDayEvents, dayDate) {\n return `\n <div class=\"fc-all-day-row\" style=\"display: grid; grid-template-columns: 60px 1fr; border-bottom: 1px solid #e5e7eb; background: #fafafa; min-height: 36px; flex-shrink: 0;\">\n <div style=\"font-size: 9px; color: #6b7280; display: flex; align-items: center; justify-content: center; border-right: 1px solid #e5e7eb; text-transform: uppercase; font-weight: 700;\">\n All day\n </div>\n <div class=\"fc-all-day-cell\" data-date=\"${dayDate.toISOString()}\" style=\"padding: 6px 12px; display: flex; flex-wrap: wrap; gap: 4px;\">\n ${allDayEvents\n .map(\n evt => `\n <div class=\"fc-event fc-all-day-event\" data-event-id=\"${this.escapeHTML(evt.id)}\"\n style=\"background-color: ${this.getEventColor(evt)}; font-size: 12px; padding: 4px 8px; border-radius: 4px; color: white; cursor: pointer; font-weight: 500;\">\n ${this.escapeHTML(evt.title)}\n </div>\n `\n )\n .join('')}\n </div>\n </div>\n `;\n }\n\n _renderTimeGrid(timedEvents, isToday, dayDate, hours) {\n return `\n <div id=\"day-scroll-container\" class=\"fc-time-grid-container\" style=\"flex: 1; overflow-y: auto; overflow-x: hidden; position: relative;\">\n <div class=\"fc-time-grid\" style=\"display: grid; grid-template-columns: 60px 1fr; position: relative; height: ${this.totalHeight}px;\">\n ${this._renderTimeGutter(hours)}\n ${this._renderDayColumn(timedEvents, isToday, dayDate, hours)}\n </div>\n </div>\n `;\n }\n\n _renderTimeGutter(hours) {\n return `\n <div class=\"fc-time-gutter\" style=\"border-right: 1px solid #e5e7eb; background: #fafafa;\">\n ${hours\n .map(\n h => `\n <div style=\"height: ${this.hourHeight}px; font-size: 11px; color: #6b7280; text-align: right; padding-right: 12px; font-weight: 500;\">\n ${h === 0 ? '' : this.formatHour(h)}\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n _renderDayColumn(timedEvents, isToday, dayDate, hours) {\n return `\n <div class=\"fc-day-column\" data-date=\"${dayDate.toISOString()}\" style=\"position: relative; cursor: pointer;\">\n <!-- Hour grid lines -->\n ${hours.map(() => `<div style=\"height: ${this.hourHeight}px; border-bottom: 1px solid #f3f4f6;\"></div>`).join('')}\n\n <!-- Now indicator for today -->\n ${isToday ? this.renderNowIndicator() : ''}\n\n <!-- Timed events -->\n ${(() => {\n const layout = this.computeOverlapLayout(timedEvents);\n return timedEvents.map(evt => this.renderTimedEvent(evt, { compact: false, overlapLayout: layout })).join('');\n })()}\n </div>\n `;\n }\n\n _attachEventHandlers() {\n this.addListener(this.container, 'click', e => {\n const dayEl = e.target.closest('.fc-day-column');\n if (!dayEl || !this.container.contains(dayEl)) return;\n if (e.target.closest('.fc-event')) return;\n\n const date = new Date(dayEl.dataset.date);\n const scrollContainer = this.container.querySelector('#day-scroll-container');\n const gridTop = dayEl.offsetTop;\n const y = e.clientY - dayEl.getBoundingClientRect().top + (scrollContainer ? scrollContainer.scrollTop : 0) - gridTop;\n\n // Calculate time from click position within the 1440px time grid\n const clampedY = Math.max(0, Math.min(y + gridTop, this.totalHeight));\n date.setHours(\n Math.floor(clampedY / this.hourHeight),\n Math.floor((clampedY % this.hourHeight) / (this.hourHeight / 60)),\n 0,\n 0\n );\n this.stateManager.selectDate(date);\n });\n\n // Common event handlers (event clicks)\n this.attachCommonEventHandlers();\n }\n\n _scrollToCurrentTime() {\n if (this._scrolled) return;\n\n const scrollContainer = this.container.querySelector('#day-scroll-container');\n if (scrollContainer) {\n // Scroll to 8 AM, minus some offset for visibility\n scrollContainer.scrollTop = 8 * this.hourHeight - 50;\n this._scrolled = true;\n }\n }\n}\n\nexport default DayViewRenderer;\n","import { BaseComponent } from '../core/BaseComponent.js';\nimport { StyleUtils } from '../utils/StyleUtils.js';\nimport { DOMUtils } from '../utils/DOMUtils.js';\n\nexport class EventForm extends BaseComponent {\n constructor() {\n super();\n this._isVisible = false;\n this._cleanupFocusTrap = null;\n this.config = {\n title: 'New Event',\n defaultDuration: 60, // minutes\n colors: [\n { color: '#2563EB', label: 'Blue' },\n { color: '#10B981', label: 'Green' },\n { color: '#F59E0B', label: 'Amber' },\n { color: '#EF4444', label: 'Red' },\n { color: '#8B5CF6', label: 'Purple' },\n { color: '#6B7280', label: 'Gray' }\n ]\n };\n this._formData = {\n title: '',\n start: new Date(),\n end: new Date(),\n allDay: false,\n color: this.config.colors[0].color\n };\n }\n\n static get observedAttributes() {\n return ['open'];\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n if (name === 'open') {\n if (newValue !== null) {\n this.open();\n } else {\n this.close();\n }\n }\n }\n\n getStyles() {\n return `\n ${StyleUtils.getBaseStyles()}\n ${StyleUtils.getButtonStyles()}\n\n :host {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: var(--fc-z-modal);\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(2px);\n }\n\n :host([open]) {\n display: flex;\n }\n\n .modal-content {\n background: var(--fc-background);\n width: 400px;\n max-width: 90vw;\n border-radius: var(--fc-border-radius-lg);\n box-shadow: var(--fc-shadow-lg);\n border: 1px solid var(--fc-border-color);\n display: flex;\n flex-direction: column;\n animation: fc-scale-in var(--fc-transition);\n }\n\n .modal-header {\n padding: var(--fc-spacing-lg);\n border-bottom: 1px solid var(--fc-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .modal-title {\n font-size: var(--fc-font-size-lg);\n font-weight: var(--fc-font-weight-semibold);\n color: var(--fc-text-color);\n }\n\n .close-btn {\n background: transparent;\n border: none;\n color: var(--fc-text-secondary);\n cursor: pointer;\n padding: 4px;\n border-radius: var(--fc-border-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .close-btn:hover {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n }\n\n .modal-body {\n padding: var(--fc-spacing-lg);\n display: flex;\n flex-direction: column;\n gap: var(--fc-spacing-md);\n }\n\n .form-group {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n label {\n font-size: var(--fc-font-size-sm);\n font-weight: var(--fc-font-weight-medium);\n color: var(--fc-text-secondary);\n }\n\n input[type=\"text\"],\n input[type=\"datetime-local\"],\n select {\n padding: 8px 12px;\n border: 1px solid var(--fc-border-color);\n border-radius: var(--fc-border-radius);\n font-family: var(--fc-font-family);\n font-size: var(--fc-font-size-base);\n color: var(--fc-text-color);\n background: var(--fc-background);\n transition: border-color var(--fc-transition-fast);\n }\n\n input:focus,\n select:focus {\n outline: none;\n border-color: var(--fc-primary-color);\n box-shadow: 0 0 0 2px var(--fc-primary-light);\n }\n\n .row {\n display: flex;\n gap: var(--fc-spacing-md);\n }\n \n .row .form-group {\n flex: 1;\n }\n\n .modal-footer {\n padding: var(--fc-spacing-lg);\n border-top: 1px solid var(--fc-border-color);\n display: flex;\n justify-content: flex-end;\n gap: var(--fc-spacing-md);\n background: var(--fc-background-alt);\n border-bottom-left-radius: var(--fc-border-radius-lg);\n border-bottom-right-radius: var(--fc-border-radius-lg);\n }\n\n /* Color picker style */\n .color-options {\n display: flex;\n gap: 8px;\n margin-top: 4px;\n }\n\n .color-btn {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n cursor: pointer;\n border: 2px solid transparent;\n transition: transform var(--fc-transition-fast), border-color var(--fc-transition-fast);\n padding: 0;\n position: relative;\n }\n\n .color-btn:hover {\n transform: scale(1.1);\n }\n\n .color-btn.selected {\n border-color: var(--fc-text-color);\n box-shadow: 0 0 0 2px var(--fc-background), 0 0 0 4px var(--fc-primary-color);\n }\n\n .color-btn:focus {\n outline: none;\n box-shadow: 0 0 0 2px var(--fc-background), 0 0 0 4px var(--fc-primary-color);\n }\n\n .error-message {\n color: var(--fc-danger-color);\n font-size: 11px;\n margin-top: 2px;\n display: none;\n }\n\n .form-group.has-error .error-message {\n display: block;\n }\n\n .form-group.has-error input {\n border-color: var(--fc-danger-color);\n }\n `;\n }\n\n template() {\n return `\n <div class=\"modal-content\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"modal-title\">\n <header class=\"modal-header\">\n <h3 class=\"modal-title\" id=\"modal-title\">${this.config.title}</h3>\n <button class=\"close-btn\" id=\"close-x\" aria-label=\"Close modal\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M18 6L6 18M6 6l12 12\"></path>\n </svg>\n </button>\n </header>\n \n <div class=\"modal-body\">\n <div class=\"form-group\" id=\"title-group\">\n <label for=\"event-title\">Title</label>\n <input type=\"text\" id=\"event-title\" placeholder=\"Event name\" autofocus required>\n <span class=\"error-message\">Title is required</span>\n </div>\n\n <div class=\"row\">\n <div class=\"form-group\" id=\"start-group\">\n <label for=\"event-start\">Start</label>\n <input type=\"datetime-local\" id=\"event-start\" required>\n </div>\n <div class=\"form-group\" id=\"end-group\">\n <label for=\"event-end\">End</label>\n <input type=\"datetime-local\" id=\"event-end\" required>\n <span class=\"error-message\">End time must be after start time</span>\n </div>\n </div>\n\n <div class=\"form-group\">\n <label id=\"color-label\">Color</label>\n <div class=\"color-options\" id=\"color-picker\" role=\"radiogroup\" aria-labelledby=\"color-label\">\n ${this.config.colors\n .map(\n c => `\n <button type=\"button\" \n class=\"color-btn ${c.color === this._formData.color ? 'selected' : ''}\" \n style=\"background-color: ${c.color}\" \n data-color=\"${c.color}\"\n title=\"${c.label}\"\n aria-label=\"${c.label}\"\n aria-checked=\"${c.color === this._formData.color ? 'true' : 'false'}\"\n role=\"radio\"></button>\n `\n )\n .join('')}\n </div>\n </div>\n </div>\n\n <footer class=\"modal-footer\">\n <button class=\"fc-btn fc-btn-secondary\" id=\"cancel-btn\">Cancel</button>\n <button class=\"fc-btn fc-btn-primary\" id=\"save-btn\">Save Event</button>\n </footer>\n </div>\n `;\n }\n\n afterRender() {\n // Bind elements\n this.modalContent = this.$('.modal-content');\n this.titleInput = this.$('#event-title');\n this.startInput = this.$('#event-start');\n this.endInput = this.$('#event-end');\n this.colorContainer = this.$('#color-picker');\n\n this.titleGroup = this.$('#title-group');\n this.endGroup = this.$('#end-group');\n\n // Event Listeners using addListener for automatic cleanup\n this.addListener(this.$('#close-x'), 'click', () => this.close());\n this.addListener(this.$('#cancel-btn'), 'click', () => this.close());\n this.addListener(this.$('#save-btn'), 'click', () => this.save());\n\n this.colorContainer.querySelectorAll('.color-btn').forEach(btn => {\n this.addListener(btn, 'click', e => {\n this._formData.color = e.currentTarget.dataset.color;\n this.updateColorSelection();\n });\n });\n\n // Close on backdrop click\n this.addListener(this, 'click', e => {\n if (e.target === this) this.close();\n });\n\n // Close on Escape key - only add once to prevent memory leaks\n if (!this._keydownListenerAdded) {\n this._handleKeyDown = e => {\n if (e.key === 'Escape' && this.hasAttribute('open')) {\n this.close();\n }\n };\n window.addEventListener('keydown', this._handleKeyDown);\n this._keydownListenerAdded = true;\n }\n }\n\n updateColorSelection() {\n const buttons = this.colorContainer.querySelectorAll('.color-btn');\n buttons.forEach(btn => {\n const isSelected = btn.dataset.color === this._formData.color;\n btn.classList.toggle('selected', isSelected);\n btn.setAttribute('aria-checked', isSelected ? 'true' : 'false');\n });\n }\n\n open(initialDate = new Date()) {\n if (!this.hasAttribute('open')) {\n this.setAttribute('open', '');\n }\n\n // Reset errors\n this.titleGroup.classList.remove('has-error');\n this.endGroup.classList.remove('has-error');\n\n // Initialize form data\n this._formData.start = initialDate;\n this._formData.end = new Date(initialDate.getTime() + this.config.defaultDuration * 60 * 1000);\n this._formData.title = '';\n this._formData.color = this.config.colors[0].color;\n\n // Update inputs\n if (this.startInput) {\n this.titleInput.value = '';\n this.startInput.value = this.formatDateForInput(this._formData.start);\n this.endInput.value = this.formatDateForInput(this._formData.end);\n this.updateColorSelection();\n\n // Clean up previous focus trap before creating a new one\n if (this._cleanupFocusTrap) {\n this._cleanupFocusTrap();\n }\n this._cleanupFocusTrap = DOMUtils.trapFocus(this.modalContent);\n }\n }\n\n close() {\n this.removeAttribute('open');\n if (this._cleanupFocusTrap) {\n this._cleanupFocusTrap();\n this._cleanupFocusTrap = null;\n }\n }\n\n validate() {\n let isValid = true;\n\n // Reset errors\n this.titleGroup.classList.remove('has-error');\n this.endGroup.classList.remove('has-error');\n\n // Check title\n if (!this.titleInput.value.trim()) {\n this.titleGroup.classList.add('has-error');\n isValid = false;\n }\n\n // Check date range\n const start = new Date(this.startInput.value);\n const end = new Date(this.endInput.value);\n if (end <= start) {\n this.endGroup.classList.add('has-error');\n isValid = false;\n }\n\n return isValid;\n }\n\n save() {\n if (!this.validate()) return;\n\n const event = {\n title: this.titleInput.value.trim(),\n start: new Date(this.startInput.value),\n end: new Date(this.endInput.value),\n backgroundColor: this._formData.color\n };\n\n this.emit('save', event);\n this.close();\n }\n\n formatDateForInput(date) {\n // Handle local date string for datetime-local input\n const pad = num => String(num).padStart(2, '0');\n const year = date.getFullYear();\n const month = pad(date.getMonth() + 1);\n const day = pad(date.getDate());\n const hours = pad(date.getHours());\n const minutes = pad(date.getMinutes());\n\n return `${year}-${month}-${day}T${hours}:${minutes}`;\n }\n\n unmount() {\n if (this._cleanupFocusTrap) {\n this._cleanupFocusTrap();\n }\n // Clean up window listener\n if (this._handleKeyDown) {\n window.removeEventListener('keydown', this._handleKeyDown);\n this._handleKeyDown = null;\n this._keydownListenerAdded = false;\n }\n }\n}\n\nif (!customElements.get('forcecal-event-form')) {\n customElements.define('forcecal-event-form', EventForm);\n}\n","/**\n * ForceCalendar - Main calendar component\n *\n * The primary interface component that integrates all views and features\n */\n\nimport { BaseComponent } from '../core/BaseComponent.js';\nimport StateManager from '../core/StateManager.js';\nimport { StyleUtils } from '../utils/StyleUtils.js';\nimport { DateUtils } from '../utils/DateUtils.js';\nimport { DOMUtils } from '../utils/DOMUtils.js';\n\n// Import view renderers (pure JS classes, Locker Service compatible)\nimport { MonthViewRenderer } from '../renderers/MonthViewRenderer.js';\nimport { WeekViewRenderer } from '../renderers/WeekViewRenderer.js';\nimport { DayViewRenderer } from '../renderers/DayViewRenderer.js';\n\n// Import EventForm component (registers custom element as side effect)\nimport './EventForm.js';\n\nexport class ForceCalendar extends BaseComponent {\n static RENDERERS = {\n month: MonthViewRenderer,\n week: WeekViewRenderer,\n day: DayViewRenderer\n };\n\n static get observedAttributes() {\n return ['view', 'date', 'locale', 'timezone', 'week-starts-on', 'height'];\n }\n\n constructor() {\n super();\n this.stateManager = null;\n this.currentView = null;\n this._hasRendered = false; // Track if initial render is complete\n this._cachedStyles = null; // Cache styles to avoid recreation\n this._busUnsubscribers = [];\n }\n\n initialize() {\n // Initialize state manager with config from attributes\n const config = {\n view: this.getAttribute('view') || 'month',\n date: this.getAttribute('date') ? new Date(this.getAttribute('date')) : new Date(),\n locale: this.getAttribute('locale') || 'en-US',\n timeZone: this.getAttribute('timezone') || Intl.DateTimeFormat().resolvedOptions().timeZone,\n weekStartsOn: parseInt(this.getAttribute('week-starts-on') || '0')\n };\n\n this.stateManager = new StateManager(config);\n\n // Subscribe to state changes (store unsubscribe for cleanup)\n this._stateUnsubscribe = this.stateManager.subscribe(this.handleStateChange.bind(this));\n\n // Listen for events\n this.setupEventListeners();\n }\n\n setupEventListeners() {\n // Clean up any existing subscriptions before re-subscribing\n this._busUnsubscribers.forEach(unsub => unsub());\n this._busUnsubscribers = [];\n\n const bus = this.stateManager.eventBus;\n\n // Navigation events\n this._busUnsubscribers.push(\n bus.on('navigation:*', (data, event) => {\n this.emit('calendar-navigate', { action: event.split(':')[1], ...data });\n })\n );\n\n // View change events\n this._busUnsubscribers.push(\n bus.on('view:changed', data => {\n this.emit('calendar-view-change', data);\n })\n );\n\n const forwardEventAction = (action, data) => {\n this.emit(`calendar-event-${action}`, data);\n };\n\n // Event management events (canonical + backward-compatible aliases)\n this._busUnsubscribers.push(\n bus.on('event:add', data => {\n forwardEventAction('add', data);\n })\n );\n this._busUnsubscribers.push(\n bus.on('event:update', data => {\n forwardEventAction('update', data);\n })\n );\n this._busUnsubscribers.push(\n bus.on('event:remove', data => {\n forwardEventAction('remove', data);\n })\n );\n // Specific lifecycle events — do NOT call forwardEventAction here; the\n // canonical event:add/update/remove handlers above already forward the\n // generic CustomEvent. These handlers emit only the specific variant so\n // consumers that care about the distinction can subscribe to it without\n // receiving the generic event a second time.\n this._busUnsubscribers.push(\n bus.on('event:added', data => {\n this.emit('calendar-event-added', data);\n })\n );\n this._busUnsubscribers.push(\n bus.on('event:updated', data => {\n this.emit('calendar-event-updated', data);\n })\n );\n this._busUnsubscribers.push(\n bus.on('event:deleted', data => {\n this.emit('calendar-event-deleted', data);\n })\n );\n\n // Date selection events\n this._busUnsubscribers.push(\n bus.on('date:selected', data => {\n this.emit('calendar-date-select', data);\n })\n );\n }\n\n handleStateChange(newState, oldState) {\n // If not yet rendered, do nothing (mount will handle initial render)\n if (!this._hasRendered) {\n return;\n }\n\n // Check what changed\n const viewChanged = newState.view !== oldState?.view;\n const dateChanged = newState.currentDate?.getTime() !== oldState?.currentDate?.getTime();\n const eventsChanged = newState.events !== oldState?.events;\n const loadingChanged = newState.loading !== oldState?.loading;\n const errorChanged = newState.error !== oldState?.error;\n\n // For loading/error state changes, do full re-render (rare)\n if (errorChanged) {\n this.render();\n return;\n }\n if (loadingChanged) {\n this._updateLoadingState(newState.loading);\n return;\n }\n\n // Update local view reference if needed\n if (viewChanged) {\n this.currentView = newState.view;\n }\n\n // Targeted updates based on what changed\n if (viewChanged) {\n // View changed: update title, buttons, and switch view\n this._updateTitle();\n this._updateViewButtons();\n this._switchView();\n } else if (dateChanged) {\n // Date changed: update title and re-render view\n this._updateTitle();\n this._updateViewContent();\n } else if (eventsChanged) {\n // Events changed: only re-render view content\n this._updateViewContent();\n }\n // Selection changes are handled by the view internally, no action needed here\n }\n\n /**\n * Update only the title text (no DOM recreation)\n */\n _updateTitle() {\n const titleEl = this.$('.fc-title');\n if (titleEl) {\n const state = this.stateManager.getState();\n titleEl.textContent = this.getTitle(state.currentDate, state.view);\n }\n }\n\n /**\n * Update view button active states (no DOM recreation)\n */\n _updateViewButtons() {\n const state = this.stateManager.getState();\n this.$$('[data-view]').forEach(button => {\n const isActive = button.dataset.view === state.view;\n button.classList.toggle('active', isActive);\n });\n }\n\n /**\n * Switch to a different view type\n */\n _switchView() {\n const container = this.$('#calendar-view-container');\n if (!container) return;\n\n // Clean up previous view\n if (this._currentViewInstance) {\n if (this._currentViewInstance.cleanup) {\n this._currentViewInstance.cleanup();\n }\n }\n\n // Create new view using renderer classes\n try {\n const RendererClass = ForceCalendar.RENDERERS[this.currentView] || MonthViewRenderer;\n const viewRenderer = new RendererClass(container, this.stateManager);\n viewRenderer._viewType = this.currentView;\n this._currentViewInstance = viewRenderer;\n viewRenderer.render();\n // Note: No subscription - handleStateChange manages all view updates\n } catch (err) {\n console.error('[ForceCalendar] Error switching view:', err);\n }\n }\n\n /**\n * Re-render only the view content (not header)\n */\n _updateViewContent() {\n if (this._currentViewInstance && this._currentViewInstance.render) {\n this._currentViewInstance.render();\n }\n }\n\n /**\n * Toggle loading overlay without rebuilding the component tree.\n */\n _updateLoadingState(isLoading) {\n const loadingEl = this.$('.fc-loading');\n const viewContainer = this.$('.fc-view-container');\n if (loadingEl) {\n loadingEl.style.display = isLoading ? 'flex' : 'none';\n }\n if (viewContainer) {\n viewContainer.style.display = isLoading ? 'none' : 'flex';\n }\n }\n\n mount() {\n this.currentView = this.stateManager.getView();\n super.mount();\n }\n\n loadView(viewType) {\n if (!viewType || this.currentView === viewType) return;\n this.currentView = viewType;\n this._switchView();\n this._updateViewButtons();\n this._updateTitle();\n }\n\n getStyles() {\n const height = this.getAttribute('height') || '800px';\n\n return `\n ${StyleUtils.getBaseStyles()}\n ${StyleUtils.getButtonStyles()}\n ${StyleUtils.getGridStyles()}\n ${StyleUtils.getAnimations()}\n\n :host {\n --calendar-height: ${height};\n display: block;\n font-family: var(--fc-font-family);\n }\n\n .force-calendar {\n display: flex;\n flex-direction: column;\n height: var(--calendar-height);\n background: var(--fc-background);\n border: 1px solid var(--fc-border-color);\n border-radius: var(--fc-border-radius-lg);\n overflow: hidden;\n box-shadow: var(--fc-shadow);\n }\n\n .fc-header {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: center;\n padding: var(--fc-spacing-md) var(--fc-spacing-lg);\n background: rgba(255, 255, 255, 0.95);\n -webkit-backdrop-filter: blur(8px); /* Safari support */\n backdrop-filter: blur(8px);\n border-bottom: 1px solid var(--fc-border-color);\n z-index: 10;\n position: sticky;\n top: 0;\n }\n\n .fc-header-left {\n display: flex;\n align-items: center;\n gap: var(--fc-spacing-md);\n justify-self: start;\n flex-basis: 0; /* Force Safari to distribute space */\n }\n\n .fc-header-center {\n display: flex;\n align-items: center;\n gap: var(--fc-spacing-lg);\n justify-self: center;\n }\n\n .fc-header-right {\n display: flex;\n align-items: center;\n gap: var(--fc-spacing-md);\n justify-self: end;\n flex-basis: 0; /* Force Safari to distribute space */\n }\n\n .fc-title {\n font-size: 14px;\n font-weight: var(--fc-font-weight-semibold);\n color: var(--fc-text-color);\n white-space: nowrap;\n letter-spacing: -0.01em;\n min-width: 140px;\n text-align: center;\n }\n\n .fc-btn-today {\n border-radius: var(--fc-border-radius-sm);\n padding: 0 12px;\n font-size: 12px;\n font-weight: var(--fc-font-weight-medium);\n border: 1px solid var(--fc-border-color);\n background: var(--fc-background);\n color: var(--fc-text-color);\n height: 28px;\n transition: all var(--fc-transition-fast);\n cursor: pointer;\n display: flex;\n align-items: center;\n }\n\n .fc-btn-today:hover {\n background: var(--fc-background-hover);\n border-color: var(--fc-border-color-hover);\n }\n\n .fc-nav-arrow {\n border: 1px solid var(--fc-border-color);\n background: var(--fc-background);\n height: 28px;\n width: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--fc-border-radius-sm);\n color: var(--fc-text-secondary);\n cursor: pointer;\n transition: all var(--fc-transition-fast);\n padding: 0;\n }\n\n .fc-nav-arrow:hover {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n border-color: var(--fc-border-color-hover);\n }\n\n /* View Switcher - Fused Button Group */\n .fc-view-buttons {\n display: flex;\n border: 1px solid var(--fc-border-color);\n border-radius: var(--fc-border-radius-sm);\n overflow: hidden;\n }\n\n .fc-view-button {\n background: var(--fc-background);\n border: none;\n border-right: 1px solid var(--fc-border-color);\n color: var(--fc-text-secondary);\n padding: 0 12px;\n font-size: var(--fc-font-size-sm);\n font-weight: var(--fc-font-weight-medium);\n transition: background-color var(--fc-transition-fast);\n cursor: pointer;\n height: 28px;\n display: flex;\n align-items: center;\n }\n \n .fc-view-button:last-child {\n border-right: none;\n }\n\n .fc-view-button:hover:not(.active) {\n background: var(--fc-background-hover);\n color: var(--fc-text-color);\n }\n\n .fc-view-button.active {\n background: var(--fc-background-alt);\n color: var(--fc-text-color);\n font-weight: var(--fc-font-weight-semibold);\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.02);\n }\n\n .fc-body {\n flex: 1;\n position: relative;\n background: var(--fc-background);\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n\n .fc-view-container {\n flex: 1;\n position: relative;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n\n /* Ensure view container has proper dimensions */\n #calendar-view-container {\n display: block;\n width: 100%;\n height: 100%;\n flex: 1;\n }\n\n #calendar-view-container > * {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n /* Loading state */\n .fc-loading {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--fc-spacing-md);\n color: var(--fc-text-secondary);\n }\n\n .fc-spinner {\n width: 24px;\n height: 24px;\n border: 3px solid var(--fc-border-color);\n border-top-color: var(--fc-primary-color);\n border-radius: 50%;\n animation: fc-spin 1s linear infinite;\n }\n\n /* Error state */\n .fc-error {\n padding: var(--fc-spacing-xl);\n text-align: center;\n color: var(--fc-danger-color);\n background: #FEF2F2;\n border-radius: var(--fc-border-radius);\n margin: var(--fc-spacing-xl);\n }\n\n /* Icons */\n .fc-icon {\n width: 18px;\n height: 18px;\n fill: currentColor;\n }\n\n /* Responsive Adjustments */\n @media (max-width: 850px) {\n .fc-header {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--fc-spacing-md);\n height: auto;\n position: static;\n padding: var(--fc-spacing-md);\n }\n\n .fc-header-center {\n order: -1;\n text-align: center;\n width: 100%;\n padding: var(--fc-spacing-xs) 0;\n }\n\n .fc-header-left,\n .fc-header-right {\n justify-content: space-between;\n width: 100%;\n }\n\n #create-event-btn {\n flex: 1;\n }\n }\n\n /* Month View Styles (inline rendering for Locker Service compatibility) */\n .fc-month-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--fc-background);\n }\n\n .fc-month-header {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n border-bottom: 1px solid var(--fc-border-color);\n background: var(--fc-background-alt);\n }\n\n .fc-month-header-cell {\n padding: 12px 8px;\n text-align: center;\n font-size: 11px;\n font-weight: 600;\n color: var(--fc-text-light);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .fc-month-body {\n display: flex;\n flex-direction: column;\n flex: 1;\n }\n\n .fc-month-week {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n flex: 1;\n min-height: 100px;\n }\n\n .fc-month-day {\n background: var(--fc-background);\n border-right: 1px solid var(--fc-border-color);\n border-bottom: 1px solid var(--fc-border-color);\n padding: 4px;\n min-height: 80px;\n cursor: pointer;\n transition: background-color 0.15s ease;\n display: flex;\n flex-direction: column;\n }\n\n .fc-month-day:hover {\n background: var(--fc-background-hover);\n }\n\n .fc-month-day:last-child {\n border-right: none;\n }\n\n .fc-month-day.other-month {\n background: var(--fc-background-alt);\n }\n\n .fc-month-day.other-month .fc-day-number {\n color: var(--fc-text-light);\n }\n\n .fc-month-day.today {\n background: rgba(37, 99, 235, 0.05);\n }\n\n .fc-month-day.today .fc-day-number {\n background: var(--fc-primary-color);\n color: white;\n border-radius: 50%;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .fc-day-number {\n font-size: 13px;\n font-weight: 500;\n color: var(--fc-text-color);\n padding: 2px 4px;\n margin-bottom: 4px;\n }\n\n .fc-day-events {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex: 1;\n overflow: hidden;\n }\n\n .fc-event {\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 3px;\n color: white;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: pointer;\n transition: transform 0.1s ease;\n }\n\n .fc-event:hover {\n transform: scale(1.02);\n }\n\n .fc-more-events {\n font-size: 10px;\n color: var(--fc-text-light);\n padding: 2px 4px;\n font-weight: 500;\n }\n\n /* Week View Styles (inline rendering for Locker Service compatibility) */\n .fc-week-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--fc-background);\n }\n\n /* Day View Styles (inline rendering for Locker Service compatibility) */\n .fc-day-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--fc-background);\n }\n `;\n }\n\n template() {\n const state = this.stateManager.getState();\n const { currentDate, view, loading, error } = state;\n\n if (error) {\n return `\n <div class=\"force-calendar\">\n <div class=\"fc-error\">\n <p><strong>Error:</strong> ${DOMUtils.escapeHTML(error.message || 'An error occurred')}</p>\n </div>\n </div>\n `;\n }\n\n const title = this.getTitle(currentDate, view);\n\n return `\n <div class=\"force-calendar\">\n <header class=\"fc-header\">\n <div class=\"fc-header-left\">\n <button class=\"fc-btn-today\" data-action=\"today\">\n Today\n </button>\n </div>\n\n <div class=\"fc-header-center\">\n <button class=\"fc-nav-arrow\" data-action=\"previous\" title=\"Previous\">\n ${this.getIcon('chevron-left')}\n </button>\n <h2 class=\"fc-title\">${title}</h2>\n <button class=\"fc-nav-arrow\" data-action=\"next\" title=\"Next\">\n ${this.getIcon('chevron-right')}\n </button>\n </div>\n\n <div class=\"fc-header-right\">\n <button class=\"fc-btn fc-btn-primary\" id=\"create-event-btn\" style=\"height: 28px; padding: 0 12px; font-size: 12px;\">\n + New Event\n </button>\n <div class=\"fc-view-buttons\" role=\"group\">\n <button class=\"fc-view-button ${view === 'month' ? 'active' : ''}\"\n data-view=\"month\">Month</button>\n <button class=\"fc-view-button ${view === 'week' ? 'active' : ''}\"\n data-view=\"week\">Week</button>\n <button class=\"fc-view-button ${view === 'day' ? 'active' : ''}\"\n data-view=\"day\">Day</button>\n </div>\n </div>\n </header>\n\n <div class=\"fc-body\">\n <div class=\"fc-loading\" style=\"display: ${loading ? 'flex' : 'none'};\">\n <div class=\"fc-spinner\"></div>\n <span>Loading...</span>\n </div>\n <div class=\"fc-view-container\" style=\"display: ${loading ? 'none' : 'flex'};\">\n ${this.renderView()}\n </div>\n </div>\n \n <forcecal-event-form id=\"event-modal\"></forcecal-event-form>\n </div>\n `;\n }\n\n renderView() {\n // Use a plain div container - we'll manually instantiate view classes\n // This bypasses Locker Service's custom element restrictions\n return '<div id=\"calendar-view-container\"></div>';\n }\n\n afterRender() {\n // Manually instantiate and mount view renderer (bypasses Locker Service)\n const container = this.$('#calendar-view-container');\n\n // Only create view once per view type change\n if (container && this.stateManager && this.currentView) {\n // Check if container actually has content (render() clears shadow DOM)\n if (\n this._currentViewInstance &&\n this._currentViewInstance._viewType === this.currentView &&\n container.children.length > 0\n ) {\n return;\n }\n\n // Clean up previous view if exists\n if (this._currentViewInstance) {\n if (this._currentViewInstance.cleanup) {\n this._currentViewInstance.cleanup();\n }\n if (this._viewUnsubscribe) {\n this._viewUnsubscribe();\n this._viewUnsubscribe = null;\n }\n }\n\n // Create view renderer using the appropriate renderer class\n try {\n const RendererClass = ForceCalendar.RENDERERS[this.currentView] || MonthViewRenderer;\n const viewRenderer = new RendererClass(container, this.stateManager);\n viewRenderer._viewType = this.currentView;\n this._currentViewInstance = viewRenderer;\n viewRenderer.render();\n // Note: No subscription here - handleStateChange manages all view updates\n // via _updateViewContent(), _switchView(), or full re-render\n } catch (err) {\n console.error('[ForceCalendar] Error creating/rendering view:', err);\n }\n }\n\n // Add event listeners for buttons using tracked addListener\n this.$$('[data-action]').forEach(button => {\n this.addListener(button, 'click', this.handleNavigation);\n });\n\n this.$$('[data-view]').forEach(button => {\n this.addListener(button, 'click', this.handleViewChange);\n });\n\n // Event Modal Handling\n const modal = this.$('#event-modal');\n const createBtn = this.$('#create-event-btn');\n\n if (createBtn && modal) {\n this.addListener(createBtn, 'click', () => {\n modal.open(new Date());\n });\n }\n\n // Listen for day clicks from the view\n this.addListener(this.shadowRoot, 'day-click', e => {\n if (modal) {\n modal.open(e.detail.date);\n }\n });\n\n // Handle event saving\n if (modal) {\n this.addListener(modal, 'save', e => {\n const eventData = e.detail;\n // Robust Safari support check for randomUUID\n const id =\n window.crypto && typeof window.crypto.randomUUID === 'function'\n ? window.crypto.randomUUID()\n : Math.random().toString(36).substring(2, 15);\n\n this.stateManager.addEvent({\n id,\n ...eventData\n });\n });\n }\n\n // Mark initial render as complete for targeted updates\n this._hasRendered = true;\n }\n\n handleNavigation(event) {\n const action = event.currentTarget.dataset.action;\n switch (action) {\n case 'today':\n this.stateManager.today();\n break;\n case 'previous':\n this.stateManager.previous();\n break;\n case 'next':\n this.stateManager.next();\n break;\n }\n }\n\n handleViewChange(event) {\n const view = event.currentTarget.dataset.view;\n this.stateManager.setView(view);\n }\n\n getTitle(date, view) {\n const locale = this.stateManager.state.config.locale;\n\n switch (view) {\n case 'month':\n return DateUtils.formatDate(date, 'month', locale);\n case 'week': {\n const weekStart = DateUtils.startOfWeek(date);\n const weekEnd = DateUtils.endOfWeek(date);\n return DateUtils.formatDateRange(weekStart, weekEnd, locale);\n }\n case 'day':\n return DateUtils.formatDate(date, 'long', locale);\n default:\n return DateUtils.formatDate(date, 'month', locale);\n }\n }\n\n getIcon(name) {\n const icons = {\n 'chevron-left': `\n <svg class=\"fc-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"/>\n </svg>\n `,\n 'chevron-right': `\n <svg class=\"fc-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z\"/>\n </svg>\n `,\n calendar: `\n <svg class=\"fc-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"/>\n </svg>\n `\n };\n\n return icons[name] || '';\n }\n\n // Public API methods\n addEvent(event) {\n return this.stateManager.addEvent(event);\n }\n\n updateEvent(eventId, updates) {\n return this.stateManager.updateEvent(eventId, updates);\n }\n\n deleteEvent(eventId) {\n return this.stateManager.deleteEvent(eventId);\n }\n\n getEvents() {\n return this.stateManager.getEvents();\n }\n\n setView(view) {\n this.stateManager.setView(view);\n }\n\n setDate(date) {\n this.stateManager.setDate(date);\n }\n\n next() {\n this.stateManager.next();\n }\n\n previous() {\n this.stateManager.previous();\n }\n\n today() {\n this.stateManager.today();\n }\n\n unmount() {\n // Called by disconnectedCallback — clean up all subscriptions\n this.destroy();\n }\n\n destroy() {\n this._busUnsubscribers.forEach(unsub => unsub());\n this._busUnsubscribers = [];\n\n if (this._stateUnsubscribe) {\n this._stateUnsubscribe();\n this._stateUnsubscribe = null;\n }\n\n if (this._currentViewInstance && this._currentViewInstance.cleanup) {\n this._currentViewInstance.cleanup();\n this._currentViewInstance = null;\n }\n\n if (this.stateManager) {\n this.stateManager.destroy();\n }\n super.cleanup();\n }\n}\n\n// Register component\nif (!customElements.get('forcecal-main')) {\n customElements.define('forcecal-main', ForceCalendar);\n}\n"],"names":["BaseComponent","element","event","handler","newState","oldState","_oldState","_newState","key","value","oldValue","_key","_oldValue","_newValue","boundHandler","eventName","detail","styles","template","selector","name","newValue","EventBus","options","once","priority","subscription","handlers","b","index","sub","pattern","data","error","toRemove","count","eventBus","StateManager","config","Calendar","force","coreEvents","arr1","arr2","ids1","e","updates","silent","callback","subscriberId","changedKeys","view","date","addedEvent","eventId","start","end","viewData","enriched","selectedDateString","_a","week","day","dayDate","today","loading","DateUtils","CoreDateUtils","format","locale","formats","showMinutes","use24Hour","startFormat","startTime","endTime","baseDate","rtf","diff","diffInSeconds","diffInMinutes","diffInHours","diffInDays","diffInWeeks","diffInMonths","diffInYears","firstDayOfYear","pastDaysOfYear","dayIndex","monthIndex","timeStr","time","period","hours","minutes","adjustedHours","DOMUtils","tag","attributes","children","child","events","delegatedHandler","target","rect","threshold","behavior","block","inline","property","className","duration","eventType","resolve","ms","htmlString","str","div","func","wait","timeout","args","later","limit","inThrottle","parents","parent","margin","deep","container","focusableElements","firstFocusable","lastFocusable","handleKeyDown","StyleUtils","variables","color","percent","num","amt","R","G","B","bgColor","g","fallback","trimmed","hex","alpha","r","breakpoint","size","__publicField","BaseViewRenderer","stateManager","date1","date2","hour","displayHour","fullColor","c","col","now","entries","evt","startMin","endMin","columns","layout","entry","placed","groups","currentGroup","groupEnd","group","maxCol","compact","overlapLayout","startMinutes","durationMinutes","padding","fontSize","baseMargin","rightPad","borderRadius","leftPx","widthCalc","column","totalColumns","colWidth","eventEl","ev","MonthViewRenderer","html","weekStartsOn","d","days","dayNames","isOtherMonth","isToday","dayBg","dayNumColor","todayStyle","visibleEvents","moreCount","dayEl","WeekViewRenderer","_config","_","i","processedDays","h","scrollContainer","gridTop","y","clampedY","DayViewRenderer","currentDate","_b","dayData","dayName","allDayEvents","timedEvents","eventMap","dayDataItem","EventForm","btn","isSelected","initialDate","isValid","pad","year","month","_ForceCalendar","unsub","bus","forwardEventAction","action","viewChanged","dateChanged","eventsChanged","loadingChanged","titleEl","state","button","isActive","RendererClass","viewRenderer","err","isLoading","loadingEl","viewContainer","viewType","height","title","modal","createBtn","eventData","id","weekStart","weekEnd","ForceCalendar"],"mappings":"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"}
|