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
7 changes: 7 additions & 0 deletions .changeset/hip-bikes-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@finsweet/attributes-date': major
'@finsweet/attributes': patch
'@finsweet/attributes-utils': patch
---

feat: new fs-date Attribute
1 change: 1 addition & 0 deletions packages/attributes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@finsweet/attributes-consent": "workspace:*",
"@finsweet/attributes-copyclip": "workspace:*",
"@finsweet/attributes-countitems": "workspace:*",
"@finsweet/attributes-date": "workspace:*",
"@finsweet/attributes-displayvalues": "workspace:*",
"@finsweet/attributes-favcustom": "workspace:*",
"@finsweet/attributes-formsubmit": "workspace:*",
Expand Down
4 changes: 4 additions & 0 deletions packages/attributes/src/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ export const loadAttribute = async (solution: FsAttributeKey) => {
return import('@finsweet/attributes-countitems');
}

case 'date': {
return import('@finsweet/attributes-date');
}

case 'displayvalues': {
return import('@finsweet/attributes-displayvalues');
}
Expand Down
21 changes: 21 additions & 0 deletions packages/attributes/tests/date.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { expect, test } from '@playwright/test';

import { waitAttributeLoaded } from './utils';

test.beforeEach(async ({ page }) => {
await page.goto('http://fs-attributes.webflow.io/date');
});

test.describe('fs-date', () => {
test('Sets the correct value to the elements', async ({ page }) => {
await waitAttributeLoaded(page, 'date');

const element1 = page.getByTestId('1');
const element2 = page.getByTestId('2');
const element3 = page.getByTestId('3');

expect(await element1.innerText()).toBe('viernes, 12 de abril de 2024');
expect(await element2.innerText()).toBe('miércoles, 24 de abril de 2024');
expect(await element3.innerText()).toBe('miércoles, 17 de abril de 2024');
});
});
3 changes: 3 additions & 0 deletions packages/date/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `fs-date` Attribute

Date formatting for Webflow elements.
23 changes: 23 additions & 0 deletions packages/date/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "@finsweet/attributes-date",
"version": "0.0.0",
"description": "Date formatting for Webflow elements.",
"private": true,
"type": "module",
"types": "src/index.ts",
"scripts": {
"lint": "eslint ./src && prettier --check ./src",
"lint:fix": "eslint ./src --fix && prettier --write ./src",
"check": "tsc --noEmit"
},
"exports": {
".": {
"types": "./src/index.ts",
"import": "./src/index.ts"
}
},
"dependencies": {
"@finsweet/attributes-utils": "workspace:*",
"chrono-node": "^2.7.5"
}
}
41 changes: 41 additions & 0 deletions packages/date/src/factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { getAttribute } from './utils/selectors';

/**
* Inits the date element.
* @param dateElement
*/
export const initDateElement = async (dateElement: HTMLElement) => {
const value = getAttribute(dateElement, 'value');
const parse = getAttribute(dateElement, 'parse');

let date: Date | undefined | null;

if (value) {
const chrono = await import('chrono-node');

date = chrono.parseDate(value);
} else if (parse) {
const chrono = await import('chrono-node');

const referenceDate = new Date(dateElement.innerText);

const ref = isNaN(referenceDate.getTime()) ? new Date() : referenceDate;

date = chrono.parseDate(parse, ref);
}

if (!date) {
date = new Date(dateElement.innerText);
}

// Get the date on the element
const locale = getAttribute(dateElement, 'locale');
const year = getAttribute(dateElement, 'year', true);
const weekday = getAttribute(dateElement, 'weekday', true);
const month = getAttribute(dateElement, 'month', true);
const day = getAttribute(dateElement, 'day', true);

const formatted = new Intl.DateTimeFormat(locale, { year, weekday, month, day }).format(date);

dateElement.innerText = formatted;
};
3 changes: 3 additions & 0 deletions packages/date/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { version } from '../package.json';
export { init } from './init';
export { ELEMENTS, SETTINGS } from './utils/constants';
18 changes: 18 additions & 0 deletions packages/date/src/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { type FsAttributeInit, waitWebflowReady } from '@finsweet/attributes-utils';

import { initDateElement } from './factory';
import { queryAllElements } from './utils/selectors';

/**
* Inits the attribute.
*/
export const init: FsAttributeInit = async () => {
await waitWebflowReady();

// localize date elements
const dateElements = queryAllElements('date');

await Promise.all(dateElements.map(initDateElement));

return {};
};
63 changes: 63 additions & 0 deletions packages/date/src/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { type AttributeElements, type AttributeSettings } from '@finsweet/attributes-utils';

export const ELEMENTS = [
/**
* Defines a date element.
*/
'date',
] as const satisfies AttributeElements;

export const SETTINGS = {
/**
* The locale used to format.
*/
locale: {
key: 'locale',
},

/**
* The representation of the year.
*/
year: {
key: 'year',
values: { numeric: 'numeric', '2-digit': '2-digit' },
},

/**
* The representation of the weekday.
*/
weekday: {
key: 'weekday',
values: { long: 'long', short: 'short', narrow: 'narrow' },
},

/**
* The representation of the month.
*/
month: {
key: 'month',
values: { numeric: 'numeric', '2-digit': '2-digit', long: 'long', short: 'short', narrow: 'narrow' },
},

/**
* The representation of the day.
*/
day: {
key: 'day',
values: { numeric: 'numeric', '2-digit': '2-digit' },
},

/**
* Defines a specific date value.
*/
value: {
key: 'value',
},

/**
* Defines a specific date value.
*/
parse: {
key: 'parse',
},
} as const satisfies AttributeSettings;
15 changes: 15 additions & 0 deletions packages/date/src/utils/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DATE_ATTRIBUTE, generateSelectors } from '@finsweet/attributes-utils';

import { ELEMENTS, SETTINGS } from './constants';

export const {
getAttribute,
getClosestElement,
getElementSelector,
getInstance,
getSettingAttributeName,
getSettingSelector,
hasAttributeValue,
queryAllElements,
queryElement,
} = generateSelectors(DATE_ATTRIBUTE, ELEMENTS, SETTINGS);
3 changes: 3 additions & 0 deletions packages/date/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig.json"
}
5 changes: 0 additions & 5 deletions packages/template/api/examples.ts

This file was deleted.

8 changes: 0 additions & 8 deletions packages/template/api/schema.ts

This file was deleted.

2 changes: 2 additions & 0 deletions packages/utils/src/constants/attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export const COPY_CLIP_ATTRIBUTE = 'copyclip';

export const COUNT_ITEMS_ATTRIBUTE = 'countitems';

export const DATE_ATTRIBUTE = 'date';

export const DISPLAY_VALUES_ATTRIBUTE = 'displayvalues';

export const DOCS_ATTRIBUTE = 'docs';
Expand Down
29 changes: 24 additions & 5 deletions pnpm-lock.yaml

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