Skip to content

WIP: Relative time component #868

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

Draft
wants to merge 23 commits into
base: v1/contrib
Choose a base branch
from
Draft
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
12 changes: 12 additions & 0 deletions package-lock.json

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

406 changes: 406 additions & 0 deletions packages/uui-base/lib/utils/Duration.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/uui-base/lib/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './Duration';
export * from './Timer';
export * from './demandCustomElement';
export * from './drag';
31 changes: 31 additions & 0 deletions packages/uui-relative-time/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# uui-relative-time

![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-relative-time?logoColor=%231B264F)

Umbraco style relative-time component.

## Installation

### ES imports

```zsh
npm i @umbraco-ui/uui-relative-time
```

Import the registration of `<uui-relative-time>` via:

```javascript
import '@umbraco-ui/uui-relative-time';
```

When looking to leverage the `UUIRelativeTimeElement` base class as a type and/or for extension purposes, do so via:

```javascript
import { UUIRelativeTimeElement } from '@umbraco-ui/uui-relative-time';
```

## Usage

```html
<uui-relative-time></uui-relative-time>
```
1 change: 1 addition & 0 deletions packages/uui-relative-time/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './uui-relative-time.element';
505 changes: 505 additions & 0 deletions packages/uui-relative-time/lib/uui-relative-time.element.ts

Large diffs are not rendered by default.

126 changes: 126 additions & 0 deletions packages/uui-relative-time/lib/uui-relative-time.story.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import type { Meta, StoryObj } from '@storybook/web-components';
import { html } from 'lit';

import './uui-relative-time.element';
import type { UUIRelativeTimeElement } from './uui-relative-time.element';
import readme from '../README.md?raw';

const meta: Meta<UUIRelativeTimeElement> = {
id: 'uui-relative-time',
title: 'Displays/Relative Time',
component: 'uui-relative-time',
parameters: {
readme: { markdown: readme },
docs: {
source: {
code: `<uui-relative-time></uui-relative-time>`,
},
},
},
};

const now = new Date();

const yesterday = new Date(now);
yesterday.setDate(now.getDate() - 1);

const tomorrow = new Date(now);
tomorrow.setDate(now.getDate() + 1);

const daysAgo = new Date(now);
daysAgo.setDate(now.getDate() - 15);

const monthsAgo = new Date(now);
monthsAgo.setMonth(now.getMonth() - 3);

const format = ['duration', 'relative', 'datetime'];
const tense = ['auto', 'past', 'future'];
const precision = [
'year',
'month',
'week',
'day',
'hour',
'minute',
'second',
'millisecond',
];

export default meta;
type Story = StoryObj<UUIRelativeTimeElement>;

const Template: Story = {
render: (args: any) => html`
<uui-relative-time
datetime="${args.datetime}"
format="${args.format}"
tense="${args.tense}"
precision="${args.precision}"
>February 16th, 2005</uui-relative-time
>
`,
args: {
datetime: '2005-02-16T16:30:00-08:00',
format: 'relative',
tense: 'auto',
precision: 'second',
},
argTypes: {
datetime: { control: 'date' },
tense: {
options: tense,
control: { type: 'select' },
},
format: {
options: format,
control: { type: 'select' },
},
precision: {
options: precision,
control: { type: 'select' },
},
},
};

export const Overview: Story = {
...Template,
args: { datetime: '2005-02-16T16:30:00-08:00' },
};

export const Yesterday: Story = {
...Template,
args: {
datetime: yesterday.toISOString(),
format: 'relative',
precision: 'day',
tense: 'past',
},
};

export const Tomorrow: Story = {
...Template,
args: {
datetime: tomorrow.toISOString(),
format: 'relative',
tense: 'auto',
},
};

export const DaysAgo: Story = {
...Template,
args: {
datetime: daysAgo.toISOString(),
format: 'relative',
precision: 'day',
tense: 'past',
},
};

export const MonthsAgo: Story = {
...Template,
args: {
datetime: monthsAgo.toISOString(),
format: 'relative',
tense: 'past',
},
};
18 changes: 18 additions & 0 deletions packages/uui-relative-time/lib/uui-relative-time.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { html, fixture, expect } from '@open-wc/testing';
import { UUIRelativeTimeElement } from './uui-relative-time.element';

describe('UUIRelativeTimeElement', () => {
let element: UUIRelativeTimeElement;

beforeEach(async () => {
element = await fixture(html` <uui-relative-time></uui-relative-time> `);
});

it('is defined with its own instance', () => {
expect(element).to.be.instanceOf(UUIRelativeTimeElement);
});

it('passes the a11y audit', async () => {
await expect(element).shadowDom.to.be.accessible();
});
});
44 changes: 44 additions & 0 deletions packages/uui-relative-time/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "@umbraco-ui/uui-relative-time",
"version": "0.0.0",
"license": "MIT",
"keywords": [
"Umbraco",
"Custom elements",
"Web components",
"UI",
"Lit",
"Relative Time"
],
"description": "Umbraco UI relative-time component",
"repository": {
"type": "git",
"url": "https://github.com/umbraco/Umbraco.UI.git",
"directory": "packages/uui-relative-time"
},
"bugs": {
"url": "https://github.com/umbraco/Umbraco.UI/issues"
},
"main": "./lib/index.js",
"module": "./lib/index.js",
"types": "./lib/index.d.ts",
"type": "module",
"customElements": "custom-elements.json",
"files": [
"lib/**/*.d.ts",
"lib/**/*.js",
"custom-elements.json"
],
"dependencies": {
"@umbraco-ui/uui-base": "1.9.0-rc.1"
},
"scripts": {
"build": "npm run analyze && tsc --build --force && rollup -c rollup.config.js",
"clean": "tsc --build --clean && rimraf -g dist lib/*.js lib/**/*.js *.tgz lib/**/*.d.ts custom-elements.json",
"analyze": "web-component-analyzer **/*.element.ts --outFile custom-elements.json"
},
"publishConfig": {
"access": "public"
},
"homepage": "https://uui.umbraco.com/?path=/story/uui-relative-time"
}
5 changes: 5 additions & 0 deletions packages/uui-relative-time/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { UUIProdConfig } from '../rollup-package.config.mjs';

export default UUIProdConfig({
entryPoints: ['index'],
});
17 changes: 17 additions & 0 deletions packages/uui-relative-time/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Don't edit this file directly. It is generated by /scripts/generate-ts-config.js

{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./lib",
"rootDir": "./lib",
"composite": true
},
"include": ["./**/*.ts"],
"exclude": ["./**/*.test.ts", "./**/*.story.ts"],
"references": [
{
"path": "../uui-base"
}
]
}
2 changes: 2 additions & 0 deletions packages/uui/lib/index.ts
Original file line number Diff line number Diff line change
@@ -80,3 +80,5 @@ export * from '@umbraco-ui/uui-toast-notification-layout/lib';
export * from '@umbraco-ui/uui-toast-notification/lib';
export * from '@umbraco-ui/uui-toggle/lib';
export * from '@umbraco-ui/uui-visually-hidden/lib';

export * from '@umbraco-ui/uui-relative-time/lib/index.js';

Unchanged files with check annotations Beta

type Constructor<T = {}> = new (...args: any[]) => T;
export declare class ActiveMixinInterface {

Check warning on line 6 in packages/uui-base/lib/mixins/ActiveMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
/**
* Set this boolean to true for then the related composition is sorted.
* @type {boolean}
export const ActiveMixin = <T extends Constructor<LitElement>>(
superClass: T,
) => {
class ActiveMixinClass extends superClass {

Check warning on line 25 in packages/uui-base/lib/mixins/ActiveMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
/**
* Set this boolean to true for then the related composition is sorted.
* @type {boolean}
type Constructor<T = {}> = new (...args: any[]) => T;
export declare class LabelMixinInterface {

Check warning on line 6 in packages/uui-base/lib/mixins/LabelMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
/**
* Label to be used for aria-label and potentially as visual label for some components
* @type {string}
/**
* Label mixin class containing the label functionality.
*/
class LabelMixinClass extends superClass {

Check warning on line 31 in packages/uui-base/lib/mixins/LabelMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
/**
* Label to be used for aria-label and potentially as visual label for some components
* @type {string}
type Constructor<T = {}> = new (...args: any[]) => T;
export declare class PopoverTargetMixinInterface {

Check warning on line 7 in packages/uui-base/lib/mixins/PopoverTargetMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
/**
* Set a popovertarget.
* @type {string}
/**
* Popover target mixin class containing the popover target functionality.
*/
class PopoverTargetMixinClass extends superClass {

Check warning on line 34 in packages/uui-base/lib/mixins/PopoverTargetMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
/**
* Set a popovertarget.
* @type {string}
type Constructor<T = {}> = new (...args: any[]) => T;
export declare class SelectOnlyMixinInterface extends SelectableMixinInterface {

Check warning on line 6 in packages/uui-base/lib/mixins/SelectOnlyMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
selectOnly: boolean;
}
>(
superClass: T,
) => {
class SelectOnlyMixinClass extends superClass {

Check warning on line 22 in packages/uui-base/lib/mixins/SelectOnlyMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
private _selectOnly = false;
/**
type Constructor<T = {}> = new (...args: any[]) => T;
export declare class SelectableMixinInterface extends LitElement {

Check warning on line 8 in packages/uui-base/lib/mixins/SelectableMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
/**
* Enable the ability to select this element.
* @attr
* @fires {UUISelectableEvent} selected - fires when the media card is selected
* @fires {UUISelectableEvent} deselected - fires when the media card is deselected
*/
class SelectableMixinClass extends superClass {

Check warning on line 42 in packages/uui-base/lib/mixins/SelectableMixin.ts

GitHub Actions / test (20)

Class declaration should be prefixed with "UUI"
private _selectable = false;
/**
* Enable the ability to select this element.