Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(datepicker): developing datepicker component #907

Merged
merged 40 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6a69a3d
feat(datepicker): developing datepicker component
dilandoogan Aug 22, 2024
75d7686
feat(datepicker): run prettier
dilandoogan Aug 23, 2024
644fd9b
feat(datepicker): fix storybook bug
dilandoogan Sep 2, 2024
04f7c52
feat(datepicker): typescript type bug fix
dilandoogan Sep 3, 2024
d02eada
feat(datepicker): ui review updates
dilandoogan Sep 3, 2024
20a2645
feat(datepicker): showing floating date count fix
dilandoogan Sep 4, 2024
29eeb96
feat(datepicker): clear unnecessary codes
dilandoogan Sep 4, 2024
d76d591
feat(datepicker): coding improvments on bl-calendar component
dilandoogan Sep 6, 2024
dcc03ee
feat(datepicker): coding improvments on bl-datepicker component
dilandoogan Sep 9, 2024
5066c5d
feat(datepicker): show calendar on popover
dilandoogan Sep 9, 2024
ca1d304
feat(datepicker): default value bug fix
dilandoogan Sep 14, 2024
7ffde5c
feat(datepicker): fixing datepicker story
dilandoogan Sep 16, 2024
adb125b
feat(datepicker): add bl-calendar test cases
dilandoogan Sep 18, 2024
116b4c6
feat(datepicker): add test cases for bl-calendar and bl-datepicker co…
dilandoogan Sep 18, 2024
4c40fba
feat(datepicker): run prettier
dilandoogan Sep 19, 2024
e4720fa
feat(datepicker): remove unnecessary tests
dilandoogan Sep 19, 2024
878f8e9
feat(datepicker): remove calendar border
dilandoogan Sep 20, 2024
1eb2853
Merge branch 'calendar-remove-border' into datepicker-component
dilandoogan Sep 20, 2024
e42df9b
Merge branch 'next' into datepicker-component
dilandoogan Oct 7, 2024
3125cf0
feat(datepicker): add all test cases for datepicker and calendar comp…
dilandoogan Oct 7, 2024
d5de706
feat(datepicker): fix lint bug
dilandoogan Oct 7, 2024
f345e82
feat(datepicker): adding missing statement tests
dilandoogan Oct 8, 2024
63a592b
feat(datepicker): adding missing test for mixin
dilandoogan Oct 9, 2024
f353d58
Merge branch 'next' into datepicker-component
dilandoogan Oct 9, 2024
a183672
feat(datepicker): add input width prop to datepicker
dilandoogan Oct 10, 2024
c2dcf15
feat(datepicker): min date and max date validation added
dilandoogan Oct 10, 2024
f929160
feat(datepicker): min date and max date validation test cases added
dilandoogan Oct 10, 2024
f3df7cd
feat(datepicker): fix css custom property
dilandoogan Oct 10, 2024
ea3a441
feat(datepicker): change story name
dilandoogan Oct 11, 2024
315915f
feat(datepicker): add secondary option to locale
dilandoogan Oct 24, 2024
c6352bc
feat(datepicker): merge next
dilandoogan Oct 31, 2024
da22f12
feat(datepicker): self-review updates
dilandoogan Nov 7, 2024
e5dd2cd
feat(datepicker): run prettier
dilandoogan Nov 18, 2024
3ab285d
feat(datepicker): get disabled date as string or date array
dilandoogan Nov 21, 2024
da3cbe8
feat(datepicker): review updates
dilandoogan Nov 28, 2024
ad99f03
feat(datepicker): string to date converter review update
dilandoogan Nov 28, 2024
c68d007
Merge branch 'next' into datepicker-component
erbilnas Nov 29, 2024
cb11c42
feat(datepicker): add css variables to wrapper class
dilandoogan Dec 2, 2024
1fec4ae
feat(datepicker): add input size and input label type as prop to date…
dilandoogan Dec 3, 2024
3b17af6
feat(datepicker): change divider width
dilandoogan Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions commitlint.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ module.exports = {
"calendar",
"table",
"split-button",
"datepicker",
],
],
},
Expand Down
3 changes: 3 additions & 0 deletions playground/template.html
AykutSarac marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ <h1>Baklava Playground</h1>
<code>npm run serve</code>.
</p>


<bl-datepicker style="padding-top: 20px" type="multiple" placeholder="Placeholder" label="label"></bl-datepicker>
dilandoogan marked this conversation as resolved.
Show resolved Hide resolved
<bl-button>Baklava is ready</bl-button>

</body>
</html>
1 change: 1 addition & 0 deletions src/baklava.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ export { default as BlTableHeaderCell } from "./components/table/table-header-ce
export { default as BlTableCell } from "./components/table/table-cell/bl-table-cell";
export { default as BlSplitButton } from "./components/split-button/bl-split-button";
export { default as BlCalendar } from "./components/calendar/bl-calendar";
export { default as BlDatePicker } from "./components/datepicker/bl-datepicker";
export { getIconPath, setIconPath } from "./utilities/asset-paths";
197 changes: 105 additions & 92 deletions src/components/calendar/bl-calendar.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { CSSResultGroup, html, LitElement } from "lit";
import { CSSResultGroup, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import DatepickerCalendarMixin from "../../mixins/datepicker-calendar-mixin/datepicker-calendar-mixin";
import { event, EventDispatcher } from "../../utilities/event";
import "../button/bl-button";
import { blDatepickerClearSelectedDatesEvent } from "../datepicker/bl-datepicker";
import "../icon/bl-icon";
import {
CALENDAR_TYPES,
Expand All @@ -14,54 +16,28 @@ import style from "./bl-calendar.css";
import {
Calendar,
CalendarDate,
CalendarType,
CalendarView,
CalendarDay,
DayValues,
CalendarView,
RangePickerDates,
} from "./bl-calendar.types";

export const blCalendarChangedEvent = "bl-calendar-change";

/**
* @tag bl-calendar
* @summary Baklava Calendar component
**/
@customElement("bl-calendar")
export default class BlCalendar extends LitElement {
/**
* Defines the calendar types, available types are single, multiple and range
*/
@property()
type: CalendarType = CALENDAR_TYPES.SINGLE;

/**
* Defines the minimum date value for the calendar
*/
@property({ type: Date, attribute: "min-date", reflect: true })
minDate: Date;

/**
* Defines the maximum date value for the calendar
*/
@property({ type: Date, attribute: "max-date", reflect: true })
maxDate: Date;

/**
* Defines the start day of the calendar (1 defines monday)
*/
@property({ type: Number, attribute: "start-of-week", reflect: true })
startOfWeek: DayValues = 0;

/**
* Defines the unselectable dates for calendar
*/
@property({ type: Array, attribute: "disabled-dates", reflect: true })
disabledDates: Date[];
export default class BlCalendar extends DatepickerCalendarMixin {
connectedCallback() {
super.connectedCallback();
window.addEventListener(blDatepickerClearSelectedDatesEvent, this.handleClearSelectedDates);
}

/**
* Defines the calendar language
*/
@property()
locale: string = document.documentElement.lang;
disconnectedCallback() {
super.disconnectedCallback();
window.removeEventListener(blDatepickerClearSelectedDatesEvent, this.handleClearSelectedDates);
}

@state()
private _selectedDates: CalendarDate[] = [];
Expand All @@ -87,24 +63,51 @@ export default class BlCalendar extends LitElement {
@state()
private _calendarDays: CalendarDay[] = [];

private _defaultValue: Date | Date[];

/**
* Defines the default selected date value for the calendar
*/
@property({ type: Array, attribute: "default-value", reflect: true })
get defaultValue(): Date | Date[] {
return this._defaultValue;
}
set defaultValue(defaultValue) {
if (this.type === CALENDAR_TYPES.SINGLE && Array.isArray(defaultValue)) {
console.warn("Invalid prop value for defaultValue");
} else if (this.defaultValue) {
if (Array.isArray(this.defaultValue)) {
this._selectedDates = { ...this.defaultValue };
} else this._selectedDates = [this.defaultValue];
@property({ attribute: "default-value", reflect: true })
set defaultValue(defaultValue: Date | Date[]) {
if (!this._defaultValue) {
if (this.type === CALENDAR_TYPES.SINGLE && Array.isArray(defaultValue)) {
console.warn(
"'defaultValue' must be of type Date when the date selection mode is set to single."
);
} else if (
(this.type === CALENDAR_TYPES.MULTIPLE || this.type === CALENDAR_TYPES.RANGE) &&
!Array.isArray(defaultValue)
dilandoogan marked this conversation as resolved.
Show resolved Hide resolved
) {
console.warn(
"'defaultValue' must be an array of two Date objects when the date selection mode is set to range."
);
} else if (
this.type === CALENDAR_TYPES.RANGE &&
Array.isArray(defaultValue) &&
(defaultValue.length < 0 || defaultValue.length > 2)
) {
console.warn(
"'defaultValue' must be an array of Date objects when the date selection mode is set to multiple."
);
} else {
this._defaultValue = defaultValue;
if (this.type === CALENDAR_TYPES.SINGLE && !Array.isArray(this._defaultValue)) {
this._selectedDates = [this._defaultValue];
} else if (this.type === CALENDAR_TYPES.MULTIPLE && Array.isArray(this._defaultValue)) {
this._selectedDates = this._defaultValue;
} else if (this.type === CALENDAR_TYPES.RANGE && Array.isArray(this._defaultValue)) {
this._selectedDates = this._defaultValue;
this._selectedRangeDates.startDate = this._defaultValue[0];
this._selectedRangeDates.endDate = this._defaultValue[1];
this.setHoverClass();
}
this._onBlCalendarChange(this._selectedDates);
}
}
}

public handleClearSelectedDates = () => {
this._selectedDates = [];
this._onBlCalendarChange([]);
this.clearRangePickerStyles();
};

get months() {
return [...Array(12).keys()].map(month => {
return {
Expand All @@ -115,6 +118,7 @@ export default class BlCalendar extends LitElement {
};
});
}

get days() {
return [...Array(7).keys()].map(day => {
return {
Expand All @@ -126,16 +130,19 @@ export default class BlCalendar extends LitElement {
/**
* Fires when date selection changes
*/
@event("bl-calendar-change") private _onBlCalendarChange: EventDispatcher<Date[]>;
@event(blCalendarChangedEvent) private _onBlCalendarChange: EventDispatcher<Date[]>;
static get styles(): CSSResultGroup {
return [style];
}

getDayNumInAMonth(year: number, month: number) {
return new Date(year, month + 1, 0).getDate();
}

getWeekDayOfDate(year: number, month: number) {
return new Date(year, month, 1).getDay();
}

setPreviousCalendarView() {
this.clearRangePickerStyles();
if (this._calendarView === CALENDAR_VIEWS.DAYS) {
Expand All @@ -157,6 +164,7 @@ export default class BlCalendar extends LitElement {
this.setHoverClass();
}
}

setNextCalendarView() {
this.clearRangePickerStyles();
if (this._calendarView === CALENDAR_VIEWS.DAYS) {
Expand Down Expand Up @@ -209,6 +217,7 @@ export default class BlCalendar extends LitElement {
);
}
}

clearRangePickerStyles() {
this.shadowRoot?.querySelectorAll(".range-day").forEach(day => {
day.classList.remove("range-day");
Expand All @@ -220,6 +229,7 @@ export default class BlCalendar extends LitElement {
day.classList.remove("range-end-day");
});
}

handleDate(date: CalendarDate) {
if (this.type !== CALENDAR_TYPES.RANGE) {
if (date.getMonth() < this._calendarMonth) {
Expand All @@ -236,14 +246,15 @@ export default class BlCalendar extends LitElement {
} else if (this.type === CALENDAR_TYPES.RANGE) {
this.handleRangeSelectCalendar(date);
}

this._onBlCalendarChange(this._selectedDates);
this.requestUpdate();
}

handleSingleSelectCalendar(calendarDate: CalendarDate) {
this._selectedDates.splice(0, 1);
this._selectedDates.push(calendarDate);
}

handleMultipleSelectCalendar(calendarDate: CalendarDate) {
const dateExist = this._selectedDates.find(function (selectedDate) {
return selectedDate.getTime() === calendarDate.getTime();
Expand All @@ -256,6 +267,7 @@ export default class BlCalendar extends LitElement {
);
else this._selectedDates.push(calendarDate);
}

handleRangeSelectCalendar(calendarDate: CalendarDate) {
if (!this._selectedRangeDates.startDate) {
this._selectedRangeDates.startDate = calendarDate;
Expand Down Expand Up @@ -291,6 +303,7 @@ export default class BlCalendar extends LitElement {

return !!day;
}

checkIfDateIsToday(calendarDate: CalendarDate) {
const today = new Date();

Expand Down Expand Up @@ -437,41 +450,41 @@ export default class BlCalendar extends LitElement {
return html` <div class="calendar-text weekday-text">${key}</div> `;
})}</div>
<div class="days-wrapper">
${[...Array(valuesArray[0].length).keys()].map(key => {
return html`<div class="week-row">
${valuesArray.map(values => {
const date = values[key];
const isSelectedDay = this.checkIfSelectedDate(date);
const isDayToday = this.checkIfDateIsToday(date);
const isDisabledDay = this.checkIfDateIsDisabled(date);

const classes = classMap({
"day": true,
"calendar-text": true,
"today-day": isDayToday,
"selected-day": isSelectedDay,
"other-month-day": values[key].getMonth() !== this._calendarMonth,
"disabled-day": isDisabledDay,
});

return html`
<div class="day-wrapper">
<bl-button
id=${date.getTime()}
variant="tertiary"
kind="neutral"
size="small"
class=${classes}
?disabled=${isDisabledDay}
@click="${() => !isDisabledDay && this.handleDate(date)}"
>
${date.getDate()}
</bl-button>
</div>
`;
})}
</div>`;
})}
${[...Array(valuesArray[0].length).keys()].map(key => {
return html`<div class="week-row">
dilandoogan marked this conversation as resolved.
Show resolved Hide resolved
${valuesArray.map(values => {
const date = values[key];
const isSelectedDay = this.checkIfSelectedDate(date);
const isDayToday = this.checkIfDateIsToday(date);
const isDisabledDay = this.checkIfDateIsDisabled(date);

const classes = classMap({
"day": true,
"calendar-text": true,
"today-day": isDayToday,
"selected-day": isSelectedDay,
"other-month-day": values[key].getMonth() !== this._calendarMonth,
"disabled-day": isDisabledDay,
});

return html`
<div class="day-wrapper">
<bl-button
id=${date.getTime()}
variant="tertiary"
kind="neutral"
size="small"
class=${classes}
?disabled=${isDisabledDay}
@click="${() => !isDisabledDay && this.handleDate(date)}"
>
${date.getDate()}
</bl-button>
</div>
`;
})}
</div>`;
})}
</div>
</div>`;
} else if (calendarView === CALENDAR_VIEWS.MONTHS) {
Expand Down
57 changes: 57 additions & 0 deletions src/components/datepicker/bl-datepicker.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
:host {
width: fit-content;
--bl-input-cursor: pointer;
--icon-size: var(--line-height);
--icon-color: var(--bl-color-neutral-light);
display: block;
}

.datepicker-content {
display: flex;
flex-direction: column;
gap: 8px;
width: fit-content;
}

.datepicker-input {
width: 314px;
white-space: nowrap;
text-overflow: ellipsis;
}

.icon-container {
display: flex;
gap: 5px;
align-items: center;
}

.calendarIcon {
display: flex;
align-items: center;
gap: var(--icon-gap);
flex-basis: var(--icon-size);
align-self: center;
margin-right: var(--label-padding);
font-size: var(--icon-size);
color: var(--icon-color);
height: var(--icon-size);
}

.popover {
position: var(--popover-position);
border: solid 1px var(--border-color);
background-color: var(--background-color);
font: var(--bl-font-title-3-regular);
border-radius: var(--bl-border-radius-s);
padding: var(--menu-padding);
outline: none;
box-sizing: border-box;
max-height: var(--menu-height);
overflow-y: auto;
display: none;
z-index: var(--bl-index-popover);
}

.show-popover {
display: block;
}
Loading
Loading