Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion web-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@momentum-ui/web-components",
"version": "2.23.38",
"version": "2.23.39",
"author": "Yana Harris",
"license": "MIT",
"repository": "https://github.com/momentum-design/momentum-ui.git",
Expand Down
12 changes: 11 additions & 1 deletion web-components/src/[sandbox]/examples/date-time-picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const minDate = now().minus({ day: 5 }).toISODate();
const maxDate = now().plus({ day: 5 }).toISODate();

@customElement("date-time-picker-sandbox")
export class DateTimePickerSandbox extends LitElement {
class DateTimePickerSandbox extends LitElement {
static get styles() {
return [
css`
Expand Down Expand Up @@ -55,6 +55,16 @@ export class DateTimePickerSandbox extends LitElement {
.shouldCloseOnSelect=${true}
.showDefaultNowDate=${false}
></md-date-time-picker>

<h3>date time picker with custom placeholder</h3>
<md-date-time-picker
placeholder=${"Select date and time"}
.showDefaultNowDate=${false}
.useISOFormat=${false}
.disableDateValidation=${true}
.controlButtons=${{ apply: { value: "Apply" }, cancel: { value: "Cancel" } }}
.shouldCloseOnSelect=${true}
></md-date-time-picker>
`;
}
}
Expand Down
120 changes: 72 additions & 48 deletions web-components/src/[sandbox]/examples/datepicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,82 @@ import "@/components/datepicker/datepicker-day/DatePickerDay";
import "@/components/datepicker/datepicker-month/DatePickerMonth";
import "@/components/datepicker/datepicker-week/DatePickerWeek";
import { now } from "@/utils/dateUtils";
import { html } from "lit-element";
import { customElement, html, LitElement, property } from "lit-element";
import { ifDefined } from "lit-html/directives/if-defined";

const minDate = now().minus({ day: 5 }).toISODate();

const maxDate = now().plus({ day: 5 }).toISODate();

export const datePickerTemplate = html`
<h2 class="sandbox-header">md-datepicker</h2>
<h3>row calendar</h3>
<md-datepicker-calendar
.datePickerProps=${{
locale: "en-US",
selected: now().plus({ days: 1 }),
focused: now().minus({ day: 1 }),
weekStart: "Sunday"
}}
.filterParams=${{ minDate: undefined, maxDate: undefined, filterDate: undefined }}
></md-datepicker-calendar>
<h3>datepicker with custom trigger</h3>
<md-datepicker value=${"2025-04-10"}></md-datepicker>
<md-datepicker custom-trigger>
<md-button slot="date-trigger" variant="primary">Date Trigger</md-button>
</md-datepicker>
<h3>default date if we set showDefaultNowDate as true</h3>
<md-datepicker .useISOFormat=${true} .showDefaultNowDate=${true} placeholder="Select date"></md-datepicker>
<h3>show the passed placeholder if we set showDefaultNowDate as false</h3>
<md-datepicker .useISOFormat=${true} .showDefaultNowDate=${false} placeholder="Select date"></md-datepicker>
@customElement("date-picker-sandbox")
class DatePickerSandbox extends LitElement {
@property({ type: Boolean }) cancelButtonDisabled = false;
@property({ type: Boolean }) acceptButtonDisabled = false;

render() {
return html`
<h2 class="sandbox-header">md-datepicker</h2>
<h3>row calendar</h3>
<md-datepicker-calendar
.datePickerProps=${{
locale: "en-US",
selected: now().plus({ days: 1 }),
focused: now().minus({ day: 1 }),
weekStart: "Sunday"
}}
.filterParams=${{ minDate: undefined, maxDate: undefined, filterDate: undefined }}
></md-datepicker-calendar>
<h3>datepicker with custom trigger</h3>
<md-datepicker value=${"2025-04-10"}></md-datepicker>
<md-datepicker custom-trigger>
<md-button slot="date-trigger" variant="primary">Date Trigger</md-button>
</md-datepicker>
<h3>default date if we set showDefaultNowDate as true</h3>
<md-datepicker .useISOFormat=${true} .showDefaultNowDate=${true} placeholder="Select date"></md-datepicker>
<h3>show the passed placeholder if we set showDefaultNowDate as false</h3>
<md-datepicker .useISOFormat=${true} .showDefaultNowDate=${false} placeholder="Select date"></md-datepicker>

<h3>datepicker with user's system locale</h3>
<md-datepicker .useISOFormat=${false}></md-datepicker>
<h3>datepicker with "ru" locale</h3>
<md-datepicker locale="ru" .useISOFormat=${false}></md-datepicker>
<h3>datepicker with "en-US" locale</h3>
<md-datepicker locale="en-US" .useISOFormat=${false}></md-datepicker>
<h3>datepicker with min / max filters</h3>
<md-datepicker minDate=${ifDefined(minDate ?? undefined)} maxDate=${ifDefined(maxDate ?? undefined)}></md-datepicker>
<h3>datepicker with Monday start week start</h3>
<md-datepicker weekStart="Monday"></md-datepicker>
<h3>datepicker with initial value</h3>
<md-datepicker weekStart="Monday" value="2021-01-31"></md-datepicker>
<h3>disabled datepicker</h3>
<md-datepicker weekStart="Monday" value="2021-01-31" disabled></md-datepicker>
<h3>Call Date (with custom aria label)</h3>
<md-datepicker ariaLabel="Call Date" weekStart="Monday" value="2021-01-31"></md-datepicker>
<h3>datepicker with initial value compact newMomentum</h3>
<md-datepicker weekStart="Monday" value="2021-01-31" compact-input newMomentum></md-datepicker>
<h3>date picker with accept and cancel buttons</h3>
<md-checkbox
style="margin-bottom: 8px;"
?checked=${this.cancelButtonDisabled}
@checkbox-change=${() => (this.cancelButtonDisabled = !this.cancelButtonDisabled)}
>
Cancel Button Disabled
</md-checkbox>
<md-checkbox
style="margin-bottom: 8px;"
?checked=${this.acceptButtonDisabled}
@checkbox-change=${() => (this.acceptButtonDisabled = !this.acceptButtonDisabled)}
>
Accept Button Disabled
</md-checkbox>
<md-datepicker
.controlButtons=${{ apply: { value: "Apply", disabled: this.acceptButtonDisabled }, cancel: { value: "Cancel", disabled: this.cancelButtonDisabled } }}
.shouldCloseOnSelect=${true}
value="2021-01-31"
newMomentum
></md-datepicker>`
};
}

export const datePickerTemplate = html` <date-picker-sandbox></date-picker-sandbox> `;

<h3>datepicker with user's system locale</h3>
<md-datepicker .useISOFormat=${false}></md-datepicker>
<h3>datepicker with "ru" locale</h3>
<md-datepicker locale="ru" .useISOFormat=${false}></md-datepicker>
<h3>datepicker with "en-US" locale</h3>
<md-datepicker locale="en-US" .useISOFormat=${false}></md-datepicker>
<h3>datepicker with min / max filters</h3>
<md-datepicker minDate=${ifDefined(minDate ?? undefined)} maxDate=${ifDefined(maxDate ?? undefined)}></md-datepicker>
<h3>datepicker with Monday start week start</h3>
<md-datepicker weekStart="Monday"></md-datepicker>
<h3>datepicker with initial value</h3>
<md-datepicker weekStart="Monday" value="2021-01-31"></md-datepicker>
<h3>disabled datepicker</h3>
<md-datepicker weekStart="Monday" value="2021-01-31" disabled></md-datepicker>
<h3>Call Date (with custom aria label)</h3>
<md-datepicker ariaLabel="Call Date" weekStart="Monday" value="2021-01-31"></md-datepicker>
<h3>datepicker with initial value compact newMomentum</h3>
<md-datepicker weekStart="Monday" value="2021-01-31" compact-input newMomentum></md-datepicker>
<h3>date picker with accept and cancel buttons</h3>
<md-datepicker
.controlButtons=${{ apply: { value: "Apply" }, cancel: { value: "Cancel" } }}
.shouldCloseOnSelect=${true}
value="2021-01-31"
newMomentum
></md-datepicker>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe("DatePicker Component", () => {
if (includeApplyButton) {
expect(el.value).toEqual(defaultValue);
const applyButton = el.shadowRoot!.querySelector("md-button.apply-button");
applyButton?.dispatchEvent(new MouseEvent("click"));
applyButton?.dispatchEvent(new MouseEvent("button-click"));
expect(updateFunc).toHaveBeenCalledTimes(1);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default {
argTypes: {
weekStart: { control: { type: "select" }, options: DatePicker.weekStartDays },
locale: { control: "text", defaultValue: "en-US" },
useISOFormat: { control: "boolean", defaultValue: true },
disabled: { control: "boolean" },
controlButtons: { control: "boolean" },
minDate: { control: { type: "text" } },
Expand Down Expand Up @@ -47,6 +48,7 @@ export const DateTimePicker: StoryObj = {
maxDate=${args.maxDate}
.controlButtons=${controlButtons}
locale=${args.locale}
.useISOFormat=${args.useISOFormat}
weekStart=${args.weekStart}
?two-digit-auto-tab=${args.twoDigitAutoTab}
?twenty-four-hour-format=${args.twentyFourHourFormat}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe("DateTimePicker Component", () => {

if (includeApplyButton) {
expect(applyButton).not.toBeNull();
applyButton?.dispatchEvent(new MouseEvent("click"));
applyButton?.dispatchEvent(new MouseEvent("button-click"));
await elementUpdated(el);
expect(dateTime2.equals(dateStringToDateTime(el.value))).toBe(true);
} else {
Expand Down
12 changes: 10 additions & 2 deletions web-components/src/components/date-time-picker/DateTimePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ export namespace DateTimePicker {
return [reset, styles];
}

private get displayValue(): string | undefined {
if (!this.useISOFormat && this.fullDateTime && this.fullDateTime.isValid) {
return this.fullDateTime.toLocaleString(DateTime.DATETIME_MED, { locale: this.locale });
}
return undefined;
}

render() {
return html`
<md-datepicker
Expand All @@ -180,7 +187,8 @@ export namespace DateTimePicker {
minDate=${ifDefined(this.minDate)}
maxDate=${ifDefined(this.maxDate)}
value=${ifDefined(this.value)}
.useISOFormat=${this.useISOFormat}
displayValue=${ifDefined(this.displayValue)}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using disaplyValue instead of value allows us to sidestep all the awkward issues with the pickers attempting to interpret their own value as DateTime objects (which won't work for localised dates!)

.allowUserTextInput=${!this.useISOFormat}
.showDefaultNowDate=${this.showDefaultNowDate}
weekStart=${this.weekStart}
placeholder=${this.placeholderValue}
Expand All @@ -189,7 +197,7 @@ export namespace DateTimePicker {
.shouldCloseOnSelect=${this.shouldCloseOnSelect}
@date-selection-change=${this.handleDateChange}
@date-input-change=${this.handleDateTimeInputChange as EventListener}
.validateDate=${!this.disableDateValidation}
.validateDate=${!this.disableDateValidation && !this.useISOFormat}
?compact-input=${this.compactInput}
>
<div slot="time-picker" class="included-timepicker-wrapper">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default {
maxDate: { control: { type: "text" } },
showDefaultNowDate: { control: "boolean", defaultValue: true },
value: { control: { type: "text" } },
displayValue: { control: { type: "text" } },
newMomentum: { control: { type: "select" }, options: [undefined, "true", "false"] },
compactInput: { control: { type: "select" }, options: [undefined, "true", "false"] },
positioningStrategy: {
Expand Down Expand Up @@ -47,6 +48,7 @@ export const DatePicker: StoryObj = {
?disabled=${args.disabled}
?should-close-on-select=${args.shouldCloseOnSelect}
value=${args.value}
displayValue=${args.value}
weekStart=${args.weekStart}
locale=${args.locale}
placeholder=${args.placeholder}
Expand Down
5 changes: 3 additions & 2 deletions web-components/src/components/datepicker/DatePicker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ describe("DatePicker Component", () => {
expect(el.menuOverlay.isOpen).toBeTruthy();

const cancelButton = el.shadowRoot!.querySelector("md-button.cancel-button");
cancelButton?.dispatchEvent(new MouseEvent("click"));
cancelButton?.dispatchEvent(new CustomEvent("button-click"));

expect(el.menuOverlay.isOpen).toBeFalsy();
});

Expand Down Expand Up @@ -92,7 +93,7 @@ describe("DatePicker Component", () => {
if (includeApplyButton) {
expect(el.selectedDate).toEqual(firstDate);
const applyButton = el.shadowRoot!.querySelector("md-button.apply-button");
applyButton?.dispatchEvent(new MouseEvent("click"));
applyButton?.dispatchEvent(new MouseEvent("button-click"));
expect(el.selectedDate).toEqual(secondDate);
} else {
expect(el.selectedDate).toEqual(secondDate);
Expand Down
9 changes: 6 additions & 3 deletions web-components/src/components/datepicker/DatePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ export namespace DatePicker {
@property({ type: String }) htmlId = "";
@property({ type: String }) label = "";
@property({ type: String }) ariaLabel: string | null = null;
@property({ type: String }) displayValue: string | null = null;
@property({ type: Boolean }) required = false;
@property({ type: String, reflect: true }) errorMessage = "";
@property({ type: Boolean, attribute: "custom-trigger" }) customTrigger = false;
@property({ type: Boolean }) isMenuOverlayOpen = false;
@property({ type: Boolean }) allowUserTextInput = false;
@property({ type: Boolean }) newMomentum?: boolean = undefined;
@property({ type: Boolean, attribute: "compact-input" }) compactInput?: boolean = undefined;
@property({ type: Object, attribute: false }) controlButtons?: DatePickerControlButtons = undefined;
Expand Down Expand Up @@ -350,7 +352,7 @@ export namespace DatePicker {
class="cancel-button"
aria-label=${ifDefined(this.controlButtons.cancel?.ariaLabel)}
?disabled=${this.controlButtons.cancel?.disabled ?? false}
@click=${this.onCancelClick}
@button-click=${this.onCancelClick}
variant="secondary"
>
${this.controlButtons.cancel.value}
Expand All @@ -363,7 +365,7 @@ export namespace DatePicker {
class="apply-button"
aria-label=${ifDefined(this.controlButtons.apply?.ariaLabel)}
?disabled=${this.controlButtons.apply?.disabled ?? false}
@click=${this.onApplyClick}
@button-click=${this.onApplyClick}
variant="primary"
>
${this.controlButtons.apply.value}
Expand Down Expand Up @@ -425,7 +427,8 @@ export namespace DatePicker {
role="combobox"
?newMomentum=${this.computedNewMomentum}
placeholder=${this.getPlaceHolderString()}
value=${ifDefined(this.value ?? undefined)}
value=${this.displayValue ?? ifDefined(this.value ?? undefined)}
.allowUserTextInput=${this.allowUserTextInput}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chatting with James N and we agreed to disable user text input when using localised dates

htmlId=${this.htmlId}
label=${this.label}
ariaLabel=${this.getAriaLabel()}
Expand Down
3 changes: 2 additions & 1 deletion web-components/src/components/input/Input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ export namespace Input {
@property({ type: Boolean }) clear = false;
@property({ type: String }) clearAriaLabel = "";
@property({ type: Boolean }) compact = false;
@property({ type: Boolean }) allowUserTextInput = true;
@property({ type: String }) containerSize: Input.ContainerSize = "small-12";
@property({ type: Boolean }) disabled = false;
@property({ type: String }) id = "";
Expand Down Expand Up @@ -452,7 +453,7 @@ export namespace Input {
id=${this.htmlId}
role=${this.role}
placeholder=${this.placeholder}
?readonly=${this.readOnly || this.disabled}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the reson i added this new allowUserTextInput prop instead of just using readOnly is that readOnly also affects styling!

?readonly=${this.readOnly || this.disabled || !this.allowUserTextInput}
min=${ifDefined(this.min)}
max=${ifDefined(this.max)}
maxlength=${ifDefined(this.maxLength)}
Expand Down