Scheduler - HTML UI Elements for Mobile & Web Applications | www.HtmlElements.com

Overview

Smart.Scheduler is a type of grid element that displays a set of Events in Day, Week, Month, Agenda, Timeline Day, Timeline Week and Timeline Month views. The Scheduler's timeline displays the events for the selected viewing range according to their start/end time. Events can be edited at any time via the Scheduler window.

Getting Started

Getting Started with Scheduler Web Component

Smart UI for Web Components is distributed as smart-webcomponents NPM package. You can also get the full download from our website with all demos from the Download page.

Setup Smart.Scheduler

  1. Download and install the package.
    npm install smart-webcomponents
  2. Once installed, import the Scheduler module in your application.
    <script type="module" src="node_modules/smart-webcomponents/source/modules/smart.scheduler.js"></script>
  3. Adding a CSS reference for the Smart components styles.
    <link rel="stylesheet" type="text/css" href="node_modules/smart-webcomponents/source/styles/smart.default.css" />
  4. Add the Scheduler tag to your Web Page
    <smart-scheduler id="scheduler"></smart-scheduler>
  5. Initialize the Scheduler Component
    <script type="module">
    const today = new Date(),
        currentYear = today.getFullYear(),
        currentMonth = today.getMonth(),
        data = [
            {
                label: 'Event 1',
                dateStart: new Date(currentYear, currentMonth, 10),
                dateEnd: new Date(currentYear, currentMonth, 11)
            }, {
                label: 'Event 2',
                dateStart: new Date(currentYear, currentMonth, 11, 11, 30),
                dateEnd: new Date(currentYear, currentMonth, 11, 14, 15)
            }, {
                label: 'Event 3',
                dateStart: new Date(currentYear, currentMonth, 12, 13, 15),
                dateEnd: new Date(currentYear, currentMonth, 12, 16, 15)
            }
        ];
    
    window.Smart('#scheduler', class {
        get properties() {
            return {
                //Properties
                view: 'week',
                dataSource: data
            };
        }
    });
    </script>
    

    Another option is to create the Scheduler is by using the traditional Javascript way:

    const scheduler = document.createElement('smart-scheduler');
    const today = new Date(),
        currentYear = today.getFullYear(),
        currentMonth = today.getMonth(),
        data = [
            {
                label: 'Event 1',
                dateStart: new Date(currentYear, currentMonth, 10),
                dateEnd: new Date(currentYear, currentMonth, 11)
            }, {
                label: 'Event 2',
                dateStart: new Date(currentYear, currentMonth, 11, 11, 30),
                dateEnd: new Date(currentYear, currentMonth, 11, 14, 15)
            }, {
                label: 'Event 3',
                dateStart: new Date(currentYear, currentMonth, 12, 13, 15),
                dateEnd: new Date(currentYear, currentMonth, 12, 16, 15)
            }
        ];
    
    scheduler.view = 'week';
    scheduler.dataSource = data;
    
    document.body.appendChild(scheduler);
    

    Smart framework provides a way to dynamically create a web component on demand from a DIV tag which is used as a host. The following imports the web component's module and creates it on demand, when the document is ready. The #scheduler is the ID of a DIV tag.

    import "../../source/modules/smart.scheduler.js";
    
    document.readyState === 'complete' ? init() : window.onload = init;
    
    function init() { 
        const today = new Date(),
        currentYear = today.getFullYear(),
        currentMonth = today.getMonth(),
        data = [
            {
                label: 'Event 1',
                dateStart: new Date(currentYear, currentMonth, 10),
                dateEnd: new Date(currentYear, currentMonth, 11)
            }, {
                label: 'Event 2',
                dateStart: new Date(currentYear, currentMonth, 11, 11, 30),
                dateEnd: new Date(currentYear, currentMonth, 11, 14, 15)
            }, {
                label: 'Event 3',
                dateStart: new Date(currentYear, currentMonth, 12, 13, 15),
                dateEnd: new Date(currentYear, currentMonth, 12, 16, 15)
            }
        ];
    
    window.Smart('#scheduler', class {
        get properties() {
            return {
                //Properties
                view: 'week',
                dataSource: data
            };
        }
    });
    }
    
  6. Open the page in your web server.

Load Scripts

Another way of initializing the Scheduler element is by referencing all of the necessary components. The following code will initialize an empty Smart.Scheduler on the page:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="../../source/styles/smart.default.css" />
<script type="text/javascript" src="../../source/smart.element.js" />
<script type="text/javascript" src="../../source/smart.button.js" />
<script type="text/javascript" src="../../source/smart.scrollbar.js" />
<script type="text/javascript" src="../../source/smart.data.js" />
<script type="text/javascript" src="../../source/smart.buttongroup.js" />
<script type="text/javascript" src="../../source/smart.radiobutton.js" />
<script type="text/javascript" src="../../source/smart.tooltip.js" />
<script type="text/javascript" src="../../source/smart.input.js" />
<script type="text/javascript" src="../../source/smart.multiinput.js" />
<script type="text/javascript" src="../../source/smart.checkinput.js" />
<script type="text/javascript" src="../../source/smart.numberinput.js" />
<script type="text/javascript" src="../../source/smart.timeinput.js" />
<script type="text/javascript" src="../../source/smart.colorinput.js" />
<script type="text/javascript" src="../../source/smart.date.js" />
<script type="text/javascript" src="../../source/smart.listbox.js" />
<script type="text/javascript" src="../../source/smart.dropdownlist.js" />
<script type="text/javascript" src="../../source/smart.calendar.js" />
<script type="text/javascript" src="../../source/smart.draw.js" />
<script type="text/javascript" src="../../source/smart.numeric.js" />
<script type="text/javascript" src="../../source/smart.math.js" />
<script type="text/javascript" src="../../source/smart.timepicker.js" />
<script type="text/javascript" src="../../source/smart.datetimepicker.js" />
<script type="text/javascript" src="../../source/smart.export.js" />
<script type="text/javascript" src="../../source/smart.window.js" />
<script type="text/javascript" src="../../source/smart.switchbutton.js" />
<script type="text/javascript" src="../../source/smart.toast.js" />
<script type="text/javascript" src="../../source/smart.checkbox.js" />
<script type="text/javascript" src="../../source/smart.scheduler.js" />
<script type="text/javascript" src="../../scripts/rrule.min.js" />
</head>
<body>
    <smart-scheduler id="scheduler"></smart-scheduler>
</body>
</html>

Note how smart.element.js is declared before everything else. This is mandatory for all custom elements.

DataSource

The dataSource property of the Smart.Scheduler allows to load an Array of Events. Each event is defined as an object with the following properties:

  • label - the label for the Event. The label should be of type 'string'.
  • dateStart - the starting date for the Event. The dateStart should be of type 'date' or 'string'.
  • dateEnd - the ending date for the Event. The end date must not be the same as the start. The dateEnd should be of type 'date' or 'string'.
  • description - the description of the Event. The description should be of type 'string'.
  • id - the unique id of the Event. The id value is applied to the DOM element that represents the event. The id should be of type 'string'.
  • class - the class of the Event. The class value is applied to the DOM element that represents the event. The class should be of type 'string'.
  • backgroundColor - a custom background color for the Event. Optional. The color should be defined as a HEX value. The backgroundColor should be ot type 'string'.
  • color - a custom color for the Event. Optional. The color should be defined as a HEX value. The color should be of type 'string'.
  • notifications - an array of objects that define the notifications for the Event. Notificaitons can appear on the same day as the event starts or before that.
    • interval - a numeric interval that indicates the number of days/weeks on which the notification will appear before the event start date.
    • type - the type of the interval. It can be 'days' or 'week'. By default it's days.
    • time - an array of numbers that indicate the hours and minutes of the date on which the notificaiton should appear.
  • allDay - a boolean property which indicates that the Event lasts all day and the Scheduler should ignore the time offset.
  • disableDrag - a boolean property that disables the abbility to drag an Event.
  • disableResize - a boolean property that disables the abbility to resize an Event.
  • repeat - a repeat object that defines the repeating settings for the Event. Optional. Repeating events have this property assigned. Here are it's attributes:
    • repeatFreq - a string that represents the repeat frequency for the event, e.g. 'daily', 'weekly', etc.
    • repeatInterval - a number that represents the repeat interval for the event.
    • repeatOn - depending on the repeatFreq the event can repeat on specific days or date. The repeatOn value can be an array of numbers which indidate the days of the week for 'weekly' repeating frequency, a number which indicates the date of the month for 'monthly' repeating frequency or a date which indicates the date of the year when repeat frequency is set to 'yearly'.
    • repeatEnd - the end condition for the repeating event. The event can end on a date or after a number of occurances. If not set the repeating event will never end.
    • exceptions - an array of objects that define the event date exceptions for the repeating event. An exception can contain a different start/end date but it's date property must be equal to an expected repeating date. Exceptions can have different backgroundColor and color. They can also be hidden via the hidden attribute.
  • These are the Event attributes that Smart.Sheduler uses. Any other attributes added to the Event objects will be preserved but not used by the element.

    Resources are assigned to the event object as key-value records. Where the key is the resource's value and value is the resource item id. Resources are described in depth in another topic on the website.

Here's an example of a Scheduler with three Events:

const today = new Date(),
    currentYear = today.getFullYear(),
    currentMonth = today.getMonth(),
    data = [
        {
            label: 'Event 1',
            dateStart: new Date(currentYear, currentMonth, 10),
            dateEnd: new Date(currentYear, currentMonth, 11)
        }, {
            label: 'Event 2',
            dateStart: new Date(currentYear, currentMonth, 11, 11, 30),
            dateEnd: new Date(currentYear, currentMonth, 11, 14, 15)
        }, {
            label: 'Event 3',
            dateStart: new Date(currentYear, currentMonth, 12, 13, 15),
            dateEnd: new Date(currentYear, currentMonth, 12, 16, 15)
        }
    ];

window.Smart('#scheduler', class {
    get properties() {
        return {
            //Properties
            view: 'week',
            dataSource: data
        };
    }
});

Demo

Scheduler

Resources

Smart.Scheduler resources can be used to assign Events to specific resources. They allow to specify the Events. Events can have one or many resources assigned to them.

Resources can have custom colors. The Scheduler can group events by one or more resources.

Resources property represents an Array of objects with the following properties:

  • label - a string that represents the label of the resource.
  • value - a string that represents the unique value of the resource by which it can be identified from the rest.
  • dataSource - an array that contains the items of the resource. Each item contains the following properties:
    • id - a number or string that acts as a unique identifier for the item.
    • label - a string that represents the label of the resource item.
    • backgroundColor - a string that represents the HEX representation of a color that will be used as the background color for the Events that have the resource item assigned.
    • color - a string that represents the HEX representation of a color that will be used as the color for the Events that have the resource item assigned.

Here's an example:

const today = new Date(),
    currentYear = today.getFullYear(),
    currentMonth = today.getMonth(),
    data = [
        {
            label: 'Event 1',
            dateStart: new Date(currentYear, currentMonth, 10),
            dateEnd: new Date(currentYear, currentMonth, 11),
            priorityId: 1
        }, {
            label: 'Event 2',
            dateStart: new Date(currentYear, currentMonth, 11, 11, 30),
            dateEnd: new Date(currentYear, currentMonth, 11, 14, 15),
            priorityId: 2
        }, {
            label: 'Event 3',
            dateStart: new Date(currentYear, currentMonth, 12, 13, 15),
            dateEnd: new Date(currentYear, currentMonth, 12, 16, 15),
            priorityId: 1
        }
    ];

const priorityData = [
    {
        label: 'Low Priority',
        id: 1,
        backgroundColor: '#1e90ff'
    }, {
        label: 'Medium Priority',
        id: 2,
        backgroundColor: '#ff9747'
    }
];

window.JQX('#scheduler', class {
    get properties() {
        return {
            //Properties
            view: 'week',
            dataSource: data,
            resources: [
                {
                    label: 'Priority',
                    value: 'priorityId',
                    dataSource: priorityData
                }
            ]
        };
    }
});

Here we have a single resource with identifier 'priorityId' that contains two priorities : 'low' and 'medium'. Each of them has individual color.

The resources items are assigned to the Events using their 'value' directly set to the Event objects where the 'key' is the resources value while the 'value' is the resource item id.

Demo

Scheduler Resources

Groups

Scheduler Events can be grouped by Resources. When groups property is set Events that do not have a resource assigned to them or the groups property does not include their resource will not be displayed.

The groups property accepts an array of strings which represent resource values.

Here's an example of grouping by a single resource that has two items.

window.JQX('#scheduler', class {
    get properties() {
        return {
            //Properties
            view: 'week',
            dataSource: data,
            resources: [
                {
                    label: 'Priority',
                    value: 'priorityId',
                    dataSource: priorityData
                }
            ],
            groups: ['priorityId']
        };
    }
});   

The timeline view of the Scheduler is separated into multiple sections for each group and the events are positioned according to their dates.

Demo

Scheduler Timeline

Smart.Scheduler is virtualized by default and does not have a limit on the groups, events or resources count.

Scheduler also allows to group events by Date in addition to Resources grouping. In order to group by date simply set the groupByDate property like so:

window.JQX('#scheduler', class {
    get properties() {
        return {
            //Properties
            view: 'week',
            dataSource: data,
            resources: [
                {
                    label: 'Priority',
                    value: 'priorityId',
                    dataSource: priorityData
                }
            ],
            groups: ['priorityId'],
            groupByDate: true
        };
    }
});  

Demo

Scheduler Grouping

The Events are grouped by date by separating each Date cell into the number of resource groups.

Event Editor

A Smart.Window component is available for Event editing inside the Scheduler. In order to open the editor the user simply has to double click on an event element or press the 'Enter' key when the event element is focused.

The window will appear in the middle of the Scheduler and will allow the user to modify all of the settings of the Event.

Creating new Events is also possible via the Window. When the user double clicks on a timeline cell or presses the 'Enter' key on focused cell the Event window editor will appear to create the new Event.

Here's an example:

Demo

Scheduler Window

The Scheduler window is modal so interaction with the Scheduler while the window is opened is disabled.

Event repeating options are avaialble when the "Repeat" switch button is on. The window will expand an additional panel with all repeating options allowing the user to create/customize the repeating series.

Scheduler Repeat

Clicking on the OK button will apply the editing changes to the event.

A 'confirm' window is the second type of window that can be opened inside the Smart.Scheduler. Confirm window appears when the user tries to edit a repeating event. This window prompts the user to select between editing the original repeating series or create a repeating exception from the target event. Repeating exceptions can have different start/end dates. They correspond to a specific repeating date of the original repeating series. Exceptions unlike other events cannot repeat but can be hidden via the edit window. This is useful in a scenario when, for example the user wants to create a repeating event for each day of the week but has to skip a day. Making the desired day as an exception and applying hidden will remove it form the repeating series. Repeating events and exceptions are covered in a separate topic.

Here's what the Confirm window looks like:

Scheduler Dialog

Time Zones

Smart.Scheduler allows to display additional Time zones at the same time thanks to the timeZones property which accepts an Array of strings which represent valid IANA timezone names. This allows the user to see the corresponding time for the events in multiple Time zones at once.

Here's an example of Smart.Scheduler with three Time zones visible:

const scheduler = document.querySelector('smart-scheduler');

scheduler.timeZones = [{ id: 'America/Chicago', label: 'US/Chicago' }, 'UTC'];

The default Time zone of the Smart.Scheduler is the local time zone. Setting the timeZones property displays additional time zones. In the example above the additional time zones include 'America/Chicago' and 'UTC'.

Here's what the Scheduler looks like:

Scheduler Time Zones

The default Smart.Scheduler Time zone can also be changed via the timeZone property. By default it does not have a label inside the timeline header.

Menus

Smart.Scheduler contains many popup menus with different actions. These menu's allow to the change the view/date or create/ edit an event. Here's a list of the menus that are used by the Scheduler:

  • Event Menu - appears when an event is clicked. It shows details about the event like start/end date and label. Also allows to quickly delete the event via a delete button. The delete button is available only on non-repeating events or exceptions.

    Scheduler Event Menu
  • Context Menu - appears when the user right clicks on a view cell or an event. The context menu allows to quickly create/delete and event.

    Scheduler Delete
  • Date Menu - appears when the user clicks on the Date Selector located inside the Header of the Smart.Scheduler. It allows to change the current view date.

    Scheduler Date Menu
  • View Menu - appears when the user clicks on the View Selector located inside the Header of the Smart.Scheduler. It allows to change the current view.

    Scheduler View Menu

All Scheduler menus are customizable.

Save/Load State

Smart.Scheduler utilizes the localStorage by allowing to save the current state of the events and load it again at a later point. This is usefull when the user is going to make changes to the events and wants to have a step by step history of the changes. Smart.Scheduler state represents an object that contains the current viewing date and a JSON Array of Events that were loaded to the Scheduler at the time it was saved.

The following methods are available for Smart.Scheduler state handling:

  • getState - returns an object containing the viewing date and a JSON Array of the Scheduler Events.
  • saveState - saves the current state of the Scheduler to localStorage. Requires an ID to be set to the element.
  • loadState - loads a previously saved state of the element. Accepts one argument - the state to load to. If no arguments are provided, localStorage lookup will be performed in order to find a previously saved state according to the id of the element. Requires an ID to be set to the element.
  • clearState - removes any stored state in localStorage of the element according to it's id. Requires an ID to be set to the element.
 const scheduler = document.querySelector('smart-scheduler');

//Saves the current state of the Scheduler to localStorage
scheduler.saveState();

//Reload the element to the previously saved state
scheduler.loadState();

//Clears the saved state
scheduler.clearState();

Keyboard Support

Smart.Scheduler implements the following key actions:

Key Action
Escape When dragging/resizing pressing the 'Escape' key will cancel the ongoing operation and return the target event to it's original state. The 'Escape' key can also close the Scheduler Windows and Menus if focused.
Tab Pressing Tab will change the focus to another focusable element. Smart.Scheduler has many focusable elements - the date,view selectors, the events inside the Timeline, the Timeline itself wihch allows to navigate through the cells, the Scheduler Window and it's editors, the Event/cell menu.
Arrow Up/Down/Left/Right When the Scheduler Timeline is focused these keys allow to navigate through the cells by selecting them.
Shift + Arrow Up/Down/Left/Right When the Scheduler Timeline is focused the Shift + Arrow combination allows to create a range selection of multiple cells in the direciton of the arrow pressed.
Shift + Mouse Left Click If a cell is selected, pressing Shift + Mouse Click on another cell allows to create a range selection from the initialy selected cell to the click target.
Enter Allows to open one of the Menus/Windows of the Smart.Scheduler. This can happen if an event or cell, or date/view selector is currently focused. If multiple cells are selected pressing Enter will open the Window to create a new event from the selection range.
Delete When an Event is focused this key allows to remove the Event form the Smart.Scheduler. The action can be canceled. Check the API of the element on the website for more details.
D The default shortcut key for the 'Day' view. When the view selector is focused, pressing this key will change the view to 'Day'. This shortcut can be customized. Check the API on the website for more details.
W The default shortcut key for the 'Week' view. When the view selector is focused, pressing this key will change the view to 'Week'. This shortcut can be customized. Check the API on the website for more details.
M The default shortcut key for the 'Month' view. When the view selector is focused, pressing this key will change the view to 'Month'. This shortcut can be customized. Check the API on the website for more details.
A The default shortcut key for the 'Agenda' view. When the view selector is focused, pressing this key will change the view to 'Agenda'. This shortcut can be customized. Check the API on the website for more details.
T + D The default shortcut key combination for the 'Timeline Day' view. When the view selector is focused, pressing this key combo will change the view to 'Timeline Day'. This shortcut can be customized. Check the API on the website for more details.
T + W The default shortcut key combination for the 'Timeline Week' view. When the view selector is focused, pressing this key combo will change the view to 'Timeline Week'. This shortcut can be customized. Check the API on the website for details.
T + W The default shortcut key combination for the 'Timeline Month' view. When the view selector is focused, pressing this key combo will change the view to 'Timeline Month'. This shortcut can be customized. Check the API on the website for details.

Create, Append, Remove, Get/Set Property, Invoke Method, Bind to Event

Create a new element:

const scheduler = document.createElement('smart-scheduler');

Append the element to the DOM:

document.body.appendChild(scheduler);

Remove the element from the DOM:

scheduler.parentNode.removeChild(scheduler);

Set a property:

scheduler.propertyName = propertyValue;

Get a property:

const propertyValue = scheduler.propertyName;

Invoke a method:

scheduler.methodName(argument1, argument2);

Add Event Listener:

const eventHandler = (event) => {
	// your code here.
};

scheduler.addEventListener(eventName, eventHandler);

Remove Event Listener:

scheduler.removeEventListener(eventName, eventHandler);

Using with TypeScript

Smart Web Components package includes TypeScript definitions which enables strongly-typed access to the Smart UI Components and their configuration.

Inside the download package, the typescript directory contains .d.ts file for each web component and a smart.elements.d.ts typescript definitions file for all web components. Copy the typescript definitions file to your project and in your TypeScript file add a reference to smart.elements.d.ts

Getting Started with Angular Scheduler Component

Setup Angular Environment

Angular provides the easiest way to set angular CLI projects using Angular CLI tool.

Install the CLI application globally to your machine.

npm install -g @angular/cli

Create a new Application

ng new smart-angular-scheduler

Navigate to the created project folder

cd smart-angular-scheduler

Setup the Scheduler

Smart UI for Angular is distributed as smart-webcomponents-angular NPM package

  1. Download and install the package.
    npm install smart-webcomponents-angular
  2. Adding CSS reference

    The following CSS file is available in ../node_modules/smart-webcomponents-angular/ package folder. This can be referenced in [src/styles.css] using following code.

    @import 'smart-webcomponents-angular/source/styles/smart.default.css';

    Another way to achieve the same is to edit the angular.json file and in the styles add the style.

    "styles": [
    		"node_modules/smart-webcomponents-angular/source/styles/smart.default.css"
    	]
    If you want to use Bootstrap, Fluent or other themes available in the package, you need to add them after 'smart.default.css'.
  3. Example with Angular Standalone Components


    app.component.html

     <div id="primaryContainer" #primaryContainer>
        <div id="header">
            <smart-button #button id="toggleButton" (onClick)="handleToggle()"></smart-button>
            <div id="title">Scheduler</div>
            <smart-button #button2 id="addNew" class="floating" (onClick)="addNew()"><span>Create</span>
            </smart-button>
        </div>
        <div class="content">
            <section id="sideA">
                <div class="button-container">
                    <div id="logo"></div>
                </div>
                <div class="controls-container">
                    <smart-calendar #calendar id="calendar" [scrollButtonsPosition]="scrollButtonsPosition" (onChange)="handleCalendarChange($event)">
                    </smart-calendar>
                    <smart-input #input id="searchBar" class="underlined" [placeholder]="'Search for people'"></smart-input>
                    <smart-tree #tree id="tree" [selectionMode]="'checkBox'" [toggleElementPosition]="'far'"
                        (onChange)="handleTreeChange($event)">
                        <smart-tree-items-group [expanded]="true">My calendars
                            <smart-tree-item [value]="'birthday'" [selected]="true">Birthdays</smart-tree-item>
                            <smart-tree-item [value]="'holiday'" [selected]="true">Holidays</smart-tree-item>
                            <smart-tree-item [value]="'event'" [selected]="true">Events</smart-tree-item>
                        </smart-tree-items-group>
                    </smart-tree>
                </div>
            </section>
            <section id="sideB">
                <smart-scheduler #scheduler id="scheduler" [dataSource]="dataSource" [view]="view" [views]="views"
                    [nonworkingDays]="nonworkingDays" [dataSource]="dataSource" [firstDayOfWeek]="firstDayOfWeek"
                    [disableDateMenu]="disableDateMenu" [currentTimeIndicator]="currentTimeIndicator"
                    (onDragEnd)="updateData($event)" (onResizeEnd)="updateData($event)" (onItemUpdate)="updateData($event)"
                    (onItemRemove)="updateData($event)" (onDateChange)="handleDateChange($event)">
                </smart-scheduler>
            </section>
        </div>
    </div>

    app.component.ts

     import { Component, ViewChild, OnInit, AfterViewInit, ViewEncapsulation, ElementRef } from '@angular/core';
    import { ButtonComponent } from 'smart-webcomponents-angular/button';
    import { CalendarComponent } from 'smart-webcomponents-angular/calendar';
    import { InputComponent } from 'smart-webcomponents-angular/input';
    import { TreeComponent, Tree, TreeItem } from 'smart-webcomponents-angular/tree';
    import { SchedulerComponent, SchedulerViewType } from 'smart-webcomponents-angular/scheduler';
    
    
    import { CommonModule } from '@angular/common';
    import { RouterOutlet } from '@angular/router';
    import { SchedulerModule } from 'smart-webcomponents-angular/scheduler';
    
    @Component({
        selector: 'app-root',
    	standalone: true,
    	imports: [CommonModule, SchedulerModule, RouterOutlet],
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css'],
        encapsulation: ViewEncapsulation.None
    })
    
    export class AppComponent implements AfterViewInit, OnInit {
        @ViewChild('button', { read: ButtonComponent, static: false }) button!: ButtonComponent;
        @ViewChild('button2', { read: ButtonComponent, static: false }) button2!: ButtonComponent;
        @ViewChild('calendar', { read: CalendarComponent, static: false }) calendar!: CalendarComponent;
        @ViewChild('input', { read: InputComponent, static: false }) input!: InputComponent;
        @ViewChild('tree', { read: TreeComponent, static: false }) tree!: TreeComponent;
        @ViewChild('scheduler', { read: SchedulerComponent, static: false }) scheduler!: SchedulerComponent;
        @ViewChild('primaryContainer', { read: ElementRef, static: false }) primaryContainer!: ElementRef;
    
        today = new Date();
    
        thanksgiving = (() => {
            const tempDate = new Date(this.today.getFullYear(), 10, 1);
    
            //4th Thursday of November
            tempDate.setDate(tempDate.getDate() - tempDate.getDay() + 25);
            return tempDate;
        })();
    
        data: any[] = (() => {
            const currentDate = this.today.getDate(),
                currentYear = this.today.getFullYear(),
                currentMonth = this.today.getMonth();
    
            return [
                {
                    label: 'Brochure Design Review',
                    dateStart: new Date(currentYear, currentMonth, 10, 13, 15),
                    dateEnd: new Date(currentYear, currentMonth, 12, 16, 15),
                    status: 'tentative',
                    class: 'event'
                }, {
                    label: 'Website Re-Design Plan',
                    dateStart: new Date(currentYear, currentMonth, 16, 16, 45),
                    dateEnd: new Date(currentYear, currentMonth, 18, 11, 15),
                    class: 'event'
                }, {
                    label: 'Update Sales Strategy Documents',
                    dateStart: new Date(currentYear, currentMonth, 2, 12, 0),
                    dateEnd: new Date(currentYear, currentMonth, 2, 13, 45),
                    class: 'event',
                    repeat: {
                        repeatFreq: 'daily',
                        repeatInterval: 2,
                        repeatEnd: 5,
                        exceptions: [
                            {
                                date: new Date(currentYear, currentMonth, 4, 12, 0),
                                label: 'Employee on sick leave. Reschedule for next day',
                                dateStart: new Date(currentYear, currentMonth, 5),
                                dateEnd: new Date(currentYear, currentMonth, 6),
                                status: 'outOfOffice',
                                backgroundColor: '#F06292'
                            },
                            {
                                date: new Date(currentYear, currentMonth, 8, 12, 0),
                                label: 'Employee on sick leave. Reschedule for next day',
                                dateStart: new Date(currentYear, currentMonth, 9),
                                dateEnd: new Date(currentYear, currentMonth, 10),
                                status: 'outOfOffice',
                                backgroundColor: '#FFA000'
                            }
                        ]
                    }
                }, {
                    label: 'Non-Compete Agreements',
                    dateStart: new Date(currentYear, currentMonth, currentDate - 1, 8, 15),
                    dateEnd: new Date(currentYear, currentMonth, currentDate - 1, 9, 0),
                    status: 'outOfOffice',
                    class: 'event'
                }, {
                    label: 'Approve Hiring of John Jeffers',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 10, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 11, 15),
                    notifications: [
                        {
                            interval: 1,
                            type: 'days',
                            time: [this.today.getHours(), this.today.getMinutes()],
                            message: 'Approve Hiring of John Jeffers tomorrow',
                            iconType: 'success'
                        }
                    ],
                    status: 'busy',
                    class: 'event'
                }, {
                    label: 'Update NDA Agreement',
                    dateStart: new Date(currentYear, currentMonth, currentDate - 2, 11, 45),
                    dateEnd: new Date(currentYear, currentMonth, currentDate - 2, 13, 45),
                    class: 'event'
                }, {
                    label: 'Update Employee Files with New NDA',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 2, 14, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 2, 16, 45),
                    class: 'event'
                }, {
                    label: 'Compete Agreements',
                    dateStart: new Date(currentYear, currentMonth, currentDate, this.today.getHours(), this.today.getMinutes() + 15),
                    dateEnd: new Date(currentYear, currentMonth, currentDate, this.today.getHours() + 1, 45),
                    notifications: [
                        {
                            interval: 0,
                            type: 'days',
                            time: [this.today.getHours(), this.today.getMinutes() + 1],
                            message: 'Compete Agreements in 15 minutes',
                            iconType: 'time'
                        },
                        {
                            interval: 0,
                            type: 'days',
                            time: [this.today.getHours(), this.today.getMinutes() + 2],
                            message: 'Compete Agreements in 14 minutes',
                            iconType: 'warning'
                        }
                    ],
                    status: 'outOfOffice',
                    class: 'event'
                }, {
                    label: 'Approve Hiring of Mark Waterberg',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 3, 10, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 3, 11, 15),
                    status: 'busy',
                    class: 'event'
                }, {
                    label: 'Update Employees Information',
                    dateStart: new Date(currentYear, currentMonth, currentDate, 14, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate, 16, 45),
                    class: 'event',
                    repeat: {
                        repeatFreq: 'weekly',
                        repeatInterval: 2,
                        repeatOn: [2, 4],
                        repeatEnd: new Date(2021, 5, 24)
                    }
                },
                {
                    label: 'Prepare Shipping Cost Analysis Report',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 12, 30),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 13, 30),
                    class: 'event',
                    repeat: {
                        repeatFreq: 'monthly',
                        repeatInterval: 1,
                        repeatOn: [new Date(currentYear, currentMonth, currentDate + 1)]
                    }
                }, {
                    label: 'Provide Feedback on Shippers',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 14, 15),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 16, 0),
                    status: 'tentative',
                    class: 'event'
                }, {
                    label: 'Complete Shipper Selection Form',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 8, 30),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 10, 0),
                    class: 'event'
                }, {
                    label: 'Upgrade Server Hardware',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 12, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 14, 15),
                    class: 'event'
                }, {
                    label: 'Upgrade Apps to Windows RT or stay with WinForms',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 2, this.today.getHours(), this.today.getMinutes() + 5),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 2, this.today.getHours() + 2),
                    status: 'tentative',
                    class: 'event',
                    repeat: {
                        repeatFreq: 'daily',
                        repeatInterval: 1,
                        repeatOn: currentDate + 1,
                        repeatEnd: new Date(currentYear, currentMonth, currentDate + 7),
                        exceptions: [{
                            date: new Date(currentYear, currentMonth, currentDate + 4, 10, 30),
                            label: 'A day off work',
                            status: 'busy',
                            backgroundColor: '#64DD17'
                        }]
                    },
                    notifications: [
                        {
                            interval: 2,
                            type: 'days',
                            time: [this.today.getHours(), this.today.getMinutes()],
                            message: 'Upgrade Apps to Windows RT in 5 minutes',
                            iconType: 'time'
                        }
                    ],
                },
                {
                    label: 'Peter\'s Birthday',
                    dateStart: new Date(currentYear, currentMonth, 5),
                    dateEnd: new Date(currentYear, currentMonth, 6),
                    class: 'birthday'
                },
                {
                    label: 'Michael\'s Brithday',
                    dateStart: new Date(currentYear, currentMonth, 10),
                    dateEnd: new Date(currentYear, currentMonth, 11),
                    class: 'birthday'
                },
                {
                    label: 'Christina\'s Birthday',
                    dateStart: new Date(currentYear, currentMonth, 20),
                    dateEnd: new Date(currentYear, currentMonth, 21),
                    class: 'birthday'
                }, {
                    label: 'Halloween',
                    dateStart: new Date(currentYear, 9, 31),
                    dateEnd: new Date(currentYear, 9, 32),
                    class: 'holiday'
                }, {
                    label: 'Marry Christmas',
                    dateStart: new Date(currentYear, 11, 24),
                    dateEnd: new Date(currentYear, 11, 26, 23, 59, 59),
                    class: 'holiday'
                },
                {
                    label: 'Thanksgiving',
                    dateStart: this.thanksgiving,
                    dateEnd: new Date(currentYear, 10, this.thanksgiving.getDate() + 1),
                    class: 'holiday'
                },
                {
                    label: 'Day after Thanksgiving',
                    dateStart: new Date(currentYear, 10, this.thanksgiving.getDate() + 1),
                    dateEnd: new Date(currentYear, 10, this.thanksgiving.getDate() + 2),
                    class: 'holiday'
                },
                {
                    label: 'Indipendence Day',
                    dateStart: new Date(currentYear, 6, 4),
                    dateEnd: new Date(currentYear, 6, 5),
                    class: 'holiday'
                },
                {
                    label: 'New Year\'s Eve',
                    dateStart: new Date(currentYear, 11, 31),
                    dateEnd: new Date(currentYear + 1, 0, 1),
                    class: 'holiday'
                }
            ];
        })();
    
        view: SchedulerViewType = 'month';
    
        views: any[] = ['day',
            {
                type: 'week',
                hideWeekend: true,
            },
            {
                type: 'month',
                hideWeekend: true,
            }, 'agenda',
            {
                label: '4 days',
                value: 'workWeek',
                type: 'week',
                shortcutKey: 'X',
                hideWeekend: false,
                hideNonworkingWeekdays: true,
            }];
    
        nonworkingDays: number[] = this.getPastThreeWeekdays(this.today.getDay());
    
        dataSource: any[] = this.data;
    
        firstDayOfWeek: number = 1;
    
        disableDateMenu: boolean = true;
    
        currentTimeIndicator: boolean = true;
    
        getPastThreeWeekdays(weekday: number) {
            let weekdays = [];
    
            for (let i = 0; i < 3; i++) {
                weekdays.push((weekday - i + 7) % 7);
            }
    
            return weekdays;
        }
    
        updateData(event: CustomEvent) {
            const item = event.detail.item,
                data = this.data;
    
            for (let i = 0; i < data.length; i++) {
                const dataItem = data[i];
    
                if (dataItem.label === item.label && dataItem.class === item.class) {
                    event.type === 'itemRemove' ? data.splice(i, 1) : data.splice(i, 1, item);
                    return;
                }
            }
        }
    
        scrollButtonsPosition: string = 'far';
    
        handleDateChange(event: CustomEvent) {
            this.calendar.selectedDates = [event.detail.value];
        }
    
        handleTreeChange(event: CustomEvent) {
            const tree = event.target as Tree,
                types = tree.selectedIndexes?.map((i) => (tree.getItem(i)).value);
    
            this.scheduler.dataSource = this.data.filter(d => (types || []).indexOf(d.class) > -1);
        }
    
        handleCalendarChange(event: CustomEvent) {
            this.scheduler.dateCurrent = event.detail.value;
        }
    
        addNew() {
            this.scheduler.openWindow({ class: 'event' });
        }
    
        handleToggle() {
            const primaryContainer = this.primaryContainer.nativeElement;
    
            primaryContainer.classList.toggle('collapse');
    
            this.scheduler.disableDateMenu = !primaryContainer.classList.contains('collapse');
        }
    
        ngOnInit(): void {
            // onInit code.
        }
    
        ngAfterViewInit(): void {
            // afterViewInit code.
            this.init();
        }
    
        init(): void {
            // init code.
        };
    }

  4. Example with Angular NGModule


    app.component.html

     <div id="primaryContainer" #primaryContainer>
        <div id="header">
            <smart-button #button id="toggleButton" (onClick)="handleToggle()"></smart-button>
            <div id="title">Scheduler</div>
            <smart-button #button2 id="addNew" class="floating" (onClick)="addNew()"><span>Create</span>
            </smart-button>
        </div>
        <div class="content">
            <section id="sideA">
                <div class="button-container">
                    <div id="logo"></div>
                </div>
                <div class="controls-container">
                    <smart-calendar #calendar id="calendar" [scrollButtonsPosition]="scrollButtonsPosition" (onChange)="handleCalendarChange($event)">
                    </smart-calendar>
                    <smart-input #input id="searchBar" class="underlined" [placeholder]="'Search for people'"></smart-input>
                    <smart-tree #tree id="tree" [selectionMode]="'checkBox'" [toggleElementPosition]="'far'"
                        (onChange)="handleTreeChange($event)">
                        <smart-tree-items-group [expanded]="true">My calendars
                            <smart-tree-item [value]="'birthday'" [selected]="true">Birthdays</smart-tree-item>
                            <smart-tree-item [value]="'holiday'" [selected]="true">Holidays</smart-tree-item>
                            <smart-tree-item [value]="'event'" [selected]="true">Events</smart-tree-item>
                        </smart-tree-items-group>
                    </smart-tree>
                </div>
            </section>
            <section id="sideB">
                <smart-scheduler #scheduler id="scheduler" [dataSource]="dataSource" [view]="view" [views]="views"
                    [nonworkingDays]="nonworkingDays" [dataSource]="dataSource" [firstDayOfWeek]="firstDayOfWeek"
                    [disableDateMenu]="disableDateMenu" [currentTimeIndicator]="currentTimeIndicator"
                    (onDragEnd)="updateData($event)" (onResizeEnd)="updateData($event)" (onItemUpdate)="updateData($event)"
                    (onItemRemove)="updateData($event)" (onDateChange)="handleDateChange($event)">
                </smart-scheduler>
            </section>
        </div>
    </div>

    app.component.ts

     import { Component, ViewChild, OnInit, AfterViewInit, ViewEncapsulation, ElementRef } from '@angular/core';
    import { ButtonComponent } from 'smart-webcomponents-angular/button';
    import { CalendarComponent } from 'smart-webcomponents-angular/calendar';
    import { InputComponent } from 'smart-webcomponents-angular/input';
    import { TreeComponent, Tree, TreeItem } from 'smart-webcomponents-angular/tree';
    import { SchedulerComponent, SchedulerViewType } from 'smart-webcomponents-angular/scheduler';
    
    
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css'],
        encapsulation: ViewEncapsulation.None
    })
    
    export class AppComponent implements AfterViewInit, OnInit {
        @ViewChild('button', { read: ButtonComponent, static: false }) button!: ButtonComponent;
        @ViewChild('button2', { read: ButtonComponent, static: false }) button2!: ButtonComponent;
        @ViewChild('calendar', { read: CalendarComponent, static: false }) calendar!: CalendarComponent;
        @ViewChild('input', { read: InputComponent, static: false }) input!: InputComponent;
        @ViewChild('tree', { read: TreeComponent, static: false }) tree!: TreeComponent;
        @ViewChild('scheduler', { read: SchedulerComponent, static: false }) scheduler!: SchedulerComponent;
        @ViewChild('primaryContainer', { read: ElementRef, static: false }) primaryContainer!: ElementRef;
    
        today = new Date();
    
        thanksgiving = (() => {
            const tempDate = new Date(this.today.getFullYear(), 10, 1);
    
            //4th Thursday of November
            tempDate.setDate(tempDate.getDate() - tempDate.getDay() + 25);
            return tempDate;
        })();
    
        data: any[] = (() => {
            const currentDate = this.today.getDate(),
                currentYear = this.today.getFullYear(),
                currentMonth = this.today.getMonth();
    
            return [
                {
                    label: 'Brochure Design Review',
                    dateStart: new Date(currentYear, currentMonth, 10, 13, 15),
                    dateEnd: new Date(currentYear, currentMonth, 12, 16, 15),
                    status: 'tentative',
                    class: 'event'
                }, {
                    label: 'Website Re-Design Plan',
                    dateStart: new Date(currentYear, currentMonth, 16, 16, 45),
                    dateEnd: new Date(currentYear, currentMonth, 18, 11, 15),
                    class: 'event'
                }, {
                    label: 'Update Sales Strategy Documents',
                    dateStart: new Date(currentYear, currentMonth, 2, 12, 0),
                    dateEnd: new Date(currentYear, currentMonth, 2, 13, 45),
                    class: 'event',
                    repeat: {
                        repeatFreq: 'daily',
                        repeatInterval: 2,
                        repeatEnd: 5,
                        exceptions: [
                            {
                                date: new Date(currentYear, currentMonth, 4, 12, 0),
                                label: 'Employee on sick leave. Reschedule for next day',
                                dateStart: new Date(currentYear, currentMonth, 5),
                                dateEnd: new Date(currentYear, currentMonth, 6),
                                status: 'outOfOffice',
                                backgroundColor: '#F06292'
                            },
                            {
                                date: new Date(currentYear, currentMonth, 8, 12, 0),
                                label: 'Employee on sick leave. Reschedule for next day',
                                dateStart: new Date(currentYear, currentMonth, 9),
                                dateEnd: new Date(currentYear, currentMonth, 10),
                                status: 'outOfOffice',
                                backgroundColor: '#FFA000'
                            }
                        ]
                    }
                }, {
                    label: 'Non-Compete Agreements',
                    dateStart: new Date(currentYear, currentMonth, currentDate - 1, 8, 15),
                    dateEnd: new Date(currentYear, currentMonth, currentDate - 1, 9, 0),
                    status: 'outOfOffice',
                    class: 'event'
                }, {
                    label: 'Approve Hiring of John Jeffers',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 10, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 11, 15),
                    notifications: [
                        {
                            interval: 1,
                            type: 'days',
                            time: [this.today.getHours(), this.today.getMinutes()],
                            message: 'Approve Hiring of John Jeffers tomorrow',
                            iconType: 'success'
                        }
                    ],
                    status: 'busy',
                    class: 'event'
                }, {
                    label: 'Update NDA Agreement',
                    dateStart: new Date(currentYear, currentMonth, currentDate - 2, 11, 45),
                    dateEnd: new Date(currentYear, currentMonth, currentDate - 2, 13, 45),
                    class: 'event'
                }, {
                    label: 'Update Employee Files with New NDA',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 2, 14, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 2, 16, 45),
                    class: 'event'
                }, {
                    label: 'Compete Agreements',
                    dateStart: new Date(currentYear, currentMonth, currentDate, this.today.getHours(), this.today.getMinutes() + 15),
                    dateEnd: new Date(currentYear, currentMonth, currentDate, this.today.getHours() + 1, 45),
                    notifications: [
                        {
                            interval: 0,
                            type: 'days',
                            time: [this.today.getHours(), this.today.getMinutes() + 1],
                            message: 'Compete Agreements in 15 minutes',
                            iconType: 'time'
                        },
                        {
                            interval: 0,
                            type: 'days',
                            time: [this.today.getHours(), this.today.getMinutes() + 2],
                            message: 'Compete Agreements in 14 minutes',
                            iconType: 'warning'
                        }
                    ],
                    status: 'outOfOffice',
                    class: 'event'
                }, {
                    label: 'Approve Hiring of Mark Waterberg',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 3, 10, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 3, 11, 15),
                    status: 'busy',
                    class: 'event'
                }, {
                    label: 'Update Employees Information',
                    dateStart: new Date(currentYear, currentMonth, currentDate, 14, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate, 16, 45),
                    class: 'event',
                    repeat: {
                        repeatFreq: 'weekly',
                        repeatInterval: 2,
                        repeatOn: [2, 4],
                        repeatEnd: new Date(2021, 5, 24)
                    }
                },
                {
                    label: 'Prepare Shipping Cost Analysis Report',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 12, 30),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 13, 30),
                    class: 'event',
                    repeat: {
                        repeatFreq: 'monthly',
                        repeatInterval: 1,
                        repeatOn: [new Date(currentYear, currentMonth, currentDate + 1)]
                    }
                }, {
                    label: 'Provide Feedback on Shippers',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 14, 15),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 16, 0),
                    status: 'tentative',
                    class: 'event'
                }, {
                    label: 'Complete Shipper Selection Form',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 8, 30),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 10, 0),
                    class: 'event'
                }, {
                    label: 'Upgrade Server Hardware',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 1, 12, 0),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 14, 15),
                    class: 'event'
                }, {
                    label: 'Upgrade Apps to Windows RT or stay with WinForms',
                    dateStart: new Date(currentYear, currentMonth, currentDate + 2, this.today.getHours(), this.today.getMinutes() + 5),
                    dateEnd: new Date(currentYear, currentMonth, currentDate + 2, this.today.getHours() + 2),
                    status: 'tentative',
                    class: 'event',
                    repeat: {
                        repeatFreq: 'daily',
                        repeatInterval: 1,
                        repeatOn: currentDate + 1,
                        repeatEnd: new Date(currentYear, currentMonth, currentDate + 7),
                        exceptions: [{
                            date: new Date(currentYear, currentMonth, currentDate + 4, 10, 30),
                            label: 'A day off work',
                            status: 'busy',
                            backgroundColor: '#64DD17'
                        }]
                    },
                    notifications: [
                        {
                            interval: 2,
                            type: 'days',
                            time: [this.today.getHours(), this.today.getMinutes()],
                            message: 'Upgrade Apps to Windows RT in 5 minutes',
                            iconType: 'time'
                        }
                    ],
                },
                {
                    label: 'Peter\'s Birthday',
                    dateStart: new Date(currentYear, currentMonth, 5),
                    dateEnd: new Date(currentYear, currentMonth, 6),
                    class: 'birthday'
                },
                {
                    label: 'Michael\'s Brithday',
                    dateStart: new Date(currentYear, currentMonth, 10),
                    dateEnd: new Date(currentYear, currentMonth, 11),
                    class: 'birthday'
                },
                {
                    label: 'Christina\'s Birthday',
                    dateStart: new Date(currentYear, currentMonth, 20),
                    dateEnd: new Date(currentYear, currentMonth, 21),
                    class: 'birthday'
                }, {
                    label: 'Halloween',
                    dateStart: new Date(currentYear, 9, 31),
                    dateEnd: new Date(currentYear, 9, 32),
                    class: 'holiday'
                }, {
                    label: 'Marry Christmas',
                    dateStart: new Date(currentYear, 11, 24),
                    dateEnd: new Date(currentYear, 11, 26, 23, 59, 59),
                    class: 'holiday'
                },
                {
                    label: 'Thanksgiving',
                    dateStart: this.thanksgiving,
                    dateEnd: new Date(currentYear, 10, this.thanksgiving.getDate() + 1),
                    class: 'holiday'
                },
                {
                    label: 'Day after Thanksgiving',
                    dateStart: new Date(currentYear, 10, this.thanksgiving.getDate() + 1),
                    dateEnd: new Date(currentYear, 10, this.thanksgiving.getDate() + 2),
                    class: 'holiday'
                },
                {
                    label: 'Indipendence Day',
                    dateStart: new Date(currentYear, 6, 4),
                    dateEnd: new Date(currentYear, 6, 5),
                    class: 'holiday'
                },
                {
                    label: 'New Year\'s Eve',
                    dateStart: new Date(currentYear, 11, 31),
                    dateEnd: new Date(currentYear + 1, 0, 1),
                    class: 'holiday'
                }
            ];
        })();
    
        view: SchedulerViewType = 'month';
    
        views: any[] = ['day',
            {
                type: 'week',
                hideWeekend: true,
            },
            {
                type: 'month',
                hideWeekend: true,
            }, 'agenda',
            {
                label: '4 days',
                value: 'workWeek',
                type: 'week',
                shortcutKey: 'X',
                hideWeekend: false,
                hideNonworkingWeekdays: true,
            }];
    
        nonworkingDays: number[] = this.getPastThreeWeekdays(this.today.getDay());
    
        dataSource: any[] = this.data;
    
        firstDayOfWeek: number = 1;
    
        disableDateMenu: boolean = true;
    
        currentTimeIndicator: boolean = true;
    
        getPastThreeWeekdays(weekday: number) {
            let weekdays = [];
    
            for (let i = 0; i < 3; i++) {
                weekdays.push((weekday - i + 7) % 7);
            }
    
            return weekdays;
        }
    
        updateData(event: CustomEvent) {
            const item = event.detail.item,
                data = this.data;
    
            for (let i = 0; i < data.length; i++) {
                const dataItem = data[i];
    
                if (dataItem.label === item.label && dataItem.class === item.class) {
                    event.type === 'itemRemove' ? data.splice(i, 1) : data.splice(i, 1, item);
                    return;
                }
            }
        }
    
        scrollButtonsPosition: string = 'far';
    
        handleDateChange(event: CustomEvent) {
            this.calendar.selectedDates = [event.detail.value];
        }
    
        handleTreeChange(event: CustomEvent) {
            const tree = event.target as Tree,
                types = tree.selectedIndexes?.map((i) => (tree.getItem(i)).value);
    
            this.scheduler.dataSource = this.data.filter(d => (types || []).indexOf(d.class) > -1);
        }
    
        handleCalendarChange(event: CustomEvent) {
            this.scheduler.dateCurrent = event.detail.value;
        }
    
        addNew() {
            this.scheduler.openWindow({ class: 'event' });
        }
    
        handleToggle() {
            const primaryContainer = this.primaryContainer.nativeElement;
    
            primaryContainer.classList.toggle('collapse');
    
            this.scheduler.disableDateMenu = !primaryContainer.classList.contains('collapse');
        }
    
        ngOnInit(): void {
            // onInit code.
        }
    
        ngAfterViewInit(): void {
            // afterViewInit code.
            this.init();
        }
    
        init(): void {
            // init code.
        };
    }

    app.module.ts

     import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    
    import { ButtonModule } from 'smart-webcomponents-angular/button';
    import { CalendarModule } from 'smart-webcomponents-angular/calendar';
    import { InputModule } from 'smart-webcomponents-angular/input';
    import { TreeModule } from 'smart-webcomponents-angular/tree';
    import { SchedulerModule } from 'smart-webcomponents-angular/scheduler';
    
    import { AppComponent } from './app.component';
    
    @NgModule({
        declarations: [ AppComponent ],
        imports: [ BrowserModule, ButtonModule, CalendarModule, InputModule, TreeModule, SchedulerModule ],
        bootstrap: [ AppComponent ]
    })
    
    export class AppModule { }


Running the Angular application

After completing the steps required to render a Scheduler, run the following command to display the output in your web browser

ng serve
and open localhost:4200 in your favorite web browser.

Read more about using Smart UI for Angular: https://www.htmlelements.com/docs/angular-cli/.

Getting Started with React Scheduler Component

Setup React Environment

The easiest way to start with React is to use NextJS Next.js is a full-stack React framework. It’s versatile and lets you create React apps of any size—from a mostly static blog to a complex dynamic application.

npx create-next-app my-app
cd my-app
npm run dev	
or
yarn create next-app my-app
cd my-app
yarn run dev

Preparation

Setup the Scheduler

Smart UI for React is distributed as smart-webcomponents-react package

  1. Download and install the package.

    In your React Next.js project, run one of the following commands to install Smart UI Scheduler for React

    With NPM:

    npm install smart-webcomponents-react
    With Yarn:
    yarn add smart-webcomponents-react

  2. Once installed, import the React Scheduler Component and CSS files in your application and render it. app.js

    import 'smart-webcomponents-react/source/styles/smart.default.css';
    import React from "react";
    import ReactDOM from 'react-dom/client';
    import { Button, RepeatButton, ToggleButton, PowerButton } from 'smart-webcomponents-react/button';
    import { Calendar } from 'smart-webcomponents-react/calendar';
    import { Input } from 'smart-webcomponents-react/input';
    import { Tree, TreeItem, TreeItemsGroup } from 'smart-webcomponents-react/tree';
    import { Scheduler } from 'smart-webcomponents-react/scheduler';
    
    class App extends React.Component {
    	constructor(props) {
    		super(props);
    
    		this.scheduler = React.createRef();
    		this.calendar = React.createRef();
    		this.tree = React.createRef();
    		this.primaryContainer = React.createRef();
    
    		const today = new Date(),
    			currentDate = today.getDate(),
    			currentYear = today.getFullYear(),
    			currentMonth = today.getMonth(),
    			currentHours = today.getHours(),
    			currentMinutes = today.getMinutes(),
    			thanksgiving = (() => {
    				const tempDate = new Date(currentYear, 10, 1);
    				//4th Thursday of November
    				tempDate.setDate(tempDate.getDate() - tempDate.getDay() + 25);
    				return tempDate;
    			})();
    
    		this.nonworkingDays = this.getPastThreeWeekdays(today.getDay());
    
    		this.data = [{
    			label: 'Brochure Design Review',
    			dateStart: new Date(currentYear, currentMonth, 10, 13, 15),
    			dateEnd: new Date(currentYear, currentMonth, 12, 16, 15),
    			status: 'tentative',
    			class: 'event'
    		}, {
    			label: 'Website Re-Design Plan',
    			dateStart: new Date(currentYear, currentMonth, 16, 16, 45),
    			dateEnd: new Date(currentYear, currentMonth, 18, 11, 15),
    			class: 'event'
    		}, {
    			label: 'Update Sales Strategy Documents',
    			dateStart: new Date(currentYear, currentMonth, 2, 12, 0),
    			dateEnd: new Date(currentYear, currentMonth, 2, 13, 45),
    			class: 'event',
    			repeat: {
    				repeatFreq: 'daily',
    				repeatInterval: 2,
    				repeatEnd: 5,
    				exceptions: [{
    					date: new Date(currentYear, currentMonth, 4, 12, 0),
    					label: 'Employee on sick leave. Reschedule for next day',
    					dateStart: new Date(currentYear, currentMonth, 5),
    					dateEnd: new Date(currentYear, currentMonth, 6),
    					status: 'outOfOffice',
    					backgroundColor: '#F06292'
    				},
    				{
    					date: new Date(currentYear, currentMonth, 8, 12, 0),
    					label: 'Employee on sick leave. Reschedule for next day',
    					dateStart: new Date(currentYear, currentMonth, 9),
    					dateEnd: new Date(currentYear, currentMonth, 10),
    					status: 'outOfOffice',
    					backgroundColor: '#FFA000'
    				}
    				]
    			}
    		}, {
    			label: 'Non-Compete Agreements',
    			dateStart: new Date(currentYear, currentMonth, currentDate - 1, 8, 15),
    			dateEnd: new Date(currentYear, currentMonth, currentDate - 1, 9, 0),
    			status: 'outOfOffice',
    			class: 'event'
    		}, {
    			label: 'Approve Hiring of John Jeffers',
    			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 10, 0),
    			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 11, 15),
    			notifications: [{
    				interval: 1,
    				type: 'days',
    				time: [currentHours, currentMinutes],
    				message: 'Approve Hiring of John Jeffers tomorrow',
    				iconType: 'success'
    			}],
    			status: 'busy',
    			class: 'event'
    		}, {
    			label: 'Update NDA Agreement',
    			dateStart: new Date(currentYear, currentMonth, currentDate - 2, 11, 45),
    			dateEnd: new Date(currentYear, currentMonth, currentDate - 2, 13, 45),
    			class: 'event'
    		}, {
    			label: 'Update Employee Files with New NDA',
    			dateStart: new Date(currentYear, currentMonth, currentDate + 2, 14, 0),
    			dateEnd: new Date(currentYear, currentMonth, currentDate + 2, 16, 45),
    			class: 'event'
    		}, {
    			label: 'Compete Agreements',
    			dateStart: new Date(currentYear, currentMonth, currentDate, currentHours, currentMinutes + 15),
    			dateEnd: new Date(currentYear, currentMonth, currentDate, currentHours + 1, 45),
    			notifications: [{
    				interval: 0,
    				type: 'days',
    				time: [currentHours, currentMinutes + 1],
    				message: 'Compete Agreements in 15 minutes',
    				iconType: 'time'
    			},
    			{
    				interval: 0,
    				type: 'days',
    				time: [currentHours, currentMinutes + 2],
    				message: 'Compete Agreements in 14 minutes',
    				iconType: 'warning'
    			}
    			],
    			status: 'outOfOffice',
    			class: 'event'
    		}, {
    			label: 'Approve Hiring of Mark Waterberg',
    			dateStart: new Date(currentYear, currentMonth, currentDate + 3, 10, 0),
    			dateEnd: new Date(currentYear, currentMonth, currentDate + 3, 11, 15),
    			status: 'busy',
    			class: 'event'
    		}, {
    			label: 'Update Employees Information',
    			dateStart: new Date(currentYear, currentMonth, currentDate, 14, 0),
    			dateEnd: new Date(currentYear, currentMonth, currentDate, 16, 45),
    			class: 'event',
    			repeat: {
    				repeatFreq: 'weekly',
    				repeatInterval: 2,
    				repeatOn: [2, 4],
    				repeatEnd: new Date(2021, 5, 24)
    			}
    		},
    		{
    			label: 'Prepare Shipping Cost Analysis Report',
    			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 12, 30),
    			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 13, 30),
    			class: 'event',
    			repeat: {
    				repeatFreq: 'monthly',
    				repeatInterval: 1,
    				repeatOn: [new Date(currentYear, currentMonth, currentDate + 1)]
    			}
    		}, {
    			label: 'Provide Feedback on Shippers',
    			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 14, 15),
    			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 16, 0),
    			status: 'tentative',
    			class: 'event'
    		}, {
    			label: 'Complete Shipper Selection Form',
    			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 8, 30),
    			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 10, 0),
    			class: 'event'
    		}, {
    			label: 'Upgrade Server Hardware',
    			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 12, 0),
    			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 14, 15),
    			class: 'event'
    		}, {
    			label: 'Upgrade Apps to Windows RT or stay with WinForms',
    			dateStart: new Date(currentYear, currentMonth, currentDate + 2, currentHours, currentMinutes + 5),
    			dateEnd: new Date(currentYear, currentMonth, currentDate + 2, currentHours + 2),
    			status: 'tentative',
    			class: 'event',
    			repeat: {
    				repeatFreq: 'daily',
    				repeatInterval: 1,
    				repeatOn: currentDate + 1,
    				repeatEnd: new Date(currentYear, currentMonth, currentDate + 7),
    				exceptions: [{
    					date: new Date(currentYear, currentMonth, currentDate + 4, 10, 30),
    					label: 'A day off work',
    					status: 'busy',
    					backgroundColor: '#64DD17'
    				}]
    			},
    			notifications: [{
    				interval: 2,
    				type: 'days',
    				time: [currentHours, currentMinutes],
    				message: 'Upgrade Apps to Windows RT in 5 minutes',
    				iconType: 'time'
    			}],
    		},
    		{
    			label: 'Peter\'s Birthday',
    			dateStart: new Date(currentYear, currentMonth, 5),
    			dateEnd: new Date(currentYear, currentMonth, 6),
    			class: 'birthday'
    		},
    		{
    			label: 'Michael\'s Brithday',
    			dateStart: new Date(currentYear, currentMonth, 10),
    			dateEnd: new Date(currentYear, currentMonth, 11),
    			class: 'birthday'
    		},
    		{
    			label: 'Christina\'s Birthday',
    			dateStart: new Date(currentYear, currentMonth, 20),
    			dateEnd: new Date(currentYear, currentMonth, 21),
    			class: 'birthday'
    		}, {
    			label: 'Halloween',
    			dateStart: new Date(currentYear, 9, 31),
    			dateEnd: new Date(currentYear, 9, 32),
    			class: 'holiday'
    		}, {
    			label: 'Marry Christmas',
    			dateStart: new Date(currentYear, 11, 24),
    			dateEnd: new Date(currentYear, 11, 26, 23, 59, 59),
    			class: 'holiday'
    		},
    		{
    			label: 'Thanksgiving',
    			dateStart: thanksgiving,
    			dateEnd: new Date(currentYear, 10, thanksgiving.getDate() + 1),
    			class: 'holiday'
    		},
    		{
    			label: 'Day after Thanksgiving',
    			dateStart: new Date(currentYear, 10, thanksgiving.getDate() + 1),
    			dateEnd: new Date(currentYear, 10, thanksgiving.getDate() + 2),
    			class: 'holiday'
    		},
    		{
    			label: 'Indipendence Day',
    			dateStart: new Date(currentYear, 6, 4),
    			dateEnd: new Date(currentYear, 6, 5),
    			class: 'holiday'
    		},
    		{
    			label: 'New Year\'s Eve',
    			dateStart: new Date(currentYear, 11, 31),
    			dateEnd: new Date(currentYear + 1, 0, 1),
    			class: 'holiday'
    		}
    		];
    	}
    
    	view = 'month';
    
    	views = ['day',
    		{
    			type: 'week',
    			hideWeekend: true,
    		},
    		{
    			type: 'month',
    			hideWeekend: true,
    		}, 'agenda',
    		{
    			label: '4 days',
    			value: 'workWeek',
    			type: 'week',
    			shortcutKey: 'X',
    			hideWeekend: false,
    			hideNonworkingWeekdays: true,
    		}
    	];
    
    	firstDayOfWeek = 1;
    
    	disableDateMenu = true;
    
    	currentTimeIndicator = true;
    
    	scrollButtonsPosition = 'far';
    
    	getPastThreeWeekdays(weekday) {
    		let weekdays = [];
    
    		for (let i = 0; i < 3; i++) {
    			weekdays.push((weekday - i + 7) % 7);
    		}
    
    		return weekdays;
    	}
    
    	updateData(event) {
    		const item = event.detail.item,
    			data = this.data;
    
    		for (let i = 0; i < data.length; i++) {
    			const dataItem = data[i];
    
    			if (dataItem.label === item.label && dataItem.class === item.class) {
    				event.type === 'itemRemove' ? this.data.splice(i, 1) : data.splice(i, 1, item);
    				return;
    			}
    		}
    	}
    
    	handleToggle() {
    		const primaryContainer = this.primaryContainer.current,
    			scheduler = this.scheduler.current;
    
    		primaryContainer.classList.toggle('collapse');
    		scheduler.disableDateMenu = !primaryContainer.classList.contains('collapse');
    	}
    
    	addNew() {
    		this.scheduler.current.openWindow({
    			class: 'event'
    		});
    	}
    
    	handleCalendarChange(event) {
    		this.scheduler.current.dateCurrent = event.detail.value;
    	}
    
    	handleTreeChange() {
    		const tree = this.tree.current;
    		let selectedIndexes = tree.selectedIndexes, types = [];
    
    		for (let i = 0; i < selectedIndexes.length; i++) {
    			tree.getItem(selectedIndexes[i]).then(result => {
    				types.push(result.value);
    
    				if (i === selectedIndexes.length - 1) {
    					this.scheduler.current.dataSource = this.data.filter(d => types.indexOf(d.class) > -1);
    				}
    			});
    		}
    	}
    
    	handleDateChange(event) {
    		this.calendar.current.selectedDates = [event.detail.value];
    	}
    
    	init() {
    	}
    
    	componentDidMount() {
    		this.init();
    	}
    
    	render() {
    		return (
    			<div>
    				<div id="primaryContainer" ref={this.primaryContainer}>
    					<div id="header">
    						<Button id="toggleButton" onClick={this.handleToggle.bind(this)}></Button>
    						<div id="title">Scheduler</div>
    						<Button id="addNew" className="floating" onClick={this.addNew.bind(this)}><span>Create</span>
    						</Button>
    					</div>
    					<div className="content">
    						<section id="sideA">
    							<div className="button-container">
    								<div id="logo"></div>
    							</div>
    							<div className="controls-container">
    								<Calendar ref={this.calendar} id="calendar" scrollButtonsPosition={this.scrollButtonsPosition} onChange={this.handleCalendarChange.bind(this)}></Calendar>
    								<Input id="searchBar" className="underlined" placeholder="Search for people"></Input>
    								<Tree ref={this.tree} id="tree" selectionMode="checkBox" toggleElementPosition="far" onChange={this.handleTreeChange.bind(this)}>
    									<TreeItemsGroup expanded>My calendars
    			                            <TreeItem value="birthday" selected>Birthdays</TreeItem>
    										<TreeItem value="holiday" selected>Holidays</TreeItem>
    										<TreeItem value="event" selected>Events</TreeItem>
    									</TreeItemsGroup>
    								</Tree>
    							</div>
    						</section>
    						<section id="sideB">
    							<Scheduler ref={this.scheduler} id="scheduler" dataSource={this.data} view={this.view} views={this.views} nonworkingDays={this.nonworkingDays}
    								firstDayOfWeek={this.firstDayOfWeek}
    								disableDateMenu={this.disableDateMenu}
    								currentTimeIndicator={this.currentTimeIndicator}
    								scrollButtonsPosition={this.scrollButtonsPosition} onDragEnd={this.updateData.bind(this)}
    								onResizeEnd={this.updateData.bind(this)} onItemUpdate={this.updateData.bind(this)}
    								onItemRemove={this.updateData.bind(this)} onDateChange={this.handleDateChange.bind(this)}></Scheduler>
    						</section>
    					</div>
    				</div>
    			</div>
    		);
    	}
    }
    
    
    
    export default App;
    	

Running the React application

Start the app with
npm run dev
or
yarn run dev
and open localhost:3000 in your favorite web browser to see the output.

Setup with Vite

Vite (French word for "quick", pronounced /vit/, like "veet") is a build tool that aims to provide a faster and leaner development experience for modern web projects
With NPM:
npm create vite@latest
With Yarn:
yarn create vite
Then follow the prompts and choose React as a project.

Navigate to your project's directory. By default it is 'vite-project' and install Smart UI for React

In your Vite project, run one of the following commands to install Smart UI Scheduler for React

With NPM:

npm install smart-webcomponents-react
With Yarn:
yarn add smart-webcomponents-react

Open src/App.tsx App.tsx

import 'smart-webcomponents-react/source/styles/smart.default.css';
import React from "react";
import ReactDOM from 'react-dom/client';
import { Button, RepeatButton, ToggleButton, PowerButton } from 'smart-webcomponents-react/button';
import { Calendar } from 'smart-webcomponents-react/calendar';
import { Input } from 'smart-webcomponents-react/input';
import { Tree, TreeItem, TreeItemsGroup } from 'smart-webcomponents-react/tree';
import { Scheduler } from 'smart-webcomponents-react/scheduler';

class App extends React.Component {
	constructor(props) {
		super(props);

		this.scheduler = React.createRef();
		this.calendar = React.createRef();
		this.tree = React.createRef();
		this.primaryContainer = React.createRef();

		const today = new Date(),
			currentDate = today.getDate(),
			currentYear = today.getFullYear(),
			currentMonth = today.getMonth(),
			currentHours = today.getHours(),
			currentMinutes = today.getMinutes(),
			thanksgiving = (() => {
				const tempDate = new Date(currentYear, 10, 1);
				//4th Thursday of November
				tempDate.setDate(tempDate.getDate() - tempDate.getDay() + 25);
				return tempDate;
			})();

		this.nonworkingDays = this.getPastThreeWeekdays(today.getDay());

		this.data = [{
			label: 'Brochure Design Review',
			dateStart: new Date(currentYear, currentMonth, 10, 13, 15),
			dateEnd: new Date(currentYear, currentMonth, 12, 16, 15),
			status: 'tentative',
			class: 'event'
		}, {
			label: 'Website Re-Design Plan',
			dateStart: new Date(currentYear, currentMonth, 16, 16, 45),
			dateEnd: new Date(currentYear, currentMonth, 18, 11, 15),
			class: 'event'
		}, {
			label: 'Update Sales Strategy Documents',
			dateStart: new Date(currentYear, currentMonth, 2, 12, 0),
			dateEnd: new Date(currentYear, currentMonth, 2, 13, 45),
			class: 'event',
			repeat: {
				repeatFreq: 'daily',
				repeatInterval: 2,
				repeatEnd: 5,
				exceptions: [{
					date: new Date(currentYear, currentMonth, 4, 12, 0),
					label: 'Employee on sick leave. Reschedule for next day',
					dateStart: new Date(currentYear, currentMonth, 5),
					dateEnd: new Date(currentYear, currentMonth, 6),
					status: 'outOfOffice',
					backgroundColor: '#F06292'
				},
				{
					date: new Date(currentYear, currentMonth, 8, 12, 0),
					label: 'Employee on sick leave. Reschedule for next day',
					dateStart: new Date(currentYear, currentMonth, 9),
					dateEnd: new Date(currentYear, currentMonth, 10),
					status: 'outOfOffice',
					backgroundColor: '#FFA000'
				}
				]
			}
		}, {
			label: 'Non-Compete Agreements',
			dateStart: new Date(currentYear, currentMonth, currentDate - 1, 8, 15),
			dateEnd: new Date(currentYear, currentMonth, currentDate - 1, 9, 0),
			status: 'outOfOffice',
			class: 'event'
		}, {
			label: 'Approve Hiring of John Jeffers',
			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 10, 0),
			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 11, 15),
			notifications: [{
				interval: 1,
				type: 'days',
				time: [currentHours, currentMinutes],
				message: 'Approve Hiring of John Jeffers tomorrow',
				iconType: 'success'
			}],
			status: 'busy',
			class: 'event'
		}, {
			label: 'Update NDA Agreement',
			dateStart: new Date(currentYear, currentMonth, currentDate - 2, 11, 45),
			dateEnd: new Date(currentYear, currentMonth, currentDate - 2, 13, 45),
			class: 'event'
		}, {
			label: 'Update Employee Files with New NDA',
			dateStart: new Date(currentYear, currentMonth, currentDate + 2, 14, 0),
			dateEnd: new Date(currentYear, currentMonth, currentDate + 2, 16, 45),
			class: 'event'
		}, {
			label: 'Compete Agreements',
			dateStart: new Date(currentYear, currentMonth, currentDate, currentHours, currentMinutes + 15),
			dateEnd: new Date(currentYear, currentMonth, currentDate, currentHours + 1, 45),
			notifications: [{
				interval: 0,
				type: 'days',
				time: [currentHours, currentMinutes + 1],
				message: 'Compete Agreements in 15 minutes',
				iconType: 'time'
			},
			{
				interval: 0,
				type: 'days',
				time: [currentHours, currentMinutes + 2],
				message: 'Compete Agreements in 14 minutes',
				iconType: 'warning'
			}
			],
			status: 'outOfOffice',
			class: 'event'
		}, {
			label: 'Approve Hiring of Mark Waterberg',
			dateStart: new Date(currentYear, currentMonth, currentDate + 3, 10, 0),
			dateEnd: new Date(currentYear, currentMonth, currentDate + 3, 11, 15),
			status: 'busy',
			class: 'event'
		}, {
			label: 'Update Employees Information',
			dateStart: new Date(currentYear, currentMonth, currentDate, 14, 0),
			dateEnd: new Date(currentYear, currentMonth, currentDate, 16, 45),
			class: 'event',
			repeat: {
				repeatFreq: 'weekly',
				repeatInterval: 2,
				repeatOn: [2, 4],
				repeatEnd: new Date(2021, 5, 24)
			}
		},
		{
			label: 'Prepare Shipping Cost Analysis Report',
			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 12, 30),
			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 13, 30),
			class: 'event',
			repeat: {
				repeatFreq: 'monthly',
				repeatInterval: 1,
				repeatOn: [new Date(currentYear, currentMonth, currentDate + 1)]
			}
		}, {
			label: 'Provide Feedback on Shippers',
			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 14, 15),
			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 16, 0),
			status: 'tentative',
			class: 'event'
		}, {
			label: 'Complete Shipper Selection Form',
			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 8, 30),
			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 10, 0),
			class: 'event'
		}, {
			label: 'Upgrade Server Hardware',
			dateStart: new Date(currentYear, currentMonth, currentDate + 1, 12, 0),
			dateEnd: new Date(currentYear, currentMonth, currentDate + 1, 14, 15),
			class: 'event'
		}, {
			label: 'Upgrade Apps to Windows RT or stay with WinForms',
			dateStart: new Date(currentYear, currentMonth, currentDate + 2, currentHours, currentMinutes + 5),
			dateEnd: new Date(currentYear, currentMonth, currentDate + 2, currentHours + 2),
			status: 'tentative',
			class: 'event',
			repeat: {
				repeatFreq: 'daily',
				repeatInterval: 1,
				repeatOn: currentDate + 1,
				repeatEnd: new Date(currentYear, currentMonth, currentDate + 7),
				exceptions: [{
					date: new Date(currentYear, currentMonth, currentDate + 4, 10, 30),
					label: 'A day off work',
					status: 'busy',
					backgroundColor: '#64DD17'
				}]
			},
			notifications: [{
				interval: 2,
				type: 'days',
				time: [currentHours, currentMinutes],
				message: 'Upgrade Apps to Windows RT in 5 minutes',
				iconType: 'time'
			}],
		},
		{
			label: 'Peter\'s Birthday',
			dateStart: new Date(currentYear, currentMonth, 5),
			dateEnd: new Date(currentYear, currentMonth, 6),
			class: 'birthday'
		},
		{
			label: 'Michael\'s Brithday',
			dateStart: new Date(currentYear, currentMonth, 10),
			dateEnd: new Date(currentYear, currentMonth, 11),
			class: 'birthday'
		},
		{
			label: 'Christina\'s Birthday',
			dateStart: new Date(currentYear, currentMonth, 20),
			dateEnd: new Date(currentYear, currentMonth, 21),
			class: 'birthday'
		}, {
			label: 'Halloween',
			dateStart: new Date(currentYear, 9, 31),
			dateEnd: new Date(currentYear, 9, 32),
			class: 'holiday'
		}, {
			label: 'Marry Christmas',
			dateStart: new Date(currentYear, 11, 24),
			dateEnd: new Date(currentYear, 11, 26, 23, 59, 59),
			class: 'holiday'
		},
		{
			label: 'Thanksgiving',
			dateStart: thanksgiving,
			dateEnd: new Date(currentYear, 10, thanksgiving.getDate() + 1),
			class: 'holiday'
		},
		{
			label: 'Day after Thanksgiving',
			dateStart: new Date(currentYear, 10, thanksgiving.getDate() + 1),
			dateEnd: new Date(currentYear, 10, thanksgiving.getDate() + 2),
			class: 'holiday'
		},
		{
			label: 'Indipendence Day',
			dateStart: new Date(currentYear, 6, 4),
			dateEnd: new Date(currentYear, 6, 5),
			class: 'holiday'
		},
		{
			label: 'New Year\'s Eve',
			dateStart: new Date(currentYear, 11, 31),
			dateEnd: new Date(currentYear + 1, 0, 1),
			class: 'holiday'
		}
		];
	}

	view = 'month';

	views = ['day',
		{
			type: 'week',
			hideWeekend: true,
		},
		{
			type: 'month',
			hideWeekend: true,
		}, 'agenda',
		{
			label: '4 days',
			value: 'workWeek',
			type: 'week',
			shortcutKey: 'X',
			hideWeekend: false,
			hideNonworkingWeekdays: true,
		}
	];

	firstDayOfWeek = 1;

	disableDateMenu = true;

	currentTimeIndicator = true;

	scrollButtonsPosition = 'far';

	getPastThreeWeekdays(weekday) {
		let weekdays = [];

		for (let i = 0; i < 3; i++) {
			weekdays.push((weekday - i + 7) % 7);
		}

		return weekdays;
	}

	updateData(event) {
		const item = event.detail.item,
			data = this.data;

		for (let i = 0; i < data.length; i++) {
			const dataItem = data[i];

			if (dataItem.label === item.label && dataItem.class === item.class) {
				event.type === 'itemRemove' ? this.data.splice(i, 1) : data.splice(i, 1, item);
				return;
			}
		}
	}

	handleToggle() {
		const primaryContainer = this.primaryContainer.current,
			scheduler = this.scheduler.current;

		primaryContainer.classList.toggle('collapse');
		scheduler.disableDateMenu = !primaryContainer.classList.contains('collapse');
	}

	addNew() {
		this.scheduler.current.openWindow({
			class: 'event'
		});
	}

	handleCalendarChange(event) {
		this.scheduler.current.dateCurrent = event.detail.value;
	}

	handleTreeChange() {
		const tree = this.tree.current;
		let selectedIndexes = tree.selectedIndexes, types = [];

		for (let i = 0; i < selectedIndexes.length; i++) {
			tree.getItem(selectedIndexes[i]).then(result => {
				types.push(result.value);

				if (i === selectedIndexes.length - 1) {
					this.scheduler.current.dataSource = this.data.filter(d => types.indexOf(d.class) > -1);
				}
			});
		}
	}

	handleDateChange(event) {
		this.calendar.current.selectedDates = [event.detail.value];
	}

	init() {
	}

	componentDidMount() {
		this.init();
	}

	render() {
		return (
			<div>
				<div id="primaryContainer" ref={this.primaryContainer}>
					<div id="header">
						<Button id="toggleButton" onClick={this.handleToggle.bind(this)}></Button>
						<div id="title">Scheduler</div>
						<Button id="addNew" className="floating" onClick={this.addNew.bind(this)}><span>Create</span>
						</Button>
					</div>
					<div className="content">
						<section id="sideA">
							<div className="button-container">
								<div id="logo"></div>
							</div>
							<div className="controls-container">
								<Calendar ref={this.calendar} id="calendar" scrollButtonsPosition={this.scrollButtonsPosition} onChange={this.handleCalendarChange.bind(this)}></Calendar>
								<Input id="searchBar" className="underlined" placeholder="Search for people"></Input>
								<Tree ref={this.tree} id="tree" selectionMode="checkBox" toggleElementPosition="far" onChange={this.handleTreeChange.bind(this)}>
									<TreeItemsGroup expanded>My calendars
			                            <TreeItem value="birthday" selected>Birthdays</TreeItem>
										<TreeItem value="holiday" selected>Holidays</TreeItem>
										<TreeItem value="event" selected>Events</TreeItem>
									</TreeItemsGroup>
								</Tree>
							</div>
						</section>
						<section id="sideB">
							<Scheduler ref={this.scheduler} id="scheduler" dataSource={this.data} view={this.view} views={this.views} nonworkingDays={this.nonworkingDays}
								firstDayOfWeek={this.firstDayOfWeek}
								disableDateMenu={this.disableDateMenu}
								currentTimeIndicator={this.currentTimeIndicator}
								scrollButtonsPosition={this.scrollButtonsPosition} onDragEnd={this.updateData.bind(this)}
								onResizeEnd={this.updateData.bind(this)} onItemUpdate={this.updateData.bind(this)}
								onItemRemove={this.updateData.bind(this)} onDateChange={this.handleDateChange.bind(this)}></Scheduler>
						</section>
					</div>
				</div>
			</div>
		);
	}
}



export default App;
	

Read more about using Smart UI for React: https://www.htmlelements.com/docs/react/.

Getting Started with Vue Scheduler Component


Setup Vue with Vite

In this section we will introduce how to scaffold a Vue Single Page Application on your local machine. The created project will be using a build setup based on Vite and allow us to use Vue Single-File Components (SFCs). Run the following command in your command line
npm create vue@latest
This command will install and execute create-vue, the official Vue project scaffolding tool. You will be presented with prompts for several optional features such as TypeScript and testing support:
✔ Project name: … 
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add an End-to-End Testing Solution? … No / Cypress / Playwright
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./...
Done.
If you are unsure about an option, simply choose No by hitting enter for now. Once the project is created, follow the instructions to install dependencies and start the dev server:
cd 
npm install
npm install smart-webcomponents
npm run dev
  • Make Vue ignore custom elements defined outside of Vue (e.g., using the Web Components APIs). Otherwise, it will throw a warning about an Unknown custom element, assuming that you forgot to register a global component or misspelled a component name.

    Open vite.config.js in your favorite text editor and change its contents to the following:

    vite.config.js

    import { fileURLToPath, URL } from 'node:url'
    
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [
        vue({
          template: {
            compilerOptions: {
              isCustomElement: tag => tag.startsWith('smart-')
            }
          }
        })
      ],
      resolve: {
        alias: {
          '@': fileURLToPath(new URL('./src', import.meta.url))
        }
      }
    })
    		
  • Open src/App.vue in your favorite text editor and change its contents to the following:

    App.vue

    <template>
      <div class="vue-root">
        <div id="primaryContainer">
          <div id="header">
            <smart-button id="toggleButton"></smart-button>
            <div id="title">Scheduler</div>
            <smart-button id="addNew" class="floating"
              ><span>Create</span>
            </smart-button>
          </div>
          <div class="content">
            <section id="sideA">
              <div class="button-container">
                <div id="logo"></div>
              </div>
              <div class="controls-container">
                <smart-calendar id="calendar"></smart-calendar>
                <smart-input
                  id="searchBar"
                  class="underlined"
                  placeholder="Search for people"
                ></smart-input>
                <smart-tree
                  id="tree"
                  selection-mode="checkBox"
                  toggle-element-position="far"
                >
                  <smart-tree-items-group expanded
                    >My calendars
                    <smart-tree-item value="birthday" selected
                      >Birthdays</smart-tree-item
                    >
                    <smart-tree-item value="holiday" selected
                      >Holidays</smart-tree-item
                    >
                    <smart-tree-item value="event" selected>Events</smart-tree-item>
                  </smart-tree-items-group>
                </smart-tree>
              </div>
            </section>
            <section id="sideB">
              <smart-scheduler id="scheduler"></smart-scheduler>
            </section>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import { onMounted } from "vue";
    import "smart-webcomponents/source/styles/smart.default.css";
    import "smart-webcomponents/source/modules/smart.button.js";
    import "smart-webcomponents/source/modules/smart.calendar.js";
    import "smart-webcomponents/source/modules/smart.input.js";
    import "smart-webcomponents/source/modules/smart.tree.js";
    import "smart-webcomponents/source/modules/smart.scheduler.js";
    import * as pkg from 'smart-webcomponents/common/rrule.min.js';
    window.rrule = { RRule:  pkg.default };
    export default {
      name: "app",
      setup() {
        onMounted(() => {
          const today = new Date(),
            currentDate = today.getDate(),
            currentYear = today.getFullYear(),
            currentMonth = today.getMonth(),
            thanksgiving = (() => {
              const tempDate = new Date(currentYear, 10, 1);
              //4th Thursday of November
              tempDate.setDate(tempDate.getDate() - tempDate.getDay() + 25);
              return tempDate;
            })(),
            data = [
              {
                label: "Brochure Design Review",
                dateStart: new Date(currentYear, currentMonth, 10, 13, 15),
                dateEnd: new Date(currentYear, currentMonth, 12, 16, 15),
                status: "tentative",
                class: "event",
              },
              {
                label: "Website Re-Design Plan",
                dateStart: new Date(currentYear, currentMonth, 16, 16, 45),
                dateEnd: new Date(currentYear, currentMonth, 18, 11, 15),
                class: "event",
              },
              {
                label: "Update Sales Strategy Documents",
                dateStart: new Date(currentYear, currentMonth, 2, 12, 0),
                dateEnd: new Date(currentYear, currentMonth, 2, 13, 45),
                class: "event",
                repeat: {
                  repeatFreq: "daily",
                  repeatInterval: 2,
                  repeatEnd: 5,
                  exceptions: [
                    {
                      date: new Date(currentYear, currentMonth, 4, 12, 0),
                      label: "Employee on sick leave. Reschedule for next day",
                      dateStart: new Date(currentYear, currentMonth, 5),
                      dateEnd: new Date(currentYear, currentMonth, 6),
                      status: "outOfOffice",
                      backgroundColor: "#F06292",
                    },
                    {
                      date: new Date(currentYear, currentMonth, 8, 12, 0),
                      label: "Employee on sick leave. Reschedule for next day",
                      dateStart: new Date(currentYear, currentMonth, 9),
                      dateEnd: new Date(currentYear, currentMonth, 10),
                      status: "outOfOffice",
                      backgroundColor: "#FFA000",
                    },
                  ],
                },
              },
              {
                label: "Non-Compete Agreements",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate - 1,
                  8,
                  15
                ),
                dateEnd: new Date(currentYear, currentMonth, currentDate - 1, 9, 0),
                status: "outOfOffice",
                class: "event",
              },
              {
                label: "Approve Hiring of John Jeffers",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  10,
                  0
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  11,
                  15
                ),
                notifications: [
                  {
                    interval: 1,
                    type: "days",
                    time: [today.getHours(), today.getMinutes()],
                    message: "Approve Hiring of John Jeffers tomorrow",
                    iconType: "success",
                  },
                ],
                status: "busy",
                class: "event",
              },
              {
                label: "Update NDA Agreement",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate - 2,
                  11,
                  45
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate - 2,
                  13,
                  45
                ),
                class: "event",
              },
              {
                label: "Update Employee Files with New NDA",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 2,
                  14,
                  0
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 2,
                  16,
                  45
                ),
                class: "event",
              },
              {
                label: "Compete Agreements",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate,
                  today.getHours(),
                  today.getMinutes() + 15
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate,
                  today.getHours() + 1,
                  45
                ),
                notifications: [
                  {
                    interval: 0,
                    type: "days",
                    time: [today.getHours(), today.getMinutes() + 1],
                    message: "Compete Agreements in 15 minutes",
                    iconType: "time",
                  },
                  {
                    interval: 0,
                    type: "days",
                    time: [today.getHours(), today.getMinutes() + 2],
                    message: "Compete Agreements in 14 minutes",
                    iconType: "warning",
                  },
                ],
                status: "outOfOffice",
                class: "event",
              },
              {
                label: "Approve Hiring of Mark Waterberg",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 3,
                  10,
                  0
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 3,
                  11,
                  15
                ),
                status: "busy",
                class: "event",
              },
              {
                label: "Update Employees Information",
                dateStart: new Date(currentYear, currentMonth, currentDate, 14, 0),
                dateEnd: new Date(currentYear, currentMonth, currentDate, 16, 45),
                class: "event",
                repeat: {
                  repeatFreq: "weekly",
                  repeatInterval: 2,
                  repeatOn: [2, 4],
                  repeatEnd: new Date(2021, 5, 24),
                },
              },
              {
                label: "Prepare Shipping Cost Analysis Report",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  12,
                  30
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  13,
                  30
                ),
                class: "event",
                repeat: {
                  repeatFreq: "monthly",
                  repeatInterval: 1,
                  repeatOn: [new Date(currentYear, currentMonth, currentDate + 1)],
                },
              },
              {
                label: "Provide Feedback on Shippers",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  14,
                  15
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  16,
                  0
                ),
                status: "tentative",
                class: "event",
              },
              {
                label: "Complete Shipper Selection Form",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  8,
                  30
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  10,
                  0
                ),
                class: "event",
              },
              {
                label: "Upgrade Server Hardware",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  12,
                  0
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 1,
                  14,
                  15
                ),
                class: "event",
              },
              {
                label: "Upgrade Apps to Windows RT or stay with WinForms",
                dateStart: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 2,
                  today.getHours(),
                  today.getMinutes() + 5
                ),
                dateEnd: new Date(
                  currentYear,
                  currentMonth,
                  currentDate + 2,
                  today.getHours() + 2
                ),
                status: "tentative",
                class: "event",
                repeat: {
                  repeatFreq: "daily",
                  repeatInterval: 1,
                  repeatOn: currentDate + 1,
                  repeatEnd: new Date(currentYear, currentMonth, currentDate + 7),
                  exceptions: [
                    {
                      date: new Date(
                        currentYear,
                        currentMonth,
                        currentDate + 4,
                        10,
                        30
                      ),
                      label: "A day off work",
                      status: "busy",
                      backgroundColor: "#64DD17",
                    },
                  ],
                },
                notifications: [
                  {
                    interval: 2,
                    type: "days",
                    time: [today.getHours(), today.getMinutes()],
                    message: "Upgrade Apps to Windows RT in 5 minutes",
                    iconType: "time",
                  },
                ],
              },
              {
                label: "Peter's Birthday",
                dateStart: new Date(currentYear, currentMonth, 5),
                dateEnd: new Date(currentYear, currentMonth, 6),
                class: "birthday",
              },
              {
                label: "Michael's Brithday",
                dateStart: new Date(currentYear, currentMonth, 10),
                dateEnd: new Date(currentYear, currentMonth, 11),
                class: "birthday",
              },
              {
                label: "Christina's Birthday",
                dateStart: new Date(currentYear, currentMonth, 20),
                dateEnd: new Date(currentYear, currentMonth, 21),
                class: "birthday",
              },
              {
                label: "Halloween",
                dateStart: new Date(currentYear, 9, 31),
                dateEnd: new Date(currentYear, 9, 32),
                class: "holiday",
              },
              {
                label: "Marry Christmas",
                dateStart: new Date(currentYear, 11, 24),
                dateEnd: new Date(currentYear, 11, 26, 23, 59, 59),
                class: "holiday",
              },
              {
                label: "Thanksgiving",
                dateStart: thanksgiving,
                dateEnd: new Date(currentYear, 10, thanksgiving.getDate() + 1),
                class: "holiday",
              },
              {
                label: "Day after Thanksgiving",
                dateStart: new Date(currentYear, 10, thanksgiving.getDate() + 1),
                dateEnd: new Date(currentYear, 10, thanksgiving.getDate() + 2),
                class: "holiday",
              },
              {
                label: "Indipendence Day",
                dateStart: new Date(currentYear, 6, 4),
                dateEnd: new Date(currentYear, 6, 5),
                class: "holiday",
              },
              {
                label: "New Year's Eve",
                dateStart: new Date(currentYear, 11, 31),
                dateEnd: new Date(currentYear + 1, 0, 1),
                class: "holiday",
              },
            ];
    
          window.Smart(
            "#scheduler",
            class {
              get properties() {
                return {
                  //Properties
                  view: "month",
                  views: [
                    "day",
                    {
                      type: "week",
                      hideWeekend: true,
                    },
                    {
                      type: "month",
                      hideWeekend: true,
                    },
                    "agenda",
                    {
                      label: "4 days",
                      value: "workWeek",
                      type: "week",
                      shortcutKey: "X",
                      hideWeekend: false,
                      hideNonworkingWeekdays: true,
                    },
                  ],
                  nonworkingDays: getPastThreeWeekdays(today.getDay()),
                  dateCurrent: new Date(),
                  dataSource: data,
                  firstDayOfWeek: 1,
                  disableDateMenu: true,
                  currentTimeIndicator: true
                };
              }
            }
          );
    
          window.Smart(
            "#calendar",
            class {
              get properties() {
                return {
                  //Properties
                  scrollButtonsPosition: "far"
                };
              }
            }
          );
    
          const primaryContainer = document.getElementById("primaryContainer"),
            calendar = document.getElementById("calendar"),
            scheduler = document.querySelector("smart-scheduler");
    
          document
            .getElementById("toggleButton")
            .addEventListener("click", function () {
              primaryContainer.classList.toggle("collapse");
              scheduler.disableDateMenu = !primaryContainer.classList.contains(
                "collapse"
              );
            });
    
          document.getElementById("addNew").addEventListener("click", function () {
            scheduler.openWindow({
              class: "event",
            });
          });
    
          document
            .getElementById("calendar")
            .addEventListener("change", function (event) {
              scheduler.dateCurrent = event.detail.value;
            });
    
          document
            .getElementById("tree")
            .addEventListener("change", function (event) {
              const tree = event.target,
                types = tree.selectedIndexes.map((i) => tree.getItem(i).value);
              scheduler.dataSource = data.filter(
                (d) => types.indexOf(d.class) > -1
              );
            });
    
          scheduler.addEventListener("dragEnd", updateData);
          scheduler.addEventListener("resizeEnd", updateData);
          scheduler.addEventListener("itemUpdate", updateData);
          scheduler.addEventListener("itemRemove", updateData);
    
          //Update the Calendar date
          scheduler.addEventListener("dateChange", function (event) {
            calendar.selectedDates = [event.detail.value];
          });
    
          function updateData(event) {
            const item = event.detail.item;
    
            for (let i = 0; i < data.length; i++) {
              const dataItem = data[i];
              if (dataItem.label === item.label && dataItem.class === item.class) {
                event.type === "itemRemove"
                  ? data.splice(i, 1)
                  : data.splice(i, 1, item);
                return;
              }
            }
          }
    
          function getPastThreeWeekdays(weekday) {
            let weekdays = [];
    
            for (let i = 0; i < 3; i++) {
              weekdays.push((weekday - i + 7) % 7);
            }
            return weekdays;
          }
        });
      }
    };
    </script>
    
    <style>
    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0 auto;
      --smart-scheduler-timeline-cell-min-width: 40px;
      --smart-scheduler-event-border-radius: 4px;
      --smart-scheduler-timeline-nonworking-color: var(--smart-background);
    }
    
    #app,
    .vue-root {
      height: 100%;
    }
    
    .smart-scheduler {
      width: 100%;
      height: 100%;
      border-radius: initial;
    }
    
    #primaryContainer,
    #primaryContainer .content {
      width: 100%;
      height: 100%;
      display: flex;
      box-sizing: border-box;
    }
    
    #primaryContainer {
      width: 100%;
      height: 100%;
      display: flex;
      box-sizing: border-box;
      flex-direction: column;
    }
    
    #primaryContainer .content {
      height: calc(100% - 50px);
    }
    
    #primaryContainer.collapse #sideA {
      width: 0;
    }
    
    #primaryContainer #sideA {
      width: 280px;
      transition: width 0.2s ease-in-out;
    }
    
    #primaryContainer.collapse #sideB {
      width: 100%;
      transition: width 0.2s ease-in-out;
    }
    
    #primaryContainer #sideB {
      width: calc(100% - 280px);
      transition: width 0.2s ease-in-out;
    }
    
    #sideA,
    #sideB {
      height: 100%;
      box-sizing: border-box;
    }
    
    #header {
      position: relative;
      width: 100%;
      height: 50px;
      background-color: var(--smart-background);
      color: var(--smart-background-color);
      display: flex;
      align-items: center;
      box-sizing: border-box;
    }
    
    #sideA {
      border-top: var(--smart-border-width) solid var(--smart-border);
    }
    
    #sideA .controls-container {
      box-sizing: border-box;
      width: 100%;
      padding: 20px;
      max-height: calc(100% - 150px);
      display: grid;
      grid-template-rows: repeat(3, auto);
      grid-template-columns: 100%;
      grid-row-gap: 20px;
      overflow: auto;
    }
    
    .button-container {
      height: 150px;
    }
    
    #sideA .smart-calendar {
      min-width: initial;
      max-width: 100%;
      height: 250px;
      min-height: initial;
      --smart-font-size: 12px;
      --smart-calendar-cell-size: 26px;
      --smart-calendar-cell-spacing: 4px;
      border: initial;
      --smart-surface: transparent;
    }
    
    .smart-input,
    .smart-tree {
      width: 100%;
    }
    
    .smart-tree {
      height: 200px;
      border: initial;
    }
    
    #primaryContainer.collapse #addNew {
      width: 45px;
      border-radius: 50%;
    }
    
    #primaryContainer.collapse #addNew::after {
      left: 0;
      width: 100%;
      height: 100%;
    }
    
    #primaryContainer.collapse #addNew span {
      display: none;
    }
    
    #addNew {
      top: 100%;
      left: 20px;
      margin-top: 100px;
      position: absolute;
      cursor: pointer;
      width: 120px;
      height: 45px;
      border-radius: 25px;
      box-shadow: var(--smart-elevation-2);
      z-index: 1;
    }
    
    #addNew button {
      padding-left: 45px;
    }
    
    #addNew::after {
      content: "+";
      font-weight: 600;
      display: flex;
      align-items: center;
      justify-content: center;
      pointer-events: none;
      position: absolute;
      top: 0;
      left: 10px;
      width: 30px;
      height: 100%;
      font-family: var(--smart-font-family-icon);
      font-size: 40px;
      color: inherit;
      background: linear-gradient(
          217deg,
          rgba(255, 0, 0, 0.8),
          rgba(255, 0, 0, 0) 70.71%
        ),
        linear-gradient(127deg, rgba(0, 255, 0, 0.8), rgba(0, 255, 0, 0) 70.71%),
        linear-gradient(336deg, rgba(0, 0, 255, 0.8), rgba(0, 0, 255, 0) 70.71%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
    }
    
    #toggleButton {
      position: relative;
      cursor: pointer;
      width: 50px;
      height: 50px;
      border-radius: 50%;
      border: initial;
      background: transparent;
      margin-right: 10px;
    }
    
    #toggleButton::after {
      content: var(--smart-icon-align-left);
      display: flex;
      align-items: center;
      justify-content: center;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      font-family: var(--smart-font-family-icon);
      font-size: 25px;
      box-sizing: border-box;
      pointer-events: none;
    }
    
    #title {
      -moz-user-select: none;
      -webkit-user-select: none;
      user-select: none;
      font-size: 20px;
      position: relative;
    }
    
    #logo {
      content: "";
      position: relative;
      width: 100%;
      height: 90px;
      background: url(https://www.htmlelements.com/wp-content/design/assets/images/csssprites.png) -465px -400px;
      filter: invert(0.8);
      box-sizing: border-box;
    }
    
    .smart-tree[selection-mode="checkBox"]
      smart-tree-items-group
      > .smart-tree-item-label-container::before,
    .smart-tree[selection-mode="checkBox"]
      smart-tree-items-group
      > .smart-tree-item-label-container::after {
      content: initial !important;
    }
    
    .smart-tree .smart-tree-item[value="birthday"] {
      --smart-primary: green;
    }
    
    .smart-tree .smart-tree-item[value="holiday"] {
      --smart-primary: cornflowerblue;
    }
    
    .smart-tree .smart-tree-item[value="event"] {
      --smart-primary: purple;
    }
    
    .birthday {
      --smart-scheduler-event-background-rgb: 0, 129, 0;
      --smart-scheduler-event-background: rgba(
        var(--smart-scheduler-event-background-rgb),
        1
      );
      --smart-scheduler-event-focus: rgba(
        var(--smart-scheduler-event-background-rgb),
        0.9
      );
      --smart-scheduler-event-hover: rgba(
        var(--smart-scheduler-event-background-rgb),
        0.8
      );
    }
    
    .holiday {
      --smart-scheduler-event-background-rgb: 100, 149, 237;
      --smart-scheduler-event-background: rgba(
        var(--smart-scheduler-event-background-rgb),
        1
      );
      --smart-scheduler-event-focus: rgba(
        var(--smart-scheduler-event-background-rgb),
        0.9
      );
      --smart-scheduler-event-hover: rgba(
        var(--smart-scheduler-event-background-rgb),
        0.8
      );
    }
    
    .event {
      --smart-scheduler-event-background-rgb: 128, 0, 128;
      --smart-scheduler-event-background: rgba(
        var(--smart-scheduler-event-background-rgb),
        1
      );
      --smart-scheduler-event-focus: rgba(
        var(--smart-scheduler-event-background-rgb),
        0.9
      );
      --smart-scheduler-event-hover: rgba(
        var(--smart-scheduler-event-background-rgb),
        0.8
      );
    }
    </style>
    		
    We can now use the smart-scheduler with Vue 3. Data binding and event handlers will just work right out of the box.

Running the Vue application

Start the app with
npm run dev
and open http://localhost:5173/ in your favorite web browser to see the output below:
When you are ready to ship your app to production, run the following:
npm run build
This will create a production-ready build of your app in the project's ./dist directory.

Read more about using Smart UI for Vue: https://www.htmlelements.com/docs/vue/.