diff --git a/packages/core/demo/index.html b/packages/core/demo/index.html index eef81b4ee..e5326f245 100644 --- a/packages/core/demo/index.html +++ b/packages/core/demo/index.html @@ -113,6 +113,19 @@

@skyra/discord-components-core

+

List items

+ + + + This is the top item + + This is the first nested item + This is the second nested item + + + + +

A normal conversation

Hey guys, I'm new here! Glad to be able to join you all! @@ -588,6 +601,51 @@

Headers

This is a header 3
+ +

Unordered list items

+ + + + Discord + + imposes + + a + + limit + + of + + eleven + + levels + + but + + we + + can + + go (this is 11) + + deeper + + ain't that cool + + + + + + + + + + + + + + +
diff --git a/packages/core/package.json b/packages/core/package.json index 4c13291fd..20d1c006c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -29,6 +29,7 @@ "./discord-invite.js": "./dist/components/discord-invite/DiscordInvite.js", "./discord-italic.js": "./dist/components/discord-italic/DiscordItalic.js", "./discord-link.js": "./dist/components/discord-link/DiscordLink.js", + "./discord-list-item.js": "./dist/components/discord-list-item/DiscordListItem.js", "./discord-mention.js": "./dist/components/discord-mention/DiscordMention.js", "./discord-message.js": "./dist/components/discord-message/DiscordMessage.js", "./discord-messages.js": "./dist/components/discord-messages/DiscordMessages.js", @@ -43,7 +44,8 @@ "./discord-thread.js": "./dist/components/discord-thread/DiscordThread.js", "./discord-thread-message.js": "./dist/components/discord-thread-message/DiscordThreadMessage.js", "./discord-time.js": "./dist/components/discord-time/DiscordTime.js", - "./discord-underlined.js": "./dist/components/discord-underlined/DiscordUnderlined.js" + "./discord-underlined.js": "./dist/components/discord-underlined/DiscordUnderlined.js", + "./discord-unordered-list.js": "./dist/components/discord-unordered-list/DiscordUnorderedList.js" }, "sideEffects": [ "./dist/index.js", @@ -65,6 +67,7 @@ "./dist/components/discord-invite/DiscordInvite.js", "./dist/components/discord-italic/DiscordItalic.js", "./dist/components/discord-link/DiscordLink.js", + "./dist/components/discord-list-item/DiscordListItem.js", "./dist/components/discord-mention/DiscordMention.js", "./dist/components/discord-message/DiscordMessage.js", "./dist/components/discord-messages/DiscordMessages.js", @@ -79,7 +82,8 @@ "./dist/components/discord-thread/DiscordThread.js", "./dist/components/discord-thread-message/DiscordThreadMessage.js", "./dist/components/discord-time/DiscordTime.js", - "./dist/components/discord-underlined/DiscordUnderlined.js" + "./dist/components/discord-underlined/DiscordUnderlined.js", + "./dist/components/discord-unordered-list/DiscordUnorderedList.js" ], "homepage": "https://github.com/skyra-project/discord-components/tree/main/packages/core#readme", "scripts": { diff --git a/packages/core/src/components/discord-list-item/DiscordListItem.ts b/packages/core/src/components/discord-list-item/DiscordListItem.ts new file mode 100644 index 000000000..a9c57d791 --- /dev/null +++ b/packages/core/src/components/discord-list-item/DiscordListItem.ts @@ -0,0 +1,40 @@ +import { css, html, LitElement } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { DiscordComponentsError } from '../../util.js'; + +@customElement('discord-list-item') +export class DiscordListItem extends LitElement { + public static override styles = css` + :host > li { + white-space: break-spaces; + margin-bottom: 4px; + } + `; + + public checkParentElement() { + if ( + this.parentElement?.tagName.toLowerCase() !== 'discord-unordered-list' && + this.parentElement?.tagName.toLowerCase() !== 'discord-ordered-list' + ) { + throw new DiscordComponentsError( + 'All components must be direct children of or .' + ); + } + } + + protected override render() { + this.checkParentElement(); + + return html` +
  • `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'discord-list-item': DiscordListItem; + } +} diff --git a/packages/core/src/components/discord-unordered-list/DiscordUnorderedList.ts b/packages/core/src/components/discord-unordered-list/DiscordUnorderedList.ts new file mode 100644 index 000000000..abe640442 --- /dev/null +++ b/packages/core/src/components/discord-unordered-list/DiscordUnorderedList.ts @@ -0,0 +1,76 @@ +import { css, html, LitElement } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { DiscordComponentsError } from '../../util.js'; + +@customElement('discord-unordered-list') +export class DiscordUnorderedList extends LitElement { + public static override styles = css` + :host > ul { + list-style: disc; + list-style-position: outside; + margin: 4px 0 0 16px; + padding: 0px; + } + + :host([nested]) > ul { + list-style: circle; + } + `; + + /** + * Whether this is a nested list or not, this will change the style of the list-style. + * + * The library will try to guess this automatically based on the component tree, but + * you can also set this manually. + * + * @default false + */ + @property({ type: Boolean, reflect: true }) + public accessor nested = false; + + public checkChildren() { + const allChildrenAreListItems = Array.from(this.children).every((child) => { + const tagNameLowerCase = child.tagName.toLowerCase(); + return ( + tagNameLowerCase === 'discord-list-item' || + tagNameLowerCase === 'discord-unordered-list' || + tagNameLowerCase === 'discord-ordered-list' + ); + }); + + if (!allChildrenAreListItems) { + throw new DiscordComponentsError( + 'All direct children inside of a components must be one of , , or .' + ); + } + } + + /** + * Sets {@link DiscordUnorderedList.nested nested} to true if the parent is either + * `` or ``. + */ + protected override willUpdate(): void { + if ( + this.parentElement?.tagName.toLowerCase() === 'discord-unordered-list' || + this.parentElement?.tagName.toLowerCase() === 'discord-ordered-list' + ) { + this.nested = true; + } + } + + protected override render() { + this.checkChildren(); + + // We disable the eslint rule here because users should use the component inside of this component. + // eslint-disable-next-line lit-a11y/list + return html`
      + +
    `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'discord-unordered-list': DiscordUnorderedList; + } +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index a65a801ba..d072ec104 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -20,6 +20,7 @@ export { DiscordHeader } from './components/discord-header/DiscordHeader.js'; export { DiscordInvite } from './components/discord-invite/DiscordInvite.js'; export { DiscordItalic } from './components/discord-italic/DiscordItalic.js'; export { DiscordLink } from './components/discord-link/DiscordLink.js'; +export { DiscordListItem } from './components/discord-list-item/DiscordListItem.js'; export { DiscordMention } from './components/discord-mention/DiscordMention.js'; export { DiscordMessage } from './components/discord-message/DiscordMessage.js'; export { DiscordMessages } from './components/discord-messages/DiscordMessages.js'; @@ -35,6 +36,7 @@ export { DiscordThread } from './components/discord-thread/DiscordThread.js'; export { DiscordThreadMessage } from './components/discord-thread-message/DiscordThreadMessage.js'; export { DiscordTime } from './components/discord-time/DiscordTime.js'; export { DiscordUnderlined } from './components/discord-underlined/DiscordUnderlined.js'; +export { DiscordUnorderedList } from './components/discord-unordered-list/DiscordUnorderedList.js'; /* EXPORTS END */ export { getConfig, setConfig } from './config.js'; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 4814a3ca4..d72be9913 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -21,6 +21,7 @@ export const DiscordHeader = createReactComponent('discord-header', ReactCompone export const DiscordInvite = createReactComponent('discord-invite', ReactComponents.DiscordInvite); export const DiscordItalic = createReactComponent('discord-italic', ReactComponents.DiscordItalic); export const DiscordLink = createReactComponent('discord-link', ReactComponents.DiscordLink); +export const DiscordListItem = createReactComponent('discord-list-item', ReactComponents.DiscordListItem); export const DiscordMention = createReactComponent('discord-mention', ReactComponents.DiscordMention); export const DiscordMessage = createReactComponent('discord-message', ReactComponents.DiscordMessage); export const DiscordMessages = createReactComponent('discord-messages', ReactComponents.DiscordMessages); @@ -36,6 +37,7 @@ export const DiscordThread = createReactComponent('discord-thread', ReactCompone export const DiscordThreadMessage = createReactComponent('discord-thread-message', ReactComponents.DiscordThreadMessage); export const DiscordTime = createReactComponent('discord-time', ReactComponents.DiscordTime); export const DiscordUnderlined = createReactComponent('discord-underlined', ReactComponents.DiscordUnderlined); +export const DiscordUnorderedList = createReactComponent('discord-unordered-list', ReactComponents.DiscordUnorderedList); /* IMPORTS END */