Skip to content

Commit

Permalink
feat: Add gcds-date-input component (#607)
Browse files Browse the repository at this point in the history
* first commit of gcds-date-input: lang + format

* Add value and internals logic

* Events + build

* new isValidDate function + basic styling changes

* Form internals + day value format

* Basic property validation

* Basic styling

* Start of validators

* Date input validators

* Storybook stories

* CSS: token plan

* Add logError function

* Add dat-input tokens

* Validation: make sure inputs reflect error

* Add gcds-date-input to delFocusElements in react-ssr package

* Change label attribute to legend

* Cleanup code

* Add part to select and input unit tests

* Unit tests: isValidDate function

* Rewrite isValidDate and requiredDatinput functions to be less relient on the DOM and passed parameters

* Remove use of Date from isValidDate

* Unit tests: Date Input validator

* Refactor select options rendering

* Date input spec tests

* Add E2E tests for gcds-date-input

* Fix typo

* Update tokens package version

* Fix required text look in fieldset legend

* Add missing fieldset updates

* PR feedback: change part to select in gcds-select

* PR feedback: Add hint text to example + change data attribute name

* Add missing function call

* Fix spec tests

* PR feedback: Update storybook + remove autocomplete

* Refactor isValidDate to allow forcing of format
  • Loading branch information
ethanWallace authored Aug 19, 2024
1 parent ca5108f commit ce0b4cc
Show file tree
Hide file tree
Showing 35 changed files with 2,914 additions and 27 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions packages/angular/src/lib/stencil-generated/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,56 @@ export class GcdsContainer {
export declare interface GcdsContainer extends Components.GcdsContainer {}


@ProxyCmp({
inputs: ['disabled', 'errorMessage', 'format', 'hint', 'legend', 'name', 'required', 'validateOn', 'validator', 'value'],
methods: ['validate'],
outputs: ['gcdsFocus', 'gcdsBlur', 'gcdsInput', 'gcdsChange', 'gcdsError', 'gcdsValid']
})
@Component({
selector: 'gcds-date-input',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['disabled', 'errorMessage', 'format', 'hint', 'legend', 'name', 'required', 'validateOn', 'validator', 'value'],outputs: ['gcdsFocus', 'gcdsBlur', 'gcdsInput', 'gcdsChange', 'gcdsError', 'gcdsValid'],
})
export class GcdsDateInput {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
this.el = r.nativeElement;
proxyOutputs(this, ['gcdsFocus', 'gcdsBlur', 'gcdsInput', 'gcdsChange', 'gcdsError', 'gcdsValid']);
}
}


export declare interface GcdsDateInput extends Components.GcdsDateInput {
/**
* Emitted when an element has focus.
*/
gcdsFocus: EventEmitter<CustomEvent<void>>;
/**
* Emitted when an element loses focus.
*/
gcdsBlur: EventEmitter<CustomEvent<void>>;
/**
* Emitted when the element has received input.
*/
gcdsInput: EventEmitter<CustomEvent<any>>;
/**
* Emitted when an element has changed.
*/
gcdsChange: EventEmitter<CustomEvent<any>>;
/**
* Emitted when an element has a validation error.
*/
gcdsError: EventEmitter<CustomEvent<object>>;
/**
* Emitted when an element has validated.
*/
gcdsValid: EventEmitter<CustomEvent<object>>;
}


@ProxyCmp({
inputs: ['type']
})
Expand Down
1 change: 1 addition & 0 deletions packages/angular/src/lib/stencil-generated/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const DIRECTIVES = [
d.GcdsCard,
d.GcdsCheckbox,
d.GcdsContainer,
d.GcdsDateInput,
d.GcdsDateModified,
d.GcdsDetails,
d.GcdsErrorMessage,
Expand Down
1 change: 1 addition & 0 deletions packages/react-ssr/lib/client/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ declare global {
const delFocusElements = [
'gcds-button',
'gcds-checkbox',
'gcds-date-input',
'gcds-fieldset',
'gcds-file-uploader',
'gcds-input',
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/components/stencil-generated/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const GcdsButton = /*@__PURE__*/createReactComponent<JSX.GcdsButton, HTML
export const GcdsCard = /*@__PURE__*/createReactComponent<JSX.GcdsCard, HTMLGcdsCardElement>('gcds-card');
export const GcdsCheckbox = /*@__PURE__*/createReactComponent<JSX.GcdsCheckbox, HTMLGcdsCheckboxElement>('gcds-checkbox');
export const GcdsContainer = /*@__PURE__*/createReactComponent<JSX.GcdsContainer, HTMLGcdsContainerElement>('gcds-container');
export const GcdsDateInput = /*@__PURE__*/createReactComponent<JSX.GcdsDateInput, HTMLGcdsDateInputElement>('gcds-date-input');
export const GcdsDateModified = /*@__PURE__*/createReactComponent<JSX.GcdsDateModified, HTMLGcdsDateModifiedElement>('gcds-date-modified');
export const GcdsDetails = /*@__PURE__*/createReactComponent<JSX.GcdsDetails, HTMLGcdsDetailsElement>('gcds-details');
export const GcdsErrorMessage = /*@__PURE__*/createReactComponent<JSX.GcdsErrorMessage, HTMLGcdsErrorMessageElement>('gcds-error-message');
Expand Down
20 changes: 20 additions & 0 deletions packages/vue/lib/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,26 @@ export const GcdsContainer = /*@__PURE__*/ defineContainer<JSX.GcdsContainer>('g
]);


export const GcdsDateInput = /*@__PURE__*/ defineContainer<JSX.GcdsDateInput>('gcds-date-input', undefined, [
'name',
'legend',
'format',
'value',
'required',
'hint',
'errorMessage',
'disabled',
'validator',
'validateOn',
'gcdsFocus',
'gcdsBlur',
'gcdsInput',
'gcdsChange',
'gcdsError',
'gcdsValid'
]);


export const GcdsDateModified = /*@__PURE__*/ defineContainer<JSX.GcdsDateModified>('gcds-date-modified', undefined, [
'type'
]);
Expand Down
2 changes: 1 addition & 1 deletion packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@babel/core": "^7.20.12",
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.21.0",
"@cdssnc/gcds-tokens": "^1.16.0",
"@cdssnc/gcds-tokens": "^1.16.1",
"@fortawesome/fontawesome-free": "^6.3.0",
"@stencil/angular-output-target": "file:../../utils/angular-output-target",
"@stencil/postcss": "^2.1.0",
Expand Down
145 changes: 145 additions & 0 deletions packages/web/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,54 @@ export namespace Components {
*/
"tag"?: string;
}
interface GcdsDateInput {
/**
* Specifies if the date input is disabled or not.
*/
"disabled"?: boolean;
/**
* Error message displayed below the legend and above form fields.
*/
"errorMessage"?: string;
/**
* Set this property to full to show month, day, and year form elements. Set it to compact to show only the month and year form elements.
*/
"format": 'full' | 'compact';
/**
* Hint displayed below the legend and above form fields.
*/
"hint"?: string;
/**
* Fieldset legend
*/
"legend": string;
/**
* Name attribute for the date input.
*/
"name": string;
/**
* Specifies if a form field is required or not.
*/
"required"?: boolean;
/**
* Call any active validators
*/
"validate": () => Promise<void>;
/**
* Set event to call validator
*/
"validateOn": 'blur' | 'submit' | 'other';
/**
* Array of validators
*/
"validator": Array<
string | ValidatorEntry | Validator<string>
>;
/**
* Default value for the date input element. Format: YYYY-MM-DD
*/
"value"?: string;
}
interface GcdsDateModified {
/**
* Set date modified type. Default is date.
Expand Down Expand Up @@ -1155,6 +1203,10 @@ export interface GcdsCheckboxCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLGcdsCheckboxElement;
}
export interface GcdsDateInputCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLGcdsDateInputElement;
}
export interface GcdsDetailsCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLGcdsDetailsElement;
Expand Down Expand Up @@ -1286,6 +1338,28 @@ declare global {
prototype: HTMLGcdsContainerElement;
new (): HTMLGcdsContainerElement;
};
interface HTMLGcdsDateInputElementEventMap {
"gcdsFocus": void;
"gcdsBlur": void;
"gcdsInput": any;
"gcdsChange": any;
"gcdsError": object;
"gcdsValid": object;
}
interface HTMLGcdsDateInputElement extends Components.GcdsDateInput, HTMLStencilElement {
addEventListener<K extends keyof HTMLGcdsDateInputElementEventMap>(type: K, listener: (this: HTMLGcdsDateInputElement, ev: GcdsDateInputCustomEvent<HTMLGcdsDateInputElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLGcdsDateInputElementEventMap>(type: K, listener: (this: HTMLGcdsDateInputElement, ev: GcdsDateInputCustomEvent<HTMLGcdsDateInputElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLGcdsDateInputElement: {
prototype: HTMLGcdsDateInputElement;
new (): HTMLGcdsDateInputElement;
};
interface HTMLGcdsDateModifiedElement extends Components.GcdsDateModified, HTMLStencilElement {
}
var HTMLGcdsDateModifiedElement: {
Expand Down Expand Up @@ -1664,6 +1738,7 @@ declare global {
"gcds-card": HTMLGcdsCardElement;
"gcds-checkbox": HTMLGcdsCheckboxElement;
"gcds-container": HTMLGcdsContainerElement;
"gcds-date-input": HTMLGcdsDateInputElement;
"gcds-date-modified": HTMLGcdsDateModifiedElement;
"gcds-details": HTMLGcdsDetailsElement;
"gcds-error-message": HTMLGcdsErrorMessageElement;
Expand Down Expand Up @@ -1958,6 +2033,74 @@ declare namespace LocalJSX {
*/
"tag"?: string;
}
interface GcdsDateInput {
/**
* Specifies if the date input is disabled or not.
*/
"disabled"?: boolean;
/**
* Error message displayed below the legend and above form fields.
*/
"errorMessage"?: string;
/**
* Set this property to full to show month, day, and year form elements. Set it to compact to show only the month and year form elements.
*/
"format": 'full' | 'compact';
/**
* Hint displayed below the legend and above form fields.
*/
"hint"?: string;
/**
* Fieldset legend
*/
"legend": string;
/**
* Name attribute for the date input.
*/
"name": string;
/**
* Emitted when an element loses focus.
*/
"onGcdsBlur"?: (event: GcdsDateInputCustomEvent<void>) => void;
/**
* Emitted when an element has changed.
*/
"onGcdsChange"?: (event: GcdsDateInputCustomEvent<any>) => void;
/**
* Emitted when an element has a validation error.
*/
"onGcdsError"?: (event: GcdsDateInputCustomEvent<object>) => void;
/**
* Emitted when an element has focus.
*/
"onGcdsFocus"?: (event: GcdsDateInputCustomEvent<void>) => void;
/**
* Emitted when the element has received input.
*/
"onGcdsInput"?: (event: GcdsDateInputCustomEvent<any>) => void;
/**
* Emitted when an element has validated.
*/
"onGcdsValid"?: (event: GcdsDateInputCustomEvent<object>) => void;
/**
* Specifies if a form field is required or not.
*/
"required"?: boolean;
/**
* Set event to call validator
*/
"validateOn"?: 'blur' | 'submit' | 'other';
/**
* Array of validators
*/
"validator"?: Array<
string | ValidatorEntry | Validator<string>
>;
/**
* Default value for the date input element. Format: YYYY-MM-DD
*/
"value"?: string;
}
interface GcdsDateModified {
/**
* Set date modified type. Default is date.
Expand Down Expand Up @@ -3026,6 +3169,7 @@ declare namespace LocalJSX {
"gcds-card": GcdsCard;
"gcds-checkbox": GcdsCheckbox;
"gcds-container": GcdsContainer;
"gcds-date-input": GcdsDateInput;
"gcds-date-modified": GcdsDateModified;
"gcds-details": GcdsDetails;
"gcds-error-message": GcdsErrorMessage;
Expand Down Expand Up @@ -3072,6 +3216,7 @@ declare module "@stencil/core" {
"gcds-card": LocalJSX.GcdsCard & JSXBase.HTMLAttributes<HTMLGcdsCardElement>;
"gcds-checkbox": LocalJSX.GcdsCheckbox & JSXBase.HTMLAttributes<HTMLGcdsCheckboxElement>;
"gcds-container": LocalJSX.GcdsContainer & JSXBase.HTMLAttributes<HTMLGcdsContainerElement>;
"gcds-date-input": LocalJSX.GcdsDateInput & JSXBase.HTMLAttributes<HTMLGcdsDateInputElement>;
"gcds-date-modified": LocalJSX.GcdsDateModified & JSXBase.HTMLAttributes<HTMLGcdsDateModifiedElement>;
"gcds-details": LocalJSX.GcdsDetails & JSXBase.HTMLAttributes<HTMLGcdsDetailsElement>;
"gcds-error-message": LocalJSX.GcdsErrorMessage & JSXBase.HTMLAttributes<HTMLGcdsErrorMessageElement>;
Expand Down
48 changes: 48 additions & 0 deletions packages/web/src/components/gcds-date-input/gcds-date-input.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@layer reset, default, hint, error;

@layer reset {
:host {
display: block;
}
}

@layer default {
:host {
.gcds-date-input__fieldset {
--gcds-fieldset-font-desktop: var(--gcds-date-input-fieldset-font-desktop);
--gcds-fieldset-font-mobile: var(--gcds-date-input-fieldset-font-mobile);
--gcds-fieldset-legend-margin: var(--gcds-date-input-fieldset-margin);
}

.gcds-date-input__month,
.gcds-date-input__year,
.gcds-date-input__day {
display: inline-block;
margin-inline-end: var(--gcds-date-input-margin);

--gcds-label-font-desktop: var(--gcds-date-input-label-font-desktop);
--gcds-label-font-mobile: var(--gcds-date-input-label-font-mobile );
}
}
}

@layer hint {
:host {
.gcds-date-input--hint {
--gcds-fieldset-legend-margin: var(--gcds-date-input-fieldset-hint-margin);
}
}
}

@layer error {
:host {
.gcds-date-input--error {
--gcds-fieldset-legend-margin: var(--gcds-date-input-fieldset-error-margin );
}

gcds-input.gcds-date-input--error::part(input),
gcds-select.gcds-date-input--error::part(select) {
border-color: var(--gcds-date-input-danger-border);
}
}
}
Loading

0 comments on commit ce0b4cc

Please sign in to comment.