2
0
Adam Shaw 5 жил өмнө
parent
commit
b255a3314c
49 өөрчлөгдсөн 920 нэмэгдсэн , 831 устгасан
  1. 1 1
      packages-premium
  2. 1 1
      packages/__tests__/src/lib/wrappers/CalendarWrapper.ts
  3. 2 2
      packages/__tests__/src/lib/wrappers/DayGridWrapper.ts
  4. 2 2
      packages/__tests__/src/lib/wrappers/TimeGridWrapper.ts
  5. 1 0
      packages/bootstrap/src/main.scss
  6. 6 5
      packages/core/src/ViewContainer.tsx
  7. 2 2
      packages/core/src/common/bg-fill.tsx
  8. 12 6
      packages/core/src/main.scss
  9. 1 1
      packages/core/src/structs/business-hours.ts
  10. 45 0
      packages/core/src/styles/_bg.scss
  11. 7 4
      packages/core/src/styles/_button.scss
  12. 13 9
      packages/core/src/styles/_calendar-root.scss
  13. 1 1
      packages/core/src/styles/_col-header.scss
  14. 9 0
      packages/core/src/styles/_divider.scss
  15. 8 0
      packages/core/src/styles/_dot.scss
  16. 0 151
      packages/core/src/styles/_event-common.scss
  17. 0 124
      packages/core/src/styles/_event-horizontal.scss
  18. 104 0
      packages/core/src/styles/_event.scss
  19. 74 0
      packages/core/src/styles/_h-event.scss
  20. 23 1
      packages/core/src/styles/_mixins.scss
  21. 17 0
      packages/core/src/styles/_page-root.scss
  22. 4 2
      packages/core/src/styles/_scroller-harness.scss
  23. 0 11
      packages/core/src/styles/_scroller.scss
  24. 13 39
      packages/core/src/styles/_scrollgrid.scss
  25. 9 0
      packages/core/src/styles/_sticky.scss
  26. 2 17
      packages/core/src/styles/_toolbar.scss
  27. 0 49
      packages/core/src/styles/_utils.scss
  28. 11 0
      packages/core/src/styles/_vars.scss
  29. 14 0
      packages/core/src/styles/_view-harness.scss
  30. 0 31
      packages/core/src/styles/_view-structure.scss
  31. 0 1
      packages/daygrid/src/MorePopover.tsx
  32. 37 35
      packages/daygrid/src/TableCell.tsx
  33. 22 17
      packages/daygrid/src/TableRow.tsx
  34. 4 0
      packages/daygrid/src/main.scss
  35. 46 10
      packages/daygrid/src/styles/_daygrid-event.scss
  36. 117 55
      packages/daygrid/src/styles/_daygrid.scss
  37. 3 7
      packages/daygrid/src/styles/_popover.scss
  38. 3 1
      packages/list/src/ListView.tsx
  39. 47 45
      packages/list/src/main.scss
  40. 4 4
      packages/timegrid/src/TimeCol.tsx
  41. 1 1
      packages/timegrid/src/TimeColEvent.tsx
  42. 6 0
      packages/timegrid/src/main.scss
  43. 52 0
      packages/timegrid/src/styles/_timegrid-cols.scss
  44. 29 54
      packages/timegrid/src/styles/_timegrid-event.scss
  45. 19 6
      packages/timegrid/src/styles/_timegrid-now-indicator.scss
  46. 71 0
      packages/timegrid/src/styles/_timegrid-slots.scss
  47. 4 136
      packages/timegrid/src/styles/_timegrid.scss
  48. 68 0
      packages/timegrid/src/styles/_v-event.scss
  49. 5 0
      packages/timegrid/src/styles/_vars.scss

+ 1 - 1
packages-premium

@@ -1 +1 @@
-Subproject commit 1e596f8973b21922d86c1e8d3d3fb8e703ddff93
+Subproject commit 260e1cf5fd2329c75aaa2057f2f2987ef905cba9

+ 1 - 1
packages/__tests__/src/lib/wrappers/CalendarWrapper.ts

@@ -63,7 +63,7 @@ export default class CalendarWrapper {
 
 
   getNonBusinessDayEls() {
-    return findElements(this.calendar.el, '.fc-nonbusiness')
+    return findElements(this.calendar.el, '.fc-non-business')
   }
 
 

+ 2 - 2
packages/__tests__/src/lib/wrappers/DayGridWrapper.ts

@@ -50,7 +50,7 @@ export default class DayGridWrapper {
 
   // TODO: discourage use
   getNonBusinessDayEls() {
-    return findElements(this.el, '.fc-nonbusiness')
+    return findElements(this.el, '.fc-non-business')
   }
 
 
@@ -77,7 +77,7 @@ export default class DayGridWrapper {
 
 
   getWeekNavLinkEls() {
-    return findElements(this.el, '.fc-daygrid-week-number a[data-navlink]')
+    return findElements(this.el, '.fc-daygrid-week-number[data-navlink]')
   }
 
 

+ 2 - 2
packages/__tests__/src/lib/wrappers/TimeGridWrapper.ts

@@ -66,7 +66,7 @@ export default class TimeGridWrapper {
 
 
   getNonBusinessDayEls() {
-    return findElements(this.el, '.fc-nonbusiness')
+    return findElements(this.el, '.fc-non-business')
   }
 
 
@@ -81,7 +81,7 @@ export default class TimeGridWrapper {
 
 
   queryNonBusinessSegsInCol(col) {
-    return findElements(this.getColEl(col), '.fc-nonbusiness')
+    return findElements(this.getColEl(col), '.fc-non-business')
   }
 
 

+ 1 - 0
packages/bootstrap/src/main.scss

@@ -26,6 +26,7 @@
 
 .fc .fc-bootstrap-bordered {
   background: transparent; // some themes provide background. undo
+  border-radius: 0; // some themes provide border-radius. undo
 }
 
 

+ 6 - 5
packages/core/src/ViewContainer.tsx

@@ -17,14 +17,15 @@ export interface ViewContainerProps {
 export default class ViewContainer extends BaseComponent<ViewContainerProps> {
 
   render(props: ViewContainerProps) {
-    let classNames = [ 'fc-view-harness' ]
+    let classNames = [
+      'fc-view-harness',
+      (props.aspectRatio || props.liquid || props.height)
+        ? 'fc-view-harness-active' // harness controls the height
+        : 'fc-view-harness-passive' // let the view do the height
+    ]
     let height: CssDimValue = ''
     let paddingBottom: CssDimValue = ''
 
-    if (props.aspectRatio || props.liquid || props.height) {
-      classNames.push('fc-view-harness-ratio')
-    }
-
     if (props.aspectRatio) {
       paddingBottom = (1 / props.aspectRatio) * 100 + '%'
     } else {

+ 2 - 2
packages/core/src/common/bg-fill.tsx

@@ -4,9 +4,9 @@ import { Seg } from '../component/DateComponent'
 import { EventMeta } from '../component/event-rendering'
 
 
-export function renderFill(fillType: string, extraClassNames: string[]) { // TODO: kill extraClassNames
+export function renderFill(fillType: string) {
   return (
-    <div class={[ `fc-${fillType}` ].concat(extraClassNames).join(' ')} />
+    <div class={`fc-${fillType}`} />
   )
 }
 

+ 12 - 6
packages/core/src/main.scss

@@ -1,16 +1,22 @@
 
 @import './styles/vars';
-@import './styles/resets';
-@import './styles/utils';
-@import './styles/event-common';
-@import './styles/event-horizontal';
+@import './styles/mixins';
+
+@import './styles/page-root';
+@import './styles/calendar-root';
+
 @import './styles/icons';
 @import './styles/button';
 @import './styles/button-group';
 @import './styles/toolbar';
-@import './styles/popover';
 @import './styles/scroller';
 @import './styles/scroller-harness';
 @import './styles/scrollgrid';
-@import './styles/view-structure';
+@import './styles/sticky';
+@import './styles/view-harness';
 @import './styles/col-header';
+@import './styles/divider';
+@import './styles/bg';
+@import './styles/event';
+@import './styles/h-event';
+@import './styles/dot';

+ 1 - 1
packages/core/src/structs/business-hours.ts

@@ -15,7 +15,7 @@ const DEF_DEFAULTS = {
   endTime: '17:00',
   daysOfWeek: [ 1, 2, 3, 4, 5 ], // monday - friday
   rendering: 'inverse-background',
-  classNames: 'fc-nonbusiness',
+  classNames: 'fc-non-business',
   groupId: '_businessHours' // so multiple defs get grouped
 }
 

+ 45 - 0
packages/core/src/styles/_bg.scss

@@ -0,0 +1,45 @@
+
+.fc-bg-event,
+.fc-non-business,
+.fc-highlight {
+  // will always have a harness with position:relative/absolute, so absolutely expand
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+
+  opacity: .3;
+}
+
+
+.fc-non-business {
+  background: #d7d7d7;
+}
+
+.fc-bg-event {
+  background: rgb(143, 223, 130);
+}
+
+.fc-highlight {
+  background: #bce8f1;
+}
+
+
+.fc-bg-event .fc-event-title {
+  margin: .5em;
+  font-size: .85em;
+  font-style: italic;
+}
+
+
+// today <td>
+// DIFFERENT SYSTEM, not within a shared container
+
+.fc-theme-standard {
+
+  .fc-day-today {
+    background: #fcf8e3; // TODO: use opacity? will be good for theme too
+  }
+
+}

+ 7 - 4
packages/core/src/styles/_button.scss

@@ -1,9 +1,12 @@
 
 /*
 Lots taken from Flatly (MIT): https://bootswatch.com/4/flatly/bootstrap.css
+
+These styles only apply when the standard-theme is activated.
+When it's NOT activated, the fc-button classes won't even be in the DOM.
 */
 
-/* reset */
+// reset
 
 .fc-button {
   border-radius: 0;
@@ -33,7 +36,7 @@ Lots taken from Flatly (MIT): https://bootswatch.com/4/flatly/bootstrap.css
   border-style: none;
 }
 
-/* theme */
+// theme
 
 .fc-button {
   display: inline-block;
@@ -68,7 +71,7 @@ Lots taken from Flatly (MIT): https://bootswatch.com/4/flatly/bootstrap.css
   opacity: 0.65;
 }
 
-/* "primary" coloring */
+// "primary" coloring
 
 .fc-button-primary {
   color: #fff;
@@ -106,7 +109,7 @@ Lots taken from Flatly (MIT): https://bootswatch.com/4/flatly/bootstrap.css
           box-shadow: 0 0 0 0.2rem rgba(76, 91, 106, 0.5);
 }
 
-/* icons within buttons */
+// icons within buttons
 
 .fc-button .fc-icon {
   vertical-align: middle;

+ 13 - 9
packages/core/src/styles/_resets.scss → packages/core/src/styles/_calendar-root.scss

@@ -2,6 +2,10 @@
 .fc {
   font-size: 1em;
 
+  // layout of immediate children
+  display: flex;
+  flex-direction: column;
+
   &,
   *,
   *:before,
@@ -19,17 +23,13 @@
   }
 
   th {
-    text-align: center;
+    text-align: center; // is this needed?
   }
 
   th, td {
     vertical-align: top;
   }
 
-
-  /* Internal Nav Links
-  --------------------------------------------------------------------------------------------------*/
-
   a[data-navlink] {
     cursor: pointer;
   }
@@ -57,11 +57,15 @@
 
 }
 
-
 .fc-media-print {
+  max-width: 100%;
+}
 
-  .fc {
-    max-width: 100% !important;
-  }
 
+// for FF, which doesn't expand a 100% div within a table cell. use absolute positioning
+// inner-wrappers are responsible for being absolute
+.fc-liquid-hack {
+  td, th {
+    position: relative;
+  }
 }

+ 1 - 1
packages/core/src/styles/_col-header.scss

@@ -1,4 +1,4 @@
 
-.fc .fc-col-header-cell {
+.fc .fc-col-header-cell { // extra precedence to OVERCOME RESET
   padding: 2px;
 }

+ 9 - 0
packages/core/src/styles/_divider.scss

@@ -0,0 +1,9 @@
+
+.fc-theme-standard {
+
+  .fc-divider {
+    background: $fc-theme-standard-muted-bg-color;
+    background: var(--fc-theme-standard-muted-bg-color, $fc-theme-standard-muted-bg-color);
+  }
+
+}

+ 8 - 0
packages/core/src/styles/_dot.scss

@@ -0,0 +1,8 @@
+
+.fc-dot {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  border-radius: 5px;
+  background-color: #3788d8; // TODO: var
+}

+ 0 - 151
packages/core/src/styles/_event-common.scss

@@ -1,151 +0,0 @@
-
-/* TODO
-.fc-not-start --> :not(.fc-event-start)
-.fc-not-end --> :not(.fc-event-end)
-*/
-
-
-.fc-bg-event,
-.fc-nonbusiness {
-  opacity: 0.3;
-}
-
-.fc-bg-event,
-.fc-nonbusiness,
-.fc-highlight {
-  // will always have a harness
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-}
-
-
-.fc-dot {
-  background-color: #3788d8; /* default BACKGROUND color */
-}
-
-
-// TODO: copy and paste to other event types
-// .fc-event {
-//   position: relative; /* for resize handle and other inner positioning */
-//   display: block; /* make the <a> tag block */
-//   font-size: .85em;
-//   line-height: 1.4;
-//   border-radius: 3px;
-//   border: 1px solid #3788d8;
-//   background-color: #3788d8;
-//   color: #fff; /* default TEXT color. TODO: test hovering over <a> when HREF and theme */
-//   text-decoration: none; /* if <a> has an href */
-// }
-
-
-
-.fc-event[href],
-.fc-event.fc-event-draggable {
-  cursor: pointer; /* give events with links and draggable events a hand mouse pointer */
-}
-
-.fc-not-allowed, /* causes a "warning" cursor. applied on body */
-.fc-not-allowed .fc-event { /* to override an event's custom cursor */
-  cursor: not-allowed;
-}
-
-
-/* resizer (cursor AND touch devices) */
-
-.fc-event .fc-event-resizer {
-  position: absolute;
-  z-index: 4;
-}
-
-/* resizer (touch devices) */
-
-.fc-event .fc-event-resizer {
-  display: none;
-}
-
-.fc-event-resizable-mouse .fc-event-resizer,
-.fc-event-selected .fc-event-resizer {
-  /* only show when hovering or selected (with touch) */
-  display: block;
-}
-
-/* hit area */
-
-.fc-event-selected .fc-event-resizer:before {
-  /* 40x40 touch area */
-  content: "";
-  position: absolute;
-  z-index: 9999; /* user of this util can scope within a lower z-index */
-  top: 50%;
-  left: 50%;
-  width: 40px;
-  height: 40px;
-  margin-left: -20px;
-  margin-top: -20px;
-}
-
-
-/* Event Selection (only for touch devices)
---------------------------------------------------------------------------------------------------*/
-
-.fc-event-selected {
-  z-index: 9999 !important; /* overcomes inline z-index */
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
-}
-
-.fc-event-selected:after {
-  content: "";
-  position: absolute;
-  z-index: 1; /* same z-index as fc-bg, behind text */
-  /* overcome the borders */
-  top: -1px;
-  right: -1px;
-  bottom: -1px;
-  left: -1px;
-  /* darkening effect */
-  background: #000;
-  opacity: .25;
-}
-
-
-/* Event Dragging
---------------------------------------------------------------------------------------------------*/
-
-.fc-event-dragging.fc-event-selected {
-  box-shadow: 0 2px 7px rgba(0, 0, 0, 0.3);
-}
-
-.fc-event-dragging:not(.fc-event-selected) {
-  opacity: .75;
-}
-
-
-/* BG events
---------------------------------------------------------------------------------------------------*/
-
-.fc-bg-event .fc-event-title {
-  margin: .5em;
-  font-size: .85em;
-  font-style: italic;
-}
-
-
-/* For Print
---------------------------------------------------------------------------------------------------*/
-
-.fc-media-print {
-
-  .fc-event {
-    background: #fff !important;
-    color: #000 !important;
-    page-break-inside: avoid;
-  }
-
-  .fc-event .fc-event-resizer {
-    display: none;
-  }
-
-}

+ 0 - 124
packages/core/src/styles/_event-horizontal.scss

@@ -1,124 +0,0 @@
-
-/*
-this class is used for:
-- left/right resizers (esp for touch)
-  - hiding/showing --- used .fc-event-resizer general class for this
-      based on .fc-event-selected/.fc-event-allow-mouse-resize
-  - the dot --- use a subclass of the subcomponent for this like fc-event-resizer-dot
-- edges for start/end  ---- implement separately for each event type
-- vertically expand the touch area when it's selected --- use mixin
-*/
-
-/* bigger touch area when selected */
-.fc-h-event.fc-event-selected:before {
-  content: "";
-  position: absolute;
-  z-index: 3; /* below resizers */
-  top: -10px;
-  bottom: -10px;
-  left: 0;
-  right: 0;
-}
-
-
-.fc-h-event {
-  position: relative; /* for resize handle and other inner positioning */
-  display: block; /* make the <a> tag block */
-  font-size: .85em;
-  line-height: 1.4;
-  border: 1px solid #3788d8;
-  background-color: #3788d8;
-  color: #fff; /* default TEXT color. TODO: test hovering over <a> when HREF and theme */
-  text-decoration: none; /* if <a> has an href */
-}
-
-
-.fc-h-event .fc-event-time,
-.fc-h-event .fc-event-title {
-  display: inline;
-}
-
-.fc-h-event .fc-event-time {
-  font-weight: bold;
-}
-
-.fc-dir-ltr .fc-h-event .fc-event-time {
-  margin-right: 2px;
-}
-
-.fc-dir-rtl .fc-h-event .fc-event-time {
-  margin-left: 2px;
-}
-
-
-/* events that are continuing to/from another week. kill rounded corners and butt up against edge */
-
-.fc-dir-ltr .fc-h-event:not(.fc-event-start),
-.fc-dir-rtl .fc-h-event:not(.fc-event-end) {
-  margin-left: 0;
-  border-left-width: 0;
-  padding-left: 1px; /* replace the border with padding */
-  border-top-left-radius: 0;
-  border-bottom-left-radius: 0;
-}
-
-.fc-dir-ltr .fc-h-event:not(.fc-event-end),
-.fc-dir-rtl .fc-h-event:not(.fc-event-start) {
-  margin-right: 0;
-  border-right-width: 0;
-  padding-right: 1px; /* replace the border with padding */
-  border-top-right-radius: 0;
-  border-bottom-right-radius: 0;
-}
-
-/* resizer (cursor AND touch devices) */
-
-/* left resizer  */
-.fc-dir-ltr .fc-h-event .fc-event-resizer-start,
-.fc-dir-rtl .fc-h-event .fc-event-resizer-end {
-  cursor: w-resize;
-  left: -1px; /* overcome border */
-}
-
-/* right resizer */
-.fc-dir-ltr .fc-h-event .fc-event-resizer-end,
-.fc-dir-rtl .fc-h-event .fc-event-resizer-start {
-  cursor: e-resize;
-  right: -1px; /* overcome border */
-}
-
-/* resizer (mouse devices) */
-
-.fc-h-event.fc-event-resizable-mouse .fc-event-resizer {
-  width: 7px;
-  top: -1px; /* overcome top border */
-  bottom: -1px; /* overcome bottom border */
-}
-
-/* resizer (touch devices) */
-
-.fc-h-event.fc-event-selected .fc-event-resizer {
-  /* 8x8 little dot */
-  border-radius: 4px;
-  border-width: 1px;
-  width: 6px;
-  height: 6px;
-  border-style: solid;
-  border-color: inherit;
-  background: #fff;
-  /* vertically center */
-  top: 50%;
-  margin-top: -4px;
-}
-
-/* left resizer  */
-.fc-dir-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,
-.fc-dir-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end {
-  margin-left: -4px; /* centers the 8x8 dot on the left edge */
-}
-
-/* right resizer */
-.fc-dir-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,
-.fc-dir-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start {
-  margin-right: -4px; /* centers the 8x8 dot on the right edge */
-}

+ 104 - 0
packages/core/src/styles/_event.scss

@@ -0,0 +1,104 @@
+
+// link resets
+a.fc-event {
+  display: block;
+  text-decoration: none;
+}
+
+// cursor
+.fc-event[href],
+.fc-event.fc-event-draggable {
+  cursor: pointer;
+}
+
+// print tweaks
+.fc-media-print {
+  .fc-event {
+    page-break-inside: avoid;
+  }
+}
+
+
+// mirror
+// ----------------------------------------------------------------------------------------------------
+
+.fc-event-mirror {
+  z-index: 9999; // always above everything else
+}
+
+
+// dragging
+// ----------------------------------------------------------------------------------------------------
+
+.fc-event-dragging:not(.fc-event-selected) { // MOUSE
+  opacity: .75;
+}
+
+.fc-event-dragging.fc-event-selected { // TOUCH
+  box-shadow: 0 2px 7px rgba(0, 0, 0, 0.3);
+}
+
+
+// resizing
+// ----------------------------------------------------------------------------------------------------
+
+.fc-event .fc-event-resizer {
+  display: none;
+}
+
+.fc-event-resizable-mouse .fc-event-resizer, // MOUSE
+.fc-event-selected .fc-event-resizer { // TOUCH
+  display: block;
+}
+
+.fc-media-print {
+  .fc-event-resizer {
+    display: none;
+  }
+}
+
+
+// selecting (with TOUCH)
+// ----------------------------------------------------------------------------------------------------
+
+// expand main hit area
+// event subclasses should expand it!
+// always use :before
+.fc-event-selected:before {
+  content: "";
+  position: absolute;
+  top: -1px; // overcome border
+  left: -1px; // overcome border
+  right: -1px; // overcome border
+  bottom: -1px; // overcome border
+}
+
+// expand resizer hit area
+.fc-event-selected .fc-event-resizer:before {
+  content: "";
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 40px;
+  height: 40px;
+  margin-left: -20px;
+  margin-top: -20px;
+}
+
+// drop-shadow effect
+.fc-event-selected {
+  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
+}
+
+// background dimmer effect
+.fc-event-selected:after {
+  content: "";
+  position: absolute;
+  z-index: $event-dimmer-z;
+  top: -1px; // overcome border
+  left: -1px; // overcome border
+  right: -1px; // overcome border
+  bottom: -1px; // overcome border
+  background: #000;
+  opacity: .25;
+}

+ 74 - 0
packages/core/src/styles/_h-event.scss

@@ -0,0 +1,74 @@
+
+/*
+A HORIZONTAL event
+*/
+
+
+.fc-h-event .fc-event-main {
+  position: relative; // specifically for the z-index
+  z-index: $event-main-z;
+}
+
+
+// resizer (mouse AND touch)
+
+.fc-h-event .fc-event-resizer {
+  position: absolute;
+  z-index: $event-resizer-z;
+}
+
+.fc-dir-ltr .fc-h-event .fc-event-resizer-start,
+.fc-dir-rtl .fc-h-event .fc-event-resizer-end {
+  cursor: w-resize;
+}
+
+.fc-dir-ltr .fc-h-event .fc-event-resizer-end,
+.fc-dir-rtl .fc-h-event .fc-event-resizer-start {
+  cursor: e-resize;
+}
+
+
+// resizer for MOUSE
+
+.fc-h-event.fc-event-resizable-mouse .fc-event-resizer {
+  width: $event-resizer-mouse-width;
+  top: -1px; // overcome border
+  bottom: -1px; // overcome border
+}
+
+.fc-dir-ltr .fc-h-event.fc-event-resizable-mouse .fc-event-resizer-start,
+.fc-dir-rtl .fc-h-event.fc-event-resizable-mouse .fc-event-resizer-end {
+  left: -($event-resizer-mouse-width / 2);
+}
+
+.fc-dir-ltr .fc-h-event.fc-event-resizable-mouse .fc-event-resizer-end,
+.fc-dir-rtl .fc-h-event.fc-event-resizable-mouse .fc-event-resizer-start {
+  right: -($event-resizer-mouse-width / 2);
+}
+
+
+// resizer for TOUCH (when event is "selected")
+
+.fc-h-event.fc-event-selected .fc-event-resizer {
+  @include event-resizer-dot;
+  top: 50%;
+  margin-top: -($event-resizer-dot-total-width / 2);
+}
+
+.fc-dir-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,
+.fc-dir-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end {
+  left: -($event-resizer-dot-total-width / 2);
+}
+
+.fc-dir-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,
+.fc-dir-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start {
+  right: -($event-resizer-dot-total-width / 2);
+}
+
+
+// expand touch area for TOUCH (when event is "selected")
+
+.fc-h-event.fc-event-selected:before {
+  top: -10px;
+  bottom: -10px;
+}

+ 23 - 1
packages/core/src/styles/_mixins.scss

@@ -1,5 +1,5 @@
 
-@mixin liquid-hack-cell-inner {
+@mixin liquid-absolute-override {
   height: auto;
   position: absolute;
   top: 0;
@@ -7,3 +7,25 @@
   bottom: 0;
   left: 0;
 }
+
+@mixin event-resizer-dot {
+  border-radius: $event-resizer-dot-total-width / 2;
+  border-width: $event-resizer-dot-border-width;
+  width: $event-resizer-dot-total-width;
+  height: $event-resizer-dot-total-width;
+  border-style: solid;
+  border-color: inherit;
+  background: #fff;
+}
+
+@mixin clearfix {
+  content: "";
+  clear: both;
+  display: table;
+}
+
+@mixin bg-z-indexes {
+  .fc-non-business { z-index: 1 }
+  .fc-bg-event { z-index: 2 }
+  .fc-highlight { z-index: 3 }
+}

+ 17 - 0
packages/core/src/styles/_page-root.scss

@@ -0,0 +1,17 @@
+
+// classes attached to <body>
+
+.fc-not-allowed,
+.fc-not-allowed .fc-event { // override events' custom cursors
+  cursor: not-allowed;
+}
+
+.fc-unselectable {
+  -webkit-user-select: none;
+   -khtml-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}

+ 4 - 2
packages/core/src/styles/_scroller-harness.scss

@@ -2,13 +2,15 @@
 .fc-scroller-harness {
   position: relative;
   overflow: hidden;
-  direction: ltr; // hack for chrome doing the scroller's right/left wrong for rtl. undone below...
+  direction: ltr;
+    // hack for chrome computing the scroller's right/left wrong for rtl. undone below...
+    // TODO: demonstrate in codepen
 }
 
 .fc-scroller-harness-liquid {
   height: 100%;
 }
 
-.fc-dir-rtl .fc-scroller-harness > .fc-scroller { // undo hack
+.fc-dir-rtl .fc-scroller-harness > .fc-scroller { // undo above hack
   direction: rtl;
 }

+ 0 - 11
packages/core/src/styles/_scroller.scss

@@ -15,14 +15,3 @@
   left: 0;
   bottom: 0;
 }
-
-
-.fc-media-print {
-
-  /* kill the scrollbars and allow natural height */
-  .fc-scroller {
-    overflow: visible !important;
-    height: auto !important;
-  }
-
-}

+ 13 - 39
packages/core/src/styles/_scrollgrid.scss

@@ -15,10 +15,15 @@
   }
 }
 
-.fc-scrollgrid-liquid {
-  height: 100% !important;
+.fc-media-print {
+  .fc-scrollgrid {
+    table-layout: auto;
+  }
 }
 
+.fc-scrollgrid-liquid {
+  height: 100%;
+}
 
 .fc-scrollgrid-section { // a <tr>
   height: 0;
@@ -26,6 +31,12 @@
   > td {
     height: 0; // needs a height so inner div within grow
   }
+
+  table {
+    height: 1px;
+      // for most browsers, if a height isn't set on the table, can't do liquid-height within cells
+      // serves as a min-height. harmless
+  }
 }
 
 .fc-scrollgrid-section-liquid {
@@ -35,40 +46,3 @@
     height: 100%; // FF needs this instead of auto
   }
 }
-
-
-
-.fc-sticky {
-  position: -webkit-sticky;
-  position: sticky;
-}
-
-
-.fc-media-print {
-
-  .fc-scrollgrid {
-    table-layout: auto;
-
-    .fc-sticky { // TODO: do this more generally
-      top: 0 !important;
-      right: 0 !important;
-      left: 0 !important;
-      bottom: 0 !important;
-    }
-  }
-
-}
-
-
-// for FF, which doesn't expand a 100% div within a table cell. use absolute positioning
-// inner-wrappers are responsible for being absolute
-.fc-liquid-hack {
-  td, th {
-    position: relative;
-  }
-}
-
-// for most browsers, if a height isn't set on the table, can't do liquid-height within cells
-.fc-scrollgrid-section table {
-  height: 1px; // serves as a min-height. harmless
-}

+ 9 - 0
packages/core/src/styles/_sticky.scss

@@ -0,0 +1,9 @@
+
+.fc-media-screen {
+
+  .fc-sticky {
+    position: -webkit-sticky;
+    position: sticky;
+  }
+
+}

+ 2 - 17
packages/core/src/styles/_toolbar.scss

@@ -5,7 +5,7 @@
   align-items: center;
 }
 
-.fc-dir-rtl .fc-toolbar-ltr {
+.fc-dir-rtl .fc-toolbar-ltr { // when the toolbar-chunk positioning system is explicitly left-to-right
   flex-direction: row-reverse;
 }
 
@@ -17,34 +17,19 @@
   margin-top: 1.5em;
 }
 
-.fc-toolbar h2 {
+.fc-toolbar-title {
   font-size: 1.75em;
   margin: 0;
 }
 
 .fc-dir-ltr {
-
   .fc-toolbar > * > :not(:first-child) {
     margin-left: .75em; // space between
   }
-
 }
 
 .fc-dir-rtl {
-
   .fc-toolbar > * > :not(:first-child) {
     margin-right: .75em; // space between
   }
-
-}
-
-.fc-media-print {
-
-  // don't display any button-related controls
-  // TODO: better to put in _button/_button-group.scss ?
-  .fc-button-group,
-  button {
-    display: none;
-  }
-
 }

+ 0 - 49
packages/core/src/styles/_utils.scss

@@ -1,49 +0,0 @@
-
-.fc-highlight { /* when user is selecting cells */
-  background: #bce8f1;
-  opacity: .3;
-}
-
-.fc-bg-event { /* default look for background events */
-  background: rgb(143, 223, 130);
-  opacity: .3;
-}
-
-.fc-nonbusiness { /* default look for non-business-hours areas */
-  /* will inherit .fc-bg-event's styles */
-  background: #d7d7d7;
-}
-
-.fc-now-indicator {
-  position: absolute;
-  border: 0 solid red;
-}
-
-.fc-unselectable {
-  -webkit-user-select: none;
-   -khtml-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-}
-
-
-.fc-theme-standard {
-
-  .fc-day-today {
-    background: #fcf8e3;
-  }
-
-  .fc-disabled-day {
-    background: #d7d7d7;
-    opacity: .3;
-  }
-
-  .fc-divider {
-    background: $fc-theme-standard-muted-bg-color;
-    background: var(--fc-theme-standard-muted-bg-color, $fc-theme-standard-muted-bg-color);
-  }
-
-}

+ 11 - 0
packages/core/src/styles/_vars.scss

@@ -1,3 +1,14 @@
 
 $fc-theme-standard-border-color: #ddd;
 $fc-theme-standard-muted-bg-color: #eee;
+
+$event-resizer-dot-total-width: 8px;
+$event-resizer-dot-border-width: 1px;
+
+$event-resizer-mouse-width: 8px; // rename to thickness
+
+$event-dimmer-z: 1;
+$event-main-z: 2;
+$event-resizer-z: 3;
+
+$now-indicator-color: red;

+ 14 - 0
packages/core/src/styles/_view-harness.scss

@@ -0,0 +1,14 @@
+
+.fc-view-harness {
+  flex-grow: 1; // because this harness is WITHIN the .fc's flexbox
+  position: relative;
+}
+
+// when the harness controls the height, make the view liquid
+.fc-view-harness-active > .fc-view {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}

+ 0 - 31
packages/core/src/styles/_view-structure.scss

@@ -1,31 +0,0 @@
-
-.fc {
-  display: flex;
-  flex-direction: column;
-}
-
-.fc-view-harness {
-  flex-grow: 1;
-  position: relative;
-
-  display: flex;
-  flex-direction: column;
-
-  > * {
-    flex-grow: 1;
-  }
-}
-
-.fc-view-harness-ratio > .fc-view {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-}
-
-.fc-view, /* scope positioning and z-index's for everything within the view */
-.fc-view > table { /* so dragged elements can be above the view's main element */
-  position: relative;
-  z-index: 1;
-}

+ 0 - 1
packages/daygrid/src/MorePopover.tsx

@@ -50,7 +50,6 @@ export default class MorePopover extends DateComponent<MorePopoverProps> {
 
               return (
                 <div
-                  class='fc-daygrid-event-harness'
                   key={instanceId}
                   style={{
                     visibility: hiddenInstances[instanceId] ? 'hidden' : ''

+ 37 - 35
packages/daygrid/src/TableCell.tsx

@@ -26,7 +26,7 @@ export interface TableCellProps extends TableCellModel {
   elRef?: Ref<HTMLTableCellElement>
   innerElRef?: Ref<HTMLDivElement>
   bgContent: ComponentChildren
-  fgContentElRef?: Ref<HTMLDivElement>
+  fgContentElRef?: Ref<HTMLDivElement> // TODO: rename!!! classname confusion. is the "event" div
   fgContent: ComponentChildren
   fgPaddingBottom: CssDimValue
   hasEvents: boolean // TODO: do something with this
@@ -96,43 +96,45 @@ export default class TableCell extends DateComponent<TableCellProps> {
                 {props.showWeekNumber &&
                   <WeekNumberRoot date={date} defaultFormat={DEFAULT_WEEK_NUM_FORMAT}>
                     {(rootElRef, classNames, innerElRef, innerContent) => (
-                      <div class={[ 'fc-daygrid-week-number' ].concat(classNames).join(' ')} ref={rootElRef}>
-                        <a ref={innerElRef}
-                          data-navlink={options.navLinks ? buildNavLinkData(date, 'week') : null}
-                        >
-                          {innerContent}
-                        </a>
-                      </div>
+                      <a
+                        ref={rootElRef}
+                        class={[ 'fc-daygrid-week-number' ].concat(classNames).join(' ')}
+                        data-navlink={options.navLinks ? buildNavLinkData(date, 'week') : null}
+                      >
+                        {innerContent}
+                      </a>
                     )}
                   </WeekNumberRoot>
                 }
-                <TableCellTop
-                  date={date}
-                  showDayNumber={props.showDayNumber}
-                  dateProfile={props.dateProfile}
-                  todayRange={props.todayRange}
-                  extraHookProps={props.extraHookProps}
-                />
-                <div
-                  class='fc-daygrid-day-events'
-                  ref={props.fgContentElRef}
-                  style={{ paddingBottom: props.fgPaddingBottom }}
-                >
-                  {props.fgContent}
-                  {Boolean(props.moreCnt) &&
-                    <div class='fc-daygrid-day-bottom' style={{ marginTop: props.moreMarginTop }}>
-                      <RenderHook name='moreLink'
-                        hookProps={{ num: props.moreCnt, text: props.buildMoreLinkText(props.moreCnt), view: context.view }}
-                        defaultContent={renderMoreLinkInner}
-                      >
-                        {(rootElRef, classNames, innerElRef, innerContent) => (
-                          <a onClick={this.handleMoreLink} ref={rootElRef} className={[ 'fc-daygrid-more-link' ].concat(classNames).join(' ')}>
-                            {innerContent}
-                          </a>
-                        )}
-                      </RenderHook>
-                    </div>
-                  }
+                <div class='fc-daygrid-day-fg'>
+                  <TableCellTop
+                    date={date}
+                    showDayNumber={props.showDayNumber}
+                    dateProfile={props.dateProfile}
+                    todayRange={props.todayRange}
+                    extraHookProps={props.extraHookProps}
+                  />
+                  <div
+                    class='fc-daygrid-day-events'
+                    ref={props.fgContentElRef}
+                    style={{ paddingBottom: props.fgPaddingBottom }}
+                  >
+                    {props.fgContent}
+                    {Boolean(props.moreCnt) &&
+                      <div class='fc-daygrid-day-bottom' style={{ marginTop: props.moreMarginTop }}>
+                        <RenderHook name='moreLink'
+                          hookProps={{ num: props.moreCnt, text: props.buildMoreLinkText(props.moreCnt), view: context.view }}
+                          defaultContent={renderMoreLinkInner}
+                        >
+                          {(rootElRef, classNames, innerElRef, innerContent) => (
+                            <a onClick={this.handleMoreLink} ref={rootElRef} className={[ 'fc-daygrid-more-link' ].concat(classNames).join(' ')}>
+                              {innerContent}
+                            </a>
+                          )}
+                        </RenderHook>
+                      </div>
+                    }
+                  </div>
                 </div>
                 <div class='fc-daygrid-day-bg'>
                   {props.bgContent}

+ 22 - 17
packages/daygrid/src/TableRow.tsx

@@ -4,7 +4,6 @@ import {
   DateComponent,
   h,
   PositionCache,
-  isPropsEqual,
   RefMap,
   mapHash,
   CssDimValue,
@@ -44,7 +43,6 @@ export interface TableRowProps {
   showDayNumbers: boolean
   showWeekNumbers: boolean
   buildMoreLinkText: (num: number) => string
-  innerHeight?: number
 }
 
 interface TableRowState {
@@ -140,8 +138,8 @@ export default class TableRow extends DateComponent<TableRowProps, TableRowState
               ]}
               bgContent={[
                 <Fragment>{this.renderFillSegs(highlightSegsByCol[col], 'highlight')}</Fragment>, // Fragment scopes the keys
-                <Fragment>{this.renderFillSegs(businessHoursByCol[col], 'nonbusiness')}</Fragment>,
-                <Fragment>{this.renderFillSegs(bgEventSegsByCol[col], 'bgevent')}</Fragment>
+                <Fragment>{this.renderFillSegs(businessHoursByCol[col], 'non-business')}</Fragment>,
+                <Fragment>{this.renderFillSegs(bgEventSegsByCol[col], 'bg-event')}</Fragment>
               ]}
             />
           )
@@ -157,8 +155,18 @@ export default class TableRow extends DateComponent<TableRowProps, TableRowState
 
 
   componentDidUpdate(prevProps: TableRowProps, prevState: TableRowState) {
+    let currentProps = this.props
+
     this.updateSizing(
-      !isPropsEqual(prevProps, this.props),
+      // any props changes that could affect sizing
+      // HACKY. fix to prevent moreLink from unmounting during event drag
+      prevProps.cells !== currentProps.cells ||
+        prevProps.fgEventSegs !== currentProps.fgEventSegs ||
+        prevProps.dayMaxEvents !== currentProps.dayMaxEvents ||
+        prevProps.dayMaxEventRows !== currentProps.dayMaxEventRows ||
+        prevProps.clientWidth !== currentProps.clientWidth ||
+        prevProps.showDayNumbers !== currentProps.showDayNumbers ||
+        prevProps.showWeekNumbers !== currentProps.showWeekNumbers,
       prevState.cellContentPositions !== this.state.cellContentPositions
     )
   }
@@ -279,10 +287,10 @@ export default class TableRow extends DateComponent<TableRowProps, TableRowState
       for (let seg of segs) {
 
         let leftRightCss = isRtl ? {
-          right: '',
+          right: 0,
           left: cellInnerPositions.lefts[seg.lastCol] - cellInnerPositions.lefts[seg.firstCol]
         } : {
-          left: '',
+          left: 0,
           right: cellInnerPositions.rights[seg.firstCol] - cellInnerPositions.rights[seg.lastCol],
         }
 
@@ -293,13 +301,13 @@ export default class TableRow extends DateComponent<TableRowProps, TableRowState
 
         nodes.push(
           <div class='fc-daygrid-bg-harness' style={leftRightCss}>
-            {fillType === 'bgevent' ?
+            {fillType === 'bg-event' ?
               <BgEvent
                 key={key}
                 seg={seg}
                 {...getSegMeta(seg, todayRange)}
               /> :
-              renderFill(fillType, [ `fc-daygrid-${fillType}` ])
+              renderFill(fillType)
             }
           </div>
         )
@@ -310,9 +318,9 @@ export default class TableRow extends DateComponent<TableRowProps, TableRowState
   }
 
 
-  updateSizing(isExternalChange, isHorizontalChange) {
+  updateSizing(isExternalSizingChange, isCellPositionsChanged) {
     if (
-      isExternalChange &&
+      isExternalSizingChange &&
       this.props.clientWidth !== null // positioning ready?
     ) {
       let cellInnerEls = this.cellInnerElRefs.collect()
@@ -321,7 +329,7 @@ export default class TableRow extends DateComponent<TableRowProps, TableRowState
       if (cellContentEls.length) {
         let originEl = this.base as HTMLElement // BAD
 
-        this.setState({ // will trigger isHorizontalChange...
+        this.setState({ // will trigger isCellPositionsChanged...
           cellInnerPositions: new PositionCache(
             originEl,
             cellInnerEls,
@@ -338,7 +346,7 @@ export default class TableRow extends DateComponent<TableRowProps, TableRowState
         })
       }
 
-    } else if (isHorizontalChange) {
+    } else if (isCellPositionsChanged) {
       let segHeights = mapHash(this.segHarnessRefs.currentMap, (eventHarnessEl) => (
         eventHarnessEl.getBoundingClientRect().height
       ))
@@ -353,10 +361,7 @@ export default class TableRow extends DateComponent<TableRowProps, TableRowState
 
   computeMaxContentHeight() {
     let contentEl = this.cellContentElRefs.currentMap[0]
-    let cellEl = this.cellElRefs.currentMap[0]
-
-    // contentEl guaranteed not to have bottom margin
-    return cellEl.getBoundingClientRect().bottom - contentEl.getBoundingClientRect().top
+    return contentEl.getBoundingClientRect().height
   }
 
 }

+ 4 - 0
packages/daygrid/src/main.scss

@@ -1,3 +1,7 @@
 
+@import '../../core/src/styles/vars';
+@import '../../core/src/styles/mixins';
+
+@import './styles/popover';
 @import './styles/daygrid';
 @import './styles/daygrid-event';

+ 46 - 10
packages/daygrid/src/styles/_daygrid-event.scss

@@ -1,17 +1,53 @@
 
-.fc-daygrid-event-harness { // dont do margins either!!!
-  padding-bottom: 2px;
-  // margin-top: 0 !important; // was overriding JS :(
+.fc-daygrid-event {
+  position: relative;
+  white-space: nowrap;
+  margin-bottom: 1px; // spacing between events
+
+  // vars for all of this...
+  font-size: .85em;
+  border: 1px solid #3788d8;
+  background-color: #3788d8;
+  color: #fff;
+  border-radius: 3px;
+
+  .fc-event-main {
+    padding: 1px;
+    overflow: hidden;
+  }
+
+  .fc-event-time,
+  .fc-event-title {
+    display: inline;
+  }
+
+  .fc-event-time {
+    font-weight: bold;
+  }
 }
 
-.fc-daygrid-event-harness-abs {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
+
+// spacing between time and title
+
+.fc-dir-ltr .fc-daygrid-event .fc-event-time {
+  margin-right: 3px; // TODO: var
 }
 
+.fc-dir-rtl .fc-daygrid-event .fc-event-time {
+  margin-left: 3px; // TODO: var
+}
 
-.fc-daygrid-event {
-  border-radius: 3px;
+
+// kill radius when event continues into future/past
+
+.fc-dir-ltr .fc-daygrid-event:not(.fc-event-start),
+.fc-dir-rtl .fc-daygrid-event:not(.fc-event-end) {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.fc-dir-ltr .fc-daygrid-event:not(.fc-event-end),
+.fc-dir-rtl .fc-daygrid-event:not(.fc-event-start) {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
 }

+ 117 - 55
packages/daygrid/src/styles/_daygrid.scss

@@ -1,114 +1,176 @@
 
-.fc-daygrid-body {
+$daygrid-top-z: 4; // one more than .fc-highlight's z-inde
+$daygrid-week-num-z: 5;
+$daygrid-fg-event-z: 6;
+$daygrid-popover-z: 7;
+
+
+.fc-daygrid-body { // a <div> that wraps the table
   position: relative;
-  z-index: 1;
+  z-index: 1; // container inner z-index's because <tr>s can't do it
 }
 
+.fc-daygrid-day {
+  height: 1px; // IE and FF need a non-zero height assigned to the <td> so that the inner flexboxes don't confuse it
+}
+
+
+// cell inner-wrappers
+
 .fc-daygrid-day-frame {
   position: relative;
-  min-height: 100%; // works better than height:100% for some reason
-  padding-top: 4px;
+  min-height: 100%; // more optimal than height
 }
 
 .fc-liquid-hack .fc-daygrid-day-frame {
-  position: static;
+  position: static; // will cause inner absolute stuff to expand to <td>
 }
 
-.fc-daygrid-day-top {
-  padding: 0 4px 4px;
-  text-align: right;
+
+// flexbox wrapper for day-top and day-events
+
+.fc-daygrid-day-fg {
+  display: flex;
+  flex-direction: column;
 }
 
-.fc-daygrid-day-events:before {
-  content: "";
-  clear: both;
-  display: table;
+.fc-daygrid-body-balanced { // for when all row heights are equal
+  .fc-daygrid-day-fg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0; // TODO: make a mixin for all this
+  }
 }
 
-.fc-daygrid-day-events {
-  margin: 0 4px;
-  margin-bottom: 0 !important; // put bottom padding on fc-daygrid-day-frame instead
+
+// cell top
+
+.fc-daygrid-day-top {
   position: relative;
-  min-height: 3em;
+  z-index: $daygrid-top-z;
+  flex-shrink: 0;
 }
 
-.fc-daygrid-body-balanced .fc-daygrid-day-events {
-  position: absolute;
-  left: 0;
-  right: 0;
-  min-height: 0;
+.fc-day-other .fc-daygrid-day-top {
+  opacity: 0.3;
 }
 
-.fc-daygrid-bg-harness {
-  position: absolute;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
+
+// day number (within cell top)
+
+.fc-daygrid-day-number {
+  padding: 4px; // TODO: variable
 }
 
-.fc-daygrid-bgevent { z-index: 1 }
-.fc-daygrid-nonbusiness { z-index: 2 }
-.fc-daygrid-highlight { z-index: 3 }
+.fc-dir-ltr .fc-daygrid-day-number {
+  float: right;
+}
 
-.fc-daygrid-event {
-  position: relative;
-  z-index: 4;
+.fc-dir-rtl .fc-daygrid-day-number {
+  float: left;
 }
 
-.fc-daygrid-event.fc-event-mirror {
-  position: relative;
-  z-index: 5;
+
+// fg events
+
+.fc-daygrid-day-events {
+  flex-grow: 1;
+  position: relative; // for absolutely positioning event-harnesses
+  min-height: 2em;
+  margin: 0 2px 1em; // want bottom margin to allow space for selecting
+
+  &:first-child { // only add top margin if no fc-daygrid-day-top
+    margin-top: 2px;
+  }
 }
 
-.fc-daygrid-day-top {
+.fc-daygrid-body-balanced { // for when all row heights are equal
+  .fc-daygrid-day-events {
+    min-height: 0;
+    margin-bottom: 0; // don't need margin-bottom because there's space around the more link for selecting
+  }
+}
+
+
+// fg event harness
+
+.fc-daygrid-event-harness {
   position: relative;
-  z-index: 4;
+  z-index: $daygrid-fg-event-z;
+
+  &:after {
+    @include clearfix; // for when event element has bottom margin
+  }
 }
 
+.fc-daygrid-event-harness-abs {
+  position: absolute;
+  top: 0; // fallback
+  left: 0; // fallback
+  right: 0; // fallback
+}
+
+
+// cell bottom (within day-events)
+
 .fc-daygrid-day-bottom {
-  position: relative;
-  z-index: 4;
   font-size: .85em;
 }
 
-.fc-daygrid-more-link { // TODO: dont put here
+.fc-daygrid-more-link {
+  position: relative;
+  z-index: $daygrid-fg-event-z; // treat as an event
   cursor: pointer;
 }
 
 
+// bg content (within frame)
 
-
-.fc-daygrid .fc-popover {
-  z-index: 6;
+.fc-daygrid-day-bg {
+  @include bg-z-indexes;
 }
 
-.fc-more-popover .fc-popover-body {
-  padding: 10px;
-  min-width: 220px;
+.fc-daygrid-bg-harness {
+  position: absolute;
+  top: 0;
+  bottom: 0;
 }
 
 
+// week number (within frame)
+// TODO: maybe we should move it within day-top
+
 .fc-daygrid-week-number {
-  position: relative;
-  z-index: 5; // above fc-daygrid-day-top
+  position: absolute;
+  z-index: $daygrid-week-num-z;
+  top: 0;
   padding: 2px;
   min-width: 1.5em;
   text-align: center;
-  background-color: #f2f2f2;
-  color: #808080;
+  background-color: #f2f2f2; // TODO: var
+  color: #808080; // TODO: var
 }
 
 .fc-dir-ltr .fc-daygrid-week-number {
-  float: left;
+  left: 0;
   border-radius: 0 0 3px 0;
 }
 
 .fc-dir-rtl .fc-daygrid-week-number {
-  float: right;
+  right: 0;
   border-radius: 0 0 0 3px;
 }
 
-.fc-day-other .fc-daygrid-day-top {
-  opacity: 0.3;
+
+// popover
+
+.fc-daygrid .fc-popover {
+  z-index: $daygrid-popover-z;
+}
+
+.fc-more-popover .fc-popover-body {
+  padding: 10px !important; // OVERCOME BOOTSTRAP
+  min-width: 220px;
 }

+ 3 - 7
packages/core/src/styles/_popover.scss → packages/daygrid/src/styles/_popover.scss

@@ -1,6 +1,6 @@
 
 .fc-popover {
-  position: fixed !important; // override bootstrap!
+  position: fixed !important; // OVERCOME BOOTSTRAP
   top: 0; // for when not positioned yet
   box-shadow: 0 2px 6px rgba(0,0,0,.15);
 }
@@ -10,7 +10,7 @@
   flex-direction: row;
   justify-content: space-between;
   align-items: center;
-  padding: 2px 4px;
+  padding: 3px 4px !important; // OVERCOME BOOTSTRAP
 }
 
 .fc-dir-rtl .fc-popover-header {
@@ -27,7 +27,6 @@
   font-size: 1.1em;
 }
 
-
 .fc-theme-standard {
 
   .fc-popover {
@@ -43,11 +42,8 @@
 
 }
 
-
 .fc-media-print {
-
   .fc-popover {
-    display: none; /* never display the "more.." popover in print mode */
+    display: none; // TODO: have JS close the popovers onbeforeprint?
   }
-
 }

+ 3 - 1
packages/list/src/ListView.tsx

@@ -89,7 +89,9 @@ export default class ListView extends DateComponent<ViewProps> {
       <RenderHook name='noEvents' hookProps={hookProps} defaultContent={renderNoEventsInner}>
         {(rootElRef, classNames, innerElRef, innerContent) => (
           <div className={[ 'fc-list-empty' ].concat(classNames).join(' ')} ref={rootElRef}>
-            {innerContent}
+            <div className='fc-list-empty-inner' ref={innerElRef}>
+              {innerContent}
+            </div>
           </div>
         )}
       </RenderHook>

+ 47 - 45
packages/list/src/main.scss

@@ -2,93 +2,95 @@
 @import '../../core/src/styles/vars';
 
 
-/* List View
---------------------------------------------------------------------------------------------------*/
+// the view wrapper
+// ----------------------------------------------------------------------------------------------------
 
-/* possibly reusable */
-
-.fc-dot {
-  display: inline-block;
-  width: 10px;
-  height: 10px;
-  border-radius: 5px;
+.fc-theme-standard {
+  .fc-list {
+    border: 1px solid $fc-theme-standard-border-color;
+    border: 1px solid var(--fc-theme-standard-border-color, $fc-theme-standard-border-color);
+  }
 }
 
-/* view wrapper */
 
-.fc-theme-standard .fc-list {
-  border: 1px solid $fc-theme-standard-border-color;
-  border: 1px solid var(--fc-theme-standard-border-color, $fc-theme-standard-border-color);
-}
+// table within the scroller
+// ----------------------------------------------------------------------------------------------------
 
-.fc .fc-list-table {
+.fc-list-table {
   width: 100%;
-  border-style: hidden; // kill outer border. already on fc-list
+  border-style: hidden !important; // kill outer border. already on fc-list. OVERCOME BOOTSTRAP
 
-  td, th { // needs to be high precedence to overcome reset :(
+  td, th {
     padding: 8px 14px;
-    border-width: 1px 0 0;
   }
 }
 
-/* day headings with the list */
 
-.fc-list-day {
-  border-bottom-width: 1px;
-}
-
-.fc-list-day td {
-  font-weight: bold;
-}
+// date heading rows
+// ----------------------------------------------------------------------------------------------------
 
 .fc-theme-standard .fc-list-day th {
   background: $fc-theme-standard-muted-bg-color;
   background: var(--fc-theme-standard-muted-bg-color, $fc-theme-standard-muted-bg-color);
 }
 
-.fc-dir-ltr .fc-list-day-text { float: left; }
-.fc-dir-ltr .fc-list-day-side-text { float: right; }
+.fc-dir-ltr .fc-list-day-text,
+.fc-dir-rtl .fc-list-day-side-text {
+  float: left;
+}
 
-.fc-dir-rtl .fc-list-day-text { float: right; }
-.fc-dir-rtl .fc-list-day-side-text { float: left; }
+.fc-dir-ltr .fc-list-day-side-text,
+.fc-dir-rtl .fc-list-day-text {
+  float: right;
+}
 
-/* event list items */
 
-.fc-theme-standard .fc-list-event:hover td {
-  background-color: #f5f5f5;
-}
+// event rows
+// ----------------------------------------------------------------------------------------------------
 
 .fc-list-event.fc-event-forced-url {
-  cursor: pointer; /* whole row will be clickable */
+  cursor: pointer; // whole row will seem clickable
 }
 
+// no borders in between cells
+.fc-list-event td {
+  border-left-width: 0 !important; // OVERCOME BOOTSTRAP
+  border-right-width: 0 !important; // OVERCOME BOOTSTRAP
+}
+
+.fc-theme-standard {
+  .fc-list-event:hover td {
+    background-color: #f5f5f5;
+  }
+}
+
+// shrink certain cols
 .fc-list-event-graphic,
 .fc-list-event-time {
   white-space: nowrap;
   width: 1px;
 }
 
-/* make the dot closer to the event title */
-.fc-dir-ltr .fc-list-event-graphic { padding-right: 0; }
-.fc-dir-rtl .fc-list-event-graphic { padding-left: 0; }
+// make the dot closer to the event title
+.fc-dir-ltr .fc-list-event-graphic { padding-right: 0 }
+.fc-dir-rtl .fc-list-event-graphic { padding-left: 0 }
 
+// reset <a> styling
 .fc-list-event-title a {
-  /* every event title cell has an <a> tag */
-  text-decoration: none;
   color: inherit;
+  text-decoration: none;
 }
 
-.fc-list-event-title a[href]:hover {
-  /* hover effect only on titles with hrefs */
+// underline link when hovering over any part of row
+.fc-list-event.fc-event-forced-url:hover a {
   text-decoration: underline;
 }
 
-/* message when no events */
-
+// message when no events
 .fc-list-empty {
   background-color: #eee;
   height: 100%;
   display: flex;
   justify-content: center;
-  align-items: center;
+  align-items: center; // vertically aligns fc-list-empty-inner
 }

+ 4 - 4
packages/timegrid/src/TimeCol.tsx

@@ -72,8 +72,8 @@ export default class TimeCol extends BaseComponent<TimeColProps> {
                 </Fragment>
               </div>
               <div class='fc-timegrid-col-bg'>
-                <Fragment>{this.renderFillSegs(props.businessHourSegs, 'nonbusiness')}</Fragment>
-                <Fragment>{this.renderFillSegs(props.bgEventSegs, 'bgevent')}</Fragment>
+                <Fragment>{this.renderFillSegs(props.businessHourSegs, 'non-business')}</Fragment>
+                <Fragment>{this.renderFillSegs(props.bgEventSegs, 'bg-event')}</Fragment>
                 <Fragment>{this.renderFillSegs(props.dateSelectionSegs, 'highlight')}</Fragment>
               </div>
               {this.renderNowIndicator(props.nowIndicatorSegs)}
@@ -152,13 +152,13 @@ export default class TimeCol extends BaseComponent<TimeColProps> {
 
       return (
         <div class='fc-timegrid-bg-harness' style={this.computeSegTopBottomCss(seg)}>
-          {fillType === 'bgevent' ?
+          {fillType === 'bg-event' ?
             <BgEvent
               key={key}
               seg={seg}
               {...getSegMeta(seg, props.todayRange, props.nowDate)}
             /> :
-            renderFill(fillType, [ `fc-timegrid-${fillType}` ])
+            renderFill(fillType)
           }
         </div>
       )

+ 1 - 1
packages/timegrid/src/TimeColEvent.tsx

@@ -15,7 +15,7 @@ export default class TimeColEvent extends BaseComponent<MinimalEventProps> {
       <StandardEvent
         {...props}
         defaultTimeFormat={DEFAULT_TIME_FORMAT}
-        extraClassNames={[ 'fc-timegrid-event' ]}
+        extraClassNames={[ 'fc-timegrid-event', 'fc-v-event' ]}
       />
     )
   }

+ 6 - 0
packages/timegrid/src/main.scss

@@ -1,5 +1,11 @@
 
+@import '../../core/src/styles/vars';
 @import '../../core/src/styles/mixins';
+@import './styles/vars';
+
+@import './styles/v-event';
 @import './styles/timegrid';
+@import './styles/timegrid-slots';
+@import './styles/timegrid-cols';
 @import './styles/timegrid-event';
 @import './styles/timegrid-now-indicator';

+ 52 - 0
packages/timegrid/src/styles/_timegrid-cols.scss

@@ -0,0 +1,52 @@
+
+.fc-timegrid-cols {
+  position: absolute; // no z-index. children will decide and go above slots
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+
+  & > table {
+    height: 100% !important;
+  }
+}
+
+.fc-timegrid-col-origin {
+  position: relative;
+  height: 0; // all segments position themselves based on this div
+}
+
+
+// fg events
+
+.fc-timegrid-col-events {
+  position: relative;
+  z-index: $timegrid-col-fg-z;
+}
+
+.fc-dir-ltr .fc-timegrid-col-events {
+  margin: 0 2.5% 0 2px;
+}
+
+.fc-dir-rtl .fc-timegrid-col-events {
+  margin: 0 2px 0 2.5%;
+}
+
+.fc-timegrid-event-harness {
+  position: absolute; // top/left/right/bottom will all be set by JS
+}
+
+
+// bg
+
+.fc-timegrid-col-bg {
+  position: relative;
+  z-index: $timegrid-col-bg-z;
+  @include bg-z-indexes;
+}
+
+.fc-timegrid-bg-harness {
+  position: absolute; // top/bottom will be set by JS
+  left: 0;
+  right: 0;
+}

+ 29 - 54
packages/timegrid/src/styles/_timegrid-event.scss

@@ -1,87 +1,62 @@
 
+// harness
+
+.fc-timegrid-event-harness-inset .fc-timegrid-event {
+  box-shadow: 0px 0px 0px 1px #fff; // TODO: var
+}
+
+
+// root
+
 .fc-timegrid-event {
   position: absolute;
   top: 0;
-  bottom: 0;
+  bottom: 1px; // stay away from bottom slot line
   left: 0;
   right: 0;
-  overflow: hidden;
-  margin-bottom: 1px;
 
-  display: block; /* make the <a> tag block */
+  // TODO: vars
   font-size: .85em;
-  line-height: 1.4;
   border-radius: 3px;
   border: 1px solid #3788d8;
   background-color: #3788d8;
-  color: #fff; /* default TEXT color. TODO: test hovering over <a> when HREF and theme */
-  text-decoration: none; /* if <a> has an href */
-}
+  color: #fff;
 
-.fc-timegrid-event-harness-inset .fc-timegrid-event {
-  // TODO: make these colors into variables
-  -webkit-box-shadow: 0px 0px 0px 1px #fff;
-          box-shadow: 0px 0px 0px 1px #fff;
+  .fc-event-main {
+    max-height: 100%;
+    overflow: hidden;
+    padding: 1px 1px 0;
+  }
 }
 
-.fc-timegrid-event:not(.fc-event-start) { /* events that are continuing from another day */
-  /* replace space made by the top border with padding */
+
+// kill radius/padding when event continues into future/past
+
+.fc-timegrid-event:not(.fc-event-start) {
+  // replace space made by the top border with padding
   border-top-width: 0;
   padding-top: 1px;
 
-  /* remove top rounded corners */
+  // remove top rounded corners
   border-top-left-radius: 0;
   border-top-right-radius: 0;
 }
 
 .fc-timegrid-event:not(.fc-event-end) {
-  /* replace space made by the top border with padding */
+  // replace space made by the top border with padding
   border-bottom-width: 0;
   padding-bottom: 1px;
 
-  /* remove bottom rounded corners */
+  // remove bottom rounded corners
   border-bottom-left-radius: 0;
   border-bottom-right-radius: 0;
 }
 
+
+// time header
+
 .fc-timegrid-event .fc-event-time {
   white-space: nowrap;
   font-size: .85em;
-}
-
-/* resizer (cursor device) */
-
-.fc-timegrid-event.fc-event-resizable-mouse .fc-event-resizer {
-  left: 0;
-  right: 0;
-  bottom: 0;
-  height: 8px;
-  overflow: hidden;
-  line-height: 8px;
-  font-size: 11px;
-  font-family: monospace;
-  text-align: center;
-  cursor: s-resize;
-}
-
-.fc-timegrid-event.fc-event-resizable-mouse .fc-event-resizer:after {
-  content: "=";
-}
-
-/* resizer (touch device) */
-
-.fc-timegrid-event.fc-event-selected .fc-event-resizer {
-  /* 10x10 dot */
-  border-radius: 5px;
-  border-width: 1px;
-  width: 8px;
-  height: 8px;
-  border-style: solid;
-  border-color: inherit;
-  background: #fff;
-  /* horizontally center */
-  left: 50%;
-  margin-left: -5px;
-  /* center on the bottom edge */
-  bottom: -5px;
+  margin-bottom: 1px;
 }

+ 19 - 6
packages/timegrid/src/styles/_timegrid-now-indicator.scss

@@ -1,19 +1,31 @@
 
+// line
+
 .fc-timegrid-now-indicator-line {
-  z-index: 999; // hack
-  border-top-width: 1px;
+  position: absolute;
+  z-index: $timegrid-now-indicator-z;
   left: 0;
   right: 0;
+  border-style: solid;
+  border-color: $now-indicator-color;
+  border-width: 1px 0 0;
 }
 
+
+// arrow
+
 .fc-timegrid-now-indicator-arrow {
-  z-index: 999; // hack
-  margin-top: -5px; /* vertically center on top coordinate */
+  position: absolute;
+  z-index: $timegrid-now-indicator-z;
+  margin-top: -5px; // vertically center on top coordinate
+  border-style: solid;
+  border-color: $now-indicator-color;
 }
 
 .fc-dir-ltr .fc-timegrid-now-indicator-arrow {
   left: 0;
-  /* triangle pointing right... */
+
+  // triangle pointing right. TODO: mixin
   border-width: 5px 0 5px 6px;
   border-top-color: transparent;
   border-bottom-color: transparent;
@@ -21,7 +33,8 @@
 
 .fc-dir-rtl .fc-timegrid-now-indicator-arrow {
   right: 0;
-  /* triangle pointing left... */
+
+  // triangle pointing left. TODO: mixin
   border-width: 5px 6px 5px 0;
   border-top-color: transparent;
   border-bottom-color: transparent;

+ 71 - 0
packages/timegrid/src/styles/_timegrid-slots.scss

@@ -0,0 +1,71 @@
+
+.fc-timegrid-slots {
+  position: relative;
+  z-index: $timegrid-slots-z;
+}
+
+.fc-timegrid-slot { // a <td>
+  height: 1.5em;
+  border-bottom: 0 !important; // OVERCOME THEME
+    // each cell is responsible for its top border
+}
+
+.fc-timegrid-slot-minor {
+  border-top-style: dotted !important;
+}
+
+.fc-timegrid-slot-label-cushion {
+  white-space: nowrap;
+}
+
+.fc .fc-timegrid-slot-label { // OVERCOME RESET
+  vertical-align: middle; // vertical align the slots
+}
+
+
+// slots AND axis cells (top-left corner of view including the "all-day" text)
+
+.fc-dir-ltr {
+  .fc-timegrid-axis-frame,
+  .fc-timegrid-slot-label-frame {
+    text-align: right;
+  }
+}
+
+.fc-dir-rtl {
+  .fc-timegrid-axis-frame,
+  .fc-timegrid-slot-label-frame {
+    text-align: left;
+  }
+}
+
+.fc-timegrid-axis-cushion,
+.fc-timegrid-slot-label-cushion {
+  padding: 0 4px;
+}
+
+
+// axis cells (top-left corner of view including the "all-day" text)
+// vertical align is more complicated, uses flexbox
+
+.fc-timegrid-axis-frame-liquid {
+  height: 100%; // will need liquid-hack in FF
+}
+
+.fc-liquid-hack {
+  .fc-timegrid-axis-frame-liquid {
+    @include liquid-absolute-override;
+  }
+}
+
+.fc-timegrid-axis-frame {
+  overflow: hidden;
+  display: flex;
+  align-items: center; // vertical align
+  justify-content: flex-end; // horizontal align. matches text-align
+}
+
+.fc-timegrid-axis-cushion {
+  max-width: 60px; // limits the width of the "all-day" text
+  flex-shrink: 0; // allows text to expand how it normally would, regardless of constrained width
+}

+ 4 - 136
packages/timegrid/src/styles/_timegrid.scss

@@ -1,142 +1,10 @@
 
-// high precedence to overcome theme
-.fc .fc-timegrid-divider {
-  padding: 0 0 2px;
+.fc .fc-timegrid-divider { // OVERCOME RESET
+  padding: 0 0 2px; // browsers get confused when you set height. use padding instead
 }
 
-
-
 .fc-timegrid-body {
-  position: relative; // for housing skeletons
-  z-index: 1; // because containers z-index'd children
-  min-height: 100%; // fill height always ... even when slat table doesn't grow
-}
-
-.fc-timegrid-slots {
   position: relative;
-  z-index: 2; // go above fc-timegrid-cols
-}
-
-.fc-timegrid-cols {
-  position: absolute; // no z-index. children will decide
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-
-  & > table {
-    height: 100% !important;
-  }
-}
-
-
-.fc-timegrid-col-origin {
-  position: relative;
-  height: 0;
-}
-
-.fc-timegrid-col-bg {
-  position: relative;
-  z-index: 1; // under slots
-}
-
-.fc-timegrid-col-events {
-  position: relative;
-  z-index: 3; // above slots
-}
-
-// within events container
-// .fc-timegrid-event { z-index: ? } // decided and assigned in JS
-.fc-timegrid-event.fc-event-mirror { z-index: 9999 } // above all events
-
-// within bg container
-.fc-timegrid-nonbusiness { z-index: 1 }
-.fc-timegrid-bgevent { z-index: 2 }
-.fc-timegrid-highlight { z-index: 3 }
-
-
-
-// SLATS (lines that run horizontally)
-
-.fc-timegrid-slot { // a <td>
-  height: 1.5em; // TODO: move to the 'frame' possibly
-  border-bottom: 0 !important;
-    /* each cell is responsible for its top border */
-    /* is !important because competing with theme declarations */
-}
-
-.fc-timegrid-slot-minor {
-  border-top-style: dotted !important;
-}
-
-.fc-timegrid-slot-label-cushion {
-  white-space: nowrap;
-}
-
-.fc-timegrid-axis-frame-liquid {
-  height: 100%;
-}
-
-.fc-liquid-hack {
-  .fc-timegrid-axis-frame-liquid {
-    @include liquid-hack-cell-inner;
-  }
-}
-
-.fc-dir-ltr {
-  .fc-timegrid-axis-frame,
-  .fc-timegrid-slot-label-frame {
-    text-align: right;
-  }
-}
-
-.fc-dir-rtl {
-  .fc-timegrid-axis-frame,
-  .fc-timegrid-slot-label-frame {
-    text-align: left;
-  }
-}
-
-.fc-timegrid-axis-cushion,
-.fc-timegrid-slot-label-cushion {
-  padding: 0 4px;
-}
-
-.fc .fc-timegrid-slot-label { // vertical align the slots
-  vertical-align: middle;
-}
-
-
-
-.fc-timegrid-axis-frame {
-  overflow: hidden;
-  display: flex;
-  align-items: center; // vertical align
-  justify-content: flex-end; // horizontal align. matches text-align
-}
-
-.fc-timegrid-axis-cushion {
-  max-width: 60px;
-  flex-shrink: 0; // allows text to expand how it normally would, regardless of constrained width
-}
-
-
-
-.fc-timegrid-bg-harness {
-  position: absolute;
-  left: 0;
-  right: 0;
-}
-
-
-.fc-dir-ltr .fc-timegrid-col-events { /* space on the sides of events for LTR (default) */
-  margin: 0 2.5% 0 2px;
-}
-
-.fc-dir-rtl .fc-timegrid-col-events { /* space on the sides of events for RTL */
-  margin: 0 2px 0 2.5%;
-}
-
-.fc-timegrid-event-harness {
-  position: absolute;
+  z-index: 1; // scope the z-indexes of slots and cols
+  min-height: 100%; // fill height always, even when slat table doesn't grow
 }

+ 68 - 0
packages/timegrid/src/styles/_v-event.scss

@@ -0,0 +1,68 @@
+
+/*
+A VERTICAL event
+*/
+
+
+.fc-v-event .fc-event-main {
+  position: relative; // specifically for the z-index
+  z-index: $event-main-z;
+}
+
+
+// resizer (mouse AND touch)
+
+.fc-v-event .fc-event-resizer {
+  position: absolute;
+  z-index: $event-resizer-z;
+}
+
+.fc-v-event .fc-event-resizer-start {
+  cursor: n-resize;
+}
+
+.fc-v-event .fc-event-resizer-end {
+  cursor: s-resize;
+}
+
+
+// resizer for MOUSE
+
+.fc-v-event.fc-event-resizable-mouse .fc-event-resizer {
+  height: $event-resizer-mouse-width;
+  left: -1px; // overcome border
+  right: -1px; // overcome border
+}
+
+.fc-v-event.fc-event-resizable-mouse .fc-event-resizer-start {
+  top: -($event-resizer-mouse-width / 2);
+}
+
+.fc-v-event.fc-event-resizable-mouse .fc-event-resizer-end {
+  bottom: -($event-resizer-mouse-width / 2);
+}
+
+
+// resizer for TOUCH (when event is "selected")
+
+.fc-v-event.fc-event-selected .fc-event-resizer {
+  @include event-resizer-dot;
+  left: 50%;
+  margin-left: -($event-resizer-dot-total-width / 2);
+}
+
+.fc-v-event.fc-event-selected .fc-event-resizer-start {
+  top: -($event-resizer-dot-total-width / 2);
+}
+
+.fc-v-event.fc-event-selected .fc-event-resizer-end {
+  bottom: -($event-resizer-dot-total-width / 2);
+}
+
+
+// expand touch area for TOUCH (when event is "selected")
+
+.fc-v-event.fc-event-selected:before {
+  left: -10px;
+  right: -10px;
+}

+ 5 - 0
packages/timegrid/src/styles/_vars.scss

@@ -0,0 +1,5 @@
+
+$timegrid-col-bg-z: 1;
+$timegrid-slots-z: 2;
+$timegrid-col-fg-z: 3;
+$timegrid-now-indicator-z: 4;