diff --git a/package-lock.json b/package-lock.json index 57b8a3aa54b9e4..671dd832c6ff1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21024,6 +21024,10 @@ "resolved": "routes/navigation", "link": true }, + "node_modules/@wordpress/news-widget": { + "resolved": "widgets/news", + "link": true + }, "node_modules/@wordpress/notices": { "resolved": "packages/notices", "link": true @@ -67091,6 +67095,19 @@ "clsx": "^2.1.1" } }, + "widgets/news": { + "name": "@wordpress/news-widget", + "version": "1.0.0", + "dependencies": { + "@wordpress/dataviews": "file:../../packages/dataviews", + "@wordpress/date": "file:../../packages/date", + "@wordpress/element": "file:../../packages/element", + "@wordpress/html-entities": "file:../../packages/html-entities", + "@wordpress/i18n": "file:../../packages/i18n", + "@wordpress/icons": "file:../../packages/icons", + "@wordpress/ui": "file:../../packages/ui" + } + }, "widgets/quick-draft": { "name": "@wordpress/quick-draft-widget", "version": "1.0.0", diff --git a/widgets/news/components/index.ts b/widgets/news/components/index.ts new file mode 100644 index 00000000000000..ceccd74481f2d7 --- /dev/null +++ b/widgets/news/components/index.ts @@ -0,0 +1 @@ +export { NewsList } from './news-list'; diff --git a/widgets/news/components/news-list/index.ts b/widgets/news/components/news-list/index.ts new file mode 100644 index 00000000000000..ceccd74481f2d7 --- /dev/null +++ b/widgets/news/components/news-list/index.ts @@ -0,0 +1 @@ +export { NewsList } from './news-list'; diff --git a/widgets/news/components/news-list/news-list.module.css b/widgets/news/components/news-list/news-list.module.css new file mode 100644 index 00000000000000..e0f6ea4e1417c7 --- /dev/null +++ b/widgets/news/components/news-list/news-list.module.css @@ -0,0 +1,28 @@ +.root { + flex: 1; + min-width: 0; + min-height: 0; + overflow: auto; +} + +.feedIcon { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + border-radius: var(--wpds-border-radius-md); + background-color: var(--wpds-color-bg-track-neutral-weak); + color: var(--wpds-color-fg-content-neutral-weak); +} + +.titleLink { + min-width: 0; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.meta { + color: var(--wpds-color-fg-content-neutral-weak); +} diff --git a/widgets/news/components/news-list/news-list.tsx b/widgets/news/components/news-list/news-list.tsx new file mode 100644 index 00000000000000..67944fbfb33f68 --- /dev/null +++ b/widgets/news/components/news-list/news-list.tsx @@ -0,0 +1,209 @@ +/** + * WordPress dependencies + */ +import { DataViews, type Field, type View } from '@wordpress/dataviews'; +import { dateI18n } from '@wordpress/date'; +import { useEffect, useMemo, useState } from '@wordpress/element'; +import { decodeEntities } from '@wordpress/html-entities'; +import { __, _x } from '@wordpress/i18n'; +import { globe, postList, wordpress } from '@wordpress/icons'; +import { EmptyState, Icon, Link, Stack, Text } from '@wordpress/ui'; + +/** + * Internal dependencies + */ +import styles from './news-list.module.css'; + +interface NewsPost { + id: number; + title: { rendered: string }; + link: string; + date: string; +} + +interface NewsFeed { + key: string; + label: string; + siteUrl: string; + posts: NewsPost[]; +} + +type NewsItem = { + id: string; + feedKey: string; + feedLabel: string; + title: string; + url: string; + date: string; +}; + +const NEWS_FEEDS = [ + { + key: 'news', + label: __( 'WordPress Blog' ), + siteUrl: _x( 'https://wordpress.org/news/', 'News dashboard widget' ), + apiUrl: 'https://wordpress.org/news/wp-json/wp/v2/posts?per_page=4&_fields=id,title,link,date', + }, + { + key: 'planet', + label: __( 'Other WordPress News' ), + siteUrl: _x( 'https://planet.wordpress.org/', 'News dashboard widget' ), + apiUrl: 'https://planet.wordpress.org/wp-json/wp/v2/posts?per_page=4&_fields=id,title,link,date', + }, +]; + +const DEFAULT_LAYOUTS = { list: {} }; + +const INITIAL_VIEW: View = { + type: 'list', + page: 1, + perPage: 4, + search: '', + filters: [], + fields: [], + titleField: 'title', + descriptionField: 'meta', + mediaField: 'feedIcon', + showMedia: true, + layout: { density: 'compact' }, +}; + +function FeedIcon( { item }: { item: NewsItem } ) { + return ( +
+ ); +} + +function NewsTitle( { item }: { item: NewsItem } ) { + return ( + + { item.title } + + ); +} + +function NewsMeta( { item }: { item: NewsItem } ) { + return ( +