@forcecalendar/interface 1.0.10 → 1.0.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forcecalendar/interface",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "type": "module",
5
5
  "description": "Official interface layer for forceCalendar Core - Enterprise calendar components",
6
6
  "main": "dist/force-calendar-interface.umd.js",
@@ -349,11 +349,147 @@ export class ForceCalendar extends BaseComponent {
349
349
  justify-content: space-between;
350
350
  width: 100%;
351
351
  }
352
-
352
+
353
353
  #create-event-btn {
354
354
  flex: 1;
355
355
  }
356
356
  }
357
+
358
+ /* Month View Styles (inline rendering for Locker Service compatibility) */
359
+ .fc-month-view {
360
+ display: flex;
361
+ flex-direction: column;
362
+ height: 100%;
363
+ background: var(--fc-background);
364
+ }
365
+
366
+ .fc-month-header {
367
+ display: grid;
368
+ grid-template-columns: repeat(7, 1fr);
369
+ border-bottom: 1px solid var(--fc-border-color);
370
+ background: var(--fc-background-alt);
371
+ }
372
+
373
+ .fc-month-header-cell {
374
+ padding: 12px 8px;
375
+ text-align: center;
376
+ font-size: 11px;
377
+ font-weight: 600;
378
+ color: var(--fc-text-light);
379
+ text-transform: uppercase;
380
+ letter-spacing: 0.05em;
381
+ }
382
+
383
+ .fc-month-body {
384
+ display: flex;
385
+ flex-direction: column;
386
+ flex: 1;
387
+ }
388
+
389
+ .fc-month-week {
390
+ display: grid;
391
+ grid-template-columns: repeat(7, 1fr);
392
+ flex: 1;
393
+ min-height: 100px;
394
+ }
395
+
396
+ .fc-month-day {
397
+ background: var(--fc-background);
398
+ border-right: 1px solid var(--fc-border-color);
399
+ border-bottom: 1px solid var(--fc-border-color);
400
+ padding: 4px;
401
+ min-height: 80px;
402
+ cursor: pointer;
403
+ transition: background-color 0.15s ease;
404
+ display: flex;
405
+ flex-direction: column;
406
+ }
407
+
408
+ .fc-month-day:hover {
409
+ background: var(--fc-background-hover);
410
+ }
411
+
412
+ .fc-month-day:last-child {
413
+ border-right: none;
414
+ }
415
+
416
+ .fc-month-day.other-month {
417
+ background: var(--fc-background-alt);
418
+ }
419
+
420
+ .fc-month-day.other-month .fc-day-number {
421
+ color: var(--fc-text-light);
422
+ }
423
+
424
+ .fc-month-day.today {
425
+ background: rgba(37, 99, 235, 0.05);
426
+ }
427
+
428
+ .fc-month-day.today .fc-day-number {
429
+ background: var(--fc-primary-color);
430
+ color: white;
431
+ border-radius: 50%;
432
+ width: 24px;
433
+ height: 24px;
434
+ display: flex;
435
+ align-items: center;
436
+ justify-content: center;
437
+ }
438
+
439
+ .fc-day-number {
440
+ font-size: 13px;
441
+ font-weight: 500;
442
+ color: var(--fc-text-color);
443
+ padding: 2px 4px;
444
+ margin-bottom: 4px;
445
+ }
446
+
447
+ .fc-day-events {
448
+ display: flex;
449
+ flex-direction: column;
450
+ gap: 2px;
451
+ flex: 1;
452
+ overflow: hidden;
453
+ }
454
+
455
+ .fc-event {
456
+ font-size: 11px;
457
+ padding: 2px 6px;
458
+ border-radius: 3px;
459
+ color: white;
460
+ white-space: nowrap;
461
+ overflow: hidden;
462
+ text-overflow: ellipsis;
463
+ cursor: pointer;
464
+ transition: transform 0.1s ease;
465
+ }
466
+
467
+ .fc-event:hover {
468
+ transform: scale(1.02);
469
+ }
470
+
471
+ .fc-more-events {
472
+ font-size: 10px;
473
+ color: var(--fc-text-light);
474
+ padding: 2px 4px;
475
+ font-weight: 500;
476
+ }
477
+
478
+ /* Week View Styles (inline rendering for Locker Service compatibility) */
479
+ .fc-week-view {
480
+ display: flex;
481
+ flex-direction: column;
482
+ height: 100%;
483
+ background: var(--fc-background);
484
+ }
485
+
486
+ /* Day View Styles (inline rendering for Locker Service compatibility) */
487
+ .fc-day-view {
488
+ display: flex;
489
+ flex-direction: column;
490
+ height: 100%;
491
+ background: var(--fc-background);
492
+ }
357
493
  `;
358
494
  }
359
495
 
@@ -436,30 +572,53 @@ export class ForceCalendar extends BaseComponent {
436
572
  const container = this.$('#calendar-view-container');
437
573
  console.log('[ForceCalendar] afterRender - container:', !!container, 'stateManager:', !!this.stateManager, 'currentView:', this.currentView);
438
574
 
575
+ // Only create view once per view type change
439
576
  if (container && this.stateManager && this.currentView) {
577
+ // Check if container actually has content (render() clears shadow DOM)
578
+ if (this._currentViewInstance && this._currentViewInstance._viewType === this.currentView && container.children.length > 0) {
579
+ console.log('[ForceCalendar] View already exists with content, skipping creation');
580
+ return;
581
+ }
582
+
440
583
  // Clean up previous view if exists
441
584
  if (this._currentViewInstance) {
442
585
  if (this._currentViewInstance.cleanup) {
443
586
  this._currentViewInstance.cleanup();
444
587
  }
588
+ if (this._viewUnsubscribe) {
589
+ this._viewUnsubscribe();
590
+ this._viewUnsubscribe = null;
591
+ }
445
592
  }
446
593
 
447
594
  console.log('[ForceCalendar] Creating view for:', this.currentView);
448
595
 
449
596
  // Create a simple view renderer that doesn't use custom elements
450
- const viewRenderer = this._createViewRenderer(this.currentView);
451
- if (viewRenderer) {
452
- this._currentViewInstance = viewRenderer;
453
- viewRenderer.stateManager = this.stateManager;
454
- viewRenderer.container = container;
455
- viewRenderer.render();
456
-
457
- // Subscribe to state changes
458
- this.stateManager.subscribe((newState, oldState) => {
459
- if (viewRenderer && viewRenderer.render) {
460
- viewRenderer.render();
461
- }
462
- });
597
+ try {
598
+ const viewRenderer = this._createViewRenderer(this.currentView);
599
+ if (viewRenderer) {
600
+ viewRenderer._viewType = this.currentView;
601
+ this._currentViewInstance = viewRenderer;
602
+ viewRenderer.stateManager = this.stateManager;
603
+ viewRenderer.container = container;
604
+
605
+ console.log('[ForceCalendar] Calling viewRenderer.render()');
606
+ viewRenderer.render();
607
+ console.log('[ForceCalendar] viewRenderer.render() completed');
608
+
609
+ // Subscribe to state changes (store unsubscribe function)
610
+ this._viewUnsubscribe = this.stateManager.subscribe((newState, oldState) => {
611
+ // Only re-render on data changes, not view changes
612
+ if (newState.events !== oldState?.events ||
613
+ newState.currentDate !== oldState?.currentDate) {
614
+ if (viewRenderer && viewRenderer.render) {
615
+ viewRenderer.render();
616
+ }
617
+ }
618
+ });
619
+ }
620
+ } catch (err) {
621
+ console.error('[ForceCalendar] Error creating/rendering view:', err);
463
622
  }
464
623
  }
465
624
 
@@ -529,18 +688,25 @@ export class ForceCalendar extends BaseComponent {
529
688
  },
530
689
 
531
690
  render() {
691
+ console.log('[ViewRenderer] render called, container:', !!this.container, 'stateManager:', !!this.stateManager);
532
692
  if (!this.container || !this.stateManager) return;
533
693
 
534
694
  const viewData = this.stateManager.getViewData();
695
+ console.log('[ViewRenderer] viewData:', viewData);
696
+ console.log('[ViewRenderer] viewData.weeks:', viewData?.weeks);
697
+
535
698
  if (!viewData || !viewData.weeks) {
536
- this.container.innerHTML = '<div style="padding: 20px; text-align: center;">Loading calendar...</div>';
699
+ this.container.innerHTML = '<div style="padding: 20px; text-align: center; background: #fee; color: #c00;">No viewData.weeks available. viewData keys: ' + (viewData ? Object.keys(viewData).join(', ') : 'null') + '</div>';
537
700
  return;
538
701
  }
539
702
 
540
703
  this.cleanup();
541
704
  const config = this.stateManager.getState().config;
705
+ console.log('[ViewRenderer] Rendering month view with', viewData.weeks.length, 'weeks');
542
706
  const html = this._renderMonthView(viewData, config);
707
+ console.log('[ViewRenderer] HTML length:', html.length);
543
708
  this.container.innerHTML = html;
709
+ console.log('[ViewRenderer] innerHTML set, container children:', this.container.children.length);
544
710
  this._attachEventHandlers();
545
711
  },
546
712
 
@@ -552,55 +718,39 @@ export class ForceCalendar extends BaseComponent {
552
718
  dayNames.push(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][dayIndex]);
553
719
  }
554
720
 
721
+ // Using inline styles for Locker Service compatibility
555
722
  let html = `
556
- <style>
557
- .fc-month-view { display: flex; flex-direction: column; height: 100%; background: #fff; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: 13px; }
558
- .fc-month-header { display: grid; grid-template-columns: repeat(7, 1fr); background: #fafafa; border-bottom: 1px solid #e5e7eb; }
559
- .fc-month-header-cell { padding: 8px; text-align: left; font-weight: 600; font-size: 10px; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.5px; }
560
- .fc-month-body { flex: 1; display: flex; flex-direction: column; }
561
- .fc-month-week { flex: 1; display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid #e5e7eb; }
562
- .fc-month-week:last-child { border-bottom: none; }
563
- .fc-month-day { background: #fff; padding: 4px; position: relative; border-right: 1px solid #e5e7eb; min-height: 80px; cursor: pointer; }
564
- .fc-month-day:last-child { border-right: none; }
565
- .fc-month-day:hover { background: #f9fafb; }
566
- .fc-month-day.other-month { background: #f9fafb; }
567
- .fc-month-day.other-month .fc-day-number { color: #d1d5db; }
568
- .fc-month-day.today .fc-day-number { background: #ef4444; color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; }
569
- .fc-day-number { font-size: 12px; font-weight: 500; color: #111827; padding: 4px; }
570
- .fc-day-events { display: flex; flex-direction: column; gap: 2px; margin-top: 2px; }
571
- .fc-event { font-size: 11px; padding: 2px 6px; border-radius: 2px; background: #2563eb; color: white; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
572
- .fc-event:hover { opacity: 0.9; }
573
- .fc-more-events { font-size: 10px; color: #6b7280; padding: 2px 4px; cursor: pointer; }
574
- .fc-more-events:hover { color: #111827; text-decoration: underline; }
575
- </style>
576
- <div class="fc-month-view">
577
- <div class="fc-month-header">
578
- ${dayNames.map(d => `<div class="fc-month-header-cell">${d}</div>`).join('')}
723
+ <div class="fc-month-view" style="display: flex; flex-direction: column; height: 100%; min-height: 400px; background: #fff; border: 1px solid #e5e7eb;">
724
+ <div class="fc-month-header" style="display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid #e5e7eb; background: #f9fafb;">
725
+ ${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('')}
579
726
  </div>
580
- <div class="fc-month-body">
727
+ <div class="fc-month-body" style="display: flex; flex-direction: column; flex: 1;">
581
728
  `;
582
729
 
583
730
  viewData.weeks.forEach(week => {
584
- html += '<div class="fc-month-week">';
731
+ html += '<div class="fc-month-week" style="display: grid; grid-template-columns: repeat(7, 1fr); flex: 1; min-height: 80px;">';
585
732
  week.days.forEach(day => {
586
- const classes = ['fc-month-day'];
587
- if (!day.isCurrentMonth) classes.push('other-month');
588
- if (day.isToday) classes.push('today');
733
+ const isOtherMonth = !day.isCurrentMonth;
734
+ const isToday = day.isToday;
735
+
736
+ const dayBg = isOtherMonth ? '#f3f4f6' : '#fff';
737
+ const dayNumColor = isOtherMonth ? '#9ca3af' : '#111827';
738
+ const todayStyle = isToday ? 'background: #2563eb; color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;' : '';
589
739
 
590
740
  const events = day.events || [];
591
741
  const visibleEvents = events.slice(0, 3);
592
742
  const moreCount = events.length - 3;
593
743
 
594
744
  html += `
595
- <div class="${classes.join(' ')}" data-date="${day.date}">
596
- <div class="fc-day-number">${day.dayOfMonth}</div>
597
- <div class="fc-day-events">
745
+ <div class="fc-month-day" data-date="${day.date}" style="background: ${dayBg}; border-right: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; padding: 4px; min-height: 80px; cursor: pointer;">
746
+ <div class="fc-day-number" style="font-size: 13px; font-weight: 500; color: ${dayNumColor}; padding: 2px 4px; margin-bottom: 4px; ${todayStyle}">${day.dayOfMonth}</div>
747
+ <div class="fc-day-events" style="display: flex; flex-direction: column; gap: 2px;">
598
748
  ${visibleEvents.map(evt => `
599
- <div class="fc-event" data-event-id="${evt.id}" style="background-color: ${evt.backgroundColor || '#2563eb'}">
749
+ <div class="fc-event" data-event-id="${evt.id}" style="background-color: ${evt.backgroundColor || '#2563eb'}; font-size: 11px; padding: 2px 6px; border-radius: 3px; color: white; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;">
600
750
  ${evt.title}
601
751
  </div>
602
752
  `).join('')}
603
- ${moreCount > 0 ? `<div class="fc-more-events">+${moreCount} more</div>` : ''}
753
+ ${moreCount > 0 ? `<div class="fc-more-events" style="font-size: 10px; color: #6b7280; padding: 2px 4px; font-weight: 500;">+${moreCount} more</div>` : ''}
604
754
  </div>
605
755
  </div>
606
756
  `;