diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
index 4b7a81c261..735cd7c00f 100644
--- a/.github/workflows/cd.yml
+++ b/.github/workflows/cd.yml
@@ -117,7 +117,7 @@ jobs:
- build-and-test
environment:
name: github-pages
- url: "https://rocketchat.github.io/Rocket.Chat.Fuselage/fuselage/${{ needs.build-and-test.outputs.branch-name }}"
+ url: "https://rocketchat.github.io/fuselage/fuselage/${{ needs.build-and-test.outputs.branch-name }}"
steps:
- uses: actions/checkout@v2
with:
diff --git a/.github/workflows/ci-pr-opened.yml b/.github/workflows/ci-pr-opened.yml
index a8120e6270..e5d7062f9e 100644
--- a/.github/workflows/ci-pr-opened.yml
+++ b/.github/workflows/ci-pr-opened.yml
@@ -61,7 +61,7 @@ jobs:
name: storybooks
path: packages
- run: |
- rm -rf "fuselage/${{ needs.download-artifact.outputs.pr-number }}" "layout/${{ needs.download-artifact.outputs.pr-number }}" "uikit-playground/${{ needs.download-artifact.outputs.pr-number }}" "fuselage-ui-kit/${{ needs.download-artifact.outputs.pr-number }}" "onboarding-ui/${{ needs.download-artifact.outputs.pr-number }}"
+ rm -rf "fuselage/${{ needs.download-artifact.outputs.pr-number }}" "layout/${{ needs.download-artifact.outputs.pr-number }}" "uikit-playground/${{ needs.download-artifact.outputs.pr-number }}" "onboarding-ui/${{ needs.download-artifact.outputs.pr-number }}"
mv -v packages/fuselage/storybook-static "fuselage/${{ needs.download-artifact.outputs.pr-number }}"
mv -v packages/onboarding-ui/storybook-static "onboarding-ui/${{ needs.download-artifact.outputs.pr-number }}"
mv -v packages/layout/storybook-static "layout/${{ needs.download-artifact.outputs.pr-number }}"
diff --git a/README.md b/README.md
index 748c8a8c59..b18bd847cf 100644
--- a/README.md
+++ b/README.md
@@ -33,4 +33,3 @@
| 📦 [`@rocket.chat/string-helpers`](/packages/string-helpers) | Helper functions for string manipulation | [![npm](https://img.shields.io/npm/v/@rocket.chat/string-helpers?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/string-helpers) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/string-helpers?style=flat-square) |
| 📦 [`@rocket.chat/styled`](/packages/styled) | A simple styled API for React components | [![npm](https://img.shields.io/npm/v/@rocket.chat/styled?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/styled) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/styled?style=flat-square) |
| 📦 [`@rocket.chat/stylis-logical-props-middleware`](/packages/stylis-logical-props-middleware) | Stylis middleware to handle CSS Logical Properties and their fallbacks | [![npm](https://img.shields.io/npm/v/@rocket.chat/stylis-logical-props-middleware?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/stylis-logical-props-middleware) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/stylis-logical-props-middleware?style=flat-square) |
-| 📦 [`@rocket.chat/ui-kit`](/packages/ui-kit) | Interactive UI elements for Rocket.Chat Apps | [![npm](https://img.shields.io/npm/v/@rocket.chat/ui-kit?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/ui-kit) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/ui-kit?style=flat-square) |
diff --git a/packages/fuselage-hooks/CHANGELOG.md b/packages/fuselage-hooks/CHANGELOG.md
index 7dd682319c..6832154b84 100644
--- a/packages/fuselage-hooks/CHANGELOG.md
+++ b/packages/fuselage-hooks/CHANGELOG.md
@@ -1,5 +1,11 @@
# Change Log
+## 0.33.1
+
+### Patch Changes
+
+- [#1334](https://github.com/RocketChat/fuselage/pull/1334) [`35155404b`](https://github.com/RocketChat/fuselage/commit/35155404baeb1e44aa1e4d767f431204d3ab2b53) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage-hooks): increase usePosition zIndex
+
## 0.33.0
### Minor Changes
diff --git a/packages/fuselage-hooks/package.json b/packages/fuselage-hooks/package.json
index f067b0dc73..13b3a74dd1 100644
--- a/packages/fuselage-hooks/package.json
+++ b/packages/fuselage-hooks/package.json
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/fuselage-hooks",
- "version": "0.33.0",
+ "version": "0.33.1",
"description": "React hooks for Fuselage, Rocket.Chat's design system and UI toolkit",
"homepage": "https://rocketchat.github.io/Rocket.Chat.Fuselage/",
"author": {
diff --git a/packages/fuselage-hooks/src/usePosition/index.ts b/packages/fuselage-hooks/src/usePosition/index.ts
index 578a310fa2..17ddbd4c3c 100644
--- a/packages/fuselage-hooks/src/usePosition/index.ts
+++ b/packages/fuselage-hooks/src/usePosition/index.ts
@@ -138,7 +138,7 @@ export function getPositionStyle({
[positionKey]: point,
[variantKey]: variantPoint,
position: 'fixed',
- zIndex: 9999,
+ zIndex: 999999,
opacity: 1,
},
placement: `${keysToPlacementMap[placementAttempt]}-${keysToPlacementMap[v]}`,
@@ -166,11 +166,11 @@ export function getPositionStyle({
top: point,
left: variantPoint,
position: 'fixed',
+ zIndex: 999999,
...(bottom < targetRect.height + point && {
bottom: margin,
overflowY: 'auto',
}),
- ...({ zIndex: '9999' } as any),
},
placement: `${keysToPlacementMap[placementAttempt]}-${
keysToPlacementMap[variantsAttempts[0]]
diff --git a/packages/fuselage-toastbar/CHANGELOG.md b/packages/fuselage-toastbar/CHANGELOG.md
new file mode 100644
index 0000000000..3f33ae7377
--- /dev/null
+++ b/packages/fuselage-toastbar/CHANGELOG.md
@@ -0,0 +1,7 @@
+# @rocket.chat/fuselage-toastbar
+
+## 0.31.26
+
+### Patch Changes
+
+- [#1323](https://github.com/RocketChat/fuselage/pull/1323) [`9ccc4e79f`](https://github.com/RocketChat/fuselage/commit/9ccc4e79f76c1ef2b182065883bd66a91860bc96) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(icons): New circle-unfilled
diff --git a/packages/fuselage-toastbar/package.json b/packages/fuselage-toastbar/package.json
index fbdaf9694c..fb90728d4f 100644
--- a/packages/fuselage-toastbar/package.json
+++ b/packages/fuselage-toastbar/package.json
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/fuselage-toastbar",
- "version": "0.31.25",
+ "version": "0.31.26",
"description": "Fuselage ToastBar component",
"keywords": [
"rocketchat",
diff --git a/packages/fuselage-tokens/CHANGELOG.md b/packages/fuselage-tokens/CHANGELOG.md
index e85e9519d5..a819b9a099 100644
--- a/packages/fuselage-tokens/CHANGELOG.md
+++ b/packages/fuselage-tokens/CHANGELOG.md
@@ -1,5 +1,11 @@
# Change Log
+## 0.33.0
+
+### Minor Changes
+
+- [#1289](https://github.com/RocketChat/fuselage/pull/1289) [`a40d471bd`](https://github.com/RocketChat/fuselage/commit/a40d471bdf71babf652f5df3108a05d92f08d975) Thanks [@juliajforesti](https://github.com/juliajforesti)! - feat(fuselage): new `PaletteStyleTag` component
+
## 0.32.0
### Minor Changes
diff --git a/packages/fuselage-tokens/build.js b/packages/fuselage-tokens/build.js
index 8206957cef..8afbe0204a 100644
--- a/packages/fuselage-tokens/build.js
+++ b/packages/fuselage-tokens/build.js
@@ -118,11 +118,15 @@ StyleDictionary.registerFormat({
const exp = /[a-z]+\/([a-z]+)\/[a-z]+.json/i;
const [, group] = dictionary.allTokens[0].filePath.match(exp);
const newPaletteGroup = [
+ 'badge',
'background',
'surface',
'stroke',
+ 'shadow',
'button',
- 'text',
+ 'font',
+ 'status',
+ 'statusBullet',
];
if (newPaletteGroup.includes(group)) {
diff --git a/packages/fuselage-tokens/config.js b/packages/fuselage-tokens/config.js
index 788d934010..009c25eecd 100644
--- a/packages/fuselage-tokens/config.js
+++ b/packages/fuselage-tokens/config.js
@@ -23,7 +23,9 @@ module.exports = {
tokenCategory === 'breakpoints' || tokenCategory === 'colors'
? customFormat
: 'json/nested',
- filter: (token) => token.filePath.includes(tokenCategory),
+ filter: (token) =>
+ // console.log(token.filePath.includes(tokenCategory), tokenCategory);
+ token.filePath.includes(tokenCategory),
};
}),
},
diff --git a/packages/fuselage-tokens/package.json b/packages/fuselage-tokens/package.json
index 89dca4a884..0c11e70dbe 100644
--- a/packages/fuselage-tokens/package.json
+++ b/packages/fuselage-tokens/package.json
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/fuselage-tokens",
- "version": "0.32.0",
+ "version": "0.33.0",
"description": "Design tokens for Fuselage, Rocket.Chat's design system",
"homepage": "https://rocketchat.github.io/Rocket.Chat.Fuselage/",
"author": {
diff --git a/packages/fuselage-tokens/src/badge/base.json b/packages/fuselage-tokens/src/badge/base.json
new file mode 100644
index 0000000000..c00c8990e8
--- /dev/null
+++ b/packages/fuselage-tokens/src/badge/base.json
@@ -0,0 +1,25 @@
+{
+ "badge": {
+ "light": {
+ "level-0": { "value": "{colors.n400}" },
+ "level-1": { "value": "{colors.n700}" },
+ "level-2": { "value": "{colors.b500}" },
+ "level-3": { "value": "{colors.o500}" },
+ "level-4": { "value": "{colors.r500}" }
+ },
+ "high-contrast": {
+ "level-0": { "value": "{colors.n400}" },
+ "level-1": { "value": "{colors.n800}" },
+ "level-2": { "value": "{colors.b700}" },
+ "level-3": { "value": "{colors.o900}" },
+ "level-4": { "value": "{colors.r800}" }
+ },
+ "dark": {
+ "level-0": { "value": "#404754" },
+ "level-1": { "value": "#484C51" },
+ "level-2": { "value": "#2C65BA" },
+ "level-3": { "value": "#955828" },
+ "level-4": { "value": "#B43C4C" }
+ }
+ }
+}
diff --git a/packages/fuselage-tokens/src/button/base.json b/packages/fuselage-tokens/src/button/base.json
index 52b662c513..fd1e2c66fa 100644
--- a/packages/fuselage-tokens/src/button/base.json
+++ b/packages/fuselage-tokens/src/button/base.json
@@ -1,77 +1,142 @@
{
"button": {
- "backgroundPrimaryDefault": { "value": "{colors.b500}" },
- "backgroundPrimaryHover": { "value": "{colors.b600}" },
- "backgroundPrimaryPress": { "value": "{colors.b700}" },
- "backgroundPrimaryFocus": { "value": "{colors.b500}" },
- "backgroundPrimaryKeyfocus": { "value": "{colors.b500}" },
- "backgroundPrimaryDisabled": { "value": "{colors.b200}" },
- "fontOnPrimary": { "value": "{colors.white}" },
- "fontOnPrimaryDisabled": { "value": "{colors.white}" },
+ "light": {
+ "backgroundPrimaryDefault": { "value": "{colors.b500}" },
+ "backgroundPrimaryHover": { "value": "{colors.b600}" },
+ "backgroundPrimaryPress": { "value": "{colors.b700}" },
+ "backgroundPrimaryFocus": { "value": "{colors.b500}" },
+ "backgroundPrimaryKeyfocus": { "value": "{colors.b500}" },
+ "backgroundPrimaryDisabled": { "value": "{colors.b200}" },
+ "fontOnPrimary": { "value": "{colors.white}" },
+ "fontOnPrimaryDisabled": { "value": "{colors.white}" },
- "backgroundSecondaryDefault": { "value": "{colors.n400}" },
- "backgroundSecondaryHover": { "value": "{colors.n500}" },
- "backgroundSecondaryPress": { "value": "{colors.n600}" },
- "backgroundSecondaryFocus": { "value": "{colors.n400}" },
- "backgroundSecondaryKeyfocus": { "value": "{colors.n400}" },
- "backgroundSecondaryDisabled": { "value": "{colors.n300}" },
- "fontOnSecondary": { "value": "{colors.n900}" },
- "fontOnSecondaryDisabled": { "value": "{colors.n500}" },
+ "backgroundSecondaryDefault": { "value": "{colors.n400}" },
+ "backgroundSecondaryHover": { "value": "{colors.n500}" },
+ "backgroundSecondaryPress": { "value": "{colors.n600}" },
+ "backgroundSecondaryFocus": { "value": "{colors.n400}" },
+ "backgroundSecondaryKeyfocus": { "value": "{colors.n400}" },
+ "backgroundSecondaryDisabled": { "value": "{colors.n300}" },
+ "fontOnSecondary": { "value": "{colors.n900}" },
+ "fontOnSecondaryDisabled": { "value": "{colors.n500}" },
- "backgroundSecondaryDangerDefault": { "value": "{colors.n400}" },
- "backgroundSecondaryDangerHover": { "value": "{colors.n500}" },
- "backgroundSecondaryDangerPress": { "value": "{colors.n600}" },
- "backgroundSecondaryDangerFocus": { "value": "{colors.n400}" },
- "backgroundSecondaryDangerKeyfocus": { "value": "{colors.n400}" },
- "backgroundSecondaryDangerDisabled": { "value": "{colors.n300}" },
- "fontOnSecondaryDanger": { "value": "{colors.r700}" },
- "onSecondaryDangerDisabled": { "value": "{colors.r300}" },
+ "backgroundSecondaryDangerDefault": { "value": "{colors.n400}" },
+ "backgroundSecondaryDangerHover": { "value": "{colors.n500}" },
+ "backgroundSecondaryDangerPress": { "value": "{colors.n600}" },
+ "backgroundSecondaryDangerFocus": { "value": "{colors.n400}" },
+ "backgroundSecondaryDangerKeyfocus": { "value": "{colors.n400}" },
+ "backgroundSecondaryDangerDisabled": { "value": "{colors.n300}" },
+ "fontOnSecondaryDanger": { "value": "{colors.r700}" },
+ "onSecondaryDangerDisabled": { "value": "{colors.r300}" },
- "backgroundDangerDefault": { "value": "{colors.r500}" },
- "backgroundDangerHover": { "value": "{colors.r600}" },
- "backgroundDangerPress": { "value": "{colors.r700}" },
- "backgroundDangerFocus": { "value": "{colors.r500}" },
- "backgroundDangerKeyfocus": { "value": "{colors.r500}" },
- "backgroundDangerDisabled": { "value": "{colors.r200}" },
- "fontOnDanger": { "value": "{colors.white}" },
- "fontOnDangerDisabled": { "value": "{colors.white}" },
+ "backgroundDangerDefault": { "value": "{colors.r500}" },
+ "backgroundDangerHover": { "value": "{colors.r600}" },
+ "backgroundDangerPress": { "value": "{colors.r700}" },
+ "backgroundDangerFocus": { "value": "{colors.r500}" },
+ "backgroundDangerKeyfocus": { "value": "{colors.r500}" },
+ "backgroundDangerDisabled": { "value": "{colors.r200}" },
+ "fontOnDanger": { "value": "{colors.white}" },
+ "fontOnDangerDisabled": { "value": "{colors.white}" },
- "backgroundWarningDefault": { "value": "{colors.y400}" },
- "backgroundWarningHover": { "value": "{colors.y500}" },
- "backgroundWarningPress": { "value": "{colors.y600}" },
- "backgroundWarningFocus": { "value": "{colors.y400}" },
- "backgroundWarningKeyfocus": { "value": "{colors.y400}" },
- "backgroundWarningDisabled": { "value": "{colors.y200}" },
- "fontOnWarning": { "value": "{colors.n900}" },
- "fontOnWarningDisabled": { "value": "{colors.n600}" },
+ "backgroundSuccessDefault": { "value": "{colors.g500}" },
+ "backgroundSuccessHover": { "value": "{colors.g600}" },
+ "backgroundSuccessPress": { "value": "{colors.g700}" },
+ "backgroundSuccessFocus": { "value": "{colors.g500}" },
+ "backgroundSuccessKeyfocus": { "value": "{colors.g500}" },
+ "backgroundSuccessDisabled": { "value": "{colors.g200}" },
+ "fontOnSuccess": { "value": "{colors.n900}" },
+ "fontOnSuccessDisabled": { "value": "{colors.white}" }
+ },
+ "high-contrast": {
+ "backgroundPrimaryDefault": { "value": "{colors.b700}" },
+ "backgroundPrimaryHover": { "value": "{colors.b800}" },
+ "backgroundPrimaryPress": { "value": "{colors.b900}" },
+ "backgroundPrimaryFocus": { "value": "{colors.b700}" },
+ "backgroundPrimaryKeyfocus": { "value": "{colors.b700}" },
+ "backgroundPrimaryDisabled": { "value": "{colors.b200}" },
+ "fontOnPrimary": { "value": "{colors.white}" },
+ "fontOnPrimaryDisabled": { "value": "{colors.white}" },
- "backgroundSecondaryWarningDefault": { "value": "{colors.n400}" },
- "backgroundSecondaryWarningHover": { "value": "{colors.n500}" },
- "backgroundSecondaryWarningPress": { "value": "{colors.n600}" },
- "backgroundSecondaryWarningFocus": { "value": "{colors.n400}" },
- "backgroundSecondaryWarningKeyfocus": { "value": "{colors.n400}" },
- "backgroundSecondaryWarningDisabled": { "value": "{colors.n300}" },
- "fontOnSecondaryWarning": { "value": "{colors.y900}" },
- "fontOnSecondaryWarningDisabled": { "value": "{colors.y600}" },
+ "backgroundSecondaryDefault": { "value": "{colors.n400}" },
+ "backgroundSecondaryHover": { "value": "{colors.n500}" },
+ "backgroundSecondaryPress": { "value": "{colors.n600}" },
+ "backgroundSecondaryFocus": { "value": "{colors.n400}" },
+ "backgroundSecondaryKeyfocus": { "value": "{colors.n400}" },
+ "backgroundSecondaryDisabled": { "value": "{colors.n300}" },
+ "fontOnSecondary": { "value": "{colors.n900}" },
+ "fontOnSecondaryDisabled": { "value": "{colors.n500}" },
- "backgroundSuccessDefault": { "value": "{colors.g500}" },
- "backgroundSuccessHover": { "value": "{colors.g600}" },
- "backgroundSuccessPress": { "value": "{colors.g700}" },
- "backgroundSuccessFocus": { "value": "{colors.g500}" },
- "backgroundSuccessKeyfocus": { "value": "{colors.g500}" },
- "backgroundSuccessDisabled": { "value": "{colors.g200}" },
- "fontOnSuccess": { "value": "{colors.n900}" },
- "fontOnSuccessDisabled": { "value": "{colors.white}" },
+ "backgroundSecondaryDangerDefault": { "value": "{colors.n400}" },
+ "backgroundSecondaryDangerHover": { "value": "{colors.n500}" },
+ "backgroundSecondaryDangerPress": { "value": "{colors.n600}" },
+ "backgroundSecondaryDangerFocus": { "value": "{colors.n400}" },
+ "backgroundSecondaryDangerKeyfocus": { "value": "{colors.n400}" },
+ "backgroundSecondaryDangerDisabled": { "value": "{colors.n300}" },
+ "fontOnSecondaryDanger": { "value": "{colors.r900}" },
+ "onSecondaryDangerDisabled": { "value": "{colors.r300}" },
- "backgroundSecondarySuccessDefault": { "value": "{colors.n400}" },
- "backgroundSecondarySuccessHover": { "value": "{colors.n500}" },
- "backgroundSecondarySuccessPress": { "value": "{colors.n600}" },
- "backgroundSecondarySuccessFocus": { "value": "{colors.n400}" },
- "backgroundSecondarySuccessKeyfocus": { "value": "{colors.n400}" },
- "backgroundSecondarySuccessDisabled": { "value": "{colors.n300}" },
- "fontOnSecondarySuccess": { "value": "{colors.g900}" },
- "fontOnSecondarySuccessDisabled": { "value": "{colors.g400}" },
+ "backgroundDangerDefault": { "value": "{colors.r800}" },
+ "backgroundDangerHover": { "value": "{colors.r900}" },
+ "backgroundDangerPress": { "value": "{colors.r900}" },
+ "backgroundDangerFocus": { "value": "{colors.r800}" },
+ "backgroundDangerKeyfocus": { "value": "{colors.r800}" },
+ "backgroundDangerDisabled": { "value": "{colors.r200}" },
+ "fontOnDanger": { "value": "{colors.white}" },
+ "fontOnDangerDisabled": { "value": "{colors.white}" },
- "onDisabled": { "value": "{colors.n600}" }
+ "backgroundSuccessDefault": { "value": "{colors.g500}" },
+ "backgroundSuccessHover": { "value": "{colors.g600}" },
+ "backgroundSuccessPress": { "value": "{colors.g700}" },
+ "backgroundSuccessFocus": { "value": "{colors.g500}" },
+ "backgroundSuccessKeyfocus": { "value": "{colors.g500}" },
+ "backgroundSuccessDisabled": { "value": "{colors.g200}" },
+ "fontOnSuccess": { "value": "{colors.n900}" },
+ "fontOnSuccessDisabled": { "value": "{colors.white}" }
+ },
+ "dark": {
+ "backgroundPrimaryDefault": { "value": "#095AD2" },
+ "backgroundPrimaryHover": { "value": "#10529E" },
+ "backgroundPrimaryPress": { "value": "#01336B" },
+ "backgroundPrimaryFocus": { "value": "#095AD2" },
+ "backgroundPrimaryKeyfocus": { "value": "#095AD2" },
+ "backgroundPrimaryDisabled": { "value": "#012247" },
+ "fontOnPrimary": { "value": "#FFFFFF" },
+ "fontOnPrimaryDisabled": { "value": "#6C727A" },
+
+ "backgroundSecondaryDefault": { "value": "#353B45" },
+ "backgroundSecondaryHover": { "value": "#404754" },
+ "backgroundSecondaryPress": { "value": "#4C5362" },
+ "backgroundSecondaryFocus": { "value": "#353B45" },
+ "backgroundSecondaryKeyfocus": { "value": "#353B45" },
+ "backgroundSecondaryDisabled": { "value": "#353B45" },
+ "fontOnSecondary": { "value": "#E4E7EA" },
+ "fontOnSecondaryDisabled": { "value": "#6C727A" },
+
+ "backgroundSecondaryDangerDefault": { "value": "#353B45" },
+ "backgroundSecondaryDangerHover": { "value": "#404754" },
+ "backgroundSecondaryDangerPress": { "value": "#4C5362" },
+ "backgroundSecondaryDangerFocus": { "value": "#353B45" },
+ "backgroundSecondaryDangerKeyfocus": { "value": "#353B45" },
+ "backgroundSecondaryDangerDisabled": { "value": "#353B45" },
+ "fontOnSecondaryDanger": { "value": "#FFC1C9" },
+ "onSecondaryDangerDisabled": { "value": "#6B0513" },
+
+ "backgroundDangerDefault": { "value": "#BB3E4E" },
+ "backgroundDangerHover": { "value": "#95323F" },
+ "backgroundDangerPress": { "value": "#822C37" },
+ "backgroundDangerFocus": { "value": "#BB3E4E" },
+ "backgroundDangerKeyfocus": { "value": "#BB3E4E" },
+ "backgroundDangerDisabled": { "value": "#3D2126" },
+ "fontOnDanger": { "value": "#FFFFFF" },
+ "fontOnDangerDisabled": { "value": "#757575" },
+
+ "backgroundSuccessDefault": { "value": "#1D7256" },
+ "backgroundSuccessHover": { "value": "#175943" },
+ "backgroundSuccessPress": { "value": "#134937" },
+ "backgroundSuccessFocus": { "value": "#1D7256" },
+ "backgroundSuccessKeyfocus": { "value": "#1D7256" },
+ "backgroundSuccessDisabled": { "value": "#1E4B40" },
+ "fontOnSuccess": { "value": "#FFFFFF" },
+ "fontOnSuccessDisabled": { "value": "#757575" }
+ }
}
}
diff --git a/packages/fuselage-tokens/src/font/base.json b/packages/fuselage-tokens/src/font/base.json
index 02b401b191..098d21009d 100644
--- a/packages/fuselage-tokens/src/font/base.json
+++ b/packages/fuselage-tokens/src/font/base.json
@@ -1,15 +1,43 @@
{
"font": {
- "white": { "value": "{colors.white}" },
- "disabled": { "value": "{colors.n500}" },
- "annotation": { "value": "{colors.n600}" },
- "hint": { "value": "{colors.n700}" },
- "secondaryInfo": { "value": "{colors.n700}" },
- "default": { "value": "{colors.n800}" },
- "titlesLabels": { "value": "{colors.n900}" },
- "info": { "value": "{colors.b600}" },
- "danger": { "value": "{colors.r600}" },
- "pure-white": { "value": "{colors.white}" },
- "pure-black": { "value": "{colors.n800}" }
+ "light": {
+ "white": { "value": "{colors.white}" },
+ "disabled": { "value": "{colors.n500}" },
+ "annotation": { "value": "{colors.n600}" },
+ "hint": { "value": "{colors.n700}" },
+ "secondaryInfo": { "value": "{colors.n700}" },
+ "default": { "value": "{colors.n800}" },
+ "titlesLabels": { "value": "{colors.n900}" },
+ "info": { "value": "{colors.b600}" },
+ "danger": { "value": "{colors.r600}" },
+ "pureWhite": { "value": "{colors.white}" },
+ "pureBlack": { "value": "{colors.n800}" }
+ },
+ "high-contrast": {
+ "white": { "value": "{colors.white}" },
+ "disabled": { "value": "{colors.n500}" },
+ "annotation": { "value": "{colors.n900}" },
+ "hint": { "value": "{colors.n900}" },
+ "secondaryInfo": { "value": "{colors.n900}" },
+ "default": { "value": "{colors.n900}" },
+ "titlesLabels": { "value": "{colors.n900}" },
+ "info": { "value": "{colors.b800}" },
+ "danger": { "value": "{colors.r800}" },
+ "pureWhite": { "value": "{colors.white}" },
+ "pureBlack": { "value": "{colors.n900}" }
+ },
+ "dark": {
+ "white": { "value": "#2F343D" },
+ "disabled": { "value": "#60646C" },
+ "annotation": { "value": "#9EA2A8" },
+ "hint": { "value": "#9EA2A8" },
+ "secondaryInfo": { "value": "#9EA2A8" },
+ "default": { "value": "#C1C7D0" },
+ "titlesLabels": { "value": "#F2F3F5" },
+ "info": { "value": "#739EDE" },
+ "danger": { "value": "#D88892" },
+ "pureWhite": { "value": "{colors.white}" },
+ "pureBlack": { "value": "{colors.n900}" }
+ }
}
}
diff --git a/packages/fuselage-tokens/src/shadow/base.json b/packages/fuselage-tokens/src/shadow/base.json
new file mode 100644
index 0000000000..3d3123032f
--- /dev/null
+++ b/packages/fuselage-tokens/src/shadow/base.json
@@ -0,0 +1,28 @@
+{
+ "shadow": {
+ "light": {
+ "highlight": { "value": "{colors.b200}" },
+ "danger": { "value": "{colors.r100}" },
+ "elevation-border": { "value": "{colors.n250}" },
+ "elevation-1": { "value": "rgba(47, 52, 61, 0.1)" },
+ "elevation-2x": { "value": "rgba(47, 52, 61, 0.08)" },
+ "elevation-2y": { "value": "rgba(47, 52, 61, 0.12)" }
+ },
+ "high-contrast": {
+ "highlight": { "value": "{colors.b200}" },
+ "danger": { "value": "{colors.r100}" },
+ "elevation-border": { "value": "{colors.n250}" },
+ "elevation-1": { "value": "rgba(47, 52, 61, 0.1)" },
+ "elevation-2x": { "value": "rgba(47, 52, 61, 0.08)" },
+ "elevation-2y": { "value": "rgba(47, 52, 61, 0.12)" }
+ },
+ "dark": {
+ "highlight": { "value": "{colors.b200}" },
+ "danger": { "value": "{colors.r100}" },
+ "elevation-border": { "value": "#2F343D" },
+ "elevation-1": { "value": "rgba(9, 9, 9, 0.35)" },
+ "elevation-2x": { "value": "rgba(9, 9, 9, 0.3)" },
+ "elevation-2y": { "value": "rgba(9, 9, 9, 0.45)" }
+ }
+ }
+}
diff --git a/packages/fuselage-tokens/src/status/base.json b/packages/fuselage-tokens/src/status/base.json
index 0453d196e5..900736e2ae 100644
--- a/packages/fuselage-tokens/src/status/base.json
+++ b/packages/fuselage-tokens/src/status/base.json
@@ -1,16 +1,58 @@
{
"status": {
- "info": { "value": "{colors.b200}" },
- "font-on-info": { "value": "{colors.b600}" },
- "success": { "value": "{colors.g200}" },
- "font-on-success": { "value": "{colors.g800}" },
- "danger": { "value": "{colors.r200}" },
- "font-on-danger": { "value": "{colors.r800}" },
- "warning": { "value": "{colors.y200}" },
- "font-on-warning": { "value": "{colors.y900}" },
- "service-1": { "value": "{colors.o200}" },
- "font-on-service-1": { "value": "{colors.o800}" },
- "service-2": { "value": "{colors.p200}" },
- "font-on-service-2": { "value": "{colors.p600}" }
+ "light": {
+ "info": { "value": "{colors.b200}" },
+ "font-on-info": { "value": "{colors.b600}" },
+ "success": { "value": "{colors.g200}" },
+ "font-on-success": { "value": "{colors.g800}" },
+ "danger": { "value": "{colors.r200}" },
+ "font-on-danger": { "value": "{colors.r800}" },
+ "warning": { "value": "{colors.y200}" },
+ "font-on-warning": { "value": "{colors.y900}" },
+ "warning-2": { "value": "{colors.y100}" },
+ "font-on-warning-2": { "value": "{colors.n800}" },
+ "service-1": { "value": "{colors.o200}" },
+ "font-on-service-1": { "value": "{colors.o800}" },
+ "service-2": { "value": "{colors.p200}" },
+ "font-on-service-2": { "value": "{colors.p600}" },
+ "service-3": { "value": "{colors.p700}" },
+ "font-on-service-3": { "value": "{colors.white}" }
+ },
+ "high-contrast": {
+ "info": { "value": "{colors.b200}" },
+ "font-on-info": { "value": "{colors.b700}" },
+ "success": { "value": "{colors.g200}" },
+ "font-on-success": { "value": "{colors.g1000}" },
+ "danger": { "value": "{colors.r200}" },
+ "font-on-danger": { "value": "{colors.r1000}" },
+ "warning": { "value": "{colors.y200}" },
+ "font-on-warning": { "value": "{colors.y1000}" },
+ "warning-2": { "value": "{colors.y100}" },
+ "font-on-warning-2": { "value": "{colors.n800}" },
+ "service-1": { "value": "{colors.o200}" },
+ "font-on-service-1": { "value": "{colors.o1000}" },
+ "service-2": { "value": "{colors.p200}" },
+ "font-on-service-2": { "value": "{colors.p600}" },
+ "service-3": { "value": "{colors.p700}" },
+ "font-on-service-3": { "value": "{colors.white}" }
+ },
+ "dark": {
+ "info": { "value": "#A8C3EB" },
+ "font-on-info": { "value": "#739EDE" },
+ "success": { "value": "#C1EBDD" },
+ "font-on-success": { "value": "#58AD90" },
+ "danger": { "value": "#F7CFD4" },
+ "font-on-danger": { "value": "#D88892" },
+ "warning": { "value": "#FEEFBE" },
+ "font-on-warning": { "value": "#C7AA66" },
+ "warning-2": { "value": "#3C3625" },
+ "font-on-warning-2": { "value": "#FFFFFF" },
+ "service-1": { "value": "#FCE3CF" },
+ "font-on-service-1": { "value": "#CA9163" },
+ "service-2": { "value": "#EDD0F7" },
+ "font-on-service-2": { "value": "#C393D2" },
+ "service-3": { "value": "#5F1477" },
+ "font-on-service-3": { "value": "#FFFFFF" }
+ }
}
}
diff --git a/packages/fuselage-tokens/src/statusBullet/base.json b/packages/fuselage-tokens/src/statusBullet/base.json
new file mode 100644
index 0000000000..1ccce4b9c9
--- /dev/null
+++ b/packages/fuselage-tokens/src/statusBullet/base.json
@@ -0,0 +1,28 @@
+{
+ "statusBullet": {
+ "light": {
+ "online": { "value": "{colors.g800}" },
+ "away": { "value": "{colors.y800}" },
+ "busy": { "value": "{colors.r600}" },
+ "disabled": { "value": "{colors.o500}" },
+ "offline": { "value": "{colors.n700}" },
+ "loading": { "value": "{colors.n700}" }
+ },
+ "high-contrast": {
+ "online": { "value": "{colors.g1000}" },
+ "away": { "value": "{colors.y800}" },
+ "busy": { "value": "{colors.r1000}" },
+ "disabled": { "value": "{colors.o700}" },
+ "offline": { "value": "{colors.n900}" },
+ "loading": { "value": "{colors.n900}" }
+ },
+ "dark": {
+ "online": { "value": "#1CBF89" },
+ "away": { "value": "#B08C30" },
+ "busy": { "value": "#C75765" },
+ "disabled": { "value": "#CC7F42" },
+ "offline": { "value": "#8B9098" },
+ "loading": { "value": "#8B9098" }
+ }
+ }
+}
diff --git a/packages/fuselage-tokens/src/stroke/base.json b/packages/fuselage-tokens/src/stroke/base.json
index 6322aeccc6..8ebe254455 100644
--- a/packages/fuselage-tokens/src/stroke/base.json
+++ b/packages/fuselage-tokens/src/stroke/base.json
@@ -1,13 +1,37 @@
{
"stroke": {
- "extraLight": { "value": "{colors.n250}" },
- "light": { "value": "{colors.n500}" },
- "medium": { "value": "{colors.n600}" },
- "dark": { "value": "{colors.n700}" },
- "extraDark": { "value": "{colors.n800}" },
- "extraLightHighlight": { "value": "{colors.b200}" },
- "highlight": { "value": "{colors.b500}" },
- "extraLightError": { "value": "{colors.r200}" },
- "error": { "value": "{colors.r500}" }
+ "light": {
+ "extraLight": { "value": "{colors.n250}" },
+ "light": { "value": "{colors.n500}" },
+ "medium": { "value": "{colors.n600}" },
+ "dark": { "value": "{colors.n700}" },
+ "extraDark": { "value": "{colors.n800}" },
+ "extraLightHighlight": { "value": "{colors.b200}" },
+ "highlight": { "value": "{colors.b500}" },
+ "extraLightError": { "value": "{colors.r200}" },
+ "error": { "value": "{colors.r500}" }
+ },
+ "high-contrast": {
+ "extraLight": { "value": "{colors.n250}" },
+ "light": { "value": "{colors.n500}" },
+ "medium": { "value": "{colors.n600}" },
+ "dark": { "value": "{colors.n700}" },
+ "extraDark": { "value": "{colors.n800}" },
+ "extraLightHighlight": { "value": "{colors.b200}" },
+ "highlight": { "value": "{colors.b500}" },
+ "extraLightError": { "value": "{colors.r200}" },
+ "error": { "value": "{colors.r500}" }
+ },
+ "dark": {
+ "extraLight": { "value": "#333842" },
+ "light": { "value": "#404754" },
+ "medium": { "value": "#4B5362" },
+ "dark": { "value": "#9EA2A8" },
+ "extraDark": { "value": "#CBCED1" },
+ "extraLightHighlight": { "value": "#D1EBFE" },
+ "highlight": { "value": "#6292DA" },
+ "extraLightError": { "value": "#F49AA6" },
+ "error": { "value": "#BB3E4E" }
+ }
}
}
diff --git a/packages/fuselage-tokens/src/surface/base.json b/packages/fuselage-tokens/src/surface/base.json
index 704426641a..275d3bc947 100644
--- a/packages/fuselage-tokens/src/surface/base.json
+++ b/packages/fuselage-tokens/src/surface/base.json
@@ -1,14 +1,46 @@
{
"surface": {
- "light": { "value": "{colors.white}" },
- "tint": { "value": "{colors.n100}" },
- "room": { "value": "{colors.white}" },
- "neutral": { "value": "{colors.n400}" },
- "disabled": { "value": "{colors.n100}" },
- "hover": { "value": "{colors.n200}" },
- "selected": { "value": "{colors.n450}" },
- "dark": { "value": "{colors.n900}" },
- "featured": { "value": "{colors.p700}" },
- "featured-hover": { "value": "{colors.p800}" }
+ "light": {
+ "light": { "value": "{colors.white}" },
+ "tint": { "value": "{colors.n100}" },
+ "room": { "value": "{colors.white}" },
+ "neutral": { "value": "{colors.n400}" },
+ "disabled": { "value": "{colors.n100}" },
+ "hover": { "value": "{colors.n200}" },
+ "selected": { "value": "{colors.n450}" },
+ "dark": { "value": "{colors.n900}" },
+ "featured": { "value": "{colors.p700}" },
+ "featuredHover": { "value": "{colors.p800}" },
+ "sidebar": { "value": "{colors.n400}" },
+ "overlay": { "value": "rgba(47, 52, 61, 0.5)" }
+ },
+ "high-contrast": {
+ "light": { "value": "{colors.white}" },
+ "tint": { "value": "{colors.n100}" },
+ "room": { "value": "{colors.white}" },
+ "neutral": { "value": "{colors.n400}" },
+ "disabled": { "value": "{colors.n100}" },
+ "hover": { "value": "{colors.n200}" },
+ "selected": { "value": "{colors.n450}" },
+ "dark": { "value": "{colors.n900}" },
+ "featured": { "value": "{colors.p700}" },
+ "featuredHover": { "value": "{colors.p800}" },
+ "sidebar": { "value": "{colors.n400}" },
+ "overlay": { "value": "rgba(47, 52, 61, 0.5)" }
+ },
+ "dark": {
+ "light": { "value": "#262931" },
+ "tint": { "value": "#1F2329" },
+ "room": { "value": "#1F2329" },
+ "neutral": { "value": "#2D3039" },
+ "disabled": { "value": "#24272E" },
+ "hover": { "value": "#1A1E23" },
+ "selected": { "value": "#4C5362" },
+ "dark": { "value": "#E4E7EA" },
+ "featured": { "value": "#5F1477" },
+ "featuredHover": { "value": "#4A105D" },
+ "sidebar": { "value": "#2F343D" },
+ "overlay": { "value": "rgba(0, 0, 0, 0.6)" }
+ }
}
}
diff --git a/packages/fuselage/.storybook/DocsContainer.tsx b/packages/fuselage/.storybook/DocsContainer.tsx
new file mode 100644
index 0000000000..34a38804a5
--- /dev/null
+++ b/packages/fuselage/.storybook/DocsContainer.tsx
@@ -0,0 +1,43 @@
+import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks';
+import { themes } from '@storybook/theming';
+import type { ComponentProps } from 'react';
+import React from 'react';
+import { useDarkMode } from 'storybook-dark-mode';
+
+import { surface } from './helpers';
+
+export const DocsContainer = ({
+ children,
+ context,
+}: ComponentProps) => {
+ const dark = useDarkMode();
+
+ return (
+ {
+ const storyContext = context.storyById(id);
+ return {
+ ...storyContext,
+ parameters: {
+ ...storyContext?.parameters,
+ docs: {
+ ...storyContext?.parameters?.docs,
+ theme: dark
+ ? {
+ ...themes.dark,
+ appContentBg: surface.main,
+ barBg: surface.main,
+ }
+ : themes.light,
+ },
+ },
+ };
+ },
+ }}
+ >
+ {children}
+
+ );
+};
diff --git a/packages/fuselage/.storybook/helpers.tsx b/packages/fuselage/.storybook/helpers.tsx
index de0ff88efb..b90254fb7c 100644
--- a/packages/fuselage/.storybook/helpers.tsx
+++ b/packages/fuselage/.storybook/helpers.tsx
@@ -2,6 +2,7 @@ import type { ComponentProps, ComponentType } from 'react';
import React from 'react';
import { Box, Icon } from '../src';
+import { dark } from '../src/components/PaletteStyleTag/lib/themePalettes';
type PropsVariationSectionProps> = {
component: TComponent;
@@ -143,3 +144,8 @@ export const menuOptions = {
action: () => console.log('[...] no longer exists'),
},
};
+
+export const surface = {
+ sidebar: dark['surface-sidebar'],
+ main: dark['surface-light'],
+};
diff --git a/packages/fuselage/.storybook/preview.ts b/packages/fuselage/.storybook/preview.tsx
similarity index 70%
rename from packages/fuselage/.storybook/preview.ts
rename to packages/fuselage/.storybook/preview.tsx
index 65c44abd21..5071b1bb93 100644
--- a/packages/fuselage/.storybook/preview.ts
+++ b/packages/fuselage/.storybook/preview.tsx
@@ -1,9 +1,15 @@
import breakpointTokens from '@rocket.chat/fuselage-tokens/breakpoints.json';
-import { DocsPage, DocsContainer } from '@storybook/addon-docs';
+import { DocsPage } from '@storybook/addon-docs';
import type { Parameters } from '@storybook/addons';
+import type { DecoratorFn } from '@storybook/react';
import { themes } from '@storybook/theming';
+import React from 'react';
+import { useDarkMode } from 'storybook-dark-mode';
import manifest from '../package.json';
+import { PaletteStyleTag } from '../src';
+import { DocsContainer } from './DocsContainer';
+import { surface } from './helpers';
import logo from './logo.svg';
import 'normalize.css/normalize.css';
@@ -56,6 +62,9 @@ export const parameters: Parameters = {
darkMode: {
dark: {
...themes.dark,
+ appBg: surface.sidebar,
+ appContentBg: surface.main,
+ barBg: surface.main,
brandTitle: manifest.name,
brandImage: logo,
brandUrl: manifest.homepage,
@@ -68,3 +77,16 @@ export const parameters: Parameters = {
},
},
};
+
+export const decorators: DecoratorFn[] = [
+ (Story) => {
+ const dark = useDarkMode();
+
+ return (
+ <>
+
+
+ >
+ );
+ },
+];
diff --git a/packages/fuselage/CHANGELOG.md b/packages/fuselage/CHANGELOG.md
index a675ba5b46..9d669b2775 100644
--- a/packages/fuselage/CHANGELOG.md
+++ b/packages/fuselage/CHANGELOG.md
@@ -1,5 +1,138 @@
# Change Log
+## 0.53.2
+
+### Patch Changes
+
+- [#1344](https://github.com/RocketChat/fuselage/pull/1344) [`8f67c5d20`](https://github.com/RocketChat/fuselage/commit/8f67c5d20939258bf4f09ee8d6ca36b68496c7ac) Thanks [@dougfabris](https://github.com/dougfabris)! - fix: wrong `MessageMetrics` export
+
+## 0.53.1
+
+### Patch Changes
+
+- [#1342](https://github.com/RocketChat/fuselage/pull/1342) [`71c221684`](https://github.com/RocketChat/fuselage/commit/71c22168458c51975b32170a53c4a835124bec2b) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage): MessageMetrics props types
+
+## 0.53.0
+
+### Minor Changes
+
+- [#1338](https://github.com/RocketChat/fuselage/pull/1338) [`ea37a3110`](https://github.com/RocketChat/fuselage/commit/ea37a3110670e507c1a33c0793b6cef1b5ff1215) Thanks [@yash-rajpal](https://github.com/yash-rajpal)! - Accept disable button prop on CodeSnippet component
+
+## 0.52.0
+
+### Minor Changes
+
+- [#1331](https://github.com/RocketChat/fuselage/pull/1331) [`bd17e9c59`](https://github.com/RocketChat/fuselage/commit/bd17e9c59696f26bf59f7f389f08f3185a780c65) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(fuselage): MessageReactions focus state
+
+### Patch Changes
+
+- [#1335](https://github.com/RocketChat/fuselage/pull/1335) [`cef61fd9f`](https://github.com/RocketChat/fuselage/commit/cef61fd9f0e2139f54036809b11782de09b9d025) Thanks [@juliajforesti](https://github.com/juliajforesti)! - fix(fuselage): show `AutoComplete` placeholder
+
+## 0.51.3
+
+### Patch Changes
+
+- [#1327](https://github.com/RocketChat/fuselage/pull/1327) [`350eaa1ac`](https://github.com/RocketChat/fuselage/commit/350eaa1ac73a4dc66f1b6787df475c52389f96b6) Thanks [@csuadev](https://github.com/csuadev)! - fix(fuselage): Add missing renderItem property on PaginatedSelect component to allow options customization.
+
+- [#1328](https://github.com/RocketChat/fuselage/pull/1328) [`6eecf95fb`](https://github.com/RocketChat/fuselage/commit/6eecf95fb1f7e77032de801033134eaed3e4501f) Thanks [@juliajforesti](https://github.com/juliajforesti)! - fix(fuselage): add missing `Bubble` gap
+
+## 0.51.2
+
+### Patch Changes
+
+- [#1322](https://github.com/RocketChat/fuselage/pull/1322) [`f67ac5dc0`](https://github.com/RocketChat/fuselage/commit/f67ac5dc0a02ce47468a640d08e8ba373eca3d51) Thanks [@csuadev](https://github.com/csuadev)! - fix(fuselage): Added missing render property from PaginatedMultiselect on PaginatedMultiSelectFiltered component to allow rendering items on it.
+
+## 0.51.1
+
+### Patch Changes
+
+- [#1324](https://github.com/RocketChat/fuselage/pull/1324) [`8f4502968`](https://github.com/RocketChat/fuselage/commit/8f450296822ee8a087831683828f513c2156b279) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage): Avoid duplicated alert on ToastBar
+
+- [#1323](https://github.com/RocketChat/fuselage/pull/1323) [`9ccc4e79f`](https://github.com/RocketChat/fuselage/commit/9ccc4e79f76c1ef2b182065883bd66a91860bc96) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(icons): New circle-unfilled
+
+## 0.51.0
+
+### Minor Changes
+
+- [#1319](https://github.com/RocketChat/fuselage/pull/1319) [`b37dd11c9`](https://github.com/RocketChat/fuselage/commit/b37dd11c9bd0fc4dbdda5ab5e623dfc46c8d8647) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(fuselage): Add forwardRef on Contextualbar
+
+### Patch Changes
+
+- [#1320](https://github.com/RocketChat/fuselage/pull/1320) [`06b1d5701`](https://github.com/RocketChat/fuselage/commit/06b1d57015c59fbba95c8986fe054c2b3336f73f) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage): `ToastBar` remove close button from content alert
+
+## 0.50.1
+
+### Patch Changes
+
+- [#1317](https://github.com/RocketChat/fuselage/pull/1317) [`410a12131`](https://github.com/RocketChat/fuselage/commit/410a1213140b6dbfccdd75c9dfcf4b90938bf51d) Thanks [@juliajforesti](https://github.com/juliajforesti)! - fix(fuselage): remove margin inline end from bubble icon
+
+## 0.50.0
+
+### Minor Changes
+
+- [#1311](https://github.com/RocketChat/fuselage/pull/1311) [`aff73a3cb`](https://github.com/RocketChat/fuselage/commit/aff73a3cbbbc80dbd2045c3644cc787f1ca5eb4e) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(fuselage): Add focus state on `MessgeHighlight`
+
+### Patch Changes
+
+- [#1310](https://github.com/RocketChat/fuselage/pull/1310) [`564174632`](https://github.com/RocketChat/fuselage/commit/564174632ccda751555a1e4128c3b897bbc1b86f) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage): `MessageToolbarWrapper` visibility
+
+- [#1312](https://github.com/RocketChat/fuselage/pull/1312) [`91fe5c9d3`](https://github.com/RocketChat/fuselage/commit/91fe5c9d3600404a11529018c01907edb00e4c05) Thanks [@csuadev](https://github.com/csuadev)! - Change border color on Accordion component that was affecting dark mode, requested by design.
+
+- [#1314](https://github.com/RocketChat/fuselage/pull/1314) [`75305d76e`](https://github.com/RocketChat/fuselage/commit/75305d76e336f635efc855f7f6545605f873126c) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage): `Contextualbar` elements syntax
+
+## 0.49.0
+
+### Minor Changes
+
+- [#1289](https://github.com/RocketChat/fuselage/pull/1289) [`a40d471bd`](https://github.com/RocketChat/fuselage/commit/a40d471bdf71babf652f5df3108a05d92f08d975) Thanks [@juliajforesti](https://github.com/juliajforesti)! - feat(fuselage): new `PaletteStyleTag` component
+
+### Patch Changes
+
+- Updated dependencies [[`a40d471bd`](https://github.com/RocketChat/fuselage/commit/a40d471bdf71babf652f5df3108a05d92f08d975)]:
+ - @rocket.chat/fuselage-tokens@0.33.0
+
+## 0.48.0
+
+### Minor Changes
+
+- [#1303](https://github.com/RocketChat/fuselage/pull/1303) [`168ff5b12`](https://github.com/RocketChat/fuselage/commit/168ff5b12a6ce1ddf3ba6a881d3634326516faee) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(fuselage): Adds `Tag` focus state
+
+## 0.47.1
+
+### Patch Changes
+
+- [#1291](https://github.com/RocketChat/fuselage/pull/1291) [`7d61a2677`](https://github.com/RocketChat/fuselage/commit/7d61a26778253cf2e022a7d9422fdbe3aaedd9f2) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage): `MessageNameContainer` missing forwardRef
+
+## 0.47.0
+
+### Minor Changes
+
+- [#1287](https://github.com/RocketChat/fuselage/pull/1287) [`2863143ae`](https://github.com/RocketChat/fuselage/commit/2863143aee7e57df16d19ca86659a59800363b24) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(fuselage): Popover
+
+### Patch Changes
+
+- [#1280](https://github.com/RocketChat/fuselage/pull/1280) [`8b8d43b74`](https://github.com/RocketChat/fuselage/commit/8b8d43b74da69094ea026aa041f8313be5c896b4) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage): MessageSystem time fontScale
+
+- [#1288](https://github.com/RocketChat/fuselage/pull/1288) [`7390c0205`](https://github.com/RocketChat/fuselage/commit/7390c02057d52d3e62206667c5c26e0aedf70f26) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(fuselage): Prevent focus state on clicking in Messages
+
+## 0.46.0
+
+### Minor Changes
+
+- [#1278](https://github.com/RocketChat/fuselage/pull/1278) [`7ed164c23`](https://github.com/RocketChat/fuselage/commit/7ed164c233fa6c511daa3951daa8c7af0c10bc86) Thanks [@juliajforesti](https://github.com/juliajforesti)! - feat(fuselage): new `Bubble` variations
+
+## 0.45.0
+
+### Minor Changes
+
+- [#1277](https://github.com/RocketChat/fuselage/pull/1277) [`775236cb4`](https://github.com/RocketChat/fuselage/commit/775236cb4f391194183a96df48ea241b1429dab6) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(fuselage): Add forwardRef in MessageToolbar
+
+### Patch Changes
+
+- [#1275](https://github.com/RocketChat/fuselage/pull/1275) [`7451ecae5`](https://github.com/RocketChat/fuselage/commit/7451ecae56d9f4a73f00ca4b212e33260cf7a81b) Thanks [@juliajforesti](https://github.com/juliajforesti)! - fix(fuselage): change `card-horizontal` row gap
+
+- [#1270](https://github.com/RocketChat/fuselage/pull/1270) [`3469b7798`](https://github.com/RocketChat/fuselage/commit/3469b7798242b1925ac243cdf3268d4d7d7c3597) Thanks [@juliajforesti](https://github.com/juliajforesti)! - feat(fuselage): normalize links
+
## 0.44.2
### Patch Changes
diff --git a/packages/fuselage/README.md b/packages/fuselage/README.md
index d2ad0eb480..d14c436206 100644
--- a/packages/fuselage/README.md
+++ b/packages/fuselage/README.md
@@ -115,6 +115,16 @@ yarn storybook
### Usage
+To use the fuselage, you need to import the css first:
+
+```tsx
+import '@rocket.chat/fuselage/dist/fuselage.css';
+
+const MyButton = () => {
+ return Fuselage Button
+};
+```
+
Note: If you are using Next.js for development and wish to use Rocket.Chat Fuselage components, you need to dynamically import the component. More on this can be found [here](https://dev.to/vvo/how-to-solve-window-is-not-defined-errors-in-react-and-next-js-5f97#3-third-solution-dynamic-loading).
Usage Example:
diff --git a/packages/fuselage/package.json b/packages/fuselage/package.json
index dd9f7ab05b..b95a501787 100644
--- a/packages/fuselage/package.json
+++ b/packages/fuselage/package.json
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/fuselage",
- "version": "0.44.2",
+ "version": "0.53.2",
"description": "Rocket.Chat's React Components Library",
"author": {
"name": "Rocket.Chat",
diff --git a/packages/fuselage/src/components/Accordion/Accordion.styles.scss b/packages/fuselage/src/components/Accordion/Accordion.styles.scss
index d2c4b6d571..b22ac696eb 100644
--- a/packages/fuselage/src/components/Accordion/Accordion.styles.scss
+++ b/packages/fuselage/src/components/Accordion/Accordion.styles.scss
@@ -28,7 +28,7 @@
color: colors.font(default);
border-width: lengths.border-width(default);
- border-color: colors.neutral(300) transparent transparent;
+ border-color: colors.stroke(extra-light) transparent transparent;
&[tabindex] {
@include clickable;
diff --git a/packages/fuselage/src/components/AutoComplete/AutoComplete.stories.tsx b/packages/fuselage/src/components/AutoComplete/AutoComplete.stories.tsx
index ef7b59bed9..4b2c468cdf 100644
--- a/packages/fuselage/src/components/AutoComplete/AutoComplete.stories.tsx
+++ b/packages/fuselage/src/components/AutoComplete/AutoComplete.stories.tsx
@@ -17,6 +17,7 @@ export default {
title: 'Inputs/AutoComplete',
component: AutoComplete,
parameters: {
+ layout: 'centered',
docs: {
description: {
component: 'An input for selection of options.',
@@ -108,3 +109,8 @@ CustomItem.args = {
/>
),
};
+
+export const WithPlaceholder = Template.bind({});
+WithPlaceholder.args = {
+ placeholder: 'Search...',
+};
diff --git a/packages/fuselage/src/components/AutoComplete/AutoComplete.tsx b/packages/fuselage/src/components/AutoComplete/AutoComplete.tsx
index 37fa990a90..8da6390f6d 100644
--- a/packages/fuselage/src/components/AutoComplete/AutoComplete.tsx
+++ b/packages/fuselage/src/components/AutoComplete/AutoComplete.tsx
@@ -153,7 +153,7 @@ export function AutoComplete({
onFocus={show}
onKeyDown={handleKeyDown}
placeholder={
- optionsAreVisible !== AnimatedVisibility.HIDDEN || !value
+ optionsAreVisible === AnimatedVisibility.HIDDEN || !value
? placeholder
: undefined
}
@@ -192,6 +192,7 @@ export function AutoComplete({
: 'magnifier'
}
size='x20'
+ color='default'
/>
}
/>
diff --git a/packages/fuselage/src/components/AutoComplete/__snapshots__/AutoComplete.spec.tsx.snap b/packages/fuselage/src/components/AutoComplete/__snapshots__/AutoComplete.spec.tsx.snap
index 90d8c62f97..39f1090330 100644
--- a/packages/fuselage/src/components/AutoComplete/__snapshots__/AutoComplete.spec.tsx.snap
+++ b/packages/fuselage/src/components/AutoComplete/__snapshots__/AutoComplete.spec.tsx.snap
@@ -21,7 +21,7 @@ exports[`[AutoComplete Rendering] renders CustomItem without crashing 1`] = `
>
@@ -119,7 +119,7 @@ v/L21v8BT/ZVoe1UItsAAAAASUVORK5CYII="
>
@@ -150,7 +150,7 @@ exports[`[AutoComplete Rendering] renders Default without crashing 1`] = `
>
@@ -217,7 +217,7 @@ exports[`[AutoComplete Rendering] renders Multiple without crashing 1`] = `
>
@@ -414,7 +414,39 @@ v/L21v8BT/ZVoe1UItsAAAAASUVORK5CYII="
>
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/fuselage/src/components/Banner/Banner.styles.scss b/packages/fuselage/src/components/Banner/Banner.styles.scss
index 0f0284c854..74dc17f5f8 100644
--- a/packages/fuselage/src/components/Banner/Banner.styles.scss
+++ b/packages/fuselage/src/components/Banner/Banner.styles.scss
@@ -151,9 +151,5 @@ $banner-colors-danger-color: functions.theme(
&__link {
padding-left: 10px;
-
- text-decoration: underline;
-
- color: inherit;
}
}
diff --git a/packages/fuselage/src/components/Box/colors.stories.tsx b/packages/fuselage/src/components/Box/colors.stories.tsx
new file mode 100644
index 0000000000..0dc26388e7
--- /dev/null
+++ b/packages/fuselage/src/components/Box/colors.stories.tsx
@@ -0,0 +1,174 @@
+import {
+ Title,
+ Description,
+ Primary,
+ Stories,
+ ArgsTable,
+ Subtitle,
+} from '@storybook/addon-docs';
+import type { ComponentStory, ComponentMeta } from '@storybook/react';
+import React from 'react';
+import flattenChildren from 'react-keyed-flatten-children';
+
+import { Box } from '../..';
+
+export default {
+ title: 'Layout/Box/Colors',
+ component: Box,
+ parameters: {
+ docs: {
+ description: {
+ component: 'Here are the available color props and values.',
+ },
+ page: () => (
+ <>
+
+
+
+
+
+
+ >
+ ),
+ },
+ },
+} as ComponentMeta
;
+
+export const SurfaceColors: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+SurfaceColors.decorators = [
+ (story: any) => (
+
+ {flattenChildren(story().props.children).map((child: any) =>
+ React.cloneElement(
+ child,
+ {
+ m: 'x4',
+ size: 'x122',
+ color: 'annotation',
+ border: '2px solid',
+ borderColor: 'stroke light',
+ borderRadius: 4,
+ textAlign: 'center',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ child.props.bg
+ )
+ )}
+
+ ),
+];
+
+export const StatusColors: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+ >
+);
+StatusColors.decorators = [
+ (story: any) => (
+
+ {flattenChildren(story().props.children).map((child: any) =>
+ React.cloneElement(
+ child,
+ {
+ m: 'x4',
+ size: 'x122',
+ border: '2px solid',
+ borderRadius: 4,
+ textAlign: 'center',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ child.props.bg.replace('status-background-', '')
+ )
+ )}
+
+ ),
+];
+
+export const StrokeColors: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+
+
+
+ >
+);
+StrokeColors.decorators = [
+ (story: any) => (
+
+ {flattenChildren(story().props.children).map((child: any) =>
+ React.cloneElement(
+ child,
+ {
+ m: 'x4',
+ textAlign: 'center',
+ size: 'x122',
+ color: 'default',
+ borderWidth: 'x8',
+ borderRadius: 4,
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ p: 8,
+ },
+ child.props.borderColor
+ )
+ )}
+
+ ),
+];
+
+export const FontColors: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+
+
+
+ >
+);
+FontColors.decorators = [
+ (story: any) => (
+
+ {flattenChildren(story().props.children).map((child: any) =>
+ React.cloneElement(child, { m: 'x4', p: 'x4' }, child.props.color)
+ )}
+
+ ),
+];
diff --git a/packages/fuselage/src/components/Box/layout.stories.tsx b/packages/fuselage/src/components/Box/layout.stories.tsx
new file mode 100644
index 0000000000..adabbe9f11
--- /dev/null
+++ b/packages/fuselage/src/components/Box/layout.stories.tsx
@@ -0,0 +1,417 @@
+import {
+ Title,
+ Description,
+ Primary,
+ Stories,
+ ArgsTable,
+ Subtitle,
+} from '@storybook/addon-docs';
+import type { ComponentStory, ComponentMeta } from '@storybook/react';
+import React from 'react';
+import flattenChildren from 'react-keyed-flatten-children';
+
+import { Box, Divider } from '../..';
+
+export default {
+ title: 'Layout/Box/Layout',
+ component: Box,
+ parameters: {
+ docs: {
+ description: {
+ component: 'Here is how rich content will be rendered, in details.',
+ },
+ page: () => (
+ <>
+
+
+
+
+
+
+ >
+ ),
+ },
+ },
+} as ComponentMeta;
+
+export const Borders: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+Borders.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, {
+ size: 'x32',
+ m: 'x16',
+ borderColor: 'stroke-dark',
+ })
+ )}
+
+ ),
+];
+
+export const BorderRadii: ComponentStory = () => (
+ <>
+
+
+
+
+
+ >
+);
+BorderRadii.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, {
+ bg: 'dark',
+ size: 'x32',
+ m: 'x16',
+ })
+ )}
+
+ ),
+];
+
+export const Display: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+ >
+);
+Display.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, {
+ children: child.props.display,
+ border: '1px solid',
+ borderColor: 'stroke-light',
+ m: 'x4',
+ p: 'x4',
+ })
+ )}
+
+ ),
+];
+
+export const Elevation: ComponentStory = () => (
+ <>
+
+
+
+
+
+ >
+);
+Elevation.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, {
+ bg: 'light',
+ size: 'x32',
+ m: 'x16',
+ })
+ )}
+
+ ),
+];
+
+export const Heights: ComponentStory = () => (
+ <>
+
+
+
+
+ >
+);
+Heights.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, { bg: 'neutral', w: 'x32', m: 'x4' })
+ )}
+
+ ),
+];
+
+export const Insets: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+Insets.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) => (
+
+ {React.cloneElement(child, {
+ bg: 'neutral',
+ position: 'absolute',
+ minSize: 'x16',
+ })}
+
+ ))}
+
+ ),
+];
+
+export const Invisible: ComponentStory = () => ;
+
+export const Margins: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+Margins.decorators = [
+ (story: any) => (
+
+ {flattenChildren(story().props.children).map((child: any, i) => (
+
+ {React.cloneElement(
+ child,
+ { bg: 'primary-200' },
+
+ )}
+
+ ))}
+
+ ),
+];
+
+export const Opacity: ComponentStory = () => (
+
+
+
+
+
+
+
+
+);
+
+export const Paddings: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+Paddings.decorators = [
+ (story: any) => (
+
+ {flattenChildren(story().props.children).map((child: any, i) => (
+
+ {React.cloneElement(
+ child,
+ { bg: 'primary-200' },
+
+ )}
+
+ ))}
+
+ ),
+];
+
+export const Position: ComponentStory = () => (
+ <>
+
+
+
+
+ >
+);
+Position.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, {
+ bg: 'neutral',
+ size: 'x32',
+ m: 'x16',
+ })
+ )}
+
+ ),
+];
+
+export const Widths: ComponentStory = () => (
+ <>
+
+
+
+
+ >
+);
+Widths.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, { bg: 'neutral', h: 'x32', m: 'x4' })
+ )}
+
+ ),
+];
+
+export const Sizes: ComponentStory = () => (
+ <>
+
+
+
+ >
+);
+Sizes.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, { bg: 'neutral', m: 'x4' })
+ )}
+
+ ),
+];
+
+export const TextAlign: ComponentStory = () => (
+
+ left
+
+ center
+
+ right
+
+ justify
+
+
+);
+
+export const VerticalAlign: ComponentStory = () => (
+ <>
+
+
+
+
+
+
+
+ >
+);
+VerticalAlign.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, {
+ display: 'inline',
+ children: child.props.verticalAlign,
+ color: 'default',
+ border: '1px solid',
+ borderColor: 'stroke-dark',
+ borderRadius: 'x4',
+ m: 'x4',
+ p: 'x4',
+ })
+ )}
+
+ ),
+];
+
+export const ZIndex: ComponentStory = () => (
+ <>
+
+
+
+
+ >
+);
+ZIndex.decorators = [
+ (fn: any) => (
+
+ {flattenChildren(fn().props.children).map((child: any) =>
+ React.cloneElement(child, {
+ bg: 'neutral',
+ borderWidth: 'x4',
+ size: 'x32',
+ m: 'neg-x2',
+ })
+ )}
+
+ ),
+];
diff --git a/packages/fuselage/src/components/Box/props.stories.mdx b/packages/fuselage/src/components/Box/props.stories.mdx
deleted file mode 100644
index 512982b027..0000000000
--- a/packages/fuselage/src/components/Box/props.stories.mdx
+++ /dev/null
@@ -1,898 +0,0 @@
-import { Meta, Canvas, ArgsTable, Story } from '@storybook/addon-docs';
-import flattenChildren from 'react-keyed-flatten-children';
-
-import { Box, Button } from '../..';
-
-
-
-# Box
-
-## Props
-
-Most of the props are designed to change styles by creating CSS rules at runtime.
-
-
-
-### `is` prop
-
-The `is` prop allows `Box` to render any component capable of handling common DOM attributes, specially `className` and
-`style`.
-
-
-
- A Box rendering a Button
-
-
-
-### Space
-
-#### Margins
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) => (
-
- {React.cloneElement(
- child,
- { bg: 'primary-200' },
-
- )}
-
- ))}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
-
-
-
-#### Paddings
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) => (
-
- {React.cloneElement(
- child,
- { bg: 'primary-200' },
-
- )}
-
- ))}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
-
-
-
-### Color
-
-#### Surface Colors
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(
- child,
- {
- m: 'x4',
- size: 'x122',
- color: 'annotation',
- textAlign: 'center',
- },
- child.props.bg
- )
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
-
-
-
-
-
- >
-
-
-
-#### Status Colors
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(
- child,
- { m: 'x4', size: 'x122', textAlign: 'center' },
- child.props.bg
- )
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
- >
-
-
-
-#### Stroke Colors
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(
- child,
- {
- m: 'x4',
- textAlign: 'center',
- size: 'x122',
- color: 'annotation',
- borderWidth: 'x8',
- },
- child.props.borderColor
- )
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
-
-
-
- >
-
-
-
-#### Font Colors
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(
- child,
- { bg: 'neutral-200', m: 'x4', p: 'x4' },
- child.props.color
- )
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
-
-
-
- >
-
-
-
-#### Opacity
-
-
- React.cloneElement(fn(), { size: 'x32', bg: 'neutral-500' }),
- ]}
- >
-
-
-
-
-### Typography
-
-#### Font families
-
-
-
- <>
- The quick brown fox jumps over the lazy dog
- The quick brown fox jumps over the lazy dog
- >
-
-
-
-#### Font sizes
-
-
-
- <>
- x12
- x16
- x20
- x24
- x32
- hero
- h1
- h2
- h3
- h4
- h5
- p1
- p1m
- p1b
- p2
- p2m
- p2b
- c1
- c2
- micro
- >
-
-
-
-#### Font weights
-
-
-
- <>
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- hero
- h1
- h2
- h3
- h4
- h5
- p1
- p1m
- p1b
- p2
- p2m
- p2b
- c1
- c2
- micro
- >
-
-
-
-#### Line heights
-
-
-
- <>
- 1
- 1.25
- 1.5
- 2
- hero
- h1
- h2
- h3
- h4
- h5
- p1
- p1m
- p1b
- p2
- p2m
- p2b
- c1
- c2
- micro
- >
-
-
-
-#### Letter spacing
-
-
-
- <>
- 4px
- -4px
- hero
- h1
- h2
- h3
- h4
- h5
- p1
- p1m
- p1b
- p2
- p2m
- p2b
- c1
- c2
- micro
- >
-
-
-
-#### Font scales
-
-
-
- <>
- hero
- h1
- h2
- h3
- h4
- h5
- p1
- p1m
- p1b
- p2
- p2m
- p2b
- c1
- c2
- micro
- >
-
-
-
-#### Font styles
-
-
-
- <>
- normal
- italic
- >
-
-
-
-#### Text alignment
-
-
-
- <>
- start
- end
- center
- justify
- >
-
-
-
-#### Text transform
-
-
-
- <>
- none
- uppercase
- lowercase
- capitalize
- >
-
-
-
-#### Text decoration
-
-
-
- <>
- none
- underline
- overline
- line-through
- >
-
-
-
-#### Word Break
-
-
-
- <>
-
- Breakwoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooord
-
-
- Breakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaall
-
- >
-
-
-
-### Layout
-
-#### Widths
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, { bg: 'primary-200', h: 'x32', m: 'x4' })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
- >
-
-
-
-#### Heights
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, { bg: 'primary-200', w: 'x32', m: 'x4' })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
- >
-
-
-
-#### Sizes
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, { bg: 'primary-200', m: 'x4' })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
- >
-
-
-
-#### Display
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, { children: child.props.display })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
-
- >
-
-
-
-#### Vertical alignment
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, {
- display: 'inline',
- children: child.props.verticalAlign,
- })
- )}
-
- ),
- ]}
- >
-
-
-
-
-
-
-
-
-
-
-
-
-### Borders
-
-#### Borders
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, {
- bg: 'primary-200',
- size: 'x32',
- m: 'x16',
- })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
-
-
-
-#### Border radii
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, {
- bg: 'primary-200',
- size: 'x32',
- m: 'x16',
- })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
- >
-
-
-
-### Position
-
-#### Position
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, {
- bg: 'primary-200',
- size: 'x32',
- m: 'x16',
- })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
- >
-
-
-
-#### Z-index
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, {
- bg: 'primary-200',
- borderWidth: 'x4',
- size: 'x32',
- m: 'neg-x2',
- })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
- >
-
-
-
-#### Inset
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) => (
-
- {React.cloneElement(child, {
- bg: 'primary-200',
- position: 'absolute',
- minSize: 'x16',
- })}
-
- ))}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- >
-
-
-
-### Special
-
-#### Elevation
-
-
- (
-
- {flattenChildren(fn().props.children).map((child) =>
- React.cloneElement(child, {
- bg: 'primary-100',
- m: 'x16',
- size: 'x64',
- })
- )}
-
- ),
- ]}
- >
- <>
-
-
-
-
-
- >
-
-
-
-#### Invisible
-
-
- (
-
- {flattenChildren(fn()).map((child) => (
-
- {React.cloneElement(child, { bg: 'primary-200', size: 'x16' })}
-
- ))}
-
- ),
- ]}
- >
-
-
-
-
-#### With rich content
-
-
-
-
-
- This text is strong
-
-
- This text has emphasis
-
-
- This is subscript and superscript
-
-
-
-
-
-#### With truncated text
-
-
-
-
- This text is truncated.
-
-
-
diff --git a/packages/fuselage/src/components/Box/props.stories.tsx b/packages/fuselage/src/components/Box/props.stories.tsx
new file mode 100644
index 0000000000..c280f33ae7
--- /dev/null
+++ b/packages/fuselage/src/components/Box/props.stories.tsx
@@ -0,0 +1,58 @@
+import {
+ Title,
+ Description,
+ Primary,
+ Stories,
+ ArgsTable,
+ Subtitle,
+} from '@storybook/addon-docs';
+import type { ComponentStory, ComponentMeta } from '@storybook/react';
+import React from 'react';
+
+import { Box, Button } from '../..';
+
+export default {
+ title: 'Layout/Box/isProp',
+ component: Box,
+ parameters: {
+ docs: {
+ description: {
+ component:
+ 'The `is` prop is used to render the Box as a different HTML tag. It can also be used to render a different fuselage component.',
+ },
+ page: () => (
+ <>
+
+
+
+
+
+
+ >
+ ),
+ },
+ },
+} as ComponentMeta;
+
+const Template: ComponentStory = (args) => ;
+
+export const isButton = Template.bind({});
+isButton.args = {
+ is: Button,
+ children: 'A Box rendering a Button',
+};
+isButton.storyName = 'is Button';
+
+export const isSpan = Template.bind({});
+isSpan.args = {
+ is: 'span',
+ children: 'A Box rendering a span',
+};
+isSpan.storyName = 'is span';
+
+export const isH4 = Template.bind({});
+isH4.args = {
+ is: 'h4',
+ children: 'A Box rendering a h4',
+};
+isH4.storyName = 'is h4';
diff --git a/packages/fuselage/src/components/Box/richContentInline.stories.tsx b/packages/fuselage/src/components/Box/richContentInline.stories.tsx
index 07a5e9078d..1e824d7253 100644
--- a/packages/fuselage/src/components/Box/richContentInline.stories.tsx
+++ b/packages/fuselage/src/components/Box/richContentInline.stories.tsx
@@ -53,20 +53,15 @@ i.storyName = 'i';
export const a: ComponentStory = () => (
<>
- Normal
-
-
- Visited
-
-
-
- Active
-
-
-
- Hovered
-
+
+
>
);
a.storyName = 'a';
diff --git a/packages/fuselage/src/components/Box/typography.stories.tsx b/packages/fuselage/src/components/Box/typography.stories.tsx
new file mode 100644
index 0000000000..4ff4397e39
--- /dev/null
+++ b/packages/fuselage/src/components/Box/typography.stories.tsx
@@ -0,0 +1,196 @@
+import {
+ Title,
+ Description,
+ Primary,
+ Stories,
+ ArgsTable,
+ Subtitle,
+} from '@storybook/addon-docs';
+import type { ComponentStory, ComponentMeta } from '@storybook/react';
+import React from 'react';
+
+import { Box, Divider } from '../..';
+
+export default {
+ title: 'Layout/Box/Typography',
+ component: Box,
+ parameters: {
+ docs: {
+ page: () => (
+ <>
+
+
+
+
+
+
+ >
+ ),
+ },
+ },
+} as ComponentMeta;
+
+export const FontFamilies: ComponentStory = () => (
+
+
+ Sans: The quick brown fox jumps over the lazy dog
+
+
+ Mono: The quick brown fox jumps over the lazy dog
+
+
+);
+
+export const FontScales: ComponentStory = () => (
+
+ hero
+ h1
+ h2
+ h3
+ h4
+ h5
+ p1
+ p1m
+ p1b
+ p2
+ p2m
+ p2b
+ c1
+ c2
+ micro
+
+);
+
+export const FontSizes: ComponentStory = () => (
+
+ hero
+ h1
+ h2
+ h3
+ h4
+ h5
+ p1
+ p1m
+ p1b
+ p2
+ p2m
+ p2b
+ c1
+ c2
+ micro
+
+);
+
+export const FontWeights: ComponentStory = () => (
+
+ 100
+ 200
+ 300
+ 400
+ 500
+ 600
+ 700
+ 800
+ 900
+ hero
+ h1
+ h2
+ h3
+ h4
+ h5
+ p1
+ p1m
+ p1b
+ p2
+ p2m
+ p2b
+ c1
+ c2
+ micro
+
+);
+
+export const LineHeights: ComponentStory = () => (
+
+ hero
+ h1
+ h2
+ h3
+ h4
+ h5
+ p1
+ p1m
+ p1b
+ p2
+ p2m
+ p2b
+ c1
+ c2
+ micro
+
+);
+
+export const LetterSpacings: ComponentStory = () => (
+
+ hero
+ h1
+ h2
+ h3
+ h4
+ h5
+ p1
+ p1m
+ p1b
+ p2
+ p2m
+ p2b
+ c1
+ c2
+ micro
+
+);
+
+export const FontStyles: ComponentStory = () => (
+
+ normal
+ italic
+
+);
+
+export const TextTransform: ComponentStory = () => (
+
+ none
+ uppercase
+ lowercase
+ capitalize
+
+);
+
+export const WordBreak: ComponentStory = () => (
+
+
+ break-word:
+ Breakwoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooord
+
+
+
+ break-all:
+ Breakaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaall
+
+
+);
+
+export const withTruncatedText: ComponentStory = () => (
+
+
+ This text is truncated.
+
+
+);
diff --git a/packages/fuselage/src/components/Bubble/Bubble.stories.tsx b/packages/fuselage/src/components/Bubble/Bubble.stories.tsx
index fa70b2f056..758a199a77 100644
--- a/packages/fuselage/src/components/Bubble/Bubble.stories.tsx
+++ b/packages/fuselage/src/components/Bubble/Bubble.stories.tsx
@@ -31,3 +31,37 @@ LabelOnly.args = {
children: 'See new messages',
onClick: action('click'),
};
+
+export const Secondary = Template.bind({});
+Secondary.args = {
+ children: 'See new messages',
+ secondary: true,
+ onClick: action('click'),
+};
+
+export const SecondaryDismissable = Template.bind({});
+SecondaryDismissable.args = {
+ children: 'New messages',
+ secondary: true,
+ onDismiss: action('dismiss'),
+};
+SecondaryDismissable.parameters = {
+ docs: {
+ description: {
+ story: 'Example with only a dismiss action - the label is not clickable.',
+ },
+ },
+};
+
+export const WithoutAction = Template.bind({});
+WithoutAction.args = {
+ children: '22 Nov 2023',
+ secondary: true,
+};
+
+export const Small = Template.bind({});
+Small.args = {
+ children: '22 Nov 2023',
+ secondary: true,
+ small: true,
+};
diff --git a/packages/fuselage/src/components/Bubble/Bubble.styles.scss b/packages/fuselage/src/components/Bubble/Bubble.styles.scss
index 9a7867f495..19eae96cfd 100644
--- a/packages/fuselage/src/components/Bubble/Bubble.styles.scss
+++ b/packages/fuselage/src/components/Bubble/Bubble.styles.scss
@@ -10,23 +10,55 @@
display: flex;
align-items: center;
- &__content,
- &__dismiss {
- @include typography.use-font-scale(c2);
- @include button.kind-variant(buttonColors.$primary);
+ &__button {
+ &--primary {
+ @include button.kind-variant(buttonColors.$primary);
+ }
+
+ &--secondary {
+ @include button.kind-variant(buttonColors.$secondary);
+ }
+
@include clickable;
@include click-animation;
+ }
+
+ &__item {
+ &--primary {
+ color: buttonColors.$button-primary-color;
+ background-color: buttonColors.$button-primary-background-color;
+ }
+ &--secondary {
+ color: buttonColors.$button-secondary-color;
+ background-color: buttonColors.$button-secondary-background-color;
+ }
+ }
+
+ &__button,
+ &__item {
+ @include typography.use-font-scale(c2);
display: flex;
justify-content: center;
align-items: center;
height: lengths.size(28);
- padding-inline-start: lengths.padding(12);
+ padding-inline: lengths.padding(12);
padding-inline-end: lengths.padding(16);
border-radius: lengths.border-radius(extra-large);
+ column-gap: lengths.padding(8);
+ }
+
+ &:not(.rcx-bubble__group) &__item {
+ padding-inline: lengths.padding(8);
+ }
+
+ &--small &__button,
+ &--small &__item {
+ @include typography.use-font-scale(micro);
+ height: lengths.size(20);
}
&__group {
diff --git a/packages/fuselage/src/components/Bubble/Bubble.tsx b/packages/fuselage/src/components/Bubble/Bubble.tsx
index d794844a59..bca0ff7200 100644
--- a/packages/fuselage/src/components/Bubble/Bubble.tsx
+++ b/packages/fuselage/src/components/Bubble/Bubble.tsx
@@ -2,45 +2,64 @@ import type { Keys as IconName } from '@rocket.chat/icons';
import type { AllHTMLAttributes, ButtonHTMLAttributes, ReactNode } from 'react';
import React from 'react';
-import { Icon } from '../Icon';
+import { BubbleButton } from './BubbleButton';
+import { BubbleItem } from './BubbleItem';
type BubbleProps = {
+ secondary?: boolean;
children: ReactNode;
- onClick: () => void;
+ small?: boolean;
+ onClick?: () => void;
icon?: IconName;
onDismiss?: () => void;
- contentProps?: ButtonHTMLAttributes;
- dismissProps?: ButtonHTMLAttributes;
-} & AllHTMLAttributes;
+ contentProps?: Omit, 'onClick'>;
+ dismissProps?: Omit, 'onClick'>;
+} & Omit, 'onClick'>;
export const Bubble = ({
+ secondary,
children,
onClick,
icon,
onDismiss,
+ small,
contentProps,
dismissProps,
...props
}: BubbleProps) => (
-
- {icon && }
- {children}
-
+ {onClick ? (
+
+ ) : (
+
+ )}
{onDismiss && (
-
-
-
+ secondary={secondary}
+ icon='cross-small'
+ {...{ 'aria-label': `Dismiss ${children}`, ...dismissProps }}
+ />
)}
);
diff --git a/packages/fuselage/src/components/Bubble/BubbleButton.tsx b/packages/fuselage/src/components/Bubble/BubbleButton.tsx
new file mode 100644
index 0000000000..357b638aff
--- /dev/null
+++ b/packages/fuselage/src/components/Bubble/BubbleButton.tsx
@@ -0,0 +1,33 @@
+import type { Keys as IconName } from '@rocket.chat/icons';
+import type { ButtonHTMLAttributes, ReactNode } from 'react';
+import React from 'react';
+
+import { Icon } from '../Icon';
+
+type BubbleButtonProps = {
+ onClick: () => void;
+ label?: ReactNode;
+ secondary?: boolean;
+ icon?: IconName;
+} & Omit, 'onClick'>;
+
+export const BubbleButton = ({
+ secondary,
+ label,
+ onClick,
+ icon,
+ ...props
+}: BubbleButtonProps) => (
+
+ {icon && }
+ {label && {label} }
+
+);
diff --git a/packages/fuselage/src/components/Bubble/BubbleItem.tsx b/packages/fuselage/src/components/Bubble/BubbleItem.tsx
new file mode 100644
index 0000000000..a7ace7851f
--- /dev/null
+++ b/packages/fuselage/src/components/Bubble/BubbleItem.tsx
@@ -0,0 +1,28 @@
+import type { Keys as IconName } from '@rocket.chat/icons';
+import type { HTMLAttributes, ReactNode } from 'react';
+import React from 'react';
+
+import { Icon } from '../Icon';
+
+type BubbleItemProps = {
+ label?: ReactNode;
+ secondary?: boolean;
+ icon?: IconName;
+} & HTMLAttributes;
+
+export const BubbleItem = ({
+ secondary,
+ label,
+ icon,
+ ...props
+}: BubbleItemProps) => (
+
+ {icon && }
+ {label && {label} }
+
+);
diff --git a/packages/fuselage/src/components/Bubble/__snapshots__/Bubble.spec.tsx.snap b/packages/fuselage/src/components/Bubble/__snapshots__/Bubble.spec.tsx.snap
index cf96a56b59..a58f2070e7 100644
--- a/packages/fuselage/src/components/Bubble/__snapshots__/Bubble.spec.tsx.snap
+++ b/packages/fuselage/src/components/Bubble/__snapshots__/Bubble.spec.tsx.snap
@@ -4,14 +4,14 @@ exports[`[Bubble Rendering] renders Dismissable without crashing 1`] = `
@@ -21,7 +21,7 @@ exports[`[Bubble Rendering] renders Dismissable without crashing 1`] = `
@@ -63,10 +63,10 @@ exports[`[Bubble Rendering] renders LabelOnly without crashing 1`] = `
See new messages
@@ -76,3 +76,86 @@ exports[`[Bubble Rendering] renders LabelOnly without crashing 1`] = `
`;
+
+exports[`[Bubble Rendering] renders Secondary without crashing 1`] = `
+
+
+
+
+
+ See new messages
+
+
+
+
+
+`;
+
+exports[`[Bubble Rendering] renders SecondaryDismissable without crashing 1`] = `
+
+
+
+
+
+ New messages
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`[Bubble Rendering] renders Small without crashing 1`] = `
+
+
+
+
+
+ 22 Nov 2023
+
+
+
+
+
+`;
+
+exports[`[Bubble Rendering] renders WithoutAction without crashing 1`] = `
+
+
+
+
+
+ 22 Nov 2023
+
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/Card/Card.styles.scss b/packages/fuselage/src/components/Card/Card.styles.scss
index 70e91752b1..a8916301be 100644
--- a/packages/fuselage/src/components/Card/Card.styles.scss
+++ b/packages/fuselage/src/components/Card/Card.styles.scss
@@ -7,6 +7,7 @@ $card-vertical-padding: lengths.padding(20);
$card-vertical-gap: lengths.margin(24);
$card-horizontal-padding: lengths.padding(12);
$card-horizontal-gap: lengths.padding(16);
+$card-horizontal-row-gap: lengths.padding(4);
$card-hero-padding: lengths.padding(28);
.rcx-card {
@@ -60,6 +61,10 @@ $card-hero-padding: lengths.padding(28);
}
}
+ &__horizontal &__col {
+ row-gap: $card-horizontal-row-gap;
+ }
+
&__vertical {
flex-direction: column;
@@ -70,12 +75,12 @@ $card-hero-padding: lengths.padding(28);
&__hero {
padding: $card-hero-padding;
}
-}
-.rcx-card__title,
-.rcx-card__row,
-.rcx-card__header,
-.rcx-card__controls {
- display: flex;
- align-items: center;
+ &__title,
+ &__row,
+ &__header,
+ &__controls {
+ display: flex;
+ align-items: center;
+ }
}
diff --git a/packages/fuselage/src/components/CodeSnippet/CodeSnippet.spec.tsx b/packages/fuselage/src/components/CodeSnippet/CodeSnippet.spec.tsx
index 536bd7aa05..a7326793fb 100644
--- a/packages/fuselage/src/components/CodeSnippet/CodeSnippet.spec.tsx
+++ b/packages/fuselage/src/components/CodeSnippet/CodeSnippet.spec.tsx
@@ -4,7 +4,7 @@ import React from 'react';
import * as stories from './CodeSnippet.stories';
-const { Default, CopyButton, CustomButtonName, LoadingCode } =
+const { Default, CopyButton, CustomButtonName, LoadingCode, DisabledButton } =
composeStories(stories);
describe('[CodeSnippet Component]', () => {
@@ -44,4 +44,10 @@ describe('[CodeSnippet Component]', () => {
const { container } = render(
);
expect(container.querySelector('.rcx-skeleton')).toBeInTheDocument();
});
+
+ it('should should render a disabled button, when buttonDisabled prop is passed', () => {
+ render(
);
+ const button = screen.getByRole('button');
+ expect(button).toBeDisabled();
+ });
});
diff --git a/packages/fuselage/src/components/CodeSnippet/CodeSnippet.stories.tsx b/packages/fuselage/src/components/CodeSnippet/CodeSnippet.stories.tsx
index 325b0bf0ea..5aa43315a7 100644
--- a/packages/fuselage/src/components/CodeSnippet/CodeSnippet.stories.tsx
+++ b/packages/fuselage/src/components/CodeSnippet/CodeSnippet.stories.tsx
@@ -60,3 +60,11 @@ LoadingCode.args = {
children: '',
onClick: action('click'),
};
+
+export const DisabledButton = Template.bind({});
+DisabledButton.args = {
+ children: 'curl -L https://go.rocket.chat/i/docker-compose.yml -O',
+ onClick: action('click'),
+ buttonText: 'Disabled Button',
+ buttonDisabled: true,
+};
diff --git a/packages/fuselage/src/components/CodeSnippet/CodeSnippet.tsx b/packages/fuselage/src/components/CodeSnippet/CodeSnippet.tsx
index 8b6d077b22..69582e5c9b 100644
--- a/packages/fuselage/src/components/CodeSnippet/CodeSnippet.tsx
+++ b/packages/fuselage/src/components/CodeSnippet/CodeSnippet.tsx
@@ -8,6 +8,7 @@ import { Skeleton } from '../Skeleton';
type CodeSnippetProps = ComponentProps
& {
children: string;
buttonText?: string;
+ buttonDisabled?: boolean;
onClick?: () => void;
};
@@ -15,6 +16,7 @@ const CodeSnippet = ({
children,
onClick,
buttonText = 'Copy',
+ buttonDisabled = false,
...props
}: CodeSnippetProps): ReactElement => {
if (!children) {
@@ -32,7 +34,7 @@ const CodeSnippet = ({
{onClick && children && (
-
+
{buttonText}
diff --git a/packages/fuselage/src/components/Contextualbar/Contextualbar.spec.tsx b/packages/fuselage/src/components/Contextualbar/Contextualbar.spec.tsx
new file mode 100644
index 0000000000..306f176858
--- /dev/null
+++ b/packages/fuselage/src/components/Contextualbar/Contextualbar.spec.tsx
@@ -0,0 +1,33 @@
+import { composeStories } from '@storybook/testing-react';
+import { render } from '@testing-library/react';
+import { axe, toHaveNoViolations } from 'jest-axe';
+import React from 'react';
+
+import * as stories from './Contextualbar.stories';
+
+expect.extend(toHaveNoViolations);
+
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
+
+describe('[Contextualbar Rendering]', () => {
+ test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render( );
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+ );
+
+ test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render( );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
+ );
+});
diff --git a/packages/fuselage/src/components/Contextualbar/Contextualbar.stories.tsx b/packages/fuselage/src/components/Contextualbar/Contextualbar.stories.tsx
index 1cc1fb81a9..47f18ecb9a 100644
--- a/packages/fuselage/src/components/Contextualbar/Contextualbar.stories.tsx
+++ b/packages/fuselage/src/components/Contextualbar/Contextualbar.stories.tsx
@@ -1,3 +1,4 @@
+import { action } from '@storybook/addon-actions';
import type { ComponentStory, ComponentMeta } from '@storybook/react';
import React from 'react';
@@ -38,18 +39,22 @@ export default {
export const Default: ComponentStory = () => (
-
-
+
Contextualbar Title
{}}
+ onClick={action('click')}
/>
console.log('close')}
+ onClick={action('click')}
/>
@@ -62,7 +67,7 @@ export const Default: ComponentStory = () => (
Save
-
+
@@ -75,13 +80,13 @@ export const Skeleton: ComponentStory = () => (
export const Empty: ComponentStory = () => (
-
+
Contextualbar Empty
{}}
+ onClick={action('click')}
/>
diff --git a/packages/fuselage/src/components/Contextualbar/Contextualbar.tsx b/packages/fuselage/src/components/Contextualbar/Contextualbar.tsx
index 9308e5e25b..4724210c60 100644
--- a/packages/fuselage/src/components/Contextualbar/Contextualbar.tsx
+++ b/packages/fuselage/src/components/Contextualbar/Contextualbar.tsx
@@ -1,36 +1,39 @@
import type { ComponentProps } from 'react';
-import React, { memo } from 'react';
+import React, { forwardRef, memo } from 'react';
import { Box } from '..';
type ContextualbarProps = ComponentProps;
-const Contextualbar = ({
- children,
- width,
- position,
- bg = 'room',
- ...props
-}: ContextualbarProps) => (
-
- {children}
-
+const Contextualbar = forwardRef(
+ function Contextualbar(
+ { children, width, position, bg = 'room', ...props },
+ ref
+ ) {
+ return (
+
+ {children}
+
+ );
+ }
);
export default memo(Contextualbar);
diff --git a/packages/fuselage/src/components/Contextualbar/ContextualbarFooter.tsx b/packages/fuselage/src/components/Contextualbar/ContextualbarFooter.tsx
index fab42762db..10ffc77ebd 100644
--- a/packages/fuselage/src/components/Contextualbar/ContextualbarFooter.tsx
+++ b/packages/fuselage/src/components/Contextualbar/ContextualbarFooter.tsx
@@ -6,7 +6,7 @@ import { Box } from '..';
const ContextualbarFooter = forwardRef>(
function ContextualbarFooter({ children, ...props }, ref) {
return (
-
+
{children}
);
diff --git a/packages/fuselage/src/components/Contextualbar/ContextualbarHeader.tsx b/packages/fuselage/src/components/Contextualbar/ContextualbarHeader.tsx
index b6a00560ae..cc2d603cc1 100644
--- a/packages/fuselage/src/components/Contextualbar/ContextualbarHeader.tsx
+++ b/packages/fuselage/src/components/Contextualbar/ContextualbarHeader.tsx
@@ -14,7 +14,6 @@ const ContextualbarHeader = ({
display='flex'
alignItems='center'
height='x56'
- is='h3'
pi={24}
borderBlockEndWidth='default'
borderBlockColor='extra-light'
@@ -26,10 +25,9 @@ const ContextualbarHeader = ({
display='flex'
alignItems='center'
justifyContent='space-between'
- fontScale='h4'
flexGrow={1}
+ height='100%'
overflow='hidden'
- color='default'
>
{children}
diff --git a/packages/fuselage/src/components/Contextualbar/ContextualbarSkeleton.tsx b/packages/fuselage/src/components/Contextualbar/ContextualbarSkeleton.tsx
index 32ea63c0e9..882e61dc68 100644
--- a/packages/fuselage/src/components/Contextualbar/ContextualbarSkeleton.tsx
+++ b/packages/fuselage/src/components/Contextualbar/ContextualbarSkeleton.tsx
@@ -7,7 +7,7 @@ import { Box, Skeleton } from '..';
const ContextualbarSkeleton = (
props: ComponentProps
): ReactElement => (
-
+
diff --git a/packages/fuselage/src/components/Contextualbar/ContextualbarTitle.tsx b/packages/fuselage/src/components/Contextualbar/ContextualbarTitle.tsx
index 32d7117ef1..39e786c333 100644
--- a/packages/fuselage/src/components/Contextualbar/ContextualbarTitle.tsx
+++ b/packages/fuselage/src/components/Contextualbar/ContextualbarTitle.tsx
@@ -6,7 +6,13 @@ import { Box } from '..';
const ContextualbarTitle = (
props: ComponentProps
): ReactElement => (
-
+
);
export default memo(ContextualbarTitle);
diff --git a/packages/fuselage/src/components/Contextualbar/__snapshots__/Contextualbar.spec.tsx.snap b/packages/fuselage/src/components/Contextualbar/__snapshots__/Contextualbar.spec.tsx.snap
new file mode 100644
index 0000000000..e8cfde4eea
--- /dev/null
+++ b/packages/fuselage/src/components/Contextualbar/__snapshots__/Contextualbar.spec.tsx.snap
@@ -0,0 +1,245 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[Contextualbar Rendering] renders Default without crashing 1`] = `
+
+
+
+
+
+
+
+
+ ⦉
+
+
+
+ Contextualbar Title
+
+
+
+
+ ⁽
+
+
+
+
+
+
+
+
+
+
+
+ Contextualbar Content
+
+
+
+
+
+ Cancel
+
+
+
+
+ Save
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`[Contextualbar Rendering] renders Empty without crashing 1`] = `
+
+
+
+
+
+
+
+
+ ⦉
+
+
+
+ Contextualbar Empty
+
+
+
+
+ ⁽
+
+
+
+
+
+
+
+
+
+
+
+ Nothing Found
+
+
+
+
+ Footer
+
+
+
+
+
+`;
+
+exports[`[Contextualbar Rendering] renders Skeleton without crashing 1`] = `
+
+
+
+`;
diff --git a/packages/fuselage/src/components/Message/MessageBody.tsx b/packages/fuselage/src/components/Message/MessageBody.tsx
index 48849ff6d5..f7e775d703 100644
--- a/packages/fuselage/src/components/Message/MessageBody.tsx
+++ b/packages/fuselage/src/components/Message/MessageBody.tsx
@@ -1,9 +1,9 @@
-import type { AllHTMLAttributes, ReactElement } from 'react';
+import type { HTMLAttributes, ReactElement } from 'react';
import React from 'react';
import { prependClassName } from '../../helpers/prependClassName';
-type MessageBodyProps = AllHTMLAttributes & {
+type MessageBodyProps = HTMLAttributes & {
clamp?: 2 | 3 | 4;
};
diff --git a/packages/fuselage/src/components/Message/MessageContainer.tsx b/packages/fuselage/src/components/Message/MessageContainer.tsx
index 6beeeb5acb..60511077e9 100644
--- a/packages/fuselage/src/components/Message/MessageContainer.tsx
+++ b/packages/fuselage/src/components/Message/MessageContainer.tsx
@@ -1,10 +1,6 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageContainerProps = {
- children?: ReactNode;
-};
-
-export const MessageContainer = (props: MessageContainerProps) => (
+export const MessageContainer = (props: HTMLAttributes) => (
);
diff --git a/packages/fuselage/src/components/Message/MessageContainerFixed.tsx b/packages/fuselage/src/components/Message/MessageContainerFixed.tsx
index ee9ff0fdd1..f4158772ac 100644
--- a/packages/fuselage/src/components/Message/MessageContainerFixed.tsx
+++ b/packages/fuselage/src/components/Message/MessageContainerFixed.tsx
@@ -1,11 +1,9 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageContainerFixedProps = {
- children?: ReactNode;
-};
-
-export const MessageContainerFixed = (props: MessageContainerFixedProps) => (
+export const MessageContainerFixed = (
+ props: HTMLAttributes
+) => (
& {
big?: boolean;
- children?: ReactNode;
};
export const MessageEmoji = ({
@@ -16,7 +12,7 @@ export const MessageEmoji = ({
className,
image,
big,
- children,
+ ...props
}: MessageEmojiProps) => (
);
diff --git a/packages/fuselage/src/components/Message/MessageEmojiBase.tsx b/packages/fuselage/src/components/Message/MessageEmojiBase.tsx
index 6237c2ea69..ee89f1b83b 100644
--- a/packages/fuselage/src/components/Message/MessageEmojiBase.tsx
+++ b/packages/fuselage/src/components/Message/MessageEmojiBase.tsx
@@ -1,22 +1,20 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
type MessageEmojiBaseProps = {
name: string;
- className?: string;
- children?: ReactNode;
image?: string;
-};
+} & HTMLAttributes
;
export const MessageEmojiBase = ({
name,
- className,
image,
- children,
+ className,
+ ...props
}: MessageEmojiBaseProps) => (
);
diff --git a/packages/fuselage/src/components/Message/MessageGenericPreview/MessageGenericPreview.styles.scss b/packages/fuselage/src/components/Message/MessageGenericPreview/MessageGenericPreview.styles.scss
index 82e4f234e5..387547fe40 100644
--- a/packages/fuselage/src/components/Message/MessageGenericPreview/MessageGenericPreview.styles.scss
+++ b/packages/fuselage/src/components/Message/MessageGenericPreview/MessageGenericPreview.styles.scss
@@ -4,6 +4,7 @@
@use '../../../styles/typography.scss';
@use '../../../styles/mixins/size.scss';
@use '../../../styles/primitives/traits/rich-text.scss';
+@import '../../../styles/primitives/link.scss';
$message-generic-preview-border-color: functions.theme(
'message-generic-preview-border-color',
@@ -62,7 +63,7 @@ $message-generic-preview-icon-background-color: functions.theme(
justify-content: center;
flex-grow: 1;
- margin-block: lengths.margin(8);
+ padding-block: lengths.margin(8);
padding-inline: lengths.margin(16);
}
}
@@ -85,32 +86,14 @@ $message-generic-preview-icon-background-color: functions.theme(
&__title {
@include typography.use-with-truncated-text();
@include typography.use-font-scale(p2);
+ display: block;
+
margin-block-end: lengths.margin(4);
color: $message-generic-preview-title-color;
- @at-root {
- a#{&} {
- &:link {
- text-decoration: none;
-
- color: colors.font(info);
- }
-
- &:visited,
- &.is-visited {
- color: colors.font(info);
- }
-
- &:active,
- &.is-active {
- color: colors.font(info);
- }
-
- &:hover,
- &.is-hovered {
- text-decoration: underline;
- }
- }
+
+ &-link {
+ @include use-link-colors();
}
}
@@ -142,7 +125,7 @@ $message-generic-preview-icon-background-color: functions.theme(
color: $message-generic-preview-context-color;
a {
- color: $message-generic-preview-context-color;
+ @include use-link-colors($color: colors.font(secondary-info));
}
}
diff --git a/packages/fuselage/src/components/Message/MessageGenericPreview/MessageGenericPreviewTitle.tsx b/packages/fuselage/src/components/Message/MessageGenericPreview/MessageGenericPreviewTitle.tsx
index 20c6a5f042..6b8d122d40 100644
--- a/packages/fuselage/src/components/Message/MessageGenericPreview/MessageGenericPreviewTitle.tsx
+++ b/packages/fuselage/src/components/Message/MessageGenericPreview/MessageGenericPreviewTitle.tsx
@@ -12,12 +12,14 @@ export const MessageGenericPreviewTitle = ({
...props
}: MessageGenericPreviewTitleProps) =>
externalUrl ? (
-
+
+
+
) : (
);
diff --git a/packages/fuselage/src/components/Message/MessageHeader.tsx b/packages/fuselage/src/components/Message/MessageHeader.tsx
index da22668f17..946be8709a 100644
--- a/packages/fuselage/src/components/Message/MessageHeader.tsx
+++ b/packages/fuselage/src/components/Message/MessageHeader.tsx
@@ -1,12 +1,11 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageHeaderProps = {
- children?: ReactNode;
-};
-
-export const MessageHeader = ({ children }: MessageHeaderProps) => (
-
+export const MessageHeader = ({
+ children,
+ ...props
+}: HTMLAttributes
) => (
+
{children}
diff --git a/packages/fuselage/src/components/Message/MessageLeftContainer.tsx b/packages/fuselage/src/components/Message/MessageLeftContainer.tsx
index aacc98d096..e60a638f4f 100644
--- a/packages/fuselage/src/components/Message/MessageLeftContainer.tsx
+++ b/packages/fuselage/src/components/Message/MessageLeftContainer.tsx
@@ -1,12 +1,8 @@
-import type { ReactElement, ReactNode } from 'react';
+import type { HTMLAttributes, ReactElement } from 'react';
import React from 'react';
-type MessageLeftContainerProps = {
- children?: ReactNode;
-};
-
export const MessageLeftContainer = (
- props: MessageLeftContainerProps
+ props: HTMLAttributes
): ReactElement => (
{
- render(
-
-
-
-
-
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
+
+describe('[MessageMetrics Rendering]', () => {
+ test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render(
);
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+ );
+
+ test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render(
);
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
);
});
diff --git a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetrics.stories.tsx b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetrics.stories.tsx
new file mode 100644
index 0000000000..8340735228
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetrics.stories.tsx
@@ -0,0 +1,51 @@
+import { action } from '@storybook/addon-actions';
+import { Title, Primary } from '@storybook/addon-docs';
+import type { ComponentMeta } from '@storybook/react';
+import React from 'react';
+
+import {
+ MessageMetrics,
+ MessageMetricsReply,
+ MessageMetricsItem,
+ MessageMetricsFollowing,
+ MessageMetricsItemIcon,
+ MessageMetricsItemLabel,
+} from '.';
+import { BasicMessageTemplate } from '../helpers';
+
+export default {
+ title: 'Message/MessageMetrics',
+ component: MessageMetrics,
+ parameters: {
+ docs: {
+ page: () => (
+ <>
+
+
+ >
+ ),
+ },
+ },
+} as ComponentMeta
;
+
+const metrics = (
+
+ Reply
+
+
+ 10
+
+
+
+
+
+);
+
+export const Default = BasicMessageTemplate.bind({});
+Default.args = {
+ metrics,
+};
diff --git a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsContent.tsx b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsContent.tsx
index 6ca5b09bc8..9a3efd2362 100644
--- a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsContent.tsx
+++ b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsContent.tsx
@@ -1,10 +1,6 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type ContentProps = {
- children?: ReactNode;
-};
-
-export const Content = (props: ContentProps) => (
-
-);
+export const MessageMetricsContent = (
+ props: HTMLAttributes
+) =>
;
diff --git a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsContentItem.tsx b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsContentItem.tsx
index 80e3a36578..d3d78df85d 100644
--- a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsContentItem.tsx
+++ b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsContentItem.tsx
@@ -1,10 +1,6 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageMetricsContentItemProps = {
- children?: ReactNode;
-};
-
export const MessageMetricsContentItem = (
- props: MessageMetricsContentItemProps
+ props: HTMLAttributes
) =>
;
diff --git a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsFollowing.tsx b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsFollowing.tsx
index afd1673369..88ffa9600a 100644
--- a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsFollowing.tsx
+++ b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsFollowing.tsx
@@ -1,9 +1,13 @@
+import type { ComponentProps } from 'react';
import React from 'react';
import { IconButton } from '../../Button';
-type MessageMetricsFollowingProps = { name: 'bell' | 'bell-off' };
+type MessageMetricsFollowingProps = {
+ name: 'bell' | 'bell-off';
+} & Omit, 'icon'>;
export const MessageMetricsFollowing = ({
name,
-}: MessageMetricsFollowingProps) => ;
+ ...props
+}: MessageMetricsFollowingProps) => ;
diff --git a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsItem/MessageMetricsItemLabel.tsx b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsItem/MessageMetricsItemLabel.tsx
index 9b277fe49d..b5c6db68b1 100644
--- a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsItem/MessageMetricsItemLabel.tsx
+++ b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsItem/MessageMetricsItemLabel.tsx
@@ -1,10 +1,6 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageMetricsItemLabelProps = {
- children?: ReactNode;
-};
-
export const MessageMetricsItemLabel = (
- props: MessageMetricsItemLabelProps
+ props: HTMLAttributes
) =>
;
diff --git a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsItem/index.ts b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsItem/index.ts
index 28af480eb8..d2917e46c6 100644
--- a/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsItem/index.ts
+++ b/packages/fuselage/src/components/Message/MessageMetrics/MessageMetricsItem/index.ts
@@ -3,6 +3,14 @@ import { MessageMetricsItemIcon } from './MessageMetricsItemIcon';
import { MessageMetricsItemLabel } from './MessageMetricsItemLabel';
export default Object.assign(MessageMetricsItem, {
+ /**
+ * @deprecated prefer using named imports
+ * */
Icon: MessageMetricsItemIcon,
+ /**
+ * @deprecated prefer using named imports
+ * */
Label: MessageMetricsItemLabel,
});
+
+export { MessageMetricsItem, MessageMetricsItemIcon, MessageMetricsItemLabel };
diff --git a/packages/fuselage/src/components/Message/MessageMetrics/__snapshots__/MessageMetrics.spec.tsx.snap b/packages/fuselage/src/components/Message/MessageMetrics/__snapshots__/MessageMetrics.spec.tsx.snap
new file mode 100644
index 0000000000..09173037e9
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageMetrics/__snapshots__/MessageMetrics.spec.tsx.snap
@@ -0,0 +1,173 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[MessageMetrics Rendering] renders Default without crashing 1`] = `
+
+
+
+
+
+
+ May, 24, 2020
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ut enim ad minim veniam
+
+
+
+
+
+
+
+ Reply
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/Message/MessageMetrics/index.tsx b/packages/fuselage/src/components/Message/MessageMetrics/index.tsx
index 2611534069..77c193e3d6 100644
--- a/packages/fuselage/src/components/Message/MessageMetrics/index.tsx
+++ b/packages/fuselage/src/components/Message/MessageMetrics/index.tsx
@@ -1,17 +1,31 @@
import { MessageMetrics } from './MessageMetrics';
import { MessageMetricsFollowing } from './MessageMetricsFollowing';
-import MessageMetricsItem from './MessageMetricsItem';
+import MessageMetricsItem, {
+ MessageMetricsItemIcon,
+ MessageMetricsItemLabel,
+} from './MessageMetricsItem';
import { MessageMetricsReply } from './MessageMetricsReply';
export default Object.assign(MessageMetrics, {
+ /**
+ * @deprecated prefer using named imports
+ * */
Reply: MessageMetricsReply,
+ /**
+ * @deprecated prefer using named imports
+ * */
Item: MessageMetricsItem,
+ /**
+ * @deprecated prefer using named imports
+ * */
Following: MessageMetricsFollowing,
});
export {
MessageMetrics,
- MessageMetricsFollowing,
MessageMetricsItem,
+ MessageMetricsItemIcon,
+ MessageMetricsItemLabel,
+ MessageMetricsFollowing,
MessageMetricsReply,
};
diff --git a/packages/fuselage/src/components/Message/MessageName.tsx b/packages/fuselage/src/components/Message/MessageName.tsx
index dd9b9dc591..6a02b0c931 100644
--- a/packages/fuselage/src/components/Message/MessageName.tsx
+++ b/packages/fuselage/src/components/Message/MessageName.tsx
@@ -1,8 +1,6 @@
-import type { AllHTMLAttributes } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageNameProps = AllHTMLAttributes;
-
-export const MessageName = (props: MessageNameProps) => (
+export const MessageName = (props: HTMLAttributes) => (
);
diff --git a/packages/fuselage/src/components/Message/MessageNameContainer.tsx b/packages/fuselage/src/components/Message/MessageNameContainer.tsx
index 92252d7a72..67ea29fb15 100644
--- a/packages/fuselage/src/components/Message/MessageNameContainer.tsx
+++ b/packages/fuselage/src/components/Message/MessageNameContainer.tsx
@@ -1,11 +1,15 @@
-import type { AllHTMLAttributes } from 'react';
-import React from 'react';
+import type { HTMLAttributes } from 'react';
+import React, { forwardRef } from 'react';
-type MessageNameContainerProps = AllHTMLAttributes;
-
-export const MessageNameContainer = (props: MessageNameContainerProps) => (
-
-);
+export const MessageNameContainer = forwardRef<
+ HTMLSpanElement,
+ HTMLAttributes
+>(function MessageNameContainer(props, ref) {
+ return (
+
+ );
+});
diff --git a/packages/fuselage/src/components/Message/MessageReactions/MessageReaction.tsx b/packages/fuselage/src/components/Message/MessageReactions/MessageReaction.tsx
index c8c0c4a695..c1ab922829 100644
--- a/packages/fuselage/src/components/Message/MessageReactions/MessageReaction.tsx
+++ b/packages/fuselage/src/components/Message/MessageReactions/MessageReaction.tsx
@@ -25,6 +25,8 @@ export const MessageReaction = forwardRef(function Reaction(
.filter(Boolean)
.join(' ')}
ref={ref}
+ role='button'
+ tabIndex={0}
{...props}
>
{children || (
diff --git a/packages/fuselage/src/components/Message/MessageReactions/MessageReactionAction.tsx b/packages/fuselage/src/components/Message/MessageReactions/MessageReactionAction.tsx
index d5452dd18c..464db03991 100644
--- a/packages/fuselage/src/components/Message/MessageReactions/MessageReactionAction.tsx
+++ b/packages/fuselage/src/components/Message/MessageReactions/MessageReactionAction.tsx
@@ -8,6 +8,8 @@ export const MessageReactionAction = ({
...props
}: HTMLAttributes) => (
(
+ ...props
+}: ComponentProps
) => (
);
diff --git a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.spec.tsx b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.spec.tsx
index 49793e492a..8a620b7219 100644
--- a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.spec.tsx
+++ b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.spec.tsx
@@ -1,13 +1,31 @@
+import { composeStories } from '@storybook/testing-react';
import { render } from '@testing-library/react';
+import { axe } from 'jest-axe';
import React from 'react';
-import MessageReactions from '.';
+import * as stories from './MessageReactions.stories';
-it('renders without crashing', () => {
- render(
-
-
-
-
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
+
+describe('[MessageReactions Rendering]', () => {
+ test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render( );
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+ );
+
+ test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render( );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
);
});
diff --git a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.stories.tsx b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.stories.tsx
new file mode 100644
index 0000000000..5198e60953
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.stories.tsx
@@ -0,0 +1,35 @@
+import { Title, Primary } from '@storybook/addon-docs';
+import type { ComponentMeta } from '@storybook/react';
+import React from 'react';
+
+import { MessageReactions, MessageReaction, MessageReactionAction } from '.';
+import { BasicMessageTemplate } from '../helpers';
+
+export default {
+ title: 'Message/MessageReactions',
+ component: MessageReactions,
+ parameters: {
+ docs: {
+ page: () => (
+ <>
+
+
+ >
+ ),
+ },
+ },
+} as ComponentMeta;
+
+const reactions = (
+
+
+
+
+
+
+);
+
+export const Default = BasicMessageTemplate.bind({});
+Default.args = {
+ reactions,
+};
diff --git a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.styles.scss b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.styles.scss
index 0d432fc9c2..f4d11029b9 100644
--- a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.styles.scss
+++ b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.styles.scss
@@ -2,6 +2,7 @@
@use '../../../styles/colors.scss';
@use '../../../styles/typography.scss';
@use '../../../styles/mixins/size.scss';
+@use '../../../styles/mixins/templates.scss';
@use '../../../styles/variables/buttons.scss';
@use '../../../styles/primitives/button.scss';
@use '../mixins.scss';
@@ -49,7 +50,9 @@
}
&--action {
- @include mixins.visible-on-hover();
+ @include mixins.message-focus-visible {
+ display: inline-flex;
+ }
padding: lengths.padding(2);
}
@@ -62,6 +65,8 @@
colors.surface(selected)
);
}
+
+ @include templates.focus-state;
}
&__emoji {
diff --git a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.tsx b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.tsx
index a470550ca5..b04b5fdc79 100644
--- a/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.tsx
+++ b/packages/fuselage/src/components/Message/MessageReactions/MessageReactions.tsx
@@ -1,12 +1,15 @@
-import type { ReactNode } from 'react';
-import React from 'react';
+import type { HTMLAttributes, Ref } from 'react';
+import React, { forwardRef } from 'react';
import { MessageBlock } from '../MessageBlock';
-type MessageReactionsProps = { children: ReactNode };
-
-export const MessageReactions = (props: MessageReactionsProps) => (
-
-
-
-);
+export const MessageReactions = forwardRef(function MessageReactions(
+ props: HTMLAttributes,
+ ref: Ref
+) {
+ return (
+
+
+
+ );
+});
diff --git a/packages/fuselage/src/components/Message/MessageReactions/__snapshots__/MessageReactions.spec.tsx.snap b/packages/fuselage/src/components/Message/MessageReactions/__snapshots__/MessageReactions.spec.tsx.snap
new file mode 100644
index 0000000000..c07136724c
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageReactions/__snapshots__/MessageReactions.spec.tsx.snap
@@ -0,0 +1,172 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[MessageReactions Rendering] renders Default without crashing 1`] = `
+
+
+
+
+
+
+ May, 24, 2020
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ut enim ad minim veniam
+
+
+
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/Message/MessageReactions/index.tsx b/packages/fuselage/src/components/Message/MessageReactions/index.tsx
index 012d7f5b43..e967a9ef57 100644
--- a/packages/fuselage/src/components/Message/MessageReactions/index.tsx
+++ b/packages/fuselage/src/components/Message/MessageReactions/index.tsx
@@ -5,7 +5,13 @@ import { MessageReactionEmoji } from './MessageReactionEmoji';
import { MessageReactions } from './MessageReactions';
export default Object.assign(MessageReactions, {
+ /**
+ * @deprecated prefer using named imports
+ * */
Reaction: MessageReaction,
+ /**
+ * @deprecated prefer using named imports
+ * */
Action: MessageReactionAction,
});
diff --git a/packages/fuselage/src/components/Message/MessageRole.tsx b/packages/fuselage/src/components/Message/MessageRole.tsx
index 092b41d57f..de6ac48334 100644
--- a/packages/fuselage/src/components/Message/MessageRole.tsx
+++ b/packages/fuselage/src/components/Message/MessageRole.tsx
@@ -1,12 +1,8 @@
-import type { ReactNode } from 'react';
+import type { ComponentProps } from 'react';
import React from 'react';
import { Tag } from '../Tag';
-type MessageRoleProps = {
- children?: ReactNode;
-};
-
-export const MessageRole = (props: MessageRoleProps) => (
+export const MessageRole = (props: ComponentProps) => (
);
diff --git a/packages/fuselage/src/components/Message/MessageRoles.tsx b/packages/fuselage/src/components/Message/MessageRoles.tsx
index 6a4ac64319..b106471c9f 100644
--- a/packages/fuselage/src/components/Message/MessageRoles.tsx
+++ b/packages/fuselage/src/components/Message/MessageRoles.tsx
@@ -1,10 +1,6 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageRolesProps = {
- children?: ReactNode;
-};
-
-export const MessageRoles = (props: MessageRolesProps) => (
+export const MessageRoles = (props: HTMLAttributes) => (
);
diff --git a/packages/fuselage/src/components/Message/MessageStatusIndicator/MessageStatusIndicator.stories.tsx b/packages/fuselage/src/components/Message/MessageStatusIndicator/MessageStatusIndicator.stories.tsx
index 823c74ad9d..a70c8c8632 100644
--- a/packages/fuselage/src/components/Message/MessageStatusIndicator/MessageStatusIndicator.stories.tsx
+++ b/packages/fuselage/src/components/Message/MessageStatusIndicator/MessageStatusIndicator.stories.tsx
@@ -5,7 +5,7 @@ import Message from '..';
import { Box, Avatar } from '../..';
import { MessageDivider } from '../MessageDivider';
import MessageReactions from '../MessageReactions';
-import MessageToolbox from '../MessageToolbox';
+import MessageToolbar from '../MessageToolbar';
import { MessageStatusIndicatorText } from './MessageStatusIndicatorText';
export default {
@@ -72,13 +72,13 @@ export const Default = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -98,13 +98,13 @@ export const Default = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -119,13 +119,13 @@ export const Default = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
diff --git a/packages/fuselage/src/components/Message/MessageSystem/MessageSystem.spec.tsx b/packages/fuselage/src/components/Message/MessageSystem/MessageSystem.spec.tsx
index ee1f4a240d..f10a3e6272 100644
--- a/packages/fuselage/src/components/Message/MessageSystem/MessageSystem.spec.tsx
+++ b/packages/fuselage/src/components/Message/MessageSystem/MessageSystem.spec.tsx
@@ -1,34 +1,29 @@
+import { composeStories } from '@storybook/testing-react';
import { render } from '@testing-library/react';
+import { axe } from 'jest-axe';
import React from 'react';
-import {
- MessageSystem,
- MessageSystemLeftContainer,
- MessageSystemContainer,
- MessageSystemBlock,
- MessageSystemName,
- MessageSystemBody,
- MessageSystemTimestamp,
-} from '.';
+import * as stories from './MessageSystem.stories';
-it('renders without crashing', () => {
- render(
-
-
-
-
- Haylie George
-
- Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
- nisi ut aliquip ex ea commodo consequat a duis aute irure dolor in
- reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
- pariatur. Consectetur adipiscing elit, sed do eiusmod tempor
- incididunt ut labore et dolore magna aliqua. Ut enim ad minim
- veniam...
-
- 12:00 PM
-
-
-
- );
-});
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
+
+test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render( );
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+);
+
+test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render( );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
+);
diff --git a/packages/fuselage/src/components/Message/MessageSystem/MessageSystem.stories.tsx b/packages/fuselage/src/components/Message/MessageSystem/MessageSystem.stories.tsx
index 2a401389f8..4b1b9a2f3b 100644
--- a/packages/fuselage/src/components/Message/MessageSystem/MessageSystem.stories.tsx
+++ b/packages/fuselage/src/components/Message/MessageSystem/MessageSystem.stories.tsx
@@ -1,3 +1,4 @@
+import type { ComponentStory } from '@storybook/react';
import React from 'react';
import {
@@ -24,12 +25,13 @@ export default {
},
};
-export const Default = () => (
+export const Default: ComponentStory = () => (
May, 24, 2020
+
+
+
+
+
+ May, 24, 2020
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat a duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam...
+
+
+ 12:00 PM
+
+
+
+
+
+
+
+ May, 24, 2020
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat a duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam...
+
+
+ 12:00 PM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reprehenderit ut aliquip ex ea commodo consequat a duis aute irure dolor in in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam...
+
+
+ 12:00 PM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat a duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam...
+
+
+ 12:00 PM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat a duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam...
+
+
+ 12:00 PM
+
+
+
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/Message/MessageTimestamp.tsx b/packages/fuselage/src/components/Message/MessageTimestamp.tsx
index aca25eb361..58c19f446c 100644
--- a/packages/fuselage/src/components/Message/MessageTimestamp.tsx
+++ b/packages/fuselage/src/components/Message/MessageTimestamp.tsx
@@ -1,8 +1,6 @@
-import type { ReactNode } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageTimestampProps = { children: ReactNode; title?: string };
-
-export const MessageTimestamp = (props: MessageTimestampProps) => (
+export const MessageTimestamp = (props: HTMLAttributes) => (
);
diff --git a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.spec.tsx b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.spec.tsx
new file mode 100644
index 0000000000..f6a526e98a
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.spec.tsx
@@ -0,0 +1,31 @@
+import { composeStories } from '@storybook/testing-react';
+import { render } from '@testing-library/react';
+import { axe } from 'jest-axe';
+import React from 'react';
+
+import * as stories from './MessageToolbar.stories';
+
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
+
+describe('[MessageToolbar Rendering]', () => {
+ test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render( );
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+ );
+
+ test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render( );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
+ );
+});
diff --git a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.stories.tsx b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.stories.tsx
new file mode 100644
index 0000000000..1c0682553a
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.stories.tsx
@@ -0,0 +1,38 @@
+import { Title, Primary } from '@storybook/addon-docs';
+import type { ComponentMeta } from '@storybook/react';
+import React from 'react';
+
+import { MessageToolbar, MessageToolbarItem } from '.';
+import Box from '../../Box';
+import { BasicMessageTemplate } from '../helpers';
+
+export default {
+ title: 'Message/MessageToolbar',
+ component: MessageToolbar,
+ parameters: {
+ docs: {
+ page: () => (
+ <>
+
+
+ >
+ ),
+ },
+ },
+} as ComponentMeta;
+
+const toolbar = (
+
+
+
+
+
+
+
+
+);
+
+export const Default = BasicMessageTemplate.bind({});
+Default.args = {
+ toolbar,
+};
diff --git a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.styles.scss b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.styles.scss
similarity index 70%
rename from packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.styles.scss
rename to packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.styles.scss
index 3f2f5e8878..58de61d441 100644
--- a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.styles.scss
+++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.styles.scss
@@ -3,15 +3,15 @@
@use '../../../styles/typography.scss';
@use '../mixins.scss';
-.rcx-message-toolbox {
- display: inline-block;
-
+.rcx-message-toolbar {
margin-inline: lengths.margin(20);
padding: lengths.padding(2);
+ opacity: 0;
+
border: lengths.border-width(default) solid colors.stroke(extra-light);
border-radius: theme(
- 'message-toolbox-border-radius',
+ 'message-toolbar-border-radius',
lengths.border-radius(medium)
);
background: colors.surface(room);
@@ -19,17 +19,24 @@
&__wrapper {
display: none;
- @at-root .rcx-message:hover &,
- &--visible {
+ .rcx-message:hover &,
+ .rcx-message:focus-within & {
display: inline-block;
}
- @at-root .rcx-message:focus-within &,
- &--visible {
+ &--visible {
display: inline-block;
+
+ .rcx-message-toolbar {
+ opacity: 1;
+ }
}
}
+ @include mixins.message-focus-visible {
+ display: inline-block;
+ }
+
@at-root .rcx-message & {
position: absolute;
z-index: 10;
diff --git a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.tsx b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.tsx
new file mode 100644
index 0000000000..8ff3c37eda
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbar.tsx
@@ -0,0 +1,17 @@
+import type { ComponentProps, ForwardedRef } from 'react';
+import React, { forwardRef } from 'react';
+
+import { ButtonGroup } from '../..';
+
+type MessageToolbarProps = ComponentProps;
+
+export const MessageToolbar = forwardRef(function MessageToolbar(
+ props: MessageToolbarProps,
+ ref: ForwardedRef
+) {
+ return (
+
+
+
+ );
+});
diff --git a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolboxItem.tsx b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarItem.tsx
similarity index 57%
rename from packages/fuselage/src/components/Message/MessageToolbox/MessageToolboxItem.tsx
rename to packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarItem.tsx
index c1e16f1383..f6fa758a65 100644
--- a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolboxItem.tsx
+++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarItem.tsx
@@ -3,10 +3,10 @@ import React, { forwardRef } from 'react';
import { IconButton } from '../../Button';
-type MessageToolboxItemProps = ComponentProps;
+type MessageToolbarItemProps = ComponentProps;
-export const MessageToolboxItem = forwardRef(function Item(
- props: MessageToolboxItemProps,
+export const MessageToolbarItem = forwardRef(function MessageToolbarItem(
+ props: MessageToolbarItemProps,
ref: Ref
) {
return ;
diff --git a/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarWrapper.tsx b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarWrapper.tsx
new file mode 100644
index 0000000000..e8d58306b2
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageToolbar/MessageToolbarWrapper.tsx
@@ -0,0 +1,25 @@
+import type { HTMLAttributes, Ref } from 'react';
+import React, { forwardRef } from 'react';
+
+type MessageToolbarWrapperProps = HTMLAttributes & {
+ visible?: boolean;
+};
+
+export const MessageToolbarWrapper = forwardRef(function MessageToolbarWrapper(
+ { className, visible, ...props }: MessageToolbarWrapperProps,
+ ref: Ref
+) {
+ return (
+
+ );
+});
diff --git a/packages/fuselage/src/components/Message/MessageToolbar/__snapshots__/MessageToolbar.spec.tsx.snap b/packages/fuselage/src/components/Message/MessageToolbar/__snapshots__/MessageToolbar.spec.tsx.snap
new file mode 100644
index 0000000000..8a5b591156
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageToolbar/__snapshots__/MessageToolbar.spec.tsx.snap
@@ -0,0 +1,176 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[MessageToolbar Rendering] renders Default without crashing 1`] = `
+
+
+
+
+
+
+ May, 24, 2020
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ut enim ad minim veniam
+
+
+
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/Message/MessageToolbar/index.tsx b/packages/fuselage/src/components/Message/MessageToolbar/index.tsx
new file mode 100644
index 0000000000..a645f42d8a
--- /dev/null
+++ b/packages/fuselage/src/components/Message/MessageToolbar/index.tsx
@@ -0,0 +1,21 @@
+import { Menu } from '../../Menu';
+import { MessageToolbar } from './MessageToolbar';
+import { MessageToolbarItem } from './MessageToolbarItem';
+import { MessageToolbarWrapper } from './MessageToolbarWrapper';
+
+export default Object.assign(MessageToolbar, {
+ /**
+ * @deprecated prefer using named imports
+ * */
+ Item: MessageToolbarItem,
+ /**
+ * @deprecated prefer using named imports
+ * */
+ Wrapper: MessageToolbarWrapper,
+ /**
+ * @deprecated prefer using named imports
+ * */
+ Menu,
+});
+
+export { MessageToolbar, MessageToolbarItem, MessageToolbarWrapper, Menu };
diff --git a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.spec.tsx b/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.spec.tsx
deleted file mode 100644
index acf9d3a027..0000000000
--- a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.spec.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { render } from '@testing-library/react';
-import React from 'react';
-
-import MessageToolbox from '.';
-
-it('renders without crashing', () => {
- render(
-
-
-
-
-
-
- );
-});
diff --git a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.stories.tsx b/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.stories.tsx
deleted file mode 100644
index 4b6b6db753..0000000000
--- a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.stories.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Title, Primary } from '@storybook/addon-docs';
-import type { ComponentStory, ComponentMeta } from '@storybook/react';
-import React from 'react';
-
-import type { MessageToolboxWrapper } from '.';
-import { MessageToolbox, MessageToolboxItem } from '.';
-import { Box } from '../..';
-
-export default {
- title: 'Message/MessageToolbox',
- component: MessageToolbox,
- parameters: {
- docs: {
- page: () => (
- <>
-
-
- >
- ),
- },
- },
-} as ComponentMeta;
-
-export const Default: ComponentStory = () => (
-
-
-
-
-
-
-
-
-);
diff --git a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.tsx b/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.tsx
deleted file mode 100644
index 97fa74e648..0000000000
--- a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolbox.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { ComponentProps } from 'react';
-import React from 'react';
-
-import { ButtonGroup } from '../..';
-
-type MessageToolboxProps = ComponentProps;
-
-export const MessageToolbox = (props: MessageToolboxProps) => (
-
-
-
-);
diff --git a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolboxWrapper.tsx b/packages/fuselage/src/components/Message/MessageToolbox/MessageToolboxWrapper.tsx
deleted file mode 100644
index ccfe17cf21..0000000000
--- a/packages/fuselage/src/components/Message/MessageToolbox/MessageToolboxWrapper.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { AllHTMLAttributes, Ref } from 'react';
-import React, { forwardRef } from 'react';
-
-type MessageToolboxWrapperProps = AllHTMLAttributes & {
- visible?: boolean;
-};
-
-export const MessageToolboxWrapper = forwardRef(function ToolboxWrapper(
- { className, visible, ...props }: MessageToolboxWrapperProps,
- ref: Ref
-) {
- return (
-
- );
-});
diff --git a/packages/fuselage/src/components/Message/MessageToolbox/index.tsx b/packages/fuselage/src/components/Message/MessageToolbox/index.tsx
deleted file mode 100644
index d5eb4edff1..0000000000
--- a/packages/fuselage/src/components/Message/MessageToolbox/index.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Menu } from '../../Menu';
-import { MessageToolbox } from './MessageToolbox';
-import { MessageToolboxItem } from './MessageToolboxItem';
-import { MessageToolboxWrapper } from './MessageToolboxWrapper';
-
-export default Object.assign(MessageToolbox, {
- Item: MessageToolboxItem,
- Wrapper: MessageToolboxWrapper,
- Menu,
-});
-
-export { MessageToolbox, MessageToolboxItem, MessageToolboxWrapper, Menu };
diff --git a/packages/fuselage/src/components/Message/MessageUsername.tsx b/packages/fuselage/src/components/Message/MessageUsername.tsx
index 59cb43377c..f32d187404 100644
--- a/packages/fuselage/src/components/Message/MessageUsername.tsx
+++ b/packages/fuselage/src/components/Message/MessageUsername.tsx
@@ -1,9 +1,7 @@
-import type { AllHTMLAttributes } from 'react';
+import type { HTMLAttributes } from 'react';
import React from 'react';
-type MessageUsernameProps = AllHTMLAttributes;
-
-export const MessageUsername = (props: MessageUsernameProps) => (
+export const MessageUsername = (props: HTMLAttributes) => (
= () => (
May, 24, 2020
@@ -92,13 +90,13 @@ export const Default: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -138,13 +136,13 @@ export const WithSequential: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -153,13 +151,13 @@ export const WithSequential: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -176,13 +174,13 @@ export const WithSequential: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -192,13 +190,13 @@ export const WithSequential: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -207,13 +205,13 @@ export const WithSequential: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -253,13 +251,13 @@ export const MessageWithThread: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -268,13 +266,13 @@ export const MessageWithThread: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -291,13 +289,13 @@ export const MessageWithThread: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -430,13 +428,13 @@ export const MessageEditing: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -445,13 +443,13 @@ export const MessageEditing: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -468,13 +466,13 @@ export const MessageEditing: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -514,13 +512,13 @@ export const MessageUnorderedList: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -560,13 +558,13 @@ export const MessageOrderedList: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -606,13 +604,13 @@ export const MessageHighlighted: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -621,13 +619,13 @@ export const MessageHighlighted: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -644,13 +642,13 @@ export const MessageHighlighted: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -684,13 +682,13 @@ export const MessagePending: ComponentStory = () => (
veniam...
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -699,13 +697,13 @@ export const MessagePending: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -722,13 +720,13 @@ export const MessagePending: ComponentStory = () => (
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -775,13 +773,13 @@ export const MessageWithMetrics: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -823,13 +821,13 @@ export const MessageWithHeadings: ComponentStory = () => (
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
@@ -869,13 +867,13 @@ export const LotsOfReactions: ComponentStory = () => (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
diff --git a/packages/fuselage/src/components/Message/Messages.styles.scss b/packages/fuselage/src/components/Message/Messages.styles.scss
index 2fd2741254..f8a03c4844 100644
--- a/packages/fuselage/src/components/Message/Messages.styles.scss
+++ b/packages/fuselage/src/components/Message/Messages.styles.scss
@@ -2,11 +2,12 @@
@use '../../styles/functions.scss';
@use '../../styles/colors.scss';
@use '../../styles/mixins/size.scss';
+@use '../../styles/mixins/templates.scss';
@use '../../styles/typography.scss';
@use './mixins.scss';
@import './MessageMetrics/MessageMetrics.styles.scss';
-@import './MessageToolbox/MessageToolbox.styles.scss';
+@import './MessageToolbar/MessageToolbar.styles.scss';
@import './MessageReactions/MessageReactions.styles.scss';
@import './ThreadMessage/ThreadMessage.styles.scss';
@import './MessageDivider/MessageDivider.styles.scss';
@@ -50,8 +51,6 @@ $message-background-color-highlight: functions.theme(
colors.status-background(warning-2)
);
-$message-link-color: functions.theme('message-link-color', colors.font(info));
-
$message-highlight-colors-critical-color: theme(
'message-highlight-colors-critical-color',
colors.font(pure-white)
@@ -106,7 +105,7 @@ $message-highlight-colors-background-other-color: theme(
background-color: $message-background-color-hover;
}
- @include mixins.focus-state();
+ @include templates.focus-state;
&--selected {
background: $message-background-color-selected !important;
@@ -188,7 +187,7 @@ $message-highlight-colors-background-other-color: theme(
@extend %rcx-margins-header;
- @include mixins.focus-state();
+ @include templates.focus-state;
}
&__name {
@@ -327,19 +326,6 @@ $message-highlight-colors-background-other-color: theme(
list-style: none;
}
-
- a {
- color: $message-link-color;
-
- &:hover {
- text-decoration: underline;
- }
-
- &:focus {
- border-radius: lengths.border-radius(small);
- box-shadow: 0 0 0 2px colors.stroke(extra-light-highlight);
- }
- }
}
&-block {
@@ -438,5 +424,7 @@ $message-highlight-colors-background-other-color: theme(
&--other {
color: $message-highlight-colors-other-color;
}
+
+ @include templates.focus-state;
}
}
diff --git a/packages/fuselage/src/components/Message/ThreadMessage/ThreadMessageEmoji.tsx b/packages/fuselage/src/components/Message/ThreadMessage/ThreadMessageEmoji.tsx
index 266b1c721a..b006c61675 100644
--- a/packages/fuselage/src/components/Message/ThreadMessage/ThreadMessageEmoji.tsx
+++ b/packages/fuselage/src/components/Message/ThreadMessage/ThreadMessageEmoji.tsx
@@ -1,25 +1,14 @@
-import type { ReactNode } from 'react';
+import type { ComponentProps } from 'react';
import React from 'react';
import { MessageEmojiBase } from '../MessageEmojiBase';
-type ThreadMessageEmojiProps = {
- name: string;
- className?: string;
- image?: string;
- children?: ReactNode;
-};
-
export const ThreadMessageEmoji = ({
- name,
className,
- image,
- children,
-}: ThreadMessageEmojiProps) => (
+ ...props
+}: ComponentProps) => (
);
diff --git a/packages/fuselage/src/components/Message/helpers.tsx b/packages/fuselage/src/components/Message/helpers.tsx
new file mode 100644
index 0000000000..5ee4aebaba
--- /dev/null
+++ b/packages/fuselage/src/components/Message/helpers.tsx
@@ -0,0 +1,48 @@
+import type { Story } from '@storybook/react';
+import type { ReactNode } from 'react';
+import React from 'react';
+
+import Message from '.';
+import { Avatar } from '../Avatar';
+import Box from '../Box';
+import { MessageDivider } from './MessageDivider';
+
+export const avatarUrl =
+ 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAoACgDASIAAhEBAxEB/8QAGwAAAgIDAQAAAAAAAAAAAAAAAAcEBgIDBQj/xAAuEAACAQQAAwcEAQUAAAAAAAABAgMABAUREiExBhMUIkFRYQcWcYGhFTJSgpH/xAAYAQADAQEAAAAAAAAAAAAAAAACAwQBAP/EAB4RAAIBBQEBAQAAAAAAAAAAAAABAgMREiExE0HR/9oADAMBAAIRAxEAPwBuXuIkhBuMe5ib/AHQP49q4L3mLitryTLTSpOiHQI5k/HzXa/qbFOEudVTu1dumWvcTaNCZYZ7vU6g6LxqjOU/24dfs1Ouh9FnkMpd3Reeyx83hAxZZEhkdV9/MBrX71WGPvJcqrJBGveKATtuXXqNU0pu02bTHXD/AGvJAluyxxRd6F4x00o+NdKoVrjbzJdvVe1t5cVLc2ck8qjnohgpPtz2v7G6JtPQ2VJwjlcw+37mchpnK6GtIuv5NFWeTsLNPvxWTvpfjvOEfwKKzEVkSct2vscS/BIzSN0YRkeX81UpPqO8masJETu7OOccY4dswYFQeftv096XV5knuJGdm2T1+agvMXj8jEaHX905QihabvcbuS7X566mLWLwSY8PuRnk/u4eZ0deTl71Ef6hY+0yM88TzeNZY4luYwpVYyduOfrvhPTnr0pXSX9y5mCsyJMdyxxvwq599em+taItqCSNc90ChvZRUruUcT0JiO18Elpk7t8v41LWzacxkBSuvjQ/FFJayjDWrCTepAQ2vUH0oo/Jk3ovpwJJeVCP5CN+lFFaaMqy+nAyuChvrTI2kN9JAsi2ZOy4IBHMnkSCP+iqBexSWdxLazoUljJVlPUH2oorkV10pRc7b1zXb/hZOzuJvM86QWEXeELxOzHSIPcmiiiunVlF2RNTpRkrs//Z';
+
+export const BasicMessageTemplate: Story = ({
+ reactions,
+ toolbar,
+ metrics,
+}: {
+ reactions?: ReactNode;
+ toolbar?: ReactNode;
+ metrics?: ReactNode;
+}) => (
+
+ May, 24, 2020
+
+
+
+
+
+
+
+ Haylie George {' '}
+ @haylie.george
+
+
+ Admin
+ User
+ Owner
+
+ 12:00 PM
+
+ Ut enim ad minim veniam
+ {reactions}
+ {metrics && {metrics} }
+
+ {toolbar}
+
+
+);
diff --git a/packages/fuselage/src/components/Message/index.tsx b/packages/fuselage/src/components/Message/index.tsx
index 771cef083d..363b0093ef 100644
--- a/packages/fuselage/src/components/Message/index.tsx
+++ b/packages/fuselage/src/components/Message/index.tsx
@@ -13,7 +13,7 @@ import { MessageNameContainer } from './MessageNameContainer';
import { MessageRole } from './MessageRole';
import { MessageRoles } from './MessageRoles';
import { MessageTimestamp } from './MessageTimestamp';
-import MessageToolbox from './MessageToolbox';
+import MessageToolbar from './MessageToolbar';
import { MessageUsername } from './MessageUsername';
export * from './MessageDivider';
@@ -22,7 +22,7 @@ export * from './MessageStatusIndicator';
export * from './MessageSystem';
export * from './MessageMetrics';
export * from './MessageReactions';
-export * from './MessageToolbox';
+export * from './MessageToolbar';
export * from './ThreadMessage';
export * from './MessageBlock';
export * from './MessageBody';
@@ -41,7 +41,7 @@ export * from './MessageHighlight';
export default Object.assign(Message, {
Metrics: MessageMetrics,
- Toolbox: MessageToolbox,
+ Toolbar: MessageToolbar,
Container: MessageContainer,
ContainerFixed: MessageContainerFixed,
LeftContainer: MessageLeftContainer,
diff --git a/packages/fuselage/src/components/Message/mixins.scss b/packages/fuselage/src/components/Message/mixins.scss
index 18ce46f4b2..7aa6e6f320 100644
--- a/packages/fuselage/src/components/Message/mixins.scss
+++ b/packages/fuselage/src/components/Message/mixins.scss
@@ -36,12 +36,14 @@
}
}
-@mixin focus-state {
- border: 1px solid transparent;
+@mixin message-focus-visible {
+ @content;
- &:focus {
- border: 1px solid colors.stroke(highlight);
- border-radius: lengths.border-radius(medium);
- box-shadow: 0 0 0 2px colors.stroke(extra-light-highlight);
+ opacity: 0;
+
+ .rcx-message:hover &,
+ .rcx-message:has(:focus-visible) &,
+ .rcx-message:focus-visible & {
+ opacity: 1;
}
}
diff --git a/packages/fuselage/src/components/Modal/Modal.styles.scss b/packages/fuselage/src/components/Modal/Modal.styles.scss
index f054656a50..8a6aa4b86b 100644
--- a/packages/fuselage/src/components/Modal/Modal.styles.scss
+++ b/packages/fuselage/src/components/Modal/Modal.styles.scss
@@ -102,7 +102,7 @@ $modal-margin: theme('modal-margin', auto);
margin: $modal-container-margin;
&-annotation {
- color: colors.font(default);
+ color: colors.font(secondary-info);
@include typography.use-font-scale(c1);
}
}
diff --git a/packages/fuselage/src/components/PaginatedSelect/PaginatedMultiSelectFiltered.tsx b/packages/fuselage/src/components/PaginatedSelect/PaginatedMultiSelectFiltered.tsx
index 5503ee114f..539081b04b 100644
--- a/packages/fuselage/src/components/PaginatedSelect/PaginatedMultiSelectFiltered.tsx
+++ b/packages/fuselage/src/components/PaginatedSelect/PaginatedMultiSelectFiltered.tsx
@@ -1,32 +1,13 @@
-import type { ComponentProps, Ref, FormEvent, ReactElement } from 'react';
+import type { ComponentProps, Ref, FormEvent } from 'react';
import React, { useCallback, forwardRef } from 'react';
-import type Box from '../Box';
import Flex from '../Flex';
import { InputBox } from '../InputBox';
-import { type OptionsPaginated } from '../OptionsPaginated';
-import PaginatedMultiSelect, {
- type PaginatedMultiSelectOption,
-} from './PaginatedMultiSelect';
+import PaginatedMultiSelect from './PaginatedMultiSelect';
-type PaginatedMultiSelectFilteredProps = Omit<
- ComponentProps,
- 'onChange' | 'value' | 'filter'
-> & {
- error?: boolean;
- options: PaginatedMultiSelectOption[];
- withTitle?: boolean;
- placeholder?: string;
- endReached?: (start?: number, end?: number) => void;
- value?: PaginatedMultiSelectOption[];
- onChange: (values: PaginatedMultiSelectOption[]) => void;
- renderOptions?: (
- props: ComponentProps
- ) => ReactElement | null;
- anchor?: any;
- filter?: string;
+type PaginatedMultiSelectFilteredProps = {
setFilter?: (value: string) => void;
-};
+} & ComponentProps;
export const PaginatedMultiSelectFiltered = ({
filter,
@@ -67,8 +48,8 @@ export const PaginatedMultiSelectFiltered = ({
);
};
diff --git a/packages/fuselage/src/components/PaginatedSelect/PaginatedSelect.tsx b/packages/fuselage/src/components/PaginatedSelect/PaginatedSelect.tsx
index e1b983b358..6d8cdd7df7 100644
--- a/packages/fuselage/src/components/PaginatedSelect/PaginatedSelect.tsx
+++ b/packages/fuselage/src/components/PaginatedSelect/PaginatedSelect.tsx
@@ -7,6 +7,7 @@ import AnimatedVisibility from '../AnimatedVisibility';
import Box from '../Box';
import { Icon } from '../Icon';
import Margins from '../Margins';
+import Option from '../Option';
import { useVisible } from '../Options/useVisible';
import { OptionsPaginated } from '../OptionsPaginated';
import PositionAnimated from '../PositionAnimated';
@@ -38,6 +39,7 @@ export const PaginatedSelect = ({
onChange = () => {},
placeholder = '',
renderOptions: _Options = OptionsPaginated,
+ renderItem = Option,
endReached,
...props
}: PaginatedSelectProps) => {
@@ -136,6 +138,7 @@ export const PaginatedSelect = ({
onSelect={internalChangedByClick}
endReached={endReached}
onMouseDown={prevent}
+ renderItem={renderItem}
/>
diff --git a/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.spec.tsx b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.spec.tsx
new file mode 100644
index 0000000000..b5a5d28746
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.spec.tsx
@@ -0,0 +1,39 @@
+import { render } from '@testing-library/react';
+import React from 'react';
+
+import PaletteStyleTag from './PaletteStyleTag';
+import { dark, light } from './lib/themePalettes';
+
+describe('[PaletteStyleTag colors]', () => {
+ it('creates the Light theme style tag', () => {
+ render( );
+ const style = document.querySelector('#main-palette');
+ expect(style?.innerHTML).toContain(
+ `surface-light: ${light['surface-light']}`
+ );
+ });
+ it('creates the Dark theme style tag', () => {
+ render( );
+ const style = document.querySelector('#main-palette');
+ expect(style?.innerHTML).toContain(
+ `surface-light: ${dark['surface-light']}`
+ );
+ });
+ it('creates tag with the given id', () => {
+ render( );
+ const style = document.querySelector('#test-palette');
+ expect(style).not.toBeNull();
+ });
+ it('creates tag with the given prefix', () => {
+ render( );
+ const style = document.querySelector('#main-palette');
+ expect(style?.innerHTML).toContain(
+ `--test-surface-light: ${light['surface-light']}`
+ );
+ });
+ it('creates tag with the given selector', () => {
+ render( );
+ const style = document.querySelector('#main-palette');
+ expect(style?.innerHTML).toContain('.test {');
+ });
+});
diff --git a/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.stories.tsx b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.stories.tsx
new file mode 100644
index 0000000000..fe1df9d366
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.stories.tsx
@@ -0,0 +1,94 @@
+import {
+ Title,
+ Subtitle,
+ Description,
+ Primary as PrimaryStory,
+ ArgsTable,
+ Stories,
+ PRIMARY_STORY,
+} from '@storybook/addon-docs';
+import type { ComponentStory, ComponentMeta } from '@storybook/react';
+import React from 'react';
+
+import {
+ Box,
+ Button,
+ PaletteStyleTag,
+ Card,
+ CardHeader,
+ FramedIcon,
+ CardTitle,
+ CardBody,
+ CardControls,
+ Divider,
+ ProgressBar,
+ CardCol,
+} from '../..';
+
+export default {
+ title: 'Layout/PaletteStyleTag',
+ component: PaletteStyleTag,
+ parameters: {
+ layout: 'centered',
+ docs: {
+ description: {
+ component:
+ "Style tag to handle the theme of the application. Import `PaletteStyleTag` and use it on the application informing the desired theme. Toggle the theme on Storybook's Control panel to see the color changes.",
+ },
+ page: () => (
+ <>
+
+
+
+
+
+
+ >
+ ),
+ },
+ },
+} as ComponentMeta;
+
+export const _PaletteStyleTag: ComponentStory = (
+ args
+) => (
+
+
+
+
+
+ {args.theme} theme
+
+
+
+ Toggle the theme on Control panel to see the color changes.
+
+
+
+
+
+
+
+
+ Default
+
+ Primary
+
+
+ Danger
+
+
+
+
+);
+
+// export const _PaletteStyleTag: ComponentStory =
+// Template.bind({});
+
+_PaletteStyleTag.parameters = {
+ docs: {
+ description: {
+ story: 'Another description on the story, overriding the comments',
+ },
+ },
+};
diff --git a/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.tsx b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.tsx
new file mode 100644
index 0000000000..689af2f017
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.tsx
@@ -0,0 +1,48 @@
+import React, { memo } from 'react';
+import { createPortal } from 'react-dom';
+
+import { convertToCss } from './helpers/convertToCss';
+import { useCreateStyleContainer } from './hooks/useCreateStyleContainer';
+import { codeBlock } from './lib/codeBlockStyles';
+import { dark, highContrast, light } from './lib/themePalettes';
+import type { Themes } from './types/themes';
+
+const themes = {
+ light,
+ dark,
+ 'high-contrast': highContrast,
+};
+
+export const PaletteStyleTag = memo(function PaletteStyleTag({
+ theme = 'light',
+ tagId = 'main-palette',
+ prefix = '--rcx-color',
+ selector,
+}: {
+ theme?: Themes;
+ /**
+ * Default is `main-palette`.
+ */
+ tagId?: string;
+ /**
+ * Token prefix. Default is `--rcx-color`.
+ */
+ prefix?: string;
+ /**
+ * Default is `:root`.
+ */
+ selector?: string;
+}) {
+ const palette = convertToCss(themes[theme], prefix, selector);
+
+ return (
+ <>
+ {createPortal(
+ theme === 'dark' ? palette + codeBlock : palette,
+ useCreateStyleContainer(tagId)
+ )}
+ >
+ );
+});
+
+export default PaletteStyleTag;
diff --git a/packages/fuselage/src/components/PaletteStyleTag/helpers/convertToCss.ts b/packages/fuselage/src/components/PaletteStyleTag/helpers/convertToCss.ts
new file mode 100644
index 0000000000..9f9be0e486
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/helpers/convertToCss.ts
@@ -0,0 +1,8 @@
+export const convertToCss = (
+ values: Record,
+ prefix: string,
+ selector = ':root'
+) =>
+ `${selector} {\n${Object.entries(values)
+ .map(([name, color]) => `${prefix}-${name}: ${color};`)
+ .join('\n')}\n}`;
diff --git a/packages/fuselage/src/components/PaletteStyleTag/helpers/getPalette.ts b/packages/fuselage/src/components/PaletteStyleTag/helpers/getPalette.ts
new file mode 100644
index 0000000000..3cc4332444
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/helpers/getPalette.ts
@@ -0,0 +1,373 @@
+import { badge } from '@rocket.chat/fuselage-tokens/dist/badge.json';
+import { button } from '@rocket.chat/fuselage-tokens/dist/button.json';
+import { font } from '@rocket.chat/fuselage-tokens/dist/font.json';
+import { shadow } from '@rocket.chat/fuselage-tokens/dist/shadow.json';
+import { status } from '@rocket.chat/fuselage-tokens/dist/status.json';
+import { statusBullet } from '@rocket.chat/fuselage-tokens/dist/statusBullet.json';
+import { stroke } from '@rocket.chat/fuselage-tokens/dist/stroke.json';
+import { surface } from '@rocket.chat/fuselage-tokens/dist/surface.json';
+
+import type { Themes } from '../types/themes';
+
+export const getTokens = (theme: Themes) => {
+ const tokens = {
+ badge: badge[theme],
+ button: button[theme],
+ font: font[theme],
+ shadow: shadow[theme],
+ status: status[theme],
+ statusBullet: statusBullet[theme],
+ stroke: stroke[theme],
+ surface: surface[theme],
+ };
+
+ return tokens;
+};
+
+export const getThemePalette = (theme: Themes) => {
+ const { badge, button, font, shadow, status, statusBullet, stroke, surface } =
+ getTokens(theme);
+
+ const palette = [
+ {
+ category: 'Stroke',
+ description: "Use as component's outline, stroke, dividers",
+ list: [
+ { name: 'stroke-extra-light', color: stroke.extraLight },
+ { name: 'stroke-light', color: stroke.light },
+ { name: 'stroke-medium', color: stroke.medium },
+ { name: 'stroke-dark', color: stroke.dark },
+ { name: 'stroke-extra-dark', color: stroke.extraDark },
+ {
+ name: 'stroke-extra-light-highlight',
+ color: stroke.extraLightHighlight,
+ },
+ { name: 'stroke-highlight', color: stroke.highlight },
+ { name: 'stroke-extra-light-error', color: stroke.extraLightError },
+ { name: 'stroke-error', color: stroke.error },
+ ],
+ },
+ {
+ category: 'Surface',
+ description: 'Use as a container on top of the background',
+ list: [
+ { name: 'surface-light', color: surface.light },
+ { name: 'surface-tint', color: surface.tint },
+ { name: 'surface-room', color: surface.room },
+ { name: 'surface-neutral', color: surface.neutral },
+ { name: 'surface-disabled', color: surface.disabled },
+ { name: 'surface-hover', color: surface.hover },
+ { name: 'surface-selected', color: surface.selected },
+ { name: 'surface-dark', color: surface.dark },
+ { name: 'surface-featured', color: surface.featured },
+ { name: 'surface-featured-hover', color: surface.featuredHover },
+ { name: 'surface-overlay', color: surface.overlay },
+ { name: 'surface-sidebar', color: surface.sidebar },
+ ],
+ },
+ {
+ category: 'Shadow',
+ description: 'Use as a shadow color',
+ list: [
+ { name: 'shadow-highlight', color: shadow.highlight },
+ { name: 'shadow-danger', color: shadow.danger },
+ { name: 'shadow-elevation-border', color: shadow['elevation-border'] },
+ { name: 'shadow-elevation-1', color: shadow['elevation-1'] },
+ {
+ name: 'shadow-elevation-2x',
+ color: shadow['elevation-2x'],
+ },
+ {
+ name: 'shadow-elevation-2y',
+ color: shadow['elevation-2y'],
+ },
+ ],
+ },
+ {
+ category: 'Font',
+ description: 'These should be applied according to surfaces',
+ list: [
+ { name: 'font-white', color: font.white },
+ { name: 'font-disabled', color: font.disabled },
+ { name: 'font-annotation', color: font.annotation },
+ { name: 'font-hint', color: font.hint },
+ { name: 'font-secondary-info', color: font.secondaryInfo },
+ { name: 'font-default', color: font.default },
+ { name: 'font-titles-labels', color: font.titlesLabels },
+ { name: 'font-info', color: font.info },
+ { name: 'font-danger', color: font.danger },
+ { name: 'font-pure-black', color: font.pureBlack },
+ { name: 'font-pure-white', color: font.pureWhite },
+ ],
+ },
+ {
+ category: 'Status',
+ description: 'Status Background',
+ list: [
+ { name: 'status-background-info', color: status.info },
+ { name: 'status-background-success', color: status.success },
+ { name: 'status-background-danger', color: status.danger },
+ { name: 'status-background-warning', color: status.warning },
+ { name: 'status-background-warning-2', color: status['warning-2'] },
+ {
+ name: 'status-background-service-1',
+ color: status['service-1'],
+ },
+ {
+ name: 'status-background-service-2',
+ color: status['service-2'],
+ },
+ {
+ name: 'status-background-service-3',
+ color: status['service-3'],
+ },
+ ],
+ },
+ {
+ description: 'Status Font',
+ list: [
+ { name: 'status-font-on-info', color: status['font-on-info'] },
+ { name: 'status-font-on-success', color: status['font-on-success'] },
+ { name: 'status-font-on-danger', color: status['font-on-danger'] },
+ { name: 'status-font-on-warning', color: status['font-on-warning'] },
+ {
+ name: 'status-font-on-warning-2',
+ color: status['font-on-warning-2'],
+ },
+ {
+ name: 'status-font-on-service-1',
+ color: status['font-on-service-1'],
+ },
+ {
+ name: 'status-font-on-service-2 ',
+ color: status['font-on-service-2'],
+ },
+ {
+ name: 'status-font-on-service-3 ',
+ color: status['font-on-service-3'],
+ },
+ ],
+ },
+ {
+ category: 'Badge',
+ description: 'Badge Background',
+ list: [
+ { name: 'badge-background-level-0', color: badge['level-0'] },
+ { name: 'badge-background-level-1', color: badge['level-1'] },
+ { name: 'badge-background-level-2', color: badge['level-2'] },
+ { name: 'badge-background-level-3', color: badge['level-3'] },
+ { name: 'badge-background-level-4', color: badge['level-4'] },
+ ],
+ },
+ {
+ category: 'Status Bullet',
+ description: 'Used to show user status',
+ list: [
+ { name: 'status-bullet-online', color: statusBullet.online },
+ { name: 'status-bullet-away', color: statusBullet.away },
+ { name: 'status-bullet-busy', color: statusBullet.busy },
+ { name: 'status-bullet-disabled', color: statusBullet.disabled },
+ { name: 'status-bullet-offline', color: statusBullet.offline },
+ { name: 'status-bullet-loading', color: statusBullet.loading },
+ ],
+ },
+ {
+ category: 'Button',
+ description: 'Primary Background',
+ list: [
+ {
+ name: 'button-background-primary-default',
+ color: button.backgroundPrimaryDefault,
+ },
+ {
+ name: 'button-background-primary-hover',
+ color: button.backgroundPrimaryHover,
+ },
+ {
+ name: 'button-background-primary-press',
+ color: button.backgroundPrimaryPress,
+ },
+ {
+ name: 'button-background-primary-focus',
+ color: button.backgroundPrimaryFocus,
+ },
+ {
+ name: 'button-background-primary-keyfocus',
+ color: button.backgroundPrimaryKeyfocus,
+ },
+ {
+ name: 'button-background-primary-disabled',
+ color: button.backgroundPrimaryDisabled,
+ },
+ ],
+ },
+ {
+ description: 'Secondary Background',
+ list: [
+ {
+ name: 'button-background-secondary-default',
+ color: button.backgroundSecondaryDefault,
+ },
+ {
+ name: 'button-background-secondary-hover',
+ color: button.backgroundSecondaryHover,
+ },
+ {
+ name: 'button-background-secondary-press',
+ color: button.backgroundSecondaryPress,
+ },
+ {
+ name: 'button-background-secondary-focus',
+ color: button.backgroundSecondaryFocus,
+ },
+ {
+ name: 'button-background-secondary-keyfocus',
+ color: button.backgroundSecondaryKeyfocus,
+ },
+ {
+ name: 'button-background-secondary-disabled',
+ color: button.backgroundSecondaryDisabled,
+ },
+ ],
+ },
+ {
+ description: 'Secondary Danger Background',
+ list: [
+ {
+ name: 'button-background-secondary-danger-default',
+ color: button.backgroundSecondaryDangerDefault,
+ },
+ {
+ name: 'button-background-secondary-danger-hover',
+ color: button.backgroundSecondaryDangerHover,
+ },
+ {
+ name: 'button-background-secondary-danger-press',
+ color: button.backgroundSecondaryDangerPress,
+ },
+ {
+ name: 'button-background-secondary-danger-focus',
+ color: button.backgroundSecondaryDangerFocus,
+ },
+ {
+ name: 'button-background-secondary-danger-keyfocus',
+ color: button.backgroundSecondaryDangerKeyfocus,
+ },
+ {
+ name: 'button-background-secondary-danger-disabled',
+ color: button.backgroundDangerDisabled,
+ },
+ ],
+ },
+ {
+ description: 'Danger Background',
+ list: [
+ {
+ name: 'button-background-danger-default',
+ color: button.backgroundDangerDefault,
+ },
+ {
+ name: 'button-background-danger-hover',
+ color: button.backgroundDangerHover,
+ },
+ {
+ name: 'button-background-danger-press',
+ color: button.backgroundDangerPress,
+ },
+ {
+ name: 'button-background-danger-focus',
+ color: button.backgroundDangerFocus,
+ },
+ {
+ name: 'button-background-danger-keyfocus',
+ color: button.backgroundDangerKeyfocus,
+ },
+ {
+ name: 'button-background-danger-disabled',
+ color: button.backgroundDangerDisabled,
+ },
+ ],
+ },
+ {
+ description: 'Success Background',
+ list: [
+ {
+ name: 'button-background-success-default',
+ color: button.backgroundSuccessDefault,
+ },
+ {
+ name: 'button-background-success-hover',
+ color: button.backgroundSuccessHover,
+ },
+ {
+ name: 'button-background-success-press',
+ color: button.backgroundSuccessPress,
+ },
+ {
+ name: 'button-background-success-focus',
+ color: button.backgroundSuccessFocus,
+ },
+ {
+ name: 'button-background-success-keyfocus',
+ color: button.backgroundSuccessKeyfocus,
+ },
+ {
+ name: 'button-background-success-disabled',
+ color: button.backgroundSuccessDisabled,
+ },
+ ],
+ },
+ {
+ description: 'Font',
+ list: [
+ { name: 'button-font-on-primary', color: button.fontOnPrimary },
+ {
+ name: 'button-font-on-primary-disabled',
+ color: button.fontOnPrimaryDisabled,
+ },
+ {
+ name: 'button-font-on-secondary',
+ color: button.fontOnSecondary,
+ },
+ {
+ name: 'button-font-on-secondary-disabled',
+ color: button.fontOnSecondaryDisabled,
+ },
+ {
+ name: 'button-font-on-secondary-danger',
+ color: button.fontOnSecondaryDanger,
+ },
+ {
+ name: 'button-font-on-secondary-danger-disabled',
+ color: button.onSecondaryDangerDisabled,
+ },
+ { name: 'button-font-on-danger', color: button.fontOnDanger },
+ {
+ name: 'button-font-on-danger-disabled',
+ color: button.fontOnDangerDisabled,
+ },
+ { name: 'button-font-on-success', color: button.fontOnSuccess },
+ {
+ name: 'button-font-on-success-disabled',
+ color: button.fontOnSuccessDisabled,
+ },
+ ],
+ },
+ ];
+
+ return {
+ ...palette.reduce(
+ (rec, group) => ({
+ ...rec,
+ ...group.list.reduce(
+ (rec, item) => ({
+ ...rec,
+ [item.name]: item.color,
+ }),
+ {} as Record
+ ),
+ }),
+ {} as Record
+ ),
+ };
+};
diff --git a/packages/fuselage/src/components/PaletteStyleTag/helpers/isHexColor.ts b/packages/fuselage/src/components/PaletteStyleTag/helpers/isHexColor.ts
new file mode 100644
index 0000000000..8bc9fcced6
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/helpers/isHexColor.ts
@@ -0,0 +1,2 @@
+export const isHexColor = (hex: string): boolean =>
+ typeof hex === 'string' && hex.length === 6 && !isNaN(Number(`0x${hex}`));
diff --git a/packages/fuselage/src/components/PaletteStyleTag/helpers/isLightColor.ts b/packages/fuselage/src/components/PaletteStyleTag/helpers/isLightColor.ts
new file mode 100644
index 0000000000..2324b75b8d
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/helpers/isLightColor.ts
@@ -0,0 +1,8 @@
+export const isLightColor = (color: string): boolean => {
+ const hex = color.replace('#', '');
+ const r = parseInt(hex.substring(0, 0 + 2), 16);
+ const g = parseInt(hex.substring(2, 2 + 2), 16);
+ const b = parseInt(hex.substring(4, 4 + 2), 16);
+ const brightness = (r * 299 + g * 587 + b * 114) / 1000;
+ return brightness > 155;
+};
diff --git a/packages/fuselage/src/components/PaletteStyleTag/hooks/useCreateStyleContainer.ts b/packages/fuselage/src/components/PaletteStyleTag/hooks/useCreateStyleContainer.ts
new file mode 100644
index 0000000000..584c81bd2e
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/hooks/useCreateStyleContainer.ts
@@ -0,0 +1,20 @@
+import { useMemo } from 'react';
+
+export const useCreateStyleContainer = (id: string) =>
+ useMemo(() => {
+ const refElement =
+ document.getElementById('rcx-styles') || document.head.lastChild;
+
+ const el = document.getElementById(id);
+
+ if (el) {
+ return el;
+ }
+
+ const styleElement = document.createElement('style');
+ styleElement.setAttribute('id', id);
+
+ document.head.insertBefore(styleElement, refElement);
+ document.head.appendChild(document.createElement('style'));
+ return styleElement;
+ }, [id]);
diff --git a/packages/fuselage/src/components/PaletteStyleTag/index.ts b/packages/fuselage/src/components/PaletteStyleTag/index.ts
new file mode 100644
index 0000000000..7003031c97
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/index.ts
@@ -0,0 +1 @@
+export * from './PaletteStyleTag';
diff --git a/packages/fuselage/src/components/PaletteStyleTag/lib/codeBlockStyles.ts b/packages/fuselage/src/components/PaletteStyleTag/lib/codeBlockStyles.ts
new file mode 100644
index 0000000000..2c6b4bf33b
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/lib/codeBlockStyles.ts
@@ -0,0 +1,74 @@
+export const codeBlock = `pre code.hljs {
+ display: block;
+ overflow-x: auto;
+ padding: 1em;
+}
+code.hljs {
+ padding: 3px 5px;
+}
+.hljs {
+ background: #1d1f21;
+ color: #c5c8c6;
+}
+.hljs span::selection,
+.hljs::selection {
+ background: #373b41;
+}
+.hljs span::-moz-selection,
+.hljs::-moz-selection {
+ background: #373b41;
+}
+.hljs-name,
+.hljs-title {
+ color: #f0c674;
+}
+.hljs-comment,
+.hljs-meta,
+.hljs-meta .hljs-keyword {
+ color: #707880;
+}
+.hljs-deletion,
+.hljs-link,
+.hljs-literal,
+.hljs-number,
+.hljs-symbol {
+ color: #c66;
+}
+.hljs-addition,
+.hljs-doctag,
+.hljs-regexp,
+.hljs-selector-attr,
+.hljs-selector-pseudo,
+.hljs-string {
+ color: #b5bd68;
+}
+.hljs-attribute,
+.hljs-code,
+.hljs-selector-id {
+ color: #b294bb;
+}
+.hljs-bullet,
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-tag {
+ color: #81a2be;
+}
+.hljs-subst,
+.hljs-template-tag,
+.hljs-template-variable,
+.hljs-variable {
+ color: #8abeb7;
+}
+.hljs-built_in,
+.hljs-quote,
+.hljs-section,
+.hljs-selector-class,
+.hljs-type {
+ color: #de935f;
+}
+.hljs-emphasis {
+ font-style: italic;
+}
+.hljs-strong {
+ font-weight: 700;
+}`;
diff --git a/packages/fuselage/src/components/PaletteStyleTag/lib/themePalettes.ts b/packages/fuselage/src/components/PaletteStyleTag/lib/themePalettes.ts
new file mode 100644
index 0000000000..a605840042
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/lib/themePalettes.ts
@@ -0,0 +1,5 @@
+import { getThemePalette } from '../helpers/getPalette';
+
+export const light = getThemePalette('light');
+export const highContrast = getThemePalette('high-contrast');
+export const dark = getThemePalette('dark');
diff --git a/packages/fuselage/src/components/PaletteStyleTag/types/themes.ts b/packages/fuselage/src/components/PaletteStyleTag/types/themes.ts
new file mode 100644
index 0000000000..2fe98dfbe2
--- /dev/null
+++ b/packages/fuselage/src/components/PaletteStyleTag/types/themes.ts
@@ -0,0 +1,3 @@
+export type ThemePreference = 'light' | 'dark' | 'auto' | 'high-contrast';
+
+export type Themes = 'light' | 'dark' | 'high-contrast';
diff --git a/packages/fuselage/src/components/Popover/Popover.spec.tsx b/packages/fuselage/src/components/Popover/Popover.spec.tsx
new file mode 100644
index 0000000000..66a6e6e118
--- /dev/null
+++ b/packages/fuselage/src/components/Popover/Popover.spec.tsx
@@ -0,0 +1,31 @@
+import { composeStories } from '@storybook/testing-react';
+import { render } from '@testing-library/react';
+import { axe } from 'jest-axe';
+import React from 'react';
+
+import * as stories from './Popover.stories';
+
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
+
+describe('[Popover Rendering]', () => {
+ test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render( );
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+ );
+
+ test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render( );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
+ );
+});
diff --git a/packages/fuselage/src/components/Popover/Popover.stories.tsx b/packages/fuselage/src/components/Popover/Popover.stories.tsx
new file mode 100644
index 0000000000..ae509f5d4f
--- /dev/null
+++ b/packages/fuselage/src/components/Popover/Popover.stories.tsx
@@ -0,0 +1,45 @@
+import type { ComponentStory, ComponentMeta } from '@storybook/react';
+import React from 'react';
+import { useOverlayTrigger } from 'react-aria';
+import { useOverlayTriggerState } from 'react-stately';
+
+import { Button, Popover, Tile } from '../..';
+
+export default {
+ title: 'Layout/Popover',
+ component: Popover,
+ parameters: {
+ layout: 'centered',
+ },
+} as ComponentMeta;
+
+const Template: ComponentStory = (args) => {
+ const ref = React.useRef(null);
+ const state = useOverlayTriggerState({});
+ const { triggerProps, overlayProps } = useOverlayTrigger(
+ { type: 'dialog' },
+ state,
+ ref
+ );
+ delete triggerProps.onPress;
+
+ return (
+ <>
+ state.toggle()} ref={ref}>
+ Open Popover
+
+ {state.isOpen && (
+
+ {args.children &&
+ React.isValidElement(args.children) &&
+ React.cloneElement(args.children, overlayProps)}
+
+ )}
+ >
+ );
+};
+
+export const Default: ComponentStory = Template.bind({});
+Default.args = {
+ children: Popover Content ,
+};
diff --git a/packages/fuselage/src/components/Select/Popover.tsx b/packages/fuselage/src/components/Popover/Popover.tsx
similarity index 78%
rename from packages/fuselage/src/components/Select/Popover.tsx
rename to packages/fuselage/src/components/Popover/Popover.tsx
index 4200233dfa..48a327298f 100644
--- a/packages/fuselage/src/components/Select/Popover.tsx
+++ b/packages/fuselage/src/components/Popover/Popover.tsx
@@ -6,18 +6,15 @@ import type { OverlayTriggerState } from 'react-stately';
interface PopoverProps extends Omit {
children: React.ReactNode;
state: OverlayTriggerState;
- className?: string;
- popoverRef?: React.RefObject;
}
export function Popover(props: PopoverProps) {
- const ref = React.useRef(null);
- const { popoverRef = ref, state, children, isNonModal } = props;
+ const popoverRef = React.useRef(null);
+ const { state, children, isNonModal } = props;
const { popoverProps, underlayProps } = usePopover(
{
...props,
- containerPadding: 8,
popoverRef,
},
state
diff --git a/packages/fuselage/src/components/Popover/__snapshots__/Popover.spec.tsx.snap b/packages/fuselage/src/components/Popover/__snapshots__/Popover.spec.tsx.snap
new file mode 100644
index 0000000000..b0791c73cc
--- /dev/null
+++ b/packages/fuselage/src/components/Popover/__snapshots__/Popover.spec.tsx.snap
@@ -0,0 +1,19 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[Popover Rendering] renders Default without crashing 1`] = `
+
+
+
+
+ Open Popover
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/Popover/index.ts b/packages/fuselage/src/components/Popover/index.ts
new file mode 100644
index 0000000000..8f473de4b9
--- /dev/null
+++ b/packages/fuselage/src/components/Popover/index.ts
@@ -0,0 +1 @@
+export * from './Popover';
diff --git a/packages/fuselage/src/components/Select/SelectAria.tsx b/packages/fuselage/src/components/Select/SelectAria.tsx
index 3b460ac02e..631c85b4b8 100644
--- a/packages/fuselage/src/components/Select/SelectAria.tsx
+++ b/packages/fuselage/src/components/Select/SelectAria.tsx
@@ -14,8 +14,8 @@ import { useSelectState } from 'react-stately';
import Box from '../Box/Box';
import { Icon } from '../Icon';
import { OptionContainer } from '../Options';
+import { Popover } from '../Popover';
import { ListBox } from './Listbox';
-import { Popover } from './Popover';
export { Item } from 'react-stately';
@@ -93,7 +93,13 @@ export const SelectAria = forwardRef(function SelectAria(
/>
{state.isOpen && (
-
+
= () => (
-
+
= () => (
-
+
= () => (
-
+
{
+describe('[Sidebar Component]', () => {
it('renders without crashing', () => {
render( );
});
diff --git a/packages/fuselage/src/components/Sidebar/Sidebar.styles.scss b/packages/fuselage/src/components/Sidebar/Sidebar.styles.scss
index 936c6dd178..569fa3e758 100644
--- a/packages/fuselage/src/components/Sidebar/Sidebar.styles.scss
+++ b/packages/fuselage/src/components/Sidebar/Sidebar.styles.scss
@@ -32,12 +32,6 @@ $sidebar-color-stroke-default: theme(
'sidebar-color-stroke-default',
colors.stroke(light)
);
-
-$sidebar-color-stroke-focus: theme(
- 'sidebar-color-stroke-focus',
- colors.stroke(highlight)
-);
-
$sidebar-item-color: theme('sidebar-item-color', colors.font(secondary-info));
$sidebar-item-color-highlighted: theme(
'sidebar-item-color-highlighted',
@@ -204,7 +198,6 @@ $sidebar-banner-color-danger: theme(
&-item {
@extend %sidebar-base;
@include highlighted;
- margin-inline: lengths.margin(-2);
padding-block: lengths.padding(4);
padding-inline: lengths.padding(16);
@@ -213,8 +206,6 @@ $sidebar-banner-color-danger: theme(
color: $sidebar-color-font-default;
- border: 2px solid transparent;
-
&__wrapper {
@extend %sidebar-base;
@include typography.use-with-truncated-text();
@@ -225,14 +216,15 @@ $sidebar-banner-color-danger: theme(
&--clickable {
@include clickable;
+ @include use-link-colors($color: colors.font(default));
@include on-hover {
- @include use-no-shadow;
background-color: $sidebar-color-surface-hover;
}
- @include on-focus-visible {
- border: 2px solid $sidebar-color-stroke-focus;
+ @include on-focus {
+ outline-offset: -1px;
+ box-shadow: none;
}
}
@@ -390,6 +382,8 @@ $sidebar-banner-color-danger: theme(
&--clickable {
cursor: pointer;
border-block-end: lengths.border-width(default) solid;
+
+ @include use-link-colors();
}
}
diff --git a/packages/fuselage/src/components/Sidebar/SidebarActions.tsx b/packages/fuselage/src/components/Sidebar/SidebarActions.tsx
index 026a7559e9..165a562c7e 100644
--- a/packages/fuselage/src/components/Sidebar/SidebarActions.tsx
+++ b/packages/fuselage/src/components/Sidebar/SidebarActions.tsx
@@ -6,9 +6,12 @@ import { ButtonGroup } from '../ButtonGroup';
type SidebarActionsProps = ComponentProps;
-export const SidebarActions = (props: SidebarActionsProps) => (
-
-);
+export const SidebarActions = forwardRef(function SidebarActions(
+ props: SidebarActionsProps,
+ ref: Ref
+) {
+ return ;
+});
type SidebarActionProps = ComponentProps;
diff --git a/packages/fuselage/src/components/Sidebar/TopBar.tsx b/packages/fuselage/src/components/Sidebar/TopBar.tsx
deleted file mode 100644
index 712b1ba5d6..0000000000
--- a/packages/fuselage/src/components/Sidebar/TopBar.tsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import type { ComponentProps, ReactNode, Ref } from 'react';
-import React, { forwardRef } from 'react';
-
-import Box from '../Box';
-import { SidebarAction, SidebarActions } from './SidebarActions';
-import { SidebarDivider } from './SidebarDivider';
-
-const Avatar: { size: 'x24' } = { size: 'x24' };
-
-type TopBarProps = {
- children?: ReactNode;
- className?: string;
-};
-
-const TopBar = ({ className, ...props }: TopBarProps) => (
-
-);
-
-type TopBarWrapperProps = {
- children?: ReactNode;
-};
-
-const TopBarWrapper = ({ children }: TopBarWrapperProps) => (
-
-);
-
-type TopBarToolBoxProps = {
- children?: ReactNode;
- className?: string;
-};
-
-export const TopBarToolBox = ({
- children,
- className,
- ...props
-}: TopBarToolBoxProps) => (
-
-
-
-
-);
-
-type TopBarSectionProps = {
- children?: React.ReactNode;
- className?: string;
-};
-
-export const TopBarSection = ({
- className,
- children,
- ...props
-}: TopBarSectionProps) => (
-
-
-
-
-);
-
-export const TopBarAvatar = Avatar;
-
-export const TopBarActions = SidebarActions;
-
-type TopBarActionProps = ComponentProps;
-
-export const TopBarAction = forwardRef(function TopBarAction(
- props: TopBarActionProps,
- ref: Ref
-) {
- return ;
-});
-
-type TopBarTitleProps = {
- children?: ReactNode;
-};
-
-export const TopBarTitle = (props: TopBarTitleProps) => (
-
-);
-
-export default Object.assign(TopBar, {
- Section: TopBarSection,
- ToolBox: TopBarToolBox,
- Wrapper: TopBarWrapper,
- Avatar: TopBarAvatar,
- Actions: TopBarActions,
- Action: TopBarAction,
- Divider: SidebarDivider,
- Title: TopBarTitle,
-});
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/TopBar.spec.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBar.spec.tsx
new file mode 100644
index 0000000000..7e4909209c
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBar.spec.tsx
@@ -0,0 +1,31 @@
+import { composeStories } from '@storybook/testing-react';
+import { render } from '@testing-library/react';
+import { axe } from 'jest-axe';
+import React from 'react';
+
+import * as stories from './TopBar.stories';
+
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
+
+describe('[TopBar Rendering]', () => {
+ test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render( );
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+ );
+
+ test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render( );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
+ );
+});
diff --git a/packages/fuselage/src/components/Sidebar/TopBar.stories.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBar.stories.tsx
similarity index 67%
rename from packages/fuselage/src/components/Sidebar/TopBar.stories.tsx
rename to packages/fuselage/src/components/Sidebar/TopBar/TopBar.stories.tsx
index 5dadd322dc..655d37ac34 100644
--- a/packages/fuselage/src/components/Sidebar/TopBar.stories.tsx
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBar.stories.tsx
@@ -2,10 +2,16 @@ import { Title, Description, Primary, Stories } from '@storybook/addon-docs';
import type { ComponentStory, ComponentMeta } from '@storybook/react';
import React from 'react';
-import { SidebarSection } from '.';
-import { TopBarToolBox } from '..';
+import {
+ TopBar,
+ TopBarAction,
+ TopBarActions,
+ TopBarAvatar,
+ TopBarTitle,
+ TopBarToolBox,
+} from '.';
+import { SidebarSection } from '..';
import { Avatar } from '../..';
-import TopBar from './TopBar';
export default {
title: 'Sidebar/TopBar',
@@ -31,40 +37,41 @@ export const Default: ComponentStory = () => (
<>
-
-
-
-
-
-
-
+
+
+
+
+
+
+
- Title
-
-
-
-
+ Title
+
+
+
+
-
+
Long Title Long Title Long Title Long Title Long Title Long Title Long
Title Long Title Long Title Long Title Long Title Long Title Long Title
Long Title Long Title Long Title Long Title Long Title Long Title Long
Title Long Title
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
>
);
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/TopBar.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBar.tsx
new file mode 100644
index 0000000000..1790b28c09
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBar.tsx
@@ -0,0 +1,16 @@
+import type { ReactNode } from 'react';
+import React from 'react';
+
+type TopBarProps = {
+ children?: ReactNode;
+ className?: string;
+};
+
+export const TopBar = ({ className, ...props }: TopBarProps) => (
+
+);
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/TopBarAction.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBarAction.tsx
new file mode 100644
index 0000000000..28aff50bd0
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBarAction.tsx
@@ -0,0 +1,13 @@
+import type { ComponentProps, Ref } from 'react';
+import React, { forwardRef } from 'react';
+
+import { SidebarAction } from '../SidebarActions';
+
+type TopBarActionProps = ComponentProps;
+
+export const TopBarAction = forwardRef(function TopBarAction(
+ props: TopBarActionProps,
+ ref: Ref
+) {
+ return ;
+});
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/TopBarActions.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBarActions.tsx
new file mode 100644
index 0000000000..e8db9a728b
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBarActions.tsx
@@ -0,0 +1,13 @@
+import type { ComponentProps, Ref } from 'react';
+import React, { forwardRef } from 'react';
+
+import { SidebarActions } from '../SidebarActions';
+
+type TopBarActionsProps = ComponentProps;
+
+export const TopBarActions = forwardRef(function TopBarActions(
+ props: TopBarActionsProps,
+ ref: Ref
+) {
+ return ;
+});
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/TopBarSection.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBarSection.tsx
new file mode 100644
index 0000000000..b181180da3
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBarSection.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+
+import { SidebarDivider } from '../SidebarDivider';
+import { TopBar } from './TopBar';
+import { TopBarWrapper } from './TopBarWrapper';
+
+type TopBarSectionProps = {
+ children?: React.ReactNode;
+ className?: string;
+};
+
+export const TopBarSection = ({
+ className,
+ children,
+ ...props
+}: TopBarSectionProps) => (
+
+
+
+
+);
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/TopBarTitle.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBarTitle.tsx
new file mode 100644
index 0000000000..d0ef933c91
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBarTitle.tsx
@@ -0,0 +1,12 @@
+import type { ReactNode } from 'react';
+import React from 'react';
+
+import Box from '../../Box';
+
+type TopBarTitleProps = {
+ children?: ReactNode;
+};
+
+export const TopBarTitle = (props: TopBarTitleProps) => (
+
+);
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/TopBarToolBox.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBarToolBox.tsx
new file mode 100644
index 0000000000..4283ef0b18
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBarToolBox.tsx
@@ -0,0 +1,27 @@
+import type { ReactNode } from 'react';
+import React from 'react';
+
+import { SidebarDivider } from '../SidebarDivider';
+import { TopBar } from './TopBar';
+import { TopBarWrapper } from './TopBarWrapper';
+
+type TopBarToolBoxProps = {
+ children?: ReactNode;
+ className?: string;
+};
+
+export const TopBarToolBox = ({
+ children,
+ className,
+ ...props
+}: TopBarToolBoxProps) => (
+
+
+
+
+);
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/TopBarWrapper.tsx b/packages/fuselage/src/components/Sidebar/TopBar/TopBarWrapper.tsx
new file mode 100644
index 0000000000..4886882b68
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/TopBarWrapper.tsx
@@ -0,0 +1,13 @@
+import type { ReactNode } from 'react';
+import React from 'react';
+
+type TopBarWrapperProps = {
+ children?: ReactNode;
+};
+
+export const TopBarWrapper = ({ children }: TopBarWrapperProps) => (
+
+);
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/__snapshots__/TopBar.spec.tsx.snap b/packages/fuselage/src/components/Sidebar/TopBar/__snapshots__/TopBar.spec.tsx.snap
new file mode 100644
index 0000000000..c88801cd45
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/__snapshots__/TopBar.spec.tsx.snap
@@ -0,0 +1,212 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[TopBar Rendering] renders Default without crashing 1`] = `
+
+
+
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/Sidebar/TopBar/index.ts b/packages/fuselage/src/components/Sidebar/TopBar/index.ts
new file mode 100644
index 0000000000..0f5a46d59f
--- /dev/null
+++ b/packages/fuselage/src/components/Sidebar/TopBar/index.ts
@@ -0,0 +1,39 @@
+import { SidebarDivider as TopBarDivider } from '../SidebarDivider';
+import { TopBar } from './TopBar';
+import { TopBarAction } from './TopBarAction';
+import { TopBarActions } from './TopBarActions';
+import { TopBarSection } from './TopBarSection';
+import { TopBarTitle } from './TopBarTitle';
+import { TopBarToolBox } from './TopBarToolBox';
+import { TopBarWrapper } from './TopBarWrapper';
+
+const Avatar: { size: 'x24' } = { size: 'x24' };
+
+export const TopBarAvatar = Avatar;
+
+export default Object.assign(TopBar, {
+ /** @deprecated use named import instead */
+ Section: TopBarSection,
+ /** @deprecated use named import instead */
+ ToolBox: TopBarToolBox,
+ /** @deprecated use named import instead */
+ Wrapper: TopBarWrapper,
+ /** @deprecated use named import instead */
+ Avatar: TopBarAvatar,
+ /** @deprecated use named import instead */
+ Actions: TopBarActions,
+ /** @deprecated use named import instead */
+ Action: TopBarAction,
+ /** @deprecated use named import instead */
+ Divider: TopBarDivider,
+ /** @deprecated use named import instead */
+ Title: TopBarTitle,
+});
+
+export * from './TopBar';
+export * from './TopBarAction';
+export * from './TopBarActions';
+export * from './TopBarSection';
+export * from './TopBarTitle';
+export * from './TopBarToolBox';
+export * from './TopBarWrapper';
diff --git a/packages/fuselage/src/components/Sidebar/index.tsx b/packages/fuselage/src/components/Sidebar/index.tsx
index a0638957a5..1948367f00 100644
--- a/packages/fuselage/src/components/Sidebar/index.tsx
+++ b/packages/fuselage/src/components/Sidebar/index.tsx
@@ -27,7 +27,6 @@ export * from './Section';
export { default as SidebarTopBar } from './TopBar';
export * from './TopBar';
export * from './SidebarBanner';
-
export * from './SidebarFooter';
export { SidebarDivider };
diff --git a/packages/fuselage/src/components/Tag/Tag.spec.tsx b/packages/fuselage/src/components/Tag/Tag.spec.tsx
index c5b04641f0..baa3bdd772 100644
--- a/packages/fuselage/src/components/Tag/Tag.spec.tsx
+++ b/packages/fuselage/src/components/Tag/Tag.spec.tsx
@@ -1,10 +1,31 @@
+import { composeStories } from '@storybook/testing-react';
import { render } from '@testing-library/react';
+import { axe } from 'jest-axe';
import React from 'react';
-import { Tag } from '.';
+import * as stories from './Tag.stories';
-describe('[Tag Component]', () => {
- it('renders without crashing', () => {
- render( );
- });
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
+
+describe('[Tag Rendering]', () => {
+ test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render( );
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+ );
+
+ test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render( );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
+ );
});
diff --git a/packages/fuselage/src/components/Tag/Tag.stories.tsx b/packages/fuselage/src/components/Tag/Tag.stories.tsx
index d521feba95..e3e26d257c 100644
--- a/packages/fuselage/src/components/Tag/Tag.stories.tsx
+++ b/packages/fuselage/src/components/Tag/Tag.stories.tsx
@@ -9,7 +9,7 @@ import {
import type { ComponentStory, ComponentMeta } from '@storybook/react';
import React from 'react';
-import { Tag, Box, Icon } from '../..';
+import { Tag, Box, Icon, ButtonGroup } from '../..';
export default {
title: 'Data Display/Tag',
@@ -99,3 +99,30 @@ export const AsLink = Template.bind({});
AsLink.args = {
href: '#',
};
+
+export const Variants = () => (
+
+ john.doe
+ john.doe
+ john.doe
+ john.doe
+ john.doe
+
+);
+export const VariantsAsLinks = () => (
+
+ john.doe
+
+ john.doe
+
+
+ john.doe
+
+
+ john.doe
+
+
+ john.doe
+
+
+);
diff --git a/packages/fuselage/src/components/Tag/Tag.styles.scss b/packages/fuselage/src/components/Tag/Tag.styles.scss
index 8f46aaf7d7..cb6eb10baa 100644
--- a/packages/fuselage/src/components/Tag/Tag.styles.scss
+++ b/packages/fuselage/src/components/Tag/Tag.styles.scss
@@ -1,6 +1,7 @@
@use '../../styles/colors.scss';
@use '../../styles/lengths.scss';
@use '../../styles/typography.scss';
+@use '../../styles/mixins/templates.scss';
$tag-colors-default-color: theme(
'tag-colors-default-color',
@@ -106,6 +107,16 @@ $tag-colors-disabled-background-color: theme(
colors.surface(neutral)
);
+@mixin use-clickable-colors($color, $background-color) {
+ &.rcx-tag--clickable {
+ @include use-link-colors($color);
+
+ &:hover {
+ background-color: $background-color;
+ }
+ }
+}
+
.rcx-tag {
display: flex;
overflow: hidden;
@@ -126,6 +137,15 @@ $tag-colors-disabled-background-color: theme(
background-color: $tag-colors-default-background-color;
@include typography.use-font-scale(micro);
+ @include templates.focus-state;
+
+ &--clickable {
+ @include clickable;
+ @include use-clickable-colors(
+ $tag-colors-default-color,
+ $tag-colors-default-hover-background-color
+ );
+ }
&__inner {
overflow: hidden;
@@ -140,72 +160,60 @@ $tag-colors-disabled-background-color: theme(
color: $tag-colors-primary-color;
background-color: $tag-colors-primary-background-color;
- &.rcx-tag--clickable {
- &:hover {
- color: $tag-colors-primary-color;
- background-color: $tag-colors-primary-hover-background-color;
- }
- }
+ @include use-clickable-colors(
+ $tag-colors-primary-color,
+ $tag-colors-primary-hover-background-color
+ );
}
&--secondary {
color: $tag-colors-secondary-color;
background-color: $tag-colors-secondary-background-color;
- &.rcx-tag--clickable {
- &:hover {
- color: $tag-colors-secondary-color;
- background-color: $tag-colors-secondary-hover-background-color;
- }
- }
+ @include use-clickable-colors(
+ $tag-colors-secondary-color,
+ $tag-colors-secondary-hover-background-color
+ );
}
&--danger {
color: $tag-colors-danger-color;
background-color: $tag-colors-danger-background-color;
- &.rcx-tag--clickable {
- &:hover {
- color: $tag-colors-danger-color;
- background-color: $tag-colors-danger-hover-background-color;
- }
- }
+ @include use-clickable-colors(
+ $tag-colors-danger-color,
+ $tag-colors-danger-hover-background-color
+ );
}
&--secondary-danger {
color: $tag-colors-secondary-danger-color;
background-color: $tag-colors-secondary-danger-background-color;
- &.rcx-tag--clickable {
- &:hover {
- color: $tag-colors-secondary-danger-color;
- background-color: $tag-colors-secondary-danger-hover-background-color;
- }
- }
+ @include use-clickable-colors(
+ $tag-colors-secondary-danger-color,
+ $tag-colors-secondary-danger-hover-background-color
+ );
}
&--warning {
color: $tag-colors-warning-color;
background-color: $tag-colors-warning-background-color;
- &.rcx-tag--clickable {
- &:hover {
- color: $tag-colors-warning-color;
- background-color: $tag-colors-warning-hover-background-color;
- }
- }
+ @include use-clickable-colors(
+ $tag-colors-warning-color,
+ $tag-colors-warning-hover-background-color
+ );
}
&--featured {
color: $tag-colors-featured-color;
background-color: $tag-colors-featured-background-color;
- &.rcx-tag--clickable {
- &:hover {
- color: $tag-colors-featured-color;
- background-color: $tag-colors-featured-hover-background-color;
- }
- }
+ @include use-clickable-colors(
+ $tag-colors-featured-color,
+ $tag-colors-featured-hover-background-color
+ );
}
&--disabled {
@@ -215,15 +223,6 @@ $tag-colors-disabled-background-color: theme(
background-color: $tag-colors-disabled-background-color;
}
- &--clickable {
- @include clickable();
-
- &:hover {
- color: $tag-colors-default-hover-color;
- background-color: $tag-colors-default-hover-background-color;
- }
- }
-
&--medium {
@include typography.use-font-scale(c2);
}
diff --git a/packages/fuselage/src/components/Tag/__snapshots__/Tag.spec.tsx.snap b/packages/fuselage/src/components/Tag/__snapshots__/Tag.spec.tsx.snap
new file mode 100644
index 0000000000..29e0f601e1
--- /dev/null
+++ b/packages/fuselage/src/components/Tag/__snapshots__/Tag.spec.tsx.snap
@@ -0,0 +1,387 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[Tag Rendering] renders _Danger without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders _Primary without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders _SecondaryDanger without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders AsLink without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Clickable without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Default without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Disabled without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Featured without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Large without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Medium without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Secondary without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Variants without crashing 1`] = `
+
+
+
+
+
+ john.doe
+
+
+
+
+ john.doe
+
+
+
+
+ john.doe
+
+
+
+
+ john.doe
+
+
+
+
+ john.doe
+
+
+
+
+
+`;
+
+exports[`[Tag Rendering] renders VariantsAsLinks without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders Warning without crashing 1`] = `
+
+
+
+`;
+
+exports[`[Tag Rendering] renders WithIcon without crashing 1`] = `
+
+
+
+
+
+
+
+
+ Team
+
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/ToastBar/ToastBar.spec.tsx b/packages/fuselage/src/components/ToastBar/ToastBar.spec.tsx
index 8fd9218621..eef439db16 100644
--- a/packages/fuselage/src/components/ToastBar/ToastBar.spec.tsx
+++ b/packages/fuselage/src/components/ToastBar/ToastBar.spec.tsx
@@ -1,18 +1,31 @@
+import { composeStories } from '@storybook/testing-react';
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';
import React from 'react';
-import { ToastBar } from '.';
+import * as stories from './ToastBar.stories';
-describe('[ToastBar Component]', () => {
- it('renders without crashing', () => {
- render( );
- });
+const testCases = Object.values(composeStories(stories)).map((Story) => [
+ Story.storyName || 'Story',
+ Story,
+]);
- it('should have no a11y violations', async () => {
- const { container } = render( );
+describe('[ToastBar Rendering]', () => {
+ test.each(testCases)(
+ `renders %s without crashing`,
+ async (_storyname, Story) => {
+ const tree = render( );
+ expect(tree.baseElement).toMatchSnapshot();
+ }
+ );
- const results = await axe(container);
- expect(results).toHaveNoViolations();
- });
+ test.each(testCases)(
+ '%s should have no a11y violations',
+ async (_storyname, Story) => {
+ const { container } = render( );
+
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ }
+ );
});
diff --git a/packages/fuselage/src/components/ToastBar/ToastBar.tsx b/packages/fuselage/src/components/ToastBar/ToastBar.tsx
index 5753eb12ff..8acc38371d 100644
--- a/packages/fuselage/src/components/ToastBar/ToastBar.tsx
+++ b/packages/fuselage/src/components/ToastBar/ToastBar.tsx
@@ -24,7 +24,7 @@ export function ToastBar({
time = 5,
id,
onClose,
- buttonLabel = 'Close',
+ buttonLabel = 'Dismiss alert',
...props
}: ToastBarProps) {
const iconName =
@@ -73,7 +73,6 @@ export function ToastBar({
]}
elevation='2nb'
borderRadius='x4'
- role='alert'
{...props}
>
@@ -82,16 +81,16 @@ export function ToastBar({
size='x20'
name={iconName}
/>
-
+
{children}
{onClose && (
onClose(toastId)}
icon='cross'
- aria-label={buttonLabel}
/>
)}
diff --git a/packages/fuselage/src/components/ToastBar/__snapshots__/ToastBar.spec.tsx.snap b/packages/fuselage/src/components/ToastBar/__snapshots__/ToastBar.spec.tsx.snap
new file mode 100644
index 0000000000..96a0e264e8
--- /dev/null
+++ b/packages/fuselage/src/components/ToastBar/__snapshots__/ToastBar.spec.tsx.snap
@@ -0,0 +1,175 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[ToastBar Rendering] renders Default without crashing 1`] = `
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ quis nostrud exercitation ullamco
+
+
+
+
+
+
+`;
+
+exports[`[ToastBar Rendering] renders Error without crashing 1`] = `
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ quis nostrud exercitation ullamco
+
+
+
+
+
+
+`;
+
+exports[`[ToastBar Rendering] renders Success without crashing 1`] = `
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ quis nostrud exercitation ullamco
+
+
+
+
+
+
+`;
+
+exports[`[ToastBar Rendering] renders TinyText without crashing 1`] = `
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet
+
+
+
+
+
+
+`;
+
+exports[`[ToastBar Rendering] renders WithCloseButton without crashing 1`] = `
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ quis nostrud exercitation ullamco
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/packages/fuselage/src/components/index.ts b/packages/fuselage/src/components/index.ts
index d64021f6b1..0681cbb9f5 100644
--- a/packages/fuselage/src/components/index.ts
+++ b/packages/fuselage/src/components/index.ts
@@ -44,6 +44,7 @@ export * from './Options';
export { default as Option } from './Option';
export * from './Option';
export * from './Pagination';
+export * from './PaletteStyleTag';
export { default as PasswordInput } from './PasswordInput';
export * from './StatusBullet';
export { default as Position } from './Position';
@@ -55,6 +56,7 @@ export * from './SearchInput';
export * from './Select';
export * from './Slider';
export * from './PaginatedSelect';
+export * from './Popover';
export * from './SelectInput';
export { default as Sidebar } from './Sidebar';
export * from './Sidebar';
diff --git a/packages/fuselage/src/index.scss b/packages/fuselage/src/index.scss
index a38e5ebfd7..c28ed2571e 100644
--- a/packages/fuselage/src/index.scss
+++ b/packages/fuselage/src/index.scss
@@ -3,3 +3,4 @@
@import './styles/mixins/all.scss';
@import './styles/primitives/all.scss';
@import './components/index.scss';
+@import './styles/normalize.scss';
diff --git a/packages/fuselage/src/styles/mixins/all.scss b/packages/fuselage/src/styles/mixins/all.scss
index cb3e2caeb7..400f7d05af 100644
--- a/packages/fuselage/src/styles/mixins/all.scss
+++ b/packages/fuselage/src/styles/mixins/all.scss
@@ -1,6 +1,7 @@
@import './breakpoints.scss';
-@import './interactivity.scss';
@import './elevation.scss';
+@import './interactivity.scss';
@import './shadows.scss';
-@import './states.scss';
@import './size.scss';
+@import './states.scss';
+@import './templates.scss';
diff --git a/packages/fuselage/src/styles/mixins/templates.scss b/packages/fuselage/src/styles/mixins/templates.scss
new file mode 100644
index 0000000000..ee7f8904b2
--- /dev/null
+++ b/packages/fuselage/src/styles/mixins/templates.scss
@@ -0,0 +1,18 @@
+@use '../colors.scss';
+@use '../lengths.scss';
+
+@import './shadows.scss';
+@import './states.scss';
+
+@mixin focus-state {
+ border-width: lengths.border-width('default');
+ border-style: solid;
+ border-color: transparent;
+
+ @include on-focus-visible {
+ border-color: colors.stroke(highlight);
+ border-radius: lengths.border-radius(medium);
+ outline: 0;
+ @include use-button-focus-shadow(colors.stroke(extra-light-highlight));
+ }
+}
diff --git a/packages/fuselage/src/styles/normalize.scss b/packages/fuselage/src/styles/normalize.scss
new file mode 100644
index 0000000000..2a484f2835
--- /dev/null
+++ b/packages/fuselage/src/styles/normalize.scss
@@ -0,0 +1,3 @@
+a:where(:not(.rcx-button)) {
+ @extend %link;
+}
diff --git a/packages/fuselage/src/styles/primitives/all.scss b/packages/fuselage/src/styles/primitives/all.scss
index 2bc7cc4a64..c58f6176a3 100644
--- a/packages/fuselage/src/styles/primitives/all.scss
+++ b/packages/fuselage/src/styles/primitives/all.scss
@@ -4,3 +4,4 @@
@import './input.scss';
@import './button.scss';
@import './selection-button.scss';
+@import './link.scss';
diff --git a/packages/fuselage/src/styles/primitives/link.scss b/packages/fuselage/src/styles/primitives/link.scss
new file mode 100644
index 0000000000..aa98b770f3
--- /dev/null
+++ b/packages/fuselage/src/styles/primitives/link.scss
@@ -0,0 +1,61 @@
+@use '../../styles/colors.scss';
+@use '../../styles/lengths.scss';
+@use '../../styles/mixins/states.scss';
+@use '../../styles//functions.scss';
+@import '../../styles/mixins/states.scss';
+
+%link {
+ color: functions.theme('link-color', colors.font(info));
+
+ &:focus-visible,
+ &.is-focused,
+ &.focus {
+ text-decoration: none;
+
+ color: functions.theme('link-focus-color', colors.font(info));
+ border-radius: lengths.border-radius(small);
+ outline: functions.theme(
+ 'link-focus-outline-color',
+ colors.stroke(highlight)
+ )
+ solid 1px;
+ outline-offset: 0;
+ box-shadow: 0 0 0 2px
+ functions.theme(
+ 'link-focus-outline-color',
+ colors.stroke(extra-light-highlight)
+ );
+ }
+
+ &:where(:visited),
+ &:where(.is-visited) {
+ color: functions.theme('link-visited-color', colors.font(info));
+ }
+
+ &:where(:active),
+ &:where(.active),
+ &:where(.is-active) {
+ color: functions.theme('link-active-color', colors.font(info));
+ }
+}
+
+@mixin use-link-colors($color: colors.font(info)) {
+ @extend %link;
+
+ color: functions.theme('link-color', $color);
+
+ @include on-focus {
+ color: functions.theme('link-focus-color', $color);
+ }
+
+ &:where(:visited),
+ &:where(.is-visited) {
+ color: functions.theme('link-visited-color', $color);
+ }
+
+ &:where(:active),
+ &:where(.active),
+ &:where(.is-active) {
+ color: functions.theme('link-active-color', $color);
+ }
+}
diff --git a/packages/fuselage/src/styles/primitives/traits/rich-text.scss b/packages/fuselage/src/styles/primitives/traits/rich-text.scss
index 9f4920cbc3..fed9624c3a 100644
--- a/packages/fuselage/src/styles/primitives/traits/rich-text.scss
+++ b/packages/fuselage/src/styles/primitives/traits/rich-text.scss
@@ -1,9 +1,9 @@
@use '../../colors.scss';
@use '../../lengths.scss';
@use '../../typography.scss';
+@import '../link.scss';
%--with-inline-elements {
- a,
abbr,
b,
cite,
@@ -30,24 +30,11 @@
}
a {
- &:link {
- color: colors.font(info);
- }
-
- &:visited,
- &.is-visited {
- color: colors.font(info);
- }
+ @extend %link;
- &:active,
- &.is-active {
- color: colors.font(info);
- }
+ letter-spacing: inherit;
- &:hover,
- &.is-hovered {
- text-decoration: underline;
- }
+ font: inherit;
}
strong {
diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md
index 97c0bbcfcf..7945591b2c 100644
--- a/packages/icons/CHANGELOG.md
+++ b/packages/icons/CHANGELOG.md
@@ -1,5 +1,11 @@
# Change Log
+## 0.34.0
+
+### Minor Changes
+
+- [#1323](https://github.com/RocketChat/fuselage/pull/1323) [`9ccc4e79f`](https://github.com/RocketChat/fuselage/commit/9ccc4e79f76c1ef2b182065883bd66a91860bc96) Thanks [@dougfabris](https://github.com/dougfabris)! - feat(icons): New circle-unfilled
+
## 0.33.0
### Minor Changes
diff --git a/packages/icons/glyphsMapping.json b/packages/icons/glyphsMapping.json
index 326bcc52bc..8bf1bb33b0 100644
--- a/packages/icons/glyphsMapping.json
+++ b/packages/icons/glyphsMapping.json
@@ -958,5 +958,8 @@
},
"arrow-up": {
"start": "\ue149"
+ },
+ "circle-unfilled": {
+ "start": "\ue14b"
}
}
diff --git a/packages/icons/package.json b/packages/icons/package.json
index 89c78a81ae..27fe1d8173 100644
--- a/packages/icons/package.json
+++ b/packages/icons/package.json
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/icons",
- "version": "0.33.0",
+ "version": "0.34.0",
"description": "Rocket.Chat's Icons",
"author": {
"name": "Rocket.Chat",
diff --git a/packages/icons/src/circle-unfilled.svg b/packages/icons/src/circle-unfilled.svg
new file mode 100644
index 0000000000..104ee7ad5c
--- /dev/null
+++ b/packages/icons/src/circle-unfilled.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/packages/logo/CHANGELOG.md b/packages/logo/CHANGELOG.md
index 2e27d08876..85d6f1e39a 100644
--- a/packages/logo/CHANGELOG.md
+++ b/packages/logo/CHANGELOG.md
@@ -1,5 +1,12 @@
# Change Log
+## 0.31.30
+
+### Patch Changes
+
+- Updated dependencies [[`35155404b`](https://github.com/RocketChat/fuselage/commit/35155404baeb1e44aa1e4d767f431204d3ab2b53)]:
+ - @rocket.chat/fuselage-hooks@0.33.1
+
## 0.31.29
### Patch Changes
diff --git a/packages/logo/package.json b/packages/logo/package.json
index 1be872c27d..d3b397d1d4 100644
--- a/packages/logo/package.json
+++ b/packages/logo/package.json
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/logo",
- "version": "0.31.29",
+ "version": "0.31.30",
"description": "Rocket.Chat logo package",
"keywords": [
"rocketchat",
diff --git a/packages/ui-kit/.eslintignore b/packages/ui-kit/.eslintignore
deleted file mode 100644
index e87b40057a..0000000000
--- a/packages/ui-kit/.eslintignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/node_modules
-/dist
-!/.eslintrc.js
-/webpack.config.js
diff --git a/packages/ui-kit/.eslintrc.js b/packages/ui-kit/.eslintrc.js
deleted file mode 100644
index d11c05a965..0000000000
--- a/packages/ui-kit/.eslintrc.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- extends: '@rocket.chat/eslint-config-alt/typescript',
- env: {
- jest: true,
- },
-};
diff --git a/packages/ui-kit/.gitignore b/packages/ui-kit/.gitignore
deleted file mode 100644
index b232802821..0000000000
--- a/packages/ui-kit/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/dist/*
diff --git a/packages/ui-kit/.prettierignore b/packages/ui-kit/.prettierignore
deleted file mode 100644
index 8225baa4a7..0000000000
--- a/packages/ui-kit/.prettierignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/node_modules
-/dist
diff --git a/packages/ui-kit/.prettierrc.js b/packages/ui-kit/.prettierrc.js
deleted file mode 100644
index b57f474edb..0000000000
--- a/packages/ui-kit/.prettierrc.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('@rocket.chat/prettier-config/fuselage');
diff --git a/packages/ui-kit/CHANGELOG.md b/packages/ui-kit/CHANGELOG.md
deleted file mode 100644
index 4658588cdc..0000000000
--- a/packages/ui-kit/CHANGELOG.md
+++ /dev/null
@@ -1,276 +0,0 @@
-# Change Log
-
-## 0.32.1
-
-### Patch Changes
-
-- [`a97c7f086`](https://github.com/RocketChat/fuselage/commit/a97c7f08633e6e36a39c8933b530f9acacb83af0) Thanks [@dougfabris](https://github.com/dougfabris)! - chore: resolve-workspace-deps to publish pkg versions
-
-## 0.32.0
-
-### Minor Changes
-
-- [`a04f9089d`](https://github.com/RocketChat/fuselage/commit/a04f9089d19ba32d2b2e80738d2d5f4dac0d3e0c) Thanks [@dougfabris](https://github.com/dougfabris)! - fix(ui-kit): Remove icons package dependency in ui-kit package
-
-- [`a04f9089d`](https://github.com/RocketChat/fuselage/commit/a04f9089d19ba32d2b2e80738d2d5f4dac0d3e0c) Thanks [@dougfabris](https://github.com/dougfabris)! - refactor(ui-kit): Review some types
-
-All notable changes to this project will be documented in this file.
-See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
-
-# [0.31.0](https://github.com/RocketChat/fuselage/compare/v0.30.1...v0.31.0) (2021-12-28)
-
-### Bug Fixes
-
-- **ui-kit:** Fix `SurfaceRendererPayload` ([#556](https://github.com/RocketChat/fuselage/issues/556)) ([8d76a0d](https://github.com/RocketChat/fuselage/commit/8d76a0dadab5798afba1d6ce3911aa974d33c103))
-
-### Features
-
-- Message Preview ([#587](https://github.com/RocketChat/fuselage/issues/587)) ([e69dad3](https://github.com/RocketChat/fuselage/commit/e69dad3a6619e98ff70bcd1cb68567a159187336))
-- New hooks for element size tracking ([#413](https://github.com/RocketChat/fuselage/issues/413)) ([8ca682c](https://github.com/RocketChat/fuselage/commit/8ca682c636d2e4813f7d346cb881513382be63cf))
-
-## [0.30.1](https://github.com/RocketChat/fuselage/compare/v0.30.0...v0.30.1) (2021-10-20)
-
-### Bug Fixes
-
-- **ui-kit:** Fix `SurfaceRendererPayload` ([#556](https://github.com/RocketChat/fuselage/issues/556)) ([0508689](https://github.com/RocketChat/fuselage/commit/05086895e0f2ea26c7a00856a5e0c6fcffbc4615))
-
-# [0.30.0](https://github.com/RocketChat/fuselage/compare/v0.29.0...v0.30.0) (2021-10-06)
-
-### Bug Fixes
-
-- **jest:** Adjust jest and ts-jest dependencies ([#547](https://github.com/RocketChat/fuselage/issues/547)) ([91a4fa1](https://github.com/RocketChat/fuselage/commit/91a4fa1365394001afe1bd46480bda3bafed5505))
-
-# [0.29.0](https://github.com/RocketChat/fuselage/compare/v0.28.0...v0.29.0) (2021-08-31)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.28.0](https://github.com/RocketChat/fuselage/compare/v0.27.0...v0.28.0) (2021-07-30)
-
-### Bug Fixes
-
-- **fuselage-ui-kit:** Implements missing url prop for buttons ([#488](https://github.com/RocketChat/fuselage/issues/488)) ([bb19344](https://github.com/RocketChat/fuselage/commit/bb193441804c9b20174e2586d22c4b2845a486c3))
-
-### Features
-
-- **onboarding-ui:** Administrator information form and Organization information form ([#489](https://github.com/RocketChat/fuselage/issues/489)) ([b289f68](https://github.com/RocketChat/fuselage/commit/b289f68676954b91c792d8d97680314178bf2c60))
-- styled API; monorepo grooming ([#482](https://github.com/RocketChat/fuselage/issues/482)) ([1b6b70c](https://github.com/RocketChat/fuselage/commit/1b6b70cf67ec16927b1566adc2350295a8927223))
-
-# [0.27.0](https://github.com/RocketChat/fuselage/compare/v0.26.0...v0.27.0) (2021-06-28)
-
-### Features
-
-- **ui-kit:** Attachment Surface ([#474](https://github.com/RocketChat/fuselage/issues/474)) ([63bb5ea](https://github.com/RocketChat/fuselage/commit/63bb5ea044afc768295a50e0155406df6091b840))
-- ui-kit-unified ([#392](https://github.com/RocketChat/fuselage/issues/392)) ([ce48ca9](https://github.com/RocketChat/fuselage/commit/ce48ca9d9806283bba8be5df7c29c7aa8c1e716f))
-
-# [0.26.0](https://github.com/RocketChat/fuselage/compare/v0.25.0...v0.26.0) (2021-05-28)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.25.0](https://github.com/RocketChat/fuselage/compare/v0.24.0...v0.25.0) (2021-05-19)
-
-### Features
-
-- [@rocket](https://github.com/rocket).chat/message-parser ([#443](https://github.com/RocketChat/fuselage/issues/443)) ([4722cdf](https://github.com/RocketChat/fuselage/commit/4722cdff46f5987f335d989be59649c7652bb12a))
-
-# [0.24.0](https://github.com/RocketChat/fuselage/compare/v0.23.0...v0.24.0) (2021-04-28)
-
-### Features
-
-- [@rocket](https://github.com/rocket).chat/string-helpers ([#431](https://github.com/RocketChat/fuselage/issues/431)) ([2509d6a](https://github.com/RocketChat/fuselage/commit/2509d6acdbe5ec8b216e8d4430373797c5f5dfe2))
-
-# [0.23.0](https://github.com/RocketChat/fuselage/compare/v0.22.0...v0.23.0) (2021-04-01)
-
-### Bug Fixes
-
-- **npm:** Wrong paths in "files" field of package.json ([6d3c811](https://github.com/RocketChat/fuselage/commit/6d3c811f6fd747de7f47aff145902d88476272ee))
-
-# [0.22.0](https://github.com/RocketChat/fuselage/compare/v0.21.0...v0.22.0) (2021-02-26)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.21.0](https://github.com/RocketChat/fuselage/compare/v0.20.3...v0.21.0) (2021-01-31)
-
-### Features
-
-- Built modules for design tokens ([#356](https://github.com/RocketChat/fuselage/issues/356)) ([f9c3449](https://github.com/RocketChat/fuselage/commit/f9c344953b8161a4385cab3a3dcc8b6a7210446f))
-- linear_scale element ([#365](https://github.com/RocketChat/fuselage/issues/365)) ([43a4c54](https://github.com/RocketChat/fuselage/commit/43a4c54ed10d096ef2259ddcd30c3bbd97ae866a))
-
-## [0.20.1](https://github.com/RocketChat/fuselage/compare/v0.20.0...v0.20.1) (2020-12-22)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.20.0](https://github.com/RocketChat/fuselage/compare/v0.19.0...v0.20.0) (2020-12-21)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.19.0](https://github.com/RocketChat/fuselage/compare/v0.18.0...v0.19.0) (2020-11-28)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.18.0](https://github.com/RocketChat/fuselage/compare/v0.17.3...v0.18.0) (2020-11-16)
-
-### Bug Fixes
-
-- Set a conservative output.environment on Webpack bundles ([#330](https://github.com/RocketChat/fuselage/issues/330)) ([62bf728](https://github.com/RocketChat/fuselage/commit/62bf728d3541d8d7ee72420347f2351359fb5df7))
-
-## [0.17.3](https://github.com/RocketChat/fuselage/compare/v0.17.2...v0.17.3) (2020-11-16)
-
-### Bug Fixes
-
-- Set a conservative output.environment on Webpack bundles ([#330](https://github.com/RocketChat/fuselage/issues/330)) ([85d4a3a](https://github.com/RocketChat/fuselage/commit/85d4a3a5fd6881b07e97fb690d31baef405cfa69))
-
-## [0.17.2](https://github.com/RocketChat/fuselage/compare/v0.17.1...v0.17.2) (2020-10-28)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-## [0.17.1](https://github.com/RocketChat/fuselage/compare/v0.17.0...v0.17.1) (2020-10-26)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.17.0](https://github.com/RocketChat/fuselage/compare/v0.16.0...v0.17.0) (2020-10-25)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.16.0](https://github.com/RocketChat/fuselage/compare/v0.15.1...v0.16.0) (2020-09-30)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-## [0.15.1](https://github.com/RocketChat/fuselage/compare/v0.15.0...v0.15.1) (2020-09-22)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.15.0](https://github.com/RocketChat/fuselage/compare/v0.14.1...v0.15.0) (2020-09-17)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-## [0.14.1](https://github.com/RocketChat/fuselage/compare/v0.14.0...v0.14.1) (2020-08-22)
-
-### Bug Fixes
-
-- UiKit - conditional block ([38d57ea](https://github.com/RocketChat/fuselage/commit/38d57ea9005aafc3820316beacfda43f620fa93f))
-
-# [0.14.0](https://github.com/RocketChat/fuselage/compare/v0.13.2...v0.14.0) (2020-08-18)
-
-### Features
-
-- UiKit types ([#274](https://github.com/RocketChat/fuselage/issues/274)) ([e2ea79b](https://github.com/RocketChat/fuselage/commit/e2ea79b02a0fd6492c3fad06ba57cbb88d89da2b))
-
-## [0.13.1](https://github.com/RocketChat/fuselage/compare/v0.13.0...v0.13.1) (2020-07-17)
-
-### Bug Fixes
-
-- Select mutations and ui-kit alerts ([#263](https://github.com/RocketChat/fuselage/issues/263)) ([661398d](https://github.com/RocketChat/fuselage/commit/661398dfdeaf827dadc46d24a7382d69f43f9742))
-
-# [0.13.0](https://github.com/RocketChat/fuselage/compare/v0.12.0...v0.13.0) (2020-07-14)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.12.0](https://github.com/RocketChat/fuselage/compare/v0.11.0...v0.12.0) (2020-07-14)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.11.0](https://github.com/RocketChat/fuselage/compare/v0.10.0...v0.11.0) (2020-07-11)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.10.0](https://github.com/RocketChat/fuselage/compare/v0.9.0...v0.10.0) (2020-06-20)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.9.0](https://github.com/RocketChat/fuselage/compare/v0.8.0...v0.9.0) (2020-05-21)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.8.0](https://github.com/RocketChat/fuselage/compare/v0.7.1...v0.8.0) (2020-04-22)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-## [0.7.1](https://github.com/RocketChat/fuselage/compare/v0.7.0...v0.7.1) (2020-04-01)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.7.0](https://github.com/RocketChat/fuselage/compare/v0.6.2...v0.7.0) (2020-04-01)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-## [0.6.2](https://github.com/RocketChat/fuselage/compare/v0.6.1...v0.6.2) (2020-03-31)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-## [0.6.1](https://github.com/RocketChat/fuselage/compare/v0.6.0...v0.6.1) (2020-03-24)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.6.0](https://github.com/RocketChat/fuselage/compare/v0.5.0...v0.6.0) (2020-03-20)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.5.0](https://github.com/RocketChat/fuselage/compare/v0.4.1...v0.5.0) (2020-03-20)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-## [0.4.1](https://github.com/RocketChat/fuselage/compare/v0.4.0...v0.4.1) (2020-03-16)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.4.0](https://github.com/RocketChat/fuselage/compare/v0.3.0...v0.4.0) (2020-03-10)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.3.0](https://github.com/RocketChat/fuselage/compare/v0.2.0...v0.3.0) (2020-02-17)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.30...v0.2.0) (2020-02-13)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.29](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.28...v0.2.0-alpha.29) (2020-02-10)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.28](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.27...v0.2.0-alpha.28) (2020-02-10)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.26](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.25...v0.2.0-alpha.26) (2020-02-10)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.25](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.24...v0.2.0-alpha.25) (2020-02-10)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.24](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.23...v0.2.0-alpha.24) (2020-02-09)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.23](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.22...v0.2.0-alpha.23) (2020-02-07)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.22](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.21...v0.2.0-alpha.22) (2020-02-07)
-
-### Bug Fixes
-
-- uikit using react components ([#135](https://github.com/RocketChat/fuselage/issues/135)) ([52fcedb](https://github.com/RocketChat/fuselage/commit/52fcedb0efbc33ad4240c83fd92a325fcc9f0f4c))
-
-# [0.2.0-alpha.21](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.20...v0.2.0-alpha.21) (2020-02-05)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.20](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.19...v0.2.0-alpha.20) (2020-02-01)
-
-**Note:** Version bump only for package @rocket.chat/ui-kit
-
-# [0.2.0-alpha.19](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.18...v0.2.0-alpha.19) (2020-01-13)
-
-### Features
-
-- Position, Modal, Options components ([#116](https://github.com/RocketChat/fuselage/issues/116)) ([af1916a](https://github.com/RocketChat/fuselage/commit/af1916a22c677939adda04fe417dafe406292762)), closes [#117](https://github.com/RocketChat/fuselage/issues/117)
-
-# [0.2.0-alpha.18](https://github.com/RocketChat/fuselage/compare/v0.2.0-alpha.17...v0.2.0-alpha.18) (2019-12-31)
-
-### Features
-
-- UI Kit ([#95](https://github.com/RocketChat/fuselage/issues/95)) ([6d4162b](https://github.com/RocketChat/fuselage/commit/6d4162bb8c121b1e89f8c818e7106bce49f09c27)), closes [#94](https://github.com/RocketChat/fuselage/issues/94) [#109](https://github.com/RocketChat/fuselage/issues/109) [#108](https://github.com/RocketChat/fuselage/issues/108) [#111](https://github.com/RocketChat/fuselage/issues/111)
diff --git a/packages/ui-kit/README.md b/packages/ui-kit/README.md
deleted file mode 100644
index cf02d0ed03..0000000000
--- a/packages/ui-kit/README.md
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-
-
-
-
-# `@rocket.chat/ui-kit`
-
-> Interactive UI elements for Rocket.Chat Apps
-
----
-
-[![npm@latest](https://img.shields.io/npm/v/@rocket.chat/ui-kit/latest?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/ui-kit/v/latest) [![npm@next](https://img.shields.io/npm/v/@rocket.chat/ui-kit/next?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/ui-kit/v/next) ![npm downloads](https://img.shields.io/npm/dw/@rocket.chat/ui-kit?style=flat-square) ![License: MIT](https://img.shields.io/npm/l/@rocket.chat/ui-kit?style=flat-square)
-
-![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/ui-kit?style=flat-square) ![npm bundle size](https://img.shields.io/bundlephobia/min/@rocket.chat/ui-kit?style=flat-square)
-
-
-
-## Install
-
-
-
-Add `@rocket.chat/ui-kit` as a dependency:
-
-```sh
-npm i @rocket.chat/ui-kit
-
-# or, if you are using yarn:
-
-yarn add @rocket.chat/ui-kit
-```
-
-
-
-## Contributing
-
-
-
-Contributions, issues, and feature requests are welcome!
-Feel free to check the [issues](https://github.com/RocketChat/fuselage/issues).
-
-
-
-### Building
-
-As this package dependends on others in this monorepo, before anything run the following at the root directory:
-
-
-
-```sh
-yarn build
-```
-
-
-
-### Linting
-
-To ensure the source is matching our coding style, we perform [linting](
).
-Before commiting, check if your code fits our style by running:
-
-
-
-```sh
-yarn lint
-```
-
-
-
-Some linter warnings and errors can be automatically fixed:
-
-
-
-```sh
-yarn lint-and-fix
-```
-
-
-
-### Running tests
-
-Whenever possible, add tests to describe exactly what your code do. You can run them by yourself:
-
-
-
-```sh
-yarn test
-```
-
-
diff --git a/packages/ui-kit/jest.config.js b/packages/ui-kit/jest.config.js
deleted file mode 100644
index 8583028a5a..0000000000
--- a/packages/ui-kit/jest.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- preset: 'ts-jest',
- testEnvironment: 'node',
- errorOnDeprecated: true,
- testMatch: ['/src/**/*.spec.[jt]s?(x)'],
-};
diff --git a/packages/ui-kit/package.json b/packages/ui-kit/package.json
deleted file mode 100644
index a076278850..0000000000
--- a/packages/ui-kit/package.json
+++ /dev/null
@@ -1,63 +0,0 @@
-{
- "name": "@rocket.chat/ui-kit",
- "version": "0.32.1",
- "description": "Interactive UI elements for Rocket.Chat Apps",
- "homepage": "https://rocketchat.github.io/Rocket.Chat.Fuselage/",
- "author": {
- "name": "Rocket.Chat",
- "url": "https://rocket.chat/"
- },
- "license": "MIT",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/RocketChat/fuselage.git"
- },
- "bugs": {
- "url": "https://github.com/RocketChat/fuselage/issues"
- },
- "main": "dist/cjs/index.js",
- "module": "dist/esm/index.js",
- "types": "dist/esm/index.d.ts",
- "files": [
- "/dist"
- ],
- "publishConfig": {
- "access": "public"
- },
- "scripts": {
- "build": "run-s .:build:clean .:build:esm .:build:cjs",
- ".:build:clean": "rimraf dist",
- ".:build:esm": "tsc -p tsconfig.json",
- ".:build:cjs": "tsc -p tsconfig-cjs.json",
- "lint": "lint",
- "lint-and-fix": "lint-and-fix",
- "lint-staged": "lint-staged",
- "test": "jest --runInBand",
- "docs": "typedoc",
- "bump-next": "bump-next"
- },
- "devDependencies": {
- "@babel/core": "~7.21.4",
- "@babel/eslint-parser": "~7.21.3",
- "@babel/plugin-transform-runtime": "~7.21.4",
- "@babel/preset-env": "~7.21.4",
- "@rocket.chat/eslint-config-alt": "workspace:~",
- "@rocket.chat/prettier-config": "workspace:~",
- "@types/jest": "~29.5.0",
- "babel-loader": "~9.1.2",
- "bump": "workspace:~",
- "eslint": "~8.38.0",
- "jest": "~29.5.0",
- "lint-all": "workspace:~",
- "lint-staged": "~13.2.1",
- "npm-run-all": "^4.1.5",
- "prettier": "~2.8.7",
- "rimraf": "^3.0.2",
- "ts-jest": "~29.1.0",
- "ts-loader": "~9.4.2",
- "typedoc": "~0.24.1",
- "typescript": "~5.0.4",
- "webpack": "~5.78.0",
- "webpack-cli": "~5.0.1"
- }
-}
diff --git a/packages/ui-kit/src/VisitibilityType.ts b/packages/ui-kit/src/VisitibilityType.ts
deleted file mode 100644
index 29d7d24e75..0000000000
--- a/packages/ui-kit/src/VisitibilityType.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export type VisibilityTypesInternal = 0;
-export type VisibilityTypesApps = 1;
-export type VisibilityTypes = VisibilityTypesInternal | VisibilityTypesApps;
diff --git a/packages/ui-kit/src/blocks/Actionable.ts b/packages/ui-kit/src/blocks/Actionable.ts
deleted file mode 100644
index d3ab3cadab..0000000000
--- a/packages/ui-kit/src/blocks/Actionable.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { ConfirmationDialog } from './ConfirmationDialog';
-import type { InputElementDispatchAction } from './InputElementDispatchAction';
-
-export type Actionable = Block & {
- appId: string;
- blockId: string;
- actionId: string;
- confirm?: ConfirmationDialog;
- dispatchActionConfig?: InputElementDispatchAction[];
-};
diff --git a/packages/ui-kit/src/blocks/ActionableElement.ts b/packages/ui-kit/src/blocks/ActionableElement.ts
deleted file mode 100644
index 2a641c03b4..0000000000
--- a/packages/ui-kit/src/blocks/ActionableElement.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import type { ButtonElement } from './elements/ButtonElement';
-import type { ChannelsSelectElement } from './elements/ChannelsSelectElement';
-import type { CheckboxElement } from './elements/CheckboxElement';
-import type { ConversationsSelectElement } from './elements/ConversationsSelectElement';
-import type { DatePickerElement } from './elements/DatePickerElement';
-import type { ExperimentalTabElement } from './elements/ExperimentalTabElement';
-import type { LinearScaleElement } from './elements/LinearScaleElement';
-import type { MultiChannelsSelectElement } from './elements/MultiChannelsSelectElement';
-import type { MultiConversationsSelectElement } from './elements/MultiConversationsSelectElement';
-import type { MultiStaticSelectElement } from './elements/MultiStaticSelectElement';
-import type { MultiUsersSelectElement } from './elements/MultiUsersSelectElement';
-import type { OverflowElement } from './elements/OverflowElement';
-import type { PlainTextInputElement } from './elements/PlainTextInputElement';
-import type { RadioButtonElement } from './elements/RadioButtonElement';
-import type { StaticSelectElement } from './elements/StaticSelectElement';
-import type { TimePickerElement } from './elements/TimePickerElement';
-import type { ToggleSwitchElement } from './elements/ToggleSwitchElement';
-import type { UsersSelectElement } from './elements/UsersSelectElement';
-
-export type ActionableElement =
- | ButtonElement
- | ChannelsSelectElement
- | ConversationsSelectElement
- | DatePickerElement
- | LinearScaleElement
- | MultiChannelsSelectElement
- | MultiConversationsSelectElement
- | MultiStaticSelectElement
- | MultiUsersSelectElement
- | OverflowElement
- | PlainTextInputElement
- | StaticSelectElement
- | UsersSelectElement
- | ToggleSwitchElement
- | RadioButtonElement
- | CheckboxElement
- | TimePickerElement
- | ExperimentalTabElement;
diff --git a/packages/ui-kit/src/blocks/Block.ts b/packages/ui-kit/src/blocks/Block.ts
deleted file mode 100644
index c945206088..0000000000
--- a/packages/ui-kit/src/blocks/Block.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { BlockElement } from './BlockElement';
-import type { LayoutBlock } from './LayoutBlock';
-import type { TextObject } from './TextObject';
-
-export type Block = TextObject | BlockElement | LayoutBlock;
diff --git a/packages/ui-kit/src/blocks/BlockElement.ts b/packages/ui-kit/src/blocks/BlockElement.ts
deleted file mode 100644
index dbceee41f7..0000000000
--- a/packages/ui-kit/src/blocks/BlockElement.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { ButtonElement } from './elements/ButtonElement';
-import type { ChannelsSelectElement } from './elements/ChannelsSelectElement';
-import type { CheckboxElement } from './elements/CheckboxElement';
-import type { ConversationsSelectElement } from './elements/ConversationsSelectElement';
-import type { DatePickerElement } from './elements/DatePickerElement';
-import type { ExperimentalTabElement } from './elements/ExperimentalTabElement';
-import type { ImageElement } from './elements/ImageElement';
-import type { LinearScaleElement } from './elements/LinearScaleElement';
-import type { MultiChannelsSelectElement } from './elements/MultiChannelsSelectElement';
-import type { MultiConversationsSelectElement } from './elements/MultiConversationsSelectElement';
-import type { MultiStaticSelectElement } from './elements/MultiStaticSelectElement';
-import type { MultiUsersSelectElement } from './elements/MultiUsersSelectElement';
-import type { OverflowElement } from './elements/OverflowElement';
-import type { PlainTextInputElement } from './elements/PlainTextInputElement';
-import type { RadioButtonElement } from './elements/RadioButtonElement';
-import type { StaticSelectElement } from './elements/StaticSelectElement';
-import type { TimePickerElement } from './elements/TimePickerElement';
-import type { ToggleSwitchElement } from './elements/ToggleSwitchElement';
-import type { UsersSelectElement } from './elements/UsersSelectElement';
-
-export type BlockElement =
- | ButtonElement
- | ChannelsSelectElement
- | ConversationsSelectElement
- | DatePickerElement
- | ImageElement
- | LinearScaleElement
- | MultiChannelsSelectElement
- | MultiConversationsSelectElement
- | MultiStaticSelectElement
- | MultiUsersSelectElement
- | OverflowElement
- | PlainTextInputElement
- | StaticSelectElement
- | UsersSelectElement
- | ToggleSwitchElement
- | RadioButtonElement
- | CheckboxElement
- | TimePickerElement
- | ExperimentalTabElement;
diff --git a/packages/ui-kit/src/blocks/BlockElementType.ts b/packages/ui-kit/src/blocks/BlockElementType.ts
deleted file mode 100644
index 73b7ef59cd..0000000000
--- a/packages/ui-kit/src/blocks/BlockElementType.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import type { BlockElement } from './BlockElement';
-
-export enum BlockElementType {
- BUTTON = 'button',
- IMAGE = 'image',
- OVERFLOW = 'overflow',
- /** @deprecated */
- OVERFLOW_MENU = 'overflow',
- PLAIN_TEXT_INPUT = 'plain_text_input',
- STATIC_SELECT = 'static_select',
- MULTI_STATIC_SELECT = 'multi_static_select',
- /** @deprecated */
- CONVERSATION_SELECT = 'conversations_select',
- /** @deprecated */
- CHANNEL_SELECT = 'channels_select',
- /** @deprecated */
- USER_SELECT = 'users_select',
- CONVERSATIONS_SELECT = 'conversations_select',
- CHANNELS_SELECT = 'channels_select',
- USERS_SELECT = 'users_select',
- DATEPICKER = 'datepicker',
- LINEAR_SCALE = 'linear_scale',
- MULTI_CHANNELS_SELECT = 'multi_channels_select',
- MULTI_CONVERSATIONS_SELECT = 'multi_conversations_select',
- MULTI_USERS_SELECT = 'multi_users_select',
- TOGGLE_SWITCH = 'toggle_switch',
- RADIO_BUTTON = 'radio_button',
- CHECKBOX = 'checkbox',
- TIME_PICKER = 'time_picker',
- TAB = 'tab',
-}
-
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-type AssertEnumKeysFromBlockUnionTypes = {
- [B in BlockElement as Uppercase<
- B['type']
- >]: (typeof BlockElementType)[Uppercase];
-};
diff --git a/packages/ui-kit/src/blocks/ButtonStyle.ts b/packages/ui-kit/src/blocks/ButtonStyle.ts
deleted file mode 100644
index f257432c06..0000000000
--- a/packages/ui-kit/src/blocks/ButtonStyle.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @deprecated */
-export enum ButtonStyle {
- PRIMARY = 'primary',
- DANGER = 'danger',
-}
diff --git a/packages/ui-kit/src/blocks/ConfirmationDialog.ts b/packages/ui-kit/src/blocks/ConfirmationDialog.ts
deleted file mode 100644
index ab6daa3098..0000000000
--- a/packages/ui-kit/src/blocks/ConfirmationDialog.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { TextObject } from './TextObject';
-import type { PlainText } from './text/PlainText';
-
-export type ConfirmationDialog = {
- title: PlainText;
- text: TextObject;
- confirm: PlainText;
- deny: PlainText;
- style: 'primary' | 'danger';
-};
diff --git a/packages/ui-kit/src/blocks/ElementType.ts b/packages/ui-kit/src/blocks/ElementType.ts
deleted file mode 100644
index 614ab9d0fc..0000000000
--- a/packages/ui-kit/src/blocks/ElementType.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/** @deprecated */
-export enum ElementType {
- PLAIN_TEXT = 'plain_text',
- MARKDOWN = 'mrkdwn',
- DIVIDER = 'divider',
- SECTION = 'section',
- INPUT = 'input',
- CONDITIONAL = 'conditional',
- IMAGE = 'image',
- ACTIONS = 'actions',
- CONTEXT = 'context',
- BUTTON = 'button',
- OVERFLOW = 'overflow',
- PLAIN_TEXT_INPUT = 'plain_text_input',
- CONVERSATION_SELECT = 'conversations_select',
- CHANNEL_SELECT = 'channels_select',
- USER_SELECT = 'users_select',
- STATIC_SELECT = 'static_select',
- MULTI_STATIC_SELECT = 'multi_static_select',
- DATEPICKER = 'datepicker',
- LINEAR_SCALE = 'linear_scale',
- TAB = 'tab',
-}
diff --git a/packages/ui-kit/src/blocks/InputElement.ts b/packages/ui-kit/src/blocks/InputElement.ts
deleted file mode 100644
index 509f5e5100..0000000000
--- a/packages/ui-kit/src/blocks/InputElement.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { SelectElement } from './SelectElement';
-import type { DatePickerElement } from './elements/DatePickerElement';
-import type { PlainTextInputElement } from './elements/PlainTextInputElement';
-
-export type InputElement =
- | DatePickerElement
- | SelectElement
- | PlainTextInputElement;
diff --git a/packages/ui-kit/src/blocks/InputElementDispatchAction.ts b/packages/ui-kit/src/blocks/InputElementDispatchAction.ts
deleted file mode 100644
index 77c230410c..0000000000
--- a/packages/ui-kit/src/blocks/InputElementDispatchAction.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export type InputElementDispatchAction =
- | 'on_character_entered'
- | 'on_item_selected';
diff --git a/packages/ui-kit/src/blocks/LayoutBlock.ts b/packages/ui-kit/src/blocks/LayoutBlock.ts
deleted file mode 100644
index b7a76b4b16..0000000000
--- a/packages/ui-kit/src/blocks/LayoutBlock.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import type { ActionsBlock } from './layout/ActionsBlock';
-import type { CalloutBlock } from './layout/CalloutBlock';
-import type { ConditionalBlock } from './layout/ConditionalBlock';
-import type { ContextBlock } from './layout/ContextBlock';
-import type { DividerBlock } from './layout/DividerBlock';
-import type { ExperimentalTabNavigationBlock } from './layout/ExperimentalTabNavigationBlock';
-import type { ImageBlock } from './layout/ImageBlock';
-import type { InputBlock } from './layout/InputBlock';
-import type { PreviewBlock } from './layout/PreviewBlock';
-import type { SectionBlock } from './layout/SectionBlock';
-import type { VideoConferenceBlock } from './layout/VideoConferenceBlock';
-
-export type LayoutBlock =
- | PreviewBlock
- | ActionsBlock
- | ConditionalBlock
- | ContextBlock
- | DividerBlock
- | ImageBlock
- | InputBlock
- | SectionBlock
- | VideoConferenceBlock
- | CalloutBlock
- | ExperimentalTabNavigationBlock;
diff --git a/packages/ui-kit/src/blocks/LayoutBlockType.ts b/packages/ui-kit/src/blocks/LayoutBlockType.ts
deleted file mode 100644
index 4dfb96c658..0000000000
--- a/packages/ui-kit/src/blocks/LayoutBlockType.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { LayoutBlock } from './LayoutBlock';
-
-export enum LayoutBlockType {
- SECTION = 'section',
- DIVIDER = 'divider',
- IMAGE = 'image',
- ACTIONS = 'actions',
- CONTEXT = 'context',
- INPUT = 'input',
- CONDITIONAL = 'conditional',
- PREVIEW = 'preview',
- VIDEO_CONF = 'video_conf',
- CALLOUT = 'callout',
- TAB_NAVIGATION = 'tab_navigation',
-}
-
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-type AssertEnumKeysFromBlockUnionTypes = {
- [B in LayoutBlock as Uppercase<
- B['type']
- >]: (typeof LayoutBlockType)[Uppercase];
-};
diff --git a/packages/ui-kit/src/blocks/LayoutBlockish.ts b/packages/ui-kit/src/blocks/LayoutBlockish.ts
deleted file mode 100644
index 20ca169876..0000000000
--- a/packages/ui-kit/src/blocks/LayoutBlockish.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export type LayoutBlockish = Block & {
- appId?: string;
- blockId?: string;
-};
diff --git a/packages/ui-kit/src/blocks/Option.ts b/packages/ui-kit/src/blocks/Option.ts
deleted file mode 100644
index 6831dffc5d..0000000000
--- a/packages/ui-kit/src/blocks/Option.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { TextObject } from './TextObject';
-import type { PlainText } from './text/PlainText';
-
-export type Option = {
- text: TextObject;
- value: string;
- description?: PlainText;
- url?: string;
-};
diff --git a/packages/ui-kit/src/blocks/OptionGroup.ts b/packages/ui-kit/src/blocks/OptionGroup.ts
deleted file mode 100644
index 7a156d0c80..0000000000
--- a/packages/ui-kit/src/blocks/OptionGroup.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { Option } from './Option';
-import type { PlainText } from './text/PlainText';
-
-export type OptionGroup = {
- label: PlainText;
- options: Option[];
-};
diff --git a/packages/ui-kit/src/blocks/RenderableBlock.ts b/packages/ui-kit/src/blocks/RenderableBlock.ts
deleted file mode 100644
index 934a475cfe..0000000000
--- a/packages/ui-kit/src/blocks/RenderableBlock.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import type { Block } from './Block';
-import type { ConditionalBlock } from './layout/ConditionalBlock';
-
-export type RenderableBlock = Exclude;
diff --git a/packages/ui-kit/src/blocks/RenderableLayoutBlock.ts b/packages/ui-kit/src/blocks/RenderableLayoutBlock.ts
deleted file mode 100644
index 6402b87602..0000000000
--- a/packages/ui-kit/src/blocks/RenderableLayoutBlock.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import type { LayoutBlock } from './LayoutBlock';
-import type { ConditionalBlock } from './layout/ConditionalBlock';
-
-export type RenderableLayoutBlock = Exclude;
diff --git a/packages/ui-kit/src/blocks/SelectElement.ts b/packages/ui-kit/src/blocks/SelectElement.ts
deleted file mode 100644
index a288e4ab93..0000000000
--- a/packages/ui-kit/src/blocks/SelectElement.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { ChannelsSelectElement } from './elements/ChannelsSelectElement';
-import type { ConversationsSelectElement } from './elements/ConversationsSelectElement';
-import type { MultiChannelsSelectElement } from './elements/MultiChannelsSelectElement';
-import type { MultiConversationsSelectElement } from './elements/MultiConversationsSelectElement';
-import type { MultiStaticSelectElement } from './elements/MultiStaticSelectElement';
-import type { MultiUsersSelectElement } from './elements/MultiUsersSelectElement';
-import type { StaticSelectElement } from './elements/StaticSelectElement';
-import type { UsersSelectElement } from './elements/UsersSelectElement';
-
-export type SelectElement =
- | ChannelsSelectElement
- | ConversationsSelectElement
- | MultiChannelsSelectElement
- | MultiConversationsSelectElement
- | MultiStaticSelectElement
- | MultiUsersSelectElement
- | StaticSelectElement
- | UsersSelectElement;
diff --git a/packages/ui-kit/src/blocks/TextObject.ts b/packages/ui-kit/src/blocks/TextObject.ts
deleted file mode 100644
index e825851c61..0000000000
--- a/packages/ui-kit/src/blocks/TextObject.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import type { Markdown } from './text/Markdown';
-import type { PlainText } from './text/PlainText';
-
-export type TextObject = PlainText | Markdown;
diff --git a/packages/ui-kit/src/blocks/TextObjectType.ts b/packages/ui-kit/src/blocks/TextObjectType.ts
deleted file mode 100644
index 5ff491846c..0000000000
--- a/packages/ui-kit/src/blocks/TextObjectType.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { TextObject } from './TextObject';
-
-export enum TextObjectType {
- /** @deprecated */
- PLAINTEXT = 'plain_text',
- PLAIN_TEXT = 'plain_text',
- /** @deprecated */
- MARKDOWN = 'mrkdwn',
- MRKDWN = 'mrkdwn',
-}
-
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-type AssertEnumKeysFromBlockUnionTypes = {
- [B in TextObject as Uppercase]: (typeof TextObjectType)[Uppercase<
- B['type']
- >];
-};
diff --git a/packages/ui-kit/src/blocks/WithTranslations.ts b/packages/ui-kit/src/blocks/WithTranslations.ts
deleted file mode 100644
index cc5f34ef70..0000000000
--- a/packages/ui-kit/src/blocks/WithTranslations.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export type WithTranslations = T & {
- i18n?: {
- key: string;
- args?: { [key: string]: string | number };
- };
-};
diff --git a/packages/ui-kit/src/blocks/deprecations.ts b/packages/ui-kit/src/blocks/deprecations.ts
deleted file mode 100644
index cd60552068..0000000000
--- a/packages/ui-kit/src/blocks/deprecations.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-/* eslint-disable @typescript-eslint/no-empty-interface */
-import type { LayoutBlock } from '..';
-import type { Actionable } from './Actionable';
-import type { Block } from './Block';
-import type { Option } from './Option';
-import type { TextObject } from './TextObject';
-import type { ButtonElement } from './elements/ButtonElement';
-import type { DatePickerElement } from './elements/DatePickerElement';
-import type { ImageElement } from './elements/ImageElement';
-import type { LinearScaleElement } from './elements/LinearScaleElement';
-import type { MultiStaticSelectElement } from './elements/MultiStaticSelectElement';
-import type { OverflowElement } from './elements/OverflowElement';
-import type { PlainTextInputElement } from './elements/PlainTextInputElement';
-import type { StaticSelectElement } from './elements/StaticSelectElement';
-import type { ActionsBlock } from './layout/ActionsBlock';
-import type { ConditionalBlock } from './layout/ConditionalBlock';
-import type { ContextBlock } from './layout/ContextBlock';
-import type { DividerBlock } from './layout/DividerBlock';
-import type { ImageBlock } from './layout/ImageBlock';
-import type { InputBlock } from './layout/InputBlock';
-import type { SectionBlock } from './layout/SectionBlock';
-import type { Markdown } from './text/Markdown';
-import type { PlainText } from './text/PlainText';
-
-type InterfaceOf = Pick;
-
-/** @deprecated */
-export type ILinearScaleElement = InterfaceOf;
-/** @deprecated */
-export type IPlainTextInput = InterfaceOf;
-/** @deprecated */
-export type IStaticSelectElement = InterfaceOf;
-/** @deprecated */
-export type IMultiStaticSelectElement = InterfaceOf;
-/** @deprecated */
-export type IDatePickerElement = InterfaceOf;
-/** @deprecated */
-export type IButtonElement = InterfaceOf;
-/** @deprecated */
-export type IOverflowElement = InterfaceOf;
-/** @deprecated */
-export type IImageElement = InterfaceOf;
-/** @deprecated */
-export type IActionableElement = InterfaceOf>>;
-
-/** @deprecated */
-export type IActionsBlock = InterfaceOf;
-/** @deprecated */
-export type ActionElement = InterfaceOf;
-/** @deprecated */
-export type ISectionBlock = InterfaceOf;
-/** @deprecated */
-export type SectionAccessoryElement = InterfaceOf<
- Exclude
->;
-/** @deprecated */
-export type AccessoryElements = InterfaceOf<
- Exclude
->;
-/** @deprecated */
-export type IImageBlock = InterfaceOf;
-/** @deprecated */
-export type IDividerBlock = InterfaceOf;
-/** @deprecated */
-export type IInputBlock = InterfaceOf;
-/** @deprecated */
-export type InputElement = InterfaceOf;
-/** @deprecated */
-export type IContextBlock = InterfaceOf;
-/** @deprecated */
-export type ContextElement = InterfaceOf;
-/** @deprecated */
-export type IConditionalBlock = InterfaceOf;
-/** @deprecated */
-export type ConditionalBlockFilters = InterfaceOf<
- Exclude
->;
-/** @deprecated */
-export type IConditionalBlockFilters = InterfaceOf;
-/** @deprecated */
-export type IBlock = InterfaceOf;
-
-/** @deprecated */
-export type IPlainText = InterfaceOf;
-/** @deprecated */
-export type IMarkdown = InterfaceOf;
-
-/** @deprecated */
-export type IElement = InterfaceOf;
-
-/** @deprecated */
-export type ITextObject = InterfaceOf;
-
-/** @deprecated */
-export type IOptionObject = InterfaceOf>;
-
-/** @deprecated */
-export type IBlockElement = Pick;
-
-/** @deprecated */
-export type IInteractiveElement = InterfaceOf<
- IBlockElement & {
- actionId: string;
- }
->;
-
-/** @deprecated */
-export type IInputElement = InterfaceOf<
- IBlockElement & {
- actionId: string;
- placeholder: ITextObject;
- initialValue?: string | string[];
- }
->;
-
-export type IOverflowMenuElement = InterfaceOf<
- IInteractiveElement & {
- type: OverflowElement['type'];
- options: IOptionObject[];
- }
->;
-
-export type IPlainTextInputElement = InterfaceOf<
- IInputElement & PlainTextInputElement
->;
-
-export type ISelectElement = InterfaceOf<
- IInputElement & {
- type: StaticSelectElement['type'] | MultiStaticSelectElement['type'];
- }
->;
-
-export {
- /** @deprecated */
- ButtonStyle,
-} from './ButtonStyle';
-export {
- /** @deprecated */
- ConditionalBlockFiltersEngine,
-} from '../rendering/ConditionalBlockFiltersEngine';
-export {
- /** @deprecated */
- LayoutBlockType as BlockType,
-} from './LayoutBlockType';
-
-export {
- ElementType,
- /** @deprecated */
- ElementType as ELEMENT_TYPES,
-} from './ElementType';
-
-export {
- /** @deprecated */
- BlockContext as BLOCK_CONTEXT,
-} from '../rendering/BlockContext';
diff --git a/packages/ui-kit/src/blocks/elements/ButtonElement.ts b/packages/ui-kit/src/blocks/elements/ButtonElement.ts
deleted file mode 100644
index 834479ecec..0000000000
--- a/packages/ui-kit/src/blocks/elements/ButtonElement.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { PlainText } from '../text/PlainText';
-
-export type ButtonElement = Actionable<{
- type: 'button';
- text: PlainText;
- url?: string;
- value?: string;
- style?: 'primary' | 'secondary' | 'danger' | 'warning' | 'success';
- secondary?: boolean;
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/ChannelsSelectElement.ts b/packages/ui-kit/src/blocks/elements/ChannelsSelectElement.ts
deleted file mode 100644
index f83e3b1d8c..0000000000
--- a/packages/ui-kit/src/blocks/elements/ChannelsSelectElement.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { Actionable } from '../Actionable';
-
-/** @todo */
-export type ChannelsSelectElement = Actionable<{
- type: 'channels_select';
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/CheckboxElement.ts b/packages/ui-kit/src/blocks/elements/CheckboxElement.ts
deleted file mode 100644
index 2411e37c17..0000000000
--- a/packages/ui-kit/src/blocks/elements/CheckboxElement.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { Option } from '../Option';
-
-export type CheckboxElement = Actionable<{
- type: 'checkbox';
- options: Option[];
- initialOptions?: Option[];
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/ConversationsSelectElement.ts b/packages/ui-kit/src/blocks/elements/ConversationsSelectElement.ts
deleted file mode 100644
index 558107e7b0..0000000000
--- a/packages/ui-kit/src/blocks/elements/ConversationsSelectElement.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { Actionable } from '../Actionable';
-
-/** @todo */
-export type ConversationsSelectElement = Actionable<{
- type: 'conversations_select';
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/DatePickerElement.ts b/packages/ui-kit/src/blocks/elements/DatePickerElement.ts
deleted file mode 100644
index 2394ce4015..0000000000
--- a/packages/ui-kit/src/blocks/elements/DatePickerElement.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { TextObject } from '../TextObject';
-
-export type DatePickerElement = Actionable<{
- type: 'datepicker';
- placeholder?: TextObject;
- initialDate?: string;
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/ExperimentalTabElement.ts b/packages/ui-kit/src/blocks/elements/ExperimentalTabElement.ts
deleted file mode 100644
index be4fc4f5ac..0000000000
--- a/packages/ui-kit/src/blocks/elements/ExperimentalTabElement.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { TextObject } from '../TextObject';
-
-export type ExperimentalTabElement = Actionable<{
- type: 'tab';
- title: TextObject;
- disabled?: boolean;
- selected?: boolean;
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/ImageElement.ts b/packages/ui-kit/src/blocks/elements/ImageElement.ts
deleted file mode 100644
index 61a6699f10..0000000000
--- a/packages/ui-kit/src/blocks/elements/ImageElement.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export type ImageElement = {
- type: 'image';
- imageUrl: string;
- altText: string;
-};
diff --git a/packages/ui-kit/src/blocks/elements/LinearScaleElement.ts b/packages/ui-kit/src/blocks/elements/LinearScaleElement.ts
deleted file mode 100644
index 38ff88c0ae..0000000000
--- a/packages/ui-kit/src/blocks/elements/LinearScaleElement.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { PlainText } from '../text/PlainText';
-
-export type LinearScaleElement = Actionable<{
- type: 'linear_scale';
- minValue?: number;
- maxValue?: number;
- initialValue?: number;
- preLabel?: PlainText;
- postLabel?: PlainText;
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/MultiChannelsSelectElement.ts b/packages/ui-kit/src/blocks/elements/MultiChannelsSelectElement.ts
deleted file mode 100644
index 546ba96549..0000000000
--- a/packages/ui-kit/src/blocks/elements/MultiChannelsSelectElement.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { Actionable } from '../Actionable';
-
-/** @todo */
-export type MultiChannelsSelectElement = Actionable<{
- type: 'multi_channels_select';
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/MultiConversationsSelectElement.ts b/packages/ui-kit/src/blocks/elements/MultiConversationsSelectElement.ts
deleted file mode 100644
index 8584ea2ad8..0000000000
--- a/packages/ui-kit/src/blocks/elements/MultiConversationsSelectElement.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { Actionable } from '../Actionable';
-
-/** @todo */
-export type MultiConversationsSelectElement = Actionable<{
- type: 'multi_conversations_select';
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/MultiStaticSelectElement.ts b/packages/ui-kit/src/blocks/elements/MultiStaticSelectElement.ts
deleted file mode 100644
index 4a5e1e4be9..0000000000
--- a/packages/ui-kit/src/blocks/elements/MultiStaticSelectElement.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { Option } from '../Option';
-import type { OptionGroup } from '../OptionGroup';
-import type { TextObject } from '../TextObject';
-
-export type MultiStaticSelectElement = Actionable<{
- type: 'multi_static_select';
- placeholder: TextObject;
- options: readonly Option[];
- optionGroups?: readonly OptionGroup[];
- maxSelectItems?: number;
- initialValue?: Option['value'][];
- initialOption?: Option[];
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/MultiUsersSelectElement.ts b/packages/ui-kit/src/blocks/elements/MultiUsersSelectElement.ts
deleted file mode 100644
index 93ffcc7bea..0000000000
--- a/packages/ui-kit/src/blocks/elements/MultiUsersSelectElement.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { Actionable } from '../Actionable';
-
-/** @todo */
-export type MultiUsersSelectElement = Actionable<{
- type: 'multi_users_select';
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/OverflowElement.ts b/packages/ui-kit/src/blocks/elements/OverflowElement.ts
deleted file mode 100644
index 0f41cb9e72..0000000000
--- a/packages/ui-kit/src/blocks/elements/OverflowElement.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { Option } from '../Option';
-
-export type OverflowElement = Actionable<{
- type: 'overflow';
- options: readonly Option[];
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/PlainTextInputElement.ts b/packages/ui-kit/src/blocks/elements/PlainTextInputElement.ts
deleted file mode 100644
index c7e0e8e252..0000000000
--- a/packages/ui-kit/src/blocks/elements/PlainTextInputElement.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { PlainText } from '../text/PlainText';
-
-export type PlainTextInputElement = Actionable<{
- type: 'plain_text_input';
- placeholder?: PlainText;
- initialValue?: string;
- multiline?: boolean;
- minLength?: number;
- maxLength?: number;
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/RadioButtonElement.ts b/packages/ui-kit/src/blocks/elements/RadioButtonElement.ts
deleted file mode 100644
index 5c87ad86e6..0000000000
--- a/packages/ui-kit/src/blocks/elements/RadioButtonElement.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { Option } from '../Option';
-
-export type RadioButtonElement = Actionable<{
- type: 'radio_button';
- options: Option[];
- initialOption?: Option;
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/StaticSelectElement.ts b/packages/ui-kit/src/blocks/elements/StaticSelectElement.ts
deleted file mode 100644
index aa0b84d753..0000000000
--- a/packages/ui-kit/src/blocks/elements/StaticSelectElement.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { Option } from '../Option';
-import type { OptionGroup } from '../OptionGroup';
-import type { TextObject } from '../TextObject';
-
-export type StaticSelectElement = Actionable<{
- type: 'static_select';
- placeholder: TextObject;
- options: readonly Option[];
- optionGroups?: readonly OptionGroup[];
- initialOption?: Option;
- initialValue?: Option['value'];
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/TimePickerElement.ts b/packages/ui-kit/src/blocks/elements/TimePickerElement.ts
deleted file mode 100644
index fa23f8ff48..0000000000
--- a/packages/ui-kit/src/blocks/elements/TimePickerElement.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { TextObject } from '../TextObject';
-
-export type TimePickerElement = Actionable<{
- type: 'time_picker';
- placeholder?: TextObject;
- initialTime?: string;
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/ToggleSwitchElement.ts b/packages/ui-kit/src/blocks/elements/ToggleSwitchElement.ts
deleted file mode 100644
index 8b7e245d5b..0000000000
--- a/packages/ui-kit/src/blocks/elements/ToggleSwitchElement.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { Actionable } from '../Actionable';
-import type { Option } from '../Option';
-
-export type ToggleSwitchElement = Actionable<{
- type: 'toggle_switch';
- options: Option[];
- initialOptions?: Option[];
-}>;
diff --git a/packages/ui-kit/src/blocks/elements/UsersSelectElement.ts b/packages/ui-kit/src/blocks/elements/UsersSelectElement.ts
deleted file mode 100644
index 53b5167007..0000000000
--- a/packages/ui-kit/src/blocks/elements/UsersSelectElement.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { Actionable } from '../Actionable';
-
-/** @todo */
-export type UsersSelectElement = Actionable<{
- type: 'users_select';
-}>;
diff --git a/packages/ui-kit/src/blocks/isActionsBlockElement.ts b/packages/ui-kit/src/blocks/isActionsBlockElement.ts
deleted file mode 100644
index d57f9da5eb..0000000000
--- a/packages/ui-kit/src/blocks/isActionsBlockElement.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import type { BlockElement } from './BlockElement';
-import { BlockElementType } from './BlockElementType';
-import type { ActionsBlock } from './layout/ActionsBlock';
-
-export const isActionsBlockElement = (
- block: BlockElement
-): block is ActionsBlock['elements'][number] => {
- switch (block.type as ActionsBlock['elements'][number]['type']) {
- case BlockElementType.BUTTON:
- case BlockElementType.DATEPICKER:
- case BlockElementType.LINEAR_SCALE:
- case BlockElementType.MULTI_STATIC_SELECT:
- case BlockElementType.OVERFLOW:
- case BlockElementType.STATIC_SELECT:
- case BlockElementType.TOGGLE_SWITCH:
- case BlockElementType.CHECKBOX:
- case BlockElementType.RADIO_BUTTON:
- case BlockElementType.TIME_PICKER:
- return true;
-
- default:
- return false;
- }
-};
diff --git a/packages/ui-kit/src/blocks/isContextBlockElement.ts b/packages/ui-kit/src/blocks/isContextBlockElement.ts
deleted file mode 100644
index b0e21d9053..0000000000
--- a/packages/ui-kit/src/blocks/isContextBlockElement.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import type { BlockElement } from './BlockElement';
-import { BlockElementType } from './BlockElementType';
-import type { TextObject } from './TextObject';
-import { TextObjectType } from './TextObjectType';
-import type { ContextBlock } from './layout/ContextBlock';
-
-export const isContextBlockElement = (
- block: TextObject | BlockElement
-): block is ContextBlock['elements'][number] => {
- switch (block.type as ContextBlock['elements'][number]['type']) {
- case BlockElementType.IMAGE:
- case TextObjectType.PLAIN_TEXT:
- case TextObjectType.MARKDOWN:
- return true;
-
- default:
- return false;
- }
-};
diff --git a/packages/ui-kit/src/blocks/isInputBlockElement.ts b/packages/ui-kit/src/blocks/isInputBlockElement.ts
deleted file mode 100644
index 2bcce5bc6d..0000000000
--- a/packages/ui-kit/src/blocks/isInputBlockElement.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { BlockElement } from './BlockElement';
-import { BlockElementType } from './BlockElementType';
-import type { InputBlock } from './layout/InputBlock';
-
-export const isInputBlockElement = (
- block: BlockElement
-): block is InputBlock['element'] => {
- switch (block.type as InputBlock['element']['type']) {
- case BlockElementType.CHANNELS_SELECT:
- case BlockElementType.CONVERSATIONS_SELECT:
- case BlockElementType.DATEPICKER:
- case BlockElementType.LINEAR_SCALE:
- case BlockElementType.MULTI_STATIC_SELECT:
- case BlockElementType.PLAIN_TEXT_INPUT:
- case BlockElementType.STATIC_SELECT:
- case BlockElementType.USERS_SELECT:
- return true;
-
- default:
- return false;
- }
-};
diff --git a/packages/ui-kit/src/blocks/isSectionBlockAccessoryElement.ts b/packages/ui-kit/src/blocks/isSectionBlockAccessoryElement.ts
deleted file mode 100644
index c15929f838..0000000000
--- a/packages/ui-kit/src/blocks/isSectionBlockAccessoryElement.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { BlockElement } from './BlockElement';
-import { BlockElementType } from './BlockElementType';
-import type { SectionBlock } from './layout/SectionBlock';
-
-export const isSectionBlockAccessoryElement = (
- block: BlockElement
-): block is Exclude => {
- switch (block.type as Exclude['type']) {
- case BlockElementType.BUTTON:
- case BlockElementType.DATEPICKER:
- case BlockElementType.IMAGE:
- case BlockElementType.MULTI_STATIC_SELECT:
- case BlockElementType.OVERFLOW:
- case BlockElementType.STATIC_SELECT:
- return true;
-
- default:
- return false;
- }
-};
diff --git a/packages/ui-kit/src/blocks/isTextObject.ts b/packages/ui-kit/src/blocks/isTextObject.ts
deleted file mode 100644
index 5d2ddea9cf..0000000000
--- a/packages/ui-kit/src/blocks/isTextObject.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { Block } from './Block';
-import type { TextObject } from './TextObject';
-import { TextObjectType } from './TextObjectType';
-
-export const isTextObject = (block: Block): block is TextObject =>
- (Object.values(TextObjectType) as string[]).includes(block.type);
diff --git a/packages/ui-kit/src/blocks/layout/ActionsBlock.ts b/packages/ui-kit/src/blocks/layout/ActionsBlock.ts
deleted file mode 100644
index 11e952a97d..0000000000
--- a/packages/ui-kit/src/blocks/layout/ActionsBlock.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import type { LayoutBlockish } from '../LayoutBlockish';
-import type { ButtonElement } from '../elements/ButtonElement';
-import type { ChannelsSelectElement } from '../elements/ChannelsSelectElement';
-import type { CheckboxElement } from '../elements/CheckboxElement';
-import type { ConversationsSelectElement } from '../elements/ConversationsSelectElement';
-import type { DatePickerElement } from '../elements/DatePickerElement';
-import type { LinearScaleElement } from '../elements/LinearScaleElement';
-import type { MultiChannelsSelectElement } from '../elements/MultiChannelsSelectElement';
-import type { MultiConversationsSelectElement } from '../elements/MultiConversationsSelectElement';
-import type { MultiStaticSelectElement } from '../elements/MultiStaticSelectElement';
-import type { MultiUsersSelectElement } from '../elements/MultiUsersSelectElement';
-import type { OverflowElement } from '../elements/OverflowElement';
-import type { RadioButtonElement } from '../elements/RadioButtonElement';
-import type { StaticSelectElement } from '../elements/StaticSelectElement';
-import type { TimePickerElement } from '../elements/TimePickerElement';
-import type { ToggleSwitchElement } from '../elements/ToggleSwitchElement';
-import type { UsersSelectElement } from '../elements/UsersSelectElement';
-
-export type ActionsBlock = LayoutBlockish<{
- type: 'actions';
- elements: readonly (
- | ButtonElement
- | ChannelsSelectElement
- | ConversationsSelectElement
- | DatePickerElement
- | LinearScaleElement
- | MultiChannelsSelectElement
- | MultiConversationsSelectElement
- | MultiStaticSelectElement
- | MultiUsersSelectElement
- | OverflowElement
- | StaticSelectElement
- | UsersSelectElement
- | ToggleSwitchElement
- | CheckboxElement
- | RadioButtonElement
- | TimePickerElement
- )[];
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/CalloutBlock.ts b/packages/ui-kit/src/blocks/layout/CalloutBlock.ts
deleted file mode 100644
index f8bb01d254..0000000000
--- a/packages/ui-kit/src/blocks/layout/CalloutBlock.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { LayoutBlockish } from '../LayoutBlockish';
-import type { TextObject } from '../TextObject';
-
-export type CalloutBlock = LayoutBlockish<{
- type: 'callout';
- title?: TextObject;
- text: TextObject;
- variant?: 'info' | 'danger' | 'warning' | 'success';
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/ConditionalBlock.ts b/packages/ui-kit/src/blocks/layout/ConditionalBlock.ts
deleted file mode 100644
index 68fe272546..0000000000
--- a/packages/ui-kit/src/blocks/layout/ConditionalBlock.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { Conditions } from '../../rendering/Conditions';
-import type { LayoutBlockish } from '../LayoutBlockish';
-import type { RenderableLayoutBlock } from '../RenderableLayoutBlock';
-
-export type ConditionalBlock = LayoutBlockish<{
- type: 'conditional';
- when?: {
- [K in keyof Conditions]: readonly Conditions[K][];
- };
- render: readonly RenderableLayoutBlock[];
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/ContextBlock.ts b/packages/ui-kit/src/blocks/layout/ContextBlock.ts
deleted file mode 100644
index 2dd444b937..0000000000
--- a/packages/ui-kit/src/blocks/layout/ContextBlock.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { LayoutBlockish } from '../LayoutBlockish';
-import type { TextObject } from '../TextObject';
-import type { ImageElement } from '../elements/ImageElement';
-
-export type ContextBlockElements = TextObject | ImageElement;
-export type ContextBlock = LayoutBlockish<{
- type: 'context';
- elements: readonly ContextBlockElements[];
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/DividerBlock.ts b/packages/ui-kit/src/blocks/layout/DividerBlock.ts
deleted file mode 100644
index 52a2e46ab6..0000000000
--- a/packages/ui-kit/src/blocks/layout/DividerBlock.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { LayoutBlockish } from '../LayoutBlockish';
-
-export type DividerBlock = LayoutBlockish<{
- type: 'divider';
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/ExperimentalTabNavigationBlock.ts b/packages/ui-kit/src/blocks/layout/ExperimentalTabNavigationBlock.ts
deleted file mode 100644
index 90a9bf39d2..0000000000
--- a/packages/ui-kit/src/blocks/layout/ExperimentalTabNavigationBlock.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { LayoutBlockish } from '../LayoutBlockish';
-import type { ExperimentalTabElement } from '../elements/ExperimentalTabElement';
-
-export type ExperimentalTabNavigationBlock = LayoutBlockish<{
- type: 'tab_navigation';
- tabs: readonly ExperimentalTabElement[];
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/ImageBlock.ts b/packages/ui-kit/src/blocks/layout/ImageBlock.ts
deleted file mode 100644
index 2a265a0f25..0000000000
--- a/packages/ui-kit/src/blocks/layout/ImageBlock.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { LayoutBlockish } from '../LayoutBlockish';
-import type { PlainText } from '../text/PlainText';
-
-export type ImageBlock = LayoutBlockish<{
- type: 'image';
- imageUrl: string;
- altText: string;
- title?: PlainText;
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/InputBlock.ts b/packages/ui-kit/src/blocks/layout/InputBlock.ts
deleted file mode 100644
index ae06b0d2c0..0000000000
--- a/packages/ui-kit/src/blocks/layout/InputBlock.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { LayoutBlockish } from '../LayoutBlockish';
-import type { ChannelsSelectElement } from '../elements/ChannelsSelectElement';
-import type { CheckboxElement } from '../elements/CheckboxElement';
-import type { ConversationsSelectElement } from '../elements/ConversationsSelectElement';
-import type { DatePickerElement } from '../elements/DatePickerElement';
-import type { LinearScaleElement } from '../elements/LinearScaleElement';
-import type { MultiChannelsSelectElement } from '../elements/MultiChannelsSelectElement';
-import type { MultiConversationsSelectElement } from '../elements/MultiConversationsSelectElement';
-import type { MultiStaticSelectElement } from '../elements/MultiStaticSelectElement';
-import type { MultiUsersSelectElement } from '../elements/MultiUsersSelectElement';
-import type { PlainTextInputElement } from '../elements/PlainTextInputElement';
-import type { RadioButtonElement } from '../elements/RadioButtonElement';
-import type { StaticSelectElement } from '../elements/StaticSelectElement';
-import type { TimePickerElement } from '../elements/TimePickerElement';
-import type { ToggleSwitchElement } from '../elements/ToggleSwitchElement';
-import type { UsersSelectElement } from '../elements/UsersSelectElement';
-import type { PlainText } from '../text/PlainText';
-
-export type InputBlock = LayoutBlockish<{
- type: 'input';
- label: PlainText;
- element:
- | ChannelsSelectElement
- | ConversationsSelectElement
- | DatePickerElement
- | LinearScaleElement
- | MultiChannelsSelectElement
- | MultiConversationsSelectElement
- | MultiStaticSelectElement
- | MultiUsersSelectElement
- | PlainTextInputElement
- | StaticSelectElement
- | UsersSelectElement
- | CheckboxElement
- | RadioButtonElement
- | TimePickerElement
- | ToggleSwitchElement;
- hint?: PlainText;
- optional?: boolean;
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/PreviewBlock.ts b/packages/ui-kit/src/blocks/layout/PreviewBlock.ts
deleted file mode 100644
index 041e21e6a2..0000000000
--- a/packages/ui-kit/src/blocks/layout/PreviewBlock.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import type { LayoutBlockType } from '../LayoutBlockType';
-import type { TextObject } from '../TextObject';
-import type { ContextBlock } from './ContextBlock';
-
-type Image = {
- url: string;
- dimensions?: {
- width: number;
- height: number;
- };
-};
-
-export type PreviewBlockBase = {
- type: `${LayoutBlockType.PREVIEW}`;
- title: TextObject[];
- description: TextObject[];
- footer?: ContextBlock;
-};
-
-export type PreviewBlockWithThumb = PreviewBlockBase & {
- thumb: Image;
-};
-
-export type PreviewBlockWithPreview = PreviewBlockBase & {
- preview: Image;
- externalUrl?: string;
- oembedUrl?: string;
- thumb: undefined;
-};
-
-export type PreviewBlock =
- | PreviewBlockBase
- | PreviewBlockWithThumb
- | PreviewBlockWithPreview;
-
-export const isPreviewBlockWithThumb = (
- previewBlock: PreviewBlock
-): previewBlock is PreviewBlockWithThumb => 'thumb' in previewBlock;
-
-export const isPreviewBlockWithPreview = (
- previewBlock: PreviewBlock
-): previewBlock is PreviewBlockWithPreview =>
- 'externalUrl' in previewBlock || 'oembedUrl' in previewBlock;
diff --git a/packages/ui-kit/src/blocks/layout/SectionBlock.ts b/packages/ui-kit/src/blocks/layout/SectionBlock.ts
deleted file mode 100644
index 19b6879870..0000000000
--- a/packages/ui-kit/src/blocks/layout/SectionBlock.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { LayoutBlockish } from '../LayoutBlockish';
-import type { TextObject } from '../TextObject';
-import type { ButtonElement } from '../elements/ButtonElement';
-import type { DatePickerElement } from '../elements/DatePickerElement';
-import type { ImageElement } from '../elements/ImageElement';
-import type { MultiStaticSelectElement } from '../elements/MultiStaticSelectElement';
-import type { OverflowElement } from '../elements/OverflowElement';
-import type { StaticSelectElement } from '../elements/StaticSelectElement';
-
-export type SectionBlock = LayoutBlockish<{
- type: 'section';
- text?: TextObject;
- fields?: readonly TextObject[];
- accessory?:
- | ButtonElement
- | DatePickerElement
- | ImageElement
- | MultiStaticSelectElement
- | OverflowElement
- | StaticSelectElement;
-}>;
diff --git a/packages/ui-kit/src/blocks/layout/VideoConferenceBlock.ts b/packages/ui-kit/src/blocks/layout/VideoConferenceBlock.ts
deleted file mode 100644
index d72db6553d..0000000000
--- a/packages/ui-kit/src/blocks/layout/VideoConferenceBlock.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { LayoutBlockType } from '../LayoutBlockType';
-import type { LayoutBlockish } from '../LayoutBlockish';
-
-export type VideoConferenceBlock = LayoutBlockish<{
- type: `${LayoutBlockType.VIDEO_CONF}`;
- callId: string;
-}>;
diff --git a/packages/ui-kit/src/blocks/text/Markdown.ts b/packages/ui-kit/src/blocks/text/Markdown.ts
deleted file mode 100644
index 0a3741b397..0000000000
--- a/packages/ui-kit/src/blocks/text/Markdown.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { WithTranslations } from '../WithTranslations';
-
-export type Markdown = WithTranslations<{
- type: 'mrkdwn';
- text: string;
- verbatim?: boolean;
-}>;
diff --git a/packages/ui-kit/src/blocks/text/PlainText.ts b/packages/ui-kit/src/blocks/text/PlainText.ts
deleted file mode 100644
index 1068337b4b..0000000000
--- a/packages/ui-kit/src/blocks/text/PlainText.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { WithTranslations } from '../WithTranslations';
-
-export type PlainText = WithTranslations<{
- type: 'plain_text';
- text: string;
- emoji?: boolean;
-}>;
diff --git a/packages/ui-kit/src/index.ts b/packages/ui-kit/src/index.ts
deleted file mode 100644
index 48e3afdcd9..0000000000
--- a/packages/ui-kit/src/index.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-export { ConfirmationDialog } from './blocks/ConfirmationDialog';
-export { Option } from './blocks/Option';
-export { OptionGroup } from './blocks/OptionGroup';
-
-export { PlainText } from './blocks/text/PlainText';
-export { Markdown } from './blocks/text/Markdown';
-export { TextObject } from './blocks/TextObject';
-
-export { Conditions } from './rendering/Conditions';
-
-export { ButtonElement } from './blocks/elements/ButtonElement';
-export { ChannelsSelectElement } from './blocks/elements/ChannelsSelectElement';
-export { ConversationsSelectElement } from './blocks/elements/ConversationsSelectElement';
-export { DatePickerElement } from './blocks/elements/DatePickerElement';
-export { ImageElement } from './blocks/elements/ImageElement';
-export { LinearScaleElement } from './blocks/elements/LinearScaleElement';
-export { MultiStaticSelectElement } from './blocks/elements/MultiStaticSelectElement';
-export { MultiChannelsSelectElement } from './blocks/elements/MultiChannelsSelectElement';
-export { MultiConversationsSelectElement } from './blocks/elements/MultiConversationsSelectElement';
-export { MultiUsersSelectElement } from './blocks/elements/MultiUsersSelectElement';
-export { OverflowElement } from './blocks/elements/OverflowElement';
-export { PlainTextInputElement } from './blocks/elements/PlainTextInputElement';
-export { StaticSelectElement } from './blocks/elements/StaticSelectElement';
-export { UsersSelectElement } from './blocks/elements/UsersSelectElement';
-export { ToggleSwitchElement } from './blocks/elements/ToggleSwitchElement';
-export { CheckboxElement } from './blocks/elements/CheckboxElement';
-export { RadioButtonElement } from './blocks/elements/RadioButtonElement';
-export { TimePickerElement } from './blocks/elements/TimePickerElement';
-export { BlockElement } from './blocks/BlockElement';
-export { ExperimentalTabElement } from './blocks/elements/ExperimentalTabElement';
-
-export { ActionsBlock } from './blocks/layout/ActionsBlock';
-export { ConditionalBlock } from './blocks/layout/ConditionalBlock';
-export { ContextBlock } from './blocks/layout/ContextBlock';
-export * from './blocks/layout/PreviewBlock';
-export { DividerBlock } from './blocks/layout/DividerBlock';
-export { ImageBlock } from './blocks/layout/ImageBlock';
-export { InputBlock } from './blocks/layout/InputBlock';
-export { SectionBlock } from './blocks/layout/SectionBlock';
-export { VideoConferenceBlock } from './blocks/layout/VideoConferenceBlock';
-export { LayoutBlock } from './blocks/LayoutBlock';
-export { CalloutBlock } from './blocks/layout/CalloutBlock';
-export { ExperimentalTabNavigationBlock } from './blocks/layout/ExperimentalTabNavigationBlock';
-
-export { InputElementDispatchAction } from './blocks/InputElementDispatchAction';
-
-export { Block } from './blocks/Block';
-export { RenderableBlock } from './blocks/RenderableBlock';
-
-export { LayoutBlockType } from './blocks/LayoutBlockType';
-export { BlockElementType } from './blocks/BlockElementType';
-export { TextObjectType } from './blocks/TextObjectType';
-export { BlockContext } from './rendering/BlockContext';
-
-export * from './blocks/deprecations';
-
-export { type BlockRenderers } from './rendering/BlockRenderers';
-export { type RenderableLayoutBlock } from './blocks/RenderableLayoutBlock';
-
-export { uiKitAttachment } from './rendering/surfaces/uiKitAttachment';
-export { uiKitBanner } from './rendering/surfaces/uiKitBanner';
-export { uiKitMessage } from './rendering/surfaces/uiKitMessage';
-export { uiKitModal } from './rendering/surfaces/uiKitModal';
-export { uiKitContextualBar } from './rendering/surfaces/uiKitContextualBar';
-
-export {
- UiKitParserAttachment,
- AttachmentSurfaceLayout,
-} from './rendering/surfaces/UiKitParserAttachment';
-export {
- UiKitParserBanner,
- BannerSurfaceLayout,
-} from './rendering/surfaces/UiKitParserBanner';
-export {
- UiKitParserMessage,
- MessageSurfaceLayout,
-} from './rendering/surfaces/UiKitParserMessage';
-export {
- UiKitParserModal,
- ModalSurfaceLayout,
-} from './rendering/surfaces/UiKitParserModal';
-export {
- UiKitParserContextualBar,
- ContextualBarSurfaceLayout,
-} from './rendering/surfaces/UiKitParserContextualBar';
-
-export { SurfaceRenderer } from './rendering/SurfaceRenderer';
-export { ActionableElement } from './blocks/ActionableElement';
-export { ActionOf } from './rendering/ActionOf';
diff --git a/packages/ui-kit/src/isNotNull.ts b/packages/ui-kit/src/isNotNull.ts
deleted file mode 100644
index 10b67188a4..0000000000
--- a/packages/ui-kit/src/isNotNull.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const isNotNull = (value: T | null): value is T => value !== null;
diff --git a/packages/ui-kit/src/rendering/ActionOf.ts b/packages/ui-kit/src/rendering/ActionOf.ts
deleted file mode 100644
index 65221eb5ed..0000000000
--- a/packages/ui-kit/src/rendering/ActionOf.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import type { ActionableElement } from '../blocks/ActionableElement';
-import type { Option } from '../blocks/Option';
-import type { ButtonElement } from '../blocks/elements/ButtonElement';
-import type { ChannelsSelectElement } from '../blocks/elements/ChannelsSelectElement';
-import type { CheckboxElement } from '../blocks/elements/CheckboxElement';
-import type { ConversationsSelectElement } from '../blocks/elements/ConversationsSelectElement';
-import type { DatePickerElement } from '../blocks/elements/DatePickerElement';
-import type { LinearScaleElement } from '../blocks/elements/LinearScaleElement';
-import type { MultiChannelsSelectElement } from '../blocks/elements/MultiChannelsSelectElement';
-import type { MultiConversationsSelectElement } from '../blocks/elements/MultiConversationsSelectElement';
-import type { MultiStaticSelectElement } from '../blocks/elements/MultiStaticSelectElement';
-import type { MultiUsersSelectElement } from '../blocks/elements/MultiUsersSelectElement';
-import type { OverflowElement } from '../blocks/elements/OverflowElement';
-import type { PlainTextInputElement } from '../blocks/elements/PlainTextInputElement';
-import type { RadioButtonElement } from '../blocks/elements/RadioButtonElement';
-import type { StaticSelectElement } from '../blocks/elements/StaticSelectElement';
-import type { TimePickerElement } from '../blocks/elements/TimePickerElement';
-import type { ToggleSwitchElement } from '../blocks/elements/ToggleSwitchElement';
-import type { UsersSelectElement } from '../blocks/elements/UsersSelectElement';
-
-export type ActionOf =
- TElement extends ButtonElement
- ? ButtonElement['value']
- : TElement extends ChannelsSelectElement
- ? unknown
- : TElement extends ConversationsSelectElement
- ? unknown
- : TElement extends DatePickerElement
- ? DatePickerElement['initialDate']
- : TElement extends LinearScaleElement
- ? LinearScaleElement['initialValue']
- : TElement extends MultiChannelsSelectElement
- ? unknown
- : TElement extends MultiConversationsSelectElement
- ? unknown
- : TElement extends MultiStaticSelectElement
- ? MultiStaticSelectElement['initialValue']
- : TElement extends MultiUsersSelectElement
- ? unknown
- : TElement extends OverflowElement
- ? OverflowElement['options'][number]['value']
- : TElement extends PlainTextInputElement
- ? PlainTextInputElement['initialValue']
- : TElement extends StaticSelectElement
- ? StaticSelectElement['initialValue']
- : TElement extends UsersSelectElement
- ? unknown
- : TElement extends ToggleSwitchElement
- ? Option['value'][]
- : TElement extends RadioButtonElement
- ? Option['value'] | undefined
- : TElement extends CheckboxElement
- ? Option['value'][] | undefined
- : TElement extends TimePickerElement
- ? TimePickerElement['initialTime']
- : never;
diff --git a/packages/ui-kit/src/rendering/BlockContext.ts b/packages/ui-kit/src/rendering/BlockContext.ts
deleted file mode 100644
index 69e610d16a..0000000000
--- a/packages/ui-kit/src/rendering/BlockContext.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export enum BlockContext {
- NONE = -1,
- BLOCK,
- SECTION,
- ACTION,
- FORM,
- CONTEXT,
-}
diff --git a/packages/ui-kit/src/rendering/BlockElementRenderer.ts b/packages/ui-kit/src/rendering/BlockElementRenderer.ts
deleted file mode 100644
index f45e63b2bd..0000000000
--- a/packages/ui-kit/src/rendering/BlockElementRenderer.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { BlockElement } from '..';
-import type { BlockContext } from './BlockContext';
-
-export type BlockElementRenderer<
- OutputElement,
- Block extends BlockElement = BlockElement
-> = (
- blockElement: Block,
- context: BlockContext,
- index: number
-) => OutputElement | null;
diff --git a/packages/ui-kit/src/rendering/BlockRenderers.ts b/packages/ui-kit/src/rendering/BlockRenderers.ts
deleted file mode 100644
index da5f11b7d7..0000000000
--- a/packages/ui-kit/src/rendering/BlockRenderers.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import type { BlockElement } from '../blocks/BlockElement';
-import type { RenderableLayoutBlock } from '../blocks/RenderableLayoutBlock';
-import type { TextObject } from '../blocks/TextObject';
-import type { DatePickerElement } from '../blocks/elements/DatePickerElement';
-import type { LinearScaleElement } from '../blocks/elements/LinearScaleElement';
-import type { MultiStaticSelectElement } from '../blocks/elements/MultiStaticSelectElement';
-import type { PlainTextInputElement } from '../blocks/elements/PlainTextInputElement';
-import type { StaticSelectElement } from '../blocks/elements/StaticSelectElement';
-import type { PlainText } from '../blocks/text/PlainText';
-import type { BlockElementRenderer } from './BlockElementRenderer';
-import type { LayoutBlockRenderer } from './LayoutBlockRenderer';
-import type { TextObjectRenderer } from './TextObjectRenderer';
-
-export type BlockRenderers = {
- [B in RenderableLayoutBlock as B['type']]?: LayoutBlockRenderer;
-} & {
- [B in TextObject as B['type']]: TextObjectRenderer;
-} & {
- [B in BlockElement as B['type']]?: BlockElementRenderer;
-} & {
- /** @deprecated */
- plainText?: TextObjectRenderer;
-
- /** @deprecated */
- text?: TextObjectRenderer;
-
- /** @deprecated */
- datePicker?: BlockElementRenderer;
-
- /** @deprecated */
- staticSelect?: BlockElementRenderer;
-
- /** @deprecated */
- multiStaticSelect?: BlockElementRenderer;
-
- /** @deprecated */
- plainInput?: BlockElementRenderer;
-
- /** @deprecated */
- linearScale?: BlockElementRenderer;
-};
diff --git a/packages/ui-kit/src/rendering/ConditionalBlockFiltersEngine.ts b/packages/ui-kit/src/rendering/ConditionalBlockFiltersEngine.ts
deleted file mode 100644
index d04c4ac5f9..0000000000
--- a/packages/ui-kit/src/rendering/ConditionalBlockFiltersEngine.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @deprecated */
-export enum ConditionalBlockFiltersEngine {
- ROCKETCHAT = 'rocket.chat',
- LIVECHAT = 'livechat',
-}
diff --git a/packages/ui-kit/src/rendering/Conditions.ts b/packages/ui-kit/src/rendering/Conditions.ts
deleted file mode 100644
index fb24c80777..0000000000
--- a/packages/ui-kit/src/rendering/Conditions.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export type Conditions = {
- engine?: 'rocket.chat' | 'livechat';
-};
diff --git a/packages/ui-kit/src/rendering/LayoutBlockRenderer.ts b/packages/ui-kit/src/rendering/LayoutBlockRenderer.ts
deleted file mode 100644
index 07b1a61c2c..0000000000
--- a/packages/ui-kit/src/rendering/LayoutBlockRenderer.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type { RenderableLayoutBlock } from '../blocks/RenderableLayoutBlock';
-import type { BlockContext } from './BlockContext';
-
-export type LayoutBlockRenderer<
- T,
- B extends RenderableLayoutBlock = RenderableLayoutBlock
-> = (layoutBlock: B, context: BlockContext.BLOCK, index: number) => T | null;
diff --git a/packages/ui-kit/src/rendering/SurfaceRenderer.ts b/packages/ui-kit/src/rendering/SurfaceRenderer.ts
deleted file mode 100644
index 6432eb994b..0000000000
--- a/packages/ui-kit/src/rendering/SurfaceRenderer.ts
+++ /dev/null
@@ -1,202 +0,0 @@
-import type { Block } from '../blocks/Block';
-import type { BlockElement } from '../blocks/BlockElement';
-import { LayoutBlockType } from '../blocks/LayoutBlockType';
-import type { RenderableLayoutBlock } from '../blocks/RenderableLayoutBlock';
-import type { TextObject } from '../blocks/TextObject';
-import { TextObjectType } from '../blocks/TextObjectType';
-import { isActionsBlockElement } from '../blocks/isActionsBlockElement';
-import { isContextBlockElement } from '../blocks/isContextBlockElement';
-import { isInputBlockElement } from '../blocks/isInputBlockElement';
-import { isSectionBlockAccessoryElement } from '../blocks/isSectionBlockAccessoryElement';
-import { isTextObject } from '../blocks/isTextObject';
-import type { ActionsBlock } from '../blocks/layout/ActionsBlock';
-import type { ContextBlock } from '../blocks/layout/ContextBlock';
-import type { InputBlock } from '../blocks/layout/InputBlock';
-import type { SectionBlock } from '../blocks/layout/SectionBlock';
-import type { Markdown } from '../blocks/text/Markdown';
-import type { PlainText } from '../blocks/text/PlainText';
-import { isNotNull } from '../isNotNull';
-import { BlockContext } from './BlockContext';
-import type { BlockRenderers } from './BlockRenderers';
-import type { Conditions } from './Conditions';
-import { renderBlockElement } from './renderBlockElement';
-import { renderLayoutBlock } from './renderLayoutBlock';
-import { renderTextObject } from './renderTextObject';
-import { resolveConditionalBlocks } from './resolveConditionalBlocks';
-
-export abstract class SurfaceRenderer<
- TOutputObject,
- TAllowedLayoutBlock extends RenderableLayoutBlock = RenderableLayoutBlock
-> implements BlockRenderers
-{
- protected readonly allowedLayoutBlockTypes: Set;
-
- public constructor(allowedLayoutBlockTypes: TAllowedLayoutBlock['type'][]) {
- this.allowedLayoutBlockTypes = new Set(allowedLayoutBlockTypes);
- }
-
- private isAllowedLayoutBlock = (block: Block): block is TAllowedLayoutBlock =>
- this.allowedLayoutBlockTypes.has(block.type as TAllowedLayoutBlock['type']);
-
- public render(
- blocks: readonly Block[],
- conditions?: Conditions
- ): TOutputObject[] {
- if (!Array.isArray(blocks)) {
- return [];
- }
-
- return blocks
- .flatMap(resolveConditionalBlocks(conditions))
- .filter(this.isAllowedLayoutBlock)
- .map(renderLayoutBlock(this))
- .filter(isNotNull);
- }
-
- public renderTextObject(
- textObject: TextObject,
- index: number,
- context: BlockContext
- ): TOutputObject | null {
- return renderTextObject(this, context)(textObject, index);
- }
-
- public renderActionsBlockElement(
- block: BlockElement,
- index: number
- ): TOutputObject | null {
- if (
- this.allowedLayoutBlockTypes.has(LayoutBlockType.ACTIONS) === false &&
- !isActionsBlockElement(block)
- ) {
- return null;
- }
-
- return renderBlockElement(this, BlockContext.ACTION)(block, index);
- }
-
- /** @deprecated */
- public renderActions(
- element: ActionsBlock['elements'][number],
- _context: BlockContext,
- _: undefined,
- index: number
- ): TOutputObject | null {
- return this.renderActionsBlockElement(element, index);
- }
-
- public renderContextBlockElement(
- block: TextObject | BlockElement,
- index: number
- ): TOutputObject | null {
- if (
- this.allowedLayoutBlockTypes.has(LayoutBlockType.CONTEXT) === false &&
- !isContextBlockElement(block)
- ) {
- return null;
- }
-
- if (isTextObject(block)) {
- return renderTextObject(this, BlockContext.CONTEXT)(block, index);
- }
-
- return renderBlockElement(this, BlockContext.CONTEXT)(block, index);
- }
-
- /** @deprecated */
- public renderContext(
- element: ContextBlock['elements'][number],
- _context: BlockContext,
- _: undefined,
- index: number
- ): TOutputObject | null {
- return this.renderContextBlockElement(element, index);
- }
-
- public renderInputBlockElement(
- block: BlockElement,
- index: number
- ): TOutputObject | null {
- if (
- this.allowedLayoutBlockTypes.has(LayoutBlockType.INPUT) === false &&
- !isInputBlockElement(block)
- ) {
- return null;
- }
-
- return renderBlockElement(this, BlockContext.FORM)(block, index);
- }
-
- /** @deprecated */
- public renderInputs(
- element: InputBlock['element'],
- _context: BlockContext,
- _: undefined,
- index: number
- ): TOutputObject | null {
- return this.renderInputBlockElement(element, index);
- }
-
- public renderSectionAccessoryBlockElement(
- block: BlockElement,
- index: number
- ): TOutputObject | null {
- if (
- this.allowedLayoutBlockTypes.has(LayoutBlockType.SECTION) === false &&
- !isSectionBlockAccessoryElement(block)
- ) {
- return null;
- }
-
- return renderBlockElement(this, BlockContext.SECTION)(block, index);
- }
-
- /** @deprecated */
- public renderAccessories(
- element: Exclude,
- _context: BlockContext,
- _: undefined,
- index: number
- ): TOutputObject | null {
- return this.renderSectionAccessoryBlockElement(element, index);
- }
-
- /** @deprecated */
- public plainText(
- element: PlainText,
- context: BlockContext = BlockContext.NONE,
- index = 0
- ): TOutputObject | null {
- return this[TextObjectType.PLAIN_TEXT](element, context, index);
- }
-
- /** @deprecated */
- public text(
- textObject: TextObject,
- context: BlockContext = BlockContext.NONE,
- index = 0
- ): TOutputObject | null {
- switch (textObject.type) {
- case TextObjectType.PLAIN_TEXT:
- return this.plain_text(textObject, context, index);
-
- case TextObjectType.MRKDWN:
- return this.mrkdwn(textObject, context, index);
-
- default:
- return null;
- }
- }
-
- public abstract plain_text(
- textObject: PlainText,
- context: BlockContext,
- index: number
- ): TOutputObject | null;
-
- public abstract mrkdwn(
- textObject: Markdown,
- context: BlockContext,
- index: number
- ): TOutputObject | null;
-}
diff --git a/packages/ui-kit/src/rendering/TextObjectRenderer.ts b/packages/ui-kit/src/rendering/TextObjectRenderer.ts
deleted file mode 100644
index b697b400bb..0000000000
--- a/packages/ui-kit/src/rendering/TextObjectRenderer.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { TextObject } from '../blocks/TextObject';
-import type { BlockContext } from './BlockContext';
-
-export type TextObjectRenderer<
- OutputElement,
- Block extends TextObject = TextObject
-> = (
- textObject: Block,
- context: BlockContext,
- index: number
-) => OutputElement | null;
diff --git a/packages/ui-kit/src/rendering/createSurfaceRenderer.ts b/packages/ui-kit/src/rendering/createSurfaceRenderer.ts
deleted file mode 100644
index ebad8de65e..0000000000
--- a/packages/ui-kit/src/rendering/createSurfaceRenderer.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { Block } from '../blocks/Block';
-import type { RenderableLayoutBlock } from '../blocks/RenderableLayoutBlock';
-import type { Conditions } from './Conditions';
-import type { SurfaceRenderer } from './SurfaceRenderer';
-
-export const createSurfaceRenderer =
- () =>
- (
- surfaceRenderer: SurfaceRenderer,
- conditions?: Conditions
- ) =>
- (blocks: readonly { type: string }[]): TOutputObject[] =>
- surfaceRenderer.render(blocks as Block[], conditions);
diff --git a/packages/ui-kit/src/rendering/renderBlockElement.ts b/packages/ui-kit/src/rendering/renderBlockElement.ts
deleted file mode 100644
index 67d7017d27..0000000000
--- a/packages/ui-kit/src/rendering/renderBlockElement.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import type { BlockElement } from '../blocks/BlockElement';
-import type { BlockContext } from './BlockContext';
-import type { BlockElementRenderer } from './BlockElementRenderer';
-import type { BlockRenderers } from './BlockRenderers';
-
-const getBlockElementRenderer = (
- renderers: BlockRenderers,
- type: BlockElement['type']
-): BlockElementRenderer | undefined => {
- const renderer = renderers[type] as BlockElementRenderer | undefined;
-
- if (renderer) {
- return renderer;
- }
-
- switch (type) {
- case 'datepicker':
- return renderers.datePicker as BlockElementRenderer | undefined;
-
- case 'static_select':
- return renderers.staticSelect as BlockElementRenderer | undefined;
-
- case 'multi_static_select':
- return renderers.multiStaticSelect as BlockElementRenderer | undefined;
-
- case 'plain_text_input':
- return renderers.plainInput as BlockElementRenderer | undefined;
-
- case 'linear_scale':
- return renderers.linearScale as BlockElementRenderer | undefined;
- }
-};
-
-export const renderBlockElement =
- (renderers: BlockRenderers, context: BlockContext) =>
- (blockElement: BlockElement, index: number): T | null => {
- const renderer = getBlockElementRenderer(renderers, blockElement.type);
-
- if (!renderer) {
- return null;
- }
-
- return renderer.call(renderers, blockElement, context, index);
- };
diff --git a/packages/ui-kit/src/rendering/renderLayoutBlock.ts b/packages/ui-kit/src/rendering/renderLayoutBlock.ts
deleted file mode 100644
index a1662035a4..0000000000
--- a/packages/ui-kit/src/rendering/renderLayoutBlock.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import type { LayoutBlock } from '../blocks/LayoutBlock';
-import type { ConditionalBlock } from '../blocks/layout/ConditionalBlock';
-import { BlockContext } from './BlockContext';
-import type { BlockRenderers } from './BlockRenderers';
-import type { LayoutBlockRenderer } from './LayoutBlockRenderer';
-
-const getLayoutBlockRenderer = (
- renderers: BlockRenderers,
- type: Exclude['type']
-): LayoutBlockRenderer | undefined =>
- renderers[type] as LayoutBlockRenderer | undefined;
-
-export const renderLayoutBlock =
- (renderers: BlockRenderers) =>
- (
- layoutBlock: Exclude,
- index: number
- ): T | null => {
- const renderer = getLayoutBlockRenderer(renderers, layoutBlock.type);
-
- if (!renderer) {
- return null;
- }
-
- return renderer.call(renderers, layoutBlock, BlockContext.BLOCK, index);
- };
diff --git a/packages/ui-kit/src/rendering/renderTextObject.ts b/packages/ui-kit/src/rendering/renderTextObject.ts
deleted file mode 100644
index f579b01fd8..0000000000
--- a/packages/ui-kit/src/rendering/renderTextObject.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import type { TextObject } from '../blocks/TextObject';
-import type { BlockContext } from './BlockContext';
-import type { BlockRenderers } from './BlockRenderers';
-import type { TextObjectRenderer } from './TextObjectRenderer';
-
-const getTextObjectRenderer = (
- renderers: BlockRenderers,
- type: TextObject['type']
-): TextObjectRenderer | undefined => {
- const renderer = renderers[type] as TextObjectRenderer | undefined;
-
- if (renderer) {
- return renderer;
- }
-
- switch (type) {
- case 'plain_text':
- return (renderers.plainText ?? renderers.text) as
- | TextObjectRenderer
- | undefined;
-
- case 'mrkdwn':
- return renderers.text as TextObjectRenderer | undefined;
- }
-};
-
-export const renderTextObject =
- (renderers: BlockRenderers, context: BlockContext) =>
- (textObject: TextObject, index: number): T | null => {
- const renderer = getTextObjectRenderer(renderers, textObject.type);
-
- if (!renderer) {
- return null;
- }
-
- return renderer.call(renderers, textObject, context, index);
- };
diff --git a/packages/ui-kit/src/rendering/resolveConditionalBlocks.ts b/packages/ui-kit/src/rendering/resolveConditionalBlocks.ts
deleted file mode 100644
index b42e39304d..0000000000
--- a/packages/ui-kit/src/rendering/resolveConditionalBlocks.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import type { Block } from '../blocks/Block';
-import { LayoutBlockType } from '../blocks/LayoutBlockType';
-import type { ConditionalBlock } from '../blocks/layout/ConditionalBlock';
-import type { Conditions } from './Conditions';
-
-const conditionsMatch = (
- conditions: Conditions | undefined = undefined,
- filters: ConditionalBlock['when'] = {}
-): boolean => {
- if (!conditions) {
- return true;
- }
-
- if (
- Array.isArray(filters.engine) &&
- !filters.engine.includes(conditions.engine)
- ) {
- return false;
- }
-
- return true;
-};
-
-export const resolveConditionalBlocks =
- (conditions?: Conditions) =>
- (block: Block): readonly Block[] => {
- if (block.type !== LayoutBlockType.CONDITIONAL) {
- return [block];
- }
-
- if (conditionsMatch(conditions, block.when)) {
- return block.render;
- }
-
- return [];
- };
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserAttachment.spec.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserAttachment.spec.ts
deleted file mode 100644
index 3ffab15e33..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserAttachment.spec.ts
+++ /dev/null
@@ -1,1465 +0,0 @@
-import { uiKitAttachment, UiKitParserAttachment } from '../..';
-import { BlockContext } from '../BlockContext';
-
-class TestParser extends UiKitParserAttachment {
- plain_text = (element: any, context: any, index: any): any => ({
- component: 'text',
- props: {
- key: index,
- children: element.text,
- emoji: element.emoji,
- block: context === BlockContext.BLOCK,
- },
- });
-
- mrkdwn = (element: any, context: any, index: any): any => ({
- component: 'markdown',
- props: {
- key: index,
- children: element.text,
- verbatim: Boolean(element.verbatim),
- block: context === BlockContext.BLOCK,
- },
- });
-
- divider = (_element: any, context: any, index: any): any => ({
- component: 'divider',
- props: {
- key: index,
- block: context === BlockContext.BLOCK,
- },
- });
-
- section = (element: any, context: any, index: any): any => {
- let key = 0;
- return {
- component: 'section',
- props: {
- key: index,
- children: [
- ...(element.text
- ? [this.text(element.text, BlockContext.SECTION, key++)]
- : []),
- ...(element.fields?.map((field: any) =>
- this.text(field, BlockContext.SECTION, key++)
- ) ?? []),
- ...(element.accessory
- ? [
- this.renderAccessories(
- element.accessory,
- BlockContext.SECTION,
- undefined,
- key++
- ),
- ]
- : []),
- ],
- block: context === BlockContext.BLOCK,
- },
- };
- };
-
- actions = (element: any, context: any, index: any): any => ({
- component: 'actions',
- props: {
- key: index,
- children: element.elements.map((element: any, key: number) =>
- this.renderActions(element, BlockContext.ACTION, undefined, key)
- ),
- block: context === BlockContext.BLOCK,
- },
- });
-
- context = (element: any, context: any, index: any): any => ({
- component: 'context',
- props: {
- key: index,
- children: element.elements.map((element: any, key: number) =>
- this.renderContext(element, BlockContext.CONTEXT, undefined, key)
- ),
- block: context === BlockContext.BLOCK,
- },
- });
-
- button = (element: any, context: any, index: any): any => ({
- component: 'button',
- props: {
- key: index,
- children: element.text
- ? [this.text(element.text, BlockContext.SECTION, 0)]
- : [],
- ...(element.url && { href: element.url }),
- ...(element.value && { value: element.value }),
- variant: element.style ?? 'normal',
- block: context === BlockContext.BLOCK,
- },
- });
-
- image = (element: any, context: any, index: any): any => {
- if (context === BlockContext.BLOCK) {
- let key = 0;
- return {
- component: 'image-container',
- props: {
- key: index,
- children: [
- {
- component: 'image',
- props: {
- key: key++,
- src: element.imageUrl,
- alt: element.altText,
- block: false,
- },
- },
- ...(element.title
- ? [this.plainText(element.title, -1, key++)]
- : []),
- ],
- block: true,
- },
- };
- }
-
- return {
- component: 'image',
- props: {
- key: index,
- src: element.imageUrl,
- alt: element.altText,
- block: false,
- },
- };
- };
-
- overflow = (element: any, _context: any, index: any): any => ({
- component: 'menu',
- props: {
- key: index,
- children: element.options.map((option: any, key: any) => ({
- component: 'menu-item',
- props: {
- key,
- children: [
- this.text(option.text, -1, 0),
- ...(option.description
- ? [this.plainText(option.description, -1, 1)]
- : []),
- ],
- value: option.value,
- ...(option.url && { url: option.url }),
- },
- })),
- },
- });
-
- datePicker = (element: any, _context: any, index: any): any => ({
- component: 'input',
- props: {
- key: index,
- type: 'date',
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- ...(element.initialDate && { defaultValue: element.initialDate }),
- },
- });
-
- staticSelect = (element: any, _context: any, index: any): any => ({
- component: 'select',
- props: {
- key: index,
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- children: element.options.map((option: any, key: any) => ({
- component: 'option',
- props: {
- key,
- children: this.text(option.text, -1, 0),
- value: option.value,
- ...(option.description && {
- description: this.text(option.description, -1, 0),
- }),
- },
- })),
- ...(element.initialOption && {
- defaultValue: element.options.find(
- (option: any) => option.value === element.initialOption.value
- )?.value,
- }),
- },
- });
-
- multiStaticSelect = (element: any, _context: any, index: any): any => ({
- component: 'select',
- props: {
- key: index,
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- multiple: true,
- children: element.options.map((option: any, key: any) => ({
- component: 'option',
- props: {
- key,
- children: this.text(option.text, -1, 0),
- value: option.value,
- ...(option.description && {
- description: this.text(option.description, -1, 0),
- }),
- },
- })),
- ...(element.initialOptions && {
- defaultValue: element.options
- .filter((option: any) =>
- element.initialOptions.some(
- (initialOption: any) => option.value === initialOption.value
- )
- )
- .map((option: any) => option.value),
- }),
- },
- });
-}
-
-const parser = new TestParser();
-const parse = uiKitAttachment(parser);
-
-const conditionalParse = uiKitAttachment(parser, {
- engine: 'rocket.chat',
-});
-
-describe('divider', () => {
- it('renders', () => {
- const payload = [
- {
- type: 'divider',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'divider',
- props: {
- key: 0,
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('section', () => {
- it('renders text as plain_text', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('render text as mrkdwn', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and ',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children:
- 'This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and ',
- verbatim: false,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders text fields', () => {
- const payload = [
- {
- type: 'section',
- fields: [
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 1,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 2,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 3,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 4,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as button', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with a button.',
- },
- accessory: {
- type: 'button',
- text: {
- type: 'plain_text',
- text: 'Click Me',
- emoji: true,
- },
- value: 'click_me_123',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with a button.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'button',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Click Me',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'click_me_123',
- variant: 'normal',
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as image', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with an accessory image.',
- },
- accessory: {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with an accessory image.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 1,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as overflow menu', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with an overflow menu.',
- },
- accessory: {
- type: 'overflow',
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-3',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-4',
- },
- ],
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with an overflow menu.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'menu',
- props: {
- key: 1,
- children: [
- {
- component: 'menu-item',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-0',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-1',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 2,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-2',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 3,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-3',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 4,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-4',
- },
- },
- ],
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as datepicker', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'Pick a date for the deadline.',
- },
- accessory: {
- type: 'datepicker',
- initial_date: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'Pick a date for the deadline.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- },
- },
- ]);
- });
-});
-
-describe('image', () => {
- it('renders with title', () => {
- const payload = [
- {
- type: 'image',
- title: {
- type: 'plain_text',
- text: 'I Need a Marg',
- emoji: true,
- },
- imageUrl:
- 'https://assets3.thrillist.com/v1/image/1682388/size/tl-horizontal_main.jpg',
- altText: 'marg',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'image-container',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://assets3.thrillist.com/v1/image/1682388/size/tl-horizontal_main.jpg',
- alt: 'marg',
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 1,
- children: 'I Need a Marg',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders with no title', () => {
- const payload = [
- {
- type: 'image',
- imageUrl:
- 'https://i1.wp.com/thetempest.co/wp-content/uploads/2017/08/The-wise-words-of-Michael-Scott-Imgur-2.jpg?w=1024&ssl=1',
- altText: 'inspiration',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'image-container',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://i1.wp.com/thetempest.co/wp-content/uploads/2017/08/The-wise-words-of-Michael-Scott-Imgur-2.jpg?w=1024&ssl=1',
- alt: 'inspiration',
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('actions', () => {
- it('renders all selects', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a conversation',
- emoji: true,
- },
- },
- {
- type: 'channels_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a channel',
- emoji: true,
- },
- },
- {
- type: 'users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a user',
- emoji: true,
- },
- },
- {
- type: 'static_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select an item',
- emoji: true,
- },
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- ],
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- null,
- null,
- null,
- {
- component: 'select',
- props: {
- key: 3,
- children: [
- {
- component: 'option',
- props: {
- key: 0,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-0',
- },
- },
- {
- component: 'option',
- props: {
- key: 1,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-1',
- },
- },
- {
- component: 'option',
- props: {
- key: 2,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-2',
- },
- },
- ],
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select an item',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders filtered conversations select', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select private conversation',
- emoji: true,
- },
- filter: {
- include: ['private'],
- },
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [null],
- block: true,
- },
- },
- ]);
- });
-
- it('renders selects with initial options', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a conversation',
- emoji: true,
- },
- initialConversation: 'D123',
- },
- {
- type: 'users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a user',
- emoji: true,
- },
- initialUser: 'U123',
- },
- {
- type: 'channels_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a channel',
- emoji: true,
- },
- initialChannel: 'C123',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [null, null, null],
- block: true,
- },
- },
- ]);
- });
-
- it('renders button', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'button',
- text: {
- type: 'plain_text',
- text: 'Click Me',
- emoji: true,
- },
- value: 'click_me_123',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- {
- component: 'button',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Click Me',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'click_me_123',
- variant: 'normal',
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders datepicker', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- {
- component: 'input',
- props: {
- key: 0,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('context', () => {
- it('renders plain text', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'plain_text',
- text: 'Author: K A Applegate',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Author: K A Applegate',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders mrkdwn', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'mrkdwn',
- text: '*Cat* has approved this message.',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'markdown',
- props: {
- key: 1,
- children: '*Cat* has approved this message.',
- verbatim: false,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders text and images', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'mrkdwn',
- text: '*This* is :smile: markdown',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'plain_text',
- text: 'Author: K A Applegate',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: '*This* is :smile: markdown',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 1,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 2,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 3,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 4,
- children: 'Author: K A Applegate',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('conditional', () => {
- it('renders when conditions match', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['rocket.chat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(conditionalParse(blocks)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders when no conditions are set', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['rocket.chat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(parse(blocks)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('does not render when conditions match', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['livechat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(conditionalParse(blocks)).toStrictEqual([]);
- });
-});
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserAttachment.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserAttachment.ts
deleted file mode 100644
index eba83cbf4c..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserAttachment.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import type { ActionsBlock } from '../../blocks/layout/ActionsBlock';
-import type { CalloutBlock } from '../../blocks/layout/CalloutBlock';
-import type { ContextBlock } from '../../blocks/layout/ContextBlock';
-import type { DividerBlock } from '../../blocks/layout/DividerBlock';
-import type { ImageBlock } from '../../blocks/layout/ImageBlock';
-import type { SectionBlock } from '../../blocks/layout/SectionBlock';
-import { SurfaceRenderer } from '../SurfaceRenderer';
-
-type AttachmentSurfaceLayoutBlock =
- | ActionsBlock
- | ContextBlock
- | DividerBlock
- | ImageBlock
- | SectionBlock
- | CalloutBlock;
-
-export abstract class UiKitParserAttachment extends SurfaceRenderer<
- T,
- AttachmentSurfaceLayoutBlock
-> {
- public constructor() {
- super(['actions', 'context', 'divider', 'image', 'section', 'callout']);
- }
-}
-
-export type AttachmentSurfaceLayout = AttachmentSurfaceLayoutBlock[];
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserBanner.spec.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserBanner.spec.ts
deleted file mode 100644
index c67dfeee0b..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserBanner.spec.ts
+++ /dev/null
@@ -1,1950 +0,0 @@
-import type { PlainText } from '../..';
-import { uiKitBanner, UiKitParserBanner } from '../..';
-import { BlockContext } from '../BlockContext';
-
-class TestParser extends UiKitParserBanner {
- plain_text = (element: any, context: any, index: any): any => ({
- component: 'text',
- props: {
- key: index,
- children: element.text,
- emoji: element.emoji,
- block: context === BlockContext.BLOCK,
- },
- });
-
- mrkdwn = (element: any, context: any, index: any): any => ({
- component: 'markdown',
- props: {
- key: index,
- children: element.text,
- verbatim: Boolean(element.verbatim),
- block: context === BlockContext.BLOCK,
- },
- });
-
- divider = (_element: any, context: any, index: any): any => ({
- component: 'divider',
- props: {
- key: index,
- block: context === BlockContext.BLOCK,
- },
- });
-
- section = (element: any, context: any, index: any): any => {
- let key = 0;
- return {
- component: 'section',
- props: {
- key: index,
- children: [
- ...(element.text
- ? [this.text(element.text, BlockContext.SECTION, key++)]
- : []),
- ...(element.fields?.map((field: any) =>
- this.text(field, BlockContext.SECTION, key++)
- ) ?? []),
- ...(element.accessory
- ? [
- this.renderAccessories(
- element.accessory,
- BlockContext.SECTION,
- undefined,
- key++
- ),
- ]
- : []),
- ],
- block: context === BlockContext.BLOCK,
- },
- };
- };
-
- actions = (element: any, context: any, index: any): any => ({
- component: 'actions',
- props: {
- key: index,
- children: element.elements.map((element: any, key: number) =>
- this.renderActions(element, BlockContext.ACTION, undefined, key)
- ),
- block: context === BlockContext.BLOCK,
- },
- });
-
- context = (element: any, context: any, index: any): any => ({
- component: 'context',
- props: {
- key: index,
- children: element.elements.map((element: any, key: number) =>
- this.renderContext(element, BlockContext.CONTEXT, undefined, key)
- ),
- block: context === BlockContext.BLOCK,
- },
- });
-
- input = (element: any, context: any, index: any): any => ({
- component: 'input-group',
- props: {
- key: index,
- children: [
- this.plainText(element.label, BlockContext.FORM, 0),
- this.renderInputs(element.element, BlockContext.FORM, undefined, 1),
- ...(element.hint
- ? [this.plainText(element.hint, BlockContext.FORM, 2)]
- : []),
- ],
- block: context === BlockContext.BLOCK,
- },
- });
-
- button = (element: any, context: any, index: any): any => ({
- component: 'button',
- props: {
- key: index,
- children: element.text
- ? [this.text(element.text, BlockContext.SECTION, 0)]
- : [],
- ...(element.url && { href: element.url }),
- ...(element.value && { value: element.value }),
- variant: element.style ?? 'normal',
- block: context === BlockContext.BLOCK,
- },
- });
-
- image = (element: any, context: any, index: any): any => {
- if (context === BlockContext.BLOCK) {
- let key = 0;
- return {
- component: 'image-container',
- props: {
- key: index,
- children: [
- {
- component: 'image',
- props: {
- key: key++,
- src: element.imageUrl,
- alt: element.altText,
- block: false,
- },
- },
- ...(element.title
- ? [this.plainText(element.title, -1, key++)]
- : []),
- ],
- block: true,
- },
- };
- }
-
- return {
- component: 'image',
- props: {
- key: index,
- src: element.imageUrl,
- alt: element.altText,
- block: false,
- },
- };
- };
-
- overflow = (element: any, _context: any, index: any): any => ({
- component: 'menu',
- props: {
- key: index,
- children: element.options.map((option: any, key: any) => ({
- component: 'menu-item',
- props: {
- key,
- children: [
- this.text(option.text, -1, 0),
- ...(option.description
- ? [this.plainText(option.description, -1, 1)]
- : []),
- ],
- value: option.value,
- ...(option.url && { url: option.url }),
- },
- })),
- },
- });
-
- datePicker = (element: any, _context: any, index: any): any => ({
- component: 'input',
- props: {
- key: index,
- type: 'date',
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- ...(element.initialDate && { defaultValue: element.initialDate }),
- },
- });
-
- staticSelect = (element: any, _context: any, index: any): any => ({
- component: 'select',
- props: {
- key: index,
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- children: element.options.map((option: any, key: any) => ({
- component: 'option',
- props: {
- key,
- children: this.text(option.text, -1, 0),
- value: option.value,
- ...(option.description && {
- description: this.text(option.description, -1, 0),
- }),
- },
- })),
- ...(element.initialOption && {
- defaultValue: element.options.find(
- (option: any) => option.value === element.initialOption.value
- )?.value,
- }),
- },
- });
-
- multiStaticSelect = (element: any, _context: any, index: any): any => ({
- component: 'select',
- props: {
- key: index,
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- multiple: true,
- children: element.options.map((option: any, key: any) => ({
- component: 'option',
- props: {
- key,
- children: this.text(option.text, -1, 0),
- value: option.value,
- ...(option.description && {
- description: this.text(option.description, -1, 0),
- }),
- },
- })),
- ...(element.initialOptions && {
- defaultValue: element.options
- .filter((option: any) =>
- element.initialOptions.some(
- (initialOption: any) => option.value === initialOption.value
- )
- )
- .map((option: any) => option.value),
- }),
- },
- });
-
- plainInput = (element: any, _context: any, index: any): any => ({
- component: 'input',
- props: {
- key: index,
- type: 'text',
- ...(element.placeholder && {
- placeholder: this.plainText(element.placeholder, -1, 0),
- }),
- ...(element.initialValue && { defaultValue: element.initialValue }),
- multiline: element.multiline ?? false,
- ...(typeof element.minLength !== 'undefined' && {
- minLength: element.minLength,
- }),
- ...(typeof element.maxLength !== 'undefined' && {
- maxLength: element.maxLength,
- }),
- },
- });
-
- linearScale = (
- { minValue = 0, maxValue = 10 }: any,
- _context: any,
- index: any
- ): any => ({
- component: 'linear-scale',
- props: {
- key: index,
- children: Array.from({ length: maxValue - minValue + 1 }).map(
- (_, key: any) => ({
- component: 'linear-scale-point',
- props: {
- key,
- children: [
- this.text(
- {
- type: 'plain_text',
- text: String(minValue + key),
- emoji: true,
- } as PlainText,
- -1,
- 0
- ),
- ],
- },
- })
- ),
- },
- });
-}
-
-const parser = new TestParser();
-const parse = uiKitBanner(parser);
-
-const conditionalParse = uiKitBanner(parser, {
- engine: 'rocket.chat',
-});
-
-describe('divider', () => {
- it('renders', () => {
- const payload = [
- {
- type: 'divider',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'divider',
- props: {
- key: 0,
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('section', () => {
- it('renders text as plain_text', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('render text as mrkdwn', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and ',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children:
- 'This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and ',
- verbatim: false,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders text fields', () => {
- const payload = [
- {
- type: 'section',
- fields: [
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 1,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 2,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 3,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 4,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as button', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with a button.',
- },
- accessory: {
- type: 'button',
- text: {
- type: 'plain_text',
- text: 'Click Me',
- emoji: true,
- },
- value: 'click_me_123',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with a button.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'button',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Click Me',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'click_me_123',
- variant: 'normal',
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as image', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with an accessory image.',
- },
- accessory: {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with an accessory image.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 1,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as overflow menu', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with an overflow menu.',
- },
- accessory: {
- type: 'overflow',
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-3',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-4',
- },
- ],
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with an overflow menu.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'menu',
- props: {
- key: 1,
- children: [
- {
- component: 'menu-item',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-0',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-1',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 2,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-2',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 3,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-3',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 4,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-4',
- },
- },
- ],
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as datepicker', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'Pick a date for the deadline.',
- },
- accessory: {
- type: 'datepicker',
- initial_date: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'Pick a date for the deadline.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- },
- },
- ]);
- });
-});
-
-describe('image', () => {
- it('renders with title', () => {
- const payload = [
- {
- type: 'image',
- title: {
- type: 'plain_text',
- text: 'I Need a Marg',
- emoji: true,
- },
- imageUrl:
- 'https://assets3.thrillist.com/v1/image/1682388/size/tl-horizontal_main.jpg',
- altText: 'marg',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'image-container',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://assets3.thrillist.com/v1/image/1682388/size/tl-horizontal_main.jpg',
- alt: 'marg',
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 1,
- children: 'I Need a Marg',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders with no title', () => {
- const payload = [
- {
- type: 'image',
- imageUrl:
- 'https://i1.wp.com/thetempest.co/wp-content/uploads/2017/08/The-wise-words-of-Michael-Scott-Imgur-2.jpg?w=1024&ssl=1',
- altText: 'inspiration',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'image-container',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://i1.wp.com/thetempest.co/wp-content/uploads/2017/08/The-wise-words-of-Michael-Scott-Imgur-2.jpg?w=1024&ssl=1',
- alt: 'inspiration',
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('actions', () => {
- it('renders all selects', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a conversation',
- emoji: true,
- },
- },
- {
- type: 'channels_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a channel',
- emoji: true,
- },
- },
- {
- type: 'users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a user',
- emoji: true,
- },
- },
- {
- type: 'static_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select an item',
- emoji: true,
- },
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- ],
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- null,
- null,
- null,
- {
- component: 'select',
- props: {
- key: 3,
- children: [
- {
- component: 'option',
- props: {
- key: 0,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-0',
- },
- },
- {
- component: 'option',
- props: {
- key: 1,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-1',
- },
- },
- {
- component: 'option',
- props: {
- key: 2,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-2',
- },
- },
- ],
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select an item',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders filtered conversations select', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select private conversation',
- emoji: true,
- },
- filter: {
- include: ['private'],
- },
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [null],
- block: true,
- },
- },
- ]);
- });
-
- it('renders selects with initial options', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a conversation',
- emoji: true,
- },
- initialConversation: 'D123',
- },
- {
- type: 'users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a user',
- emoji: true,
- },
- initialUser: 'U123',
- },
- {
- type: 'channels_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a channel',
- emoji: true,
- },
- initialChannel: 'C123',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [null, null, null],
- block: true,
- },
- },
- ]);
- });
-
- it('renders button', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'button',
- text: {
- type: 'plain_text',
- text: 'Click Me',
- emoji: true,
- },
- value: 'click_me_123',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- {
- component: 'button',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Click Me',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'click_me_123',
- variant: 'normal',
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders datepicker', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- {
- component: 'input',
- props: {
- key: 0,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('context', () => {
- it('renders plain text', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'plain_text',
- text: 'Author: K A Applegate',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Author: K A Applegate',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders mrkdwn', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'mrkdwn',
- text: '*Cat* has approved this message.',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'markdown',
- props: {
- key: 1,
- children: '*Cat* has approved this message.',
- verbatim: false,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders text and images', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'mrkdwn',
- text: '*This* is :smile: markdown',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'plain_text',
- text: 'Author: K A Applegate',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: '*This* is :smile: markdown',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 1,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 2,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 3,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 4,
- children: 'Author: K A Applegate',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('input', () => {
- it('renders multiline plain text input', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'plain_text_input',
- multiline: true,
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'text',
- multiline: true,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders plain text input', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'plain_text_input',
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'text',
- multiline: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders multi users select', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'multi_users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select users',
- emoji: true,
- },
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- null,
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders static select', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'static_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select an item',
- emoji: true,
- },
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- ],
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'select',
- props: {
- key: 1,
- children: [
- {
- component: 'option',
- props: {
- key: 0,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-0',
- },
- },
- {
- component: 'option',
- props: {
- key: 1,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-1',
- },
- },
- {
- component: 'option',
- props: {
- key: 2,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-2',
- },
- },
- ],
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select an item',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders datepicker', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders linear scale', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'linear_scale',
- maxValue: 2,
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'linear-scale',
- props: {
- key: 1,
- children: [
- {
- component: 'linear-scale-point',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '0',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- {
- component: 'linear-scale-point',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '1',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- {
- component: 'linear-scale-point',
- props: {
- key: 2,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '2',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- ],
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('conditional', () => {
- it('renders when conditions match', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['rocket.chat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(conditionalParse(blocks)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders when no conditions are set', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['rocket.chat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(parse(blocks)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('does not render when conditions match', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['livechat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(conditionalParse(blocks)).toStrictEqual([]);
- });
-});
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserBanner.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserBanner.ts
deleted file mode 100644
index 8d36c15675..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserBanner.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { ActionsBlock } from '../../blocks/layout/ActionsBlock';
-import type { CalloutBlock } from '../../blocks/layout/CalloutBlock';
-import type { ContextBlock } from '../../blocks/layout/ContextBlock';
-import type { DividerBlock } from '../../blocks/layout/DividerBlock';
-import type { ImageBlock } from '../../blocks/layout/ImageBlock';
-import type { InputBlock } from '../../blocks/layout/InputBlock';
-import type { SectionBlock } from '../../blocks/layout/SectionBlock';
-import { SurfaceRenderer } from '../SurfaceRenderer';
-
-type BannerSurfaceLayoutBlock =
- | ActionsBlock
- | ContextBlock
- | DividerBlock
- | ImageBlock
- | InputBlock
- | SectionBlock
- | CalloutBlock;
-
-export abstract class UiKitParserBanner extends SurfaceRenderer<
- T,
- BannerSurfaceLayoutBlock
-> {
- public constructor() {
- super(['actions', 'context', 'divider', 'image', 'input', 'section']);
- }
-}
-
-export type BannerSurfaceLayout = BannerSurfaceLayoutBlock[];
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserContextualBar.spec.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserContextualBar.spec.ts
deleted file mode 100644
index 4cb869b5ab..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserContextualBar.spec.ts
+++ /dev/null
@@ -1,1950 +0,0 @@
-import type { PlainText, OverflowElement } from '../..';
-import { uiKitContextualBar, UiKitParserContextualBar } from '../..';
-import { BlockContext } from '../BlockContext';
-
-class TestParser extends UiKitParserContextualBar {
- plain_text = (element: any, context: any, index: any): any => ({
- component: 'text',
- props: {
- key: index,
- children: element.text,
- emoji: element.emoji,
- block: context === BlockContext.BLOCK,
- },
- });
-
- mrkdwn = (element: any, context: any, index: any): any => ({
- component: 'markdown',
- props: {
- key: index,
- children: element.text,
- verbatim: Boolean(element.verbatim),
- block: context === BlockContext.BLOCK,
- },
- });
-
- divider = (_element: any, context: any, index: any): any => ({
- component: 'divider',
- props: {
- key: index,
- block: context === BlockContext.BLOCK,
- },
- });
-
- section = (element: any, context: any, index: any): any => {
- let key = 0;
- return {
- component: 'section',
- props: {
- key: index,
- children: [
- ...(element.text
- ? [this.text(element.text, BlockContext.SECTION, key++)]
- : []),
- ...(element.fields?.map((field: any) =>
- this.text(field, BlockContext.SECTION, key++)
- ) ?? []),
- ...(element.accessory
- ? [
- this.renderAccessories(
- element.accessory,
- BlockContext.SECTION,
- undefined,
- key++
- ),
- ]
- : []),
- ],
- block: context === BlockContext.BLOCK,
- },
- };
- };
-
- actions = (element: any, context: any, index: any): any => ({
- component: 'actions',
- props: {
- key: index,
- children: element.elements.map((element: any, key: number) =>
- this.renderActions(element, BlockContext.ACTION, undefined, key)
- ),
- block: context === BlockContext.BLOCK,
- },
- });
-
- context = (element: any, context: any, index: any): any => ({
- component: 'context',
- props: {
- key: index,
- children: element.elements.map((element: any, key: number) =>
- this.renderContext(element, BlockContext.CONTEXT, undefined, key)
- ),
- block: context === BlockContext.BLOCK,
- },
- });
-
- input = (element: any, context: any, index: any): any => ({
- component: 'input-group',
- props: {
- key: index,
- children: [
- this.plainText(element.label, BlockContext.FORM, 0),
- this.renderInputs(element.element, BlockContext.FORM, undefined, 1),
- ...(element.hint
- ? [this.plainText(element.hint, BlockContext.FORM, 2)]
- : []),
- ],
- block: context === BlockContext.BLOCK,
- },
- });
-
- button = (element: any, context: any, index: any): any => ({
- component: 'button',
- props: {
- key: index,
- children: element.text
- ? [this.text(element.text, BlockContext.SECTION, 0)]
- : [],
- ...(element.url && { href: element.url }),
- ...(element.value && { value: element.value }),
- variant: element.style ?? 'normal',
- block: context === BlockContext.BLOCK,
- },
- });
-
- image = (element: any, context: any, index: any): any => {
- if (context === BlockContext.BLOCK) {
- let key = 0;
- return {
- component: 'image-container',
- props: {
- key: index,
- children: [
- {
- component: 'image',
- props: {
- key: key++,
- src: element.imageUrl,
- alt: element.altText,
- block: false,
- },
- },
- ...(element.title
- ? [this.plainText(element.title, -1, key++)]
- : []),
- ],
- block: true,
- },
- };
- }
-
- return {
- component: 'image',
- props: {
- key: index,
- src: element.imageUrl,
- alt: element.altText,
- block: false,
- },
- };
- };
-
- overflow = (element: OverflowElement, _context: any, index: any): any => ({
- component: 'menu',
- props: {
- key: index,
- children: element.options.map((option, key) => ({
- component: 'menu-item',
- props: {
- key,
- children: [
- this.text(option.text, -1, 0),
- ...(option.description
- ? [this.plainText(option.description, -1, 1)]
- : []),
- ],
- value: option.value,
- ...(option.url && { url: option.url }),
- },
- })),
- },
- });
-
- datePicker = (element: any, _context: any, index: any): any => ({
- component: 'input',
- props: {
- key: index,
- type: 'date',
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- ...(element.initialDate && { defaultValue: element.initialDate }),
- },
- });
-
- staticSelect = (element: any, _context: any, index: any): any => ({
- component: 'select',
- props: {
- key: index,
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- children: element.options.map((option: any, key: any) => ({
- component: 'option',
- props: {
- key,
- children: this.text(option.text, -1, 0),
- value: option.value,
- ...(option.description && {
- description: this.text(option.description, -1, 0),
- }),
- },
- })),
- ...(element.initialOption && {
- defaultValue: element.options.find(
- (option: any) => option.value === element.initialOption.value
- )?.value,
- }),
- },
- });
-
- multiStaticSelect = (element: any, _context: any, index: any): any => ({
- component: 'select',
- props: {
- key: index,
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- multiple: true,
- children: element.options.map((option: any, key: any) => ({
- component: 'option',
- props: {
- key,
- children: this.text(option.text, -1, 0),
- value: option.value,
- ...(option.description && {
- description: this.text(option.description, -1, 0),
- }),
- },
- })),
- ...(element.initialOptions && {
- defaultValue: element.options
- .filter((option: any) =>
- element.initialOptions.some(
- (initialOption: any) => option.value === initialOption.value
- )
- )
- .map((option: any) => option.value),
- }),
- },
- });
-
- plainInput = (element: any, _context: any, index: any): any => ({
- component: 'input',
- props: {
- key: index,
- type: 'text',
- ...(element.placeholder && {
- placeholder: this.plainText(element.placeholder, -1, 0),
- }),
- ...(element.initialValue && { defaultValue: element.initialValue }),
- multiline: element.multiline ?? false,
- ...(typeof element.minLength !== 'undefined' && {
- minLength: element.minLength,
- }),
- ...(typeof element.maxLength !== 'undefined' && {
- maxLength: element.maxLength,
- }),
- },
- });
-
- linearScale = (
- { minValue = 0, maxValue = 10 }: any,
- _context: any,
- index: any
- ): any => ({
- component: 'linear-scale',
- props: {
- key: index,
- children: Array.from({ length: maxValue - minValue + 1 }).map(
- (_, key: any) => ({
- component: 'linear-scale-point',
- props: {
- key,
- children: [
- this.text(
- {
- type: 'plain_text',
- text: String(minValue + key),
- emoji: true,
- } as PlainText,
- -1,
- 0
- ),
- ],
- },
- })
- ),
- },
- });
-}
-
-const parser = new TestParser();
-const parse = uiKitContextualBar(parser);
-
-const conditionalParse = uiKitContextualBar(parser, {
- engine: 'rocket.chat',
-});
-
-describe('divider', () => {
- it('renders', () => {
- const payload = [
- {
- type: 'divider',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'divider',
- props: {
- key: 0,
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('section', () => {
- it('renders text as plain_text', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('render text as mrkdwn', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and ',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children:
- 'This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and ',
- verbatim: false,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders text fields', () => {
- const payload = [
- {
- type: 'section',
- fields: [
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 1,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 2,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 3,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 4,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as button', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with a button.',
- },
- accessory: {
- type: 'button',
- text: {
- type: 'plain_text',
- text: 'Click Me',
- emoji: true,
- },
- value: 'click_me_123',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with a button.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'button',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Click Me',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'click_me_123',
- variant: 'normal',
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as image', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with an accessory image.',
- },
- accessory: {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with an accessory image.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 1,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as overflow menu', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with an overflow menu.',
- },
- accessory: {
- type: 'overflow',
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-3',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-4',
- },
- ],
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with an overflow menu.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'menu',
- props: {
- key: 1,
- children: [
- {
- component: 'menu-item',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-0',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-1',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 2,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-2',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 3,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-3',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 4,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-4',
- },
- },
- ],
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as datepicker', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'Pick a date for the deadline.',
- },
- accessory: {
- type: 'datepicker',
- initial_date: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'Pick a date for the deadline.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- },
- },
- ]);
- });
-});
-
-describe('image', () => {
- it('renders with title', () => {
- const payload = [
- {
- type: 'image',
- title: {
- type: 'plain_text',
- text: 'I Need a Marg',
- emoji: true,
- },
- imageUrl:
- 'https://assets3.thrillist.com/v1/image/1682388/size/tl-horizontal_main.jpg',
- altText: 'marg',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'image-container',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://assets3.thrillist.com/v1/image/1682388/size/tl-horizontal_main.jpg',
- alt: 'marg',
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 1,
- children: 'I Need a Marg',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders with no title', () => {
- const payload = [
- {
- type: 'image',
- imageUrl:
- 'https://i1.wp.com/thetempest.co/wp-content/uploads/2017/08/The-wise-words-of-Michael-Scott-Imgur-2.jpg?w=1024&ssl=1',
- altText: 'inspiration',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'image-container',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://i1.wp.com/thetempest.co/wp-content/uploads/2017/08/The-wise-words-of-Michael-Scott-Imgur-2.jpg?w=1024&ssl=1',
- alt: 'inspiration',
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('actions', () => {
- it('renders all selects', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a conversation',
- emoji: true,
- },
- },
- {
- type: 'channels_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a channel',
- emoji: true,
- },
- },
- {
- type: 'users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a user',
- emoji: true,
- },
- },
- {
- type: 'static_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select an item',
- emoji: true,
- },
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- ],
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- null,
- null,
- null,
- {
- component: 'select',
- props: {
- key: 3,
- children: [
- {
- component: 'option',
- props: {
- key: 0,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-0',
- },
- },
- {
- component: 'option',
- props: {
- key: 1,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-1',
- },
- },
- {
- component: 'option',
- props: {
- key: 2,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-2',
- },
- },
- ],
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select an item',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders filtered conversations select', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select private conversation',
- emoji: true,
- },
- filter: {
- include: ['private'],
- },
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [null],
- block: true,
- },
- },
- ]);
- });
-
- it('renders selects with initial options', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a conversation',
- emoji: true,
- },
- initialConversation: 'D123',
- },
- {
- type: 'users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a user',
- emoji: true,
- },
- initialUser: 'U123',
- },
- {
- type: 'channels_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a channel',
- emoji: true,
- },
- initialChannel: 'C123',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [null, null, null],
- block: true,
- },
- },
- ]);
- });
-
- it('renders button', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'button',
- text: {
- type: 'plain_text',
- text: 'Click Me',
- emoji: true,
- },
- value: 'click_me_123',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- {
- component: 'button',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Click Me',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'click_me_123',
- variant: 'normal',
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders datepicker', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- {
- component: 'input',
- props: {
- key: 0,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('context', () => {
- it('renders plain text', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'plain_text',
- text: 'Author: K A Applegate',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Author: K A Applegate',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders mrkdwn', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'mrkdwn',
- text: '*Cat* has approved this message.',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'markdown',
- props: {
- key: 1,
- children: '*Cat* has approved this message.',
- verbatim: false,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders text and images', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'mrkdwn',
- text: '*This* is :smile: markdown',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'plain_text',
- text: 'Author: K A Applegate',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: '*This* is :smile: markdown',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 1,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 2,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 3,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 4,
- children: 'Author: K A Applegate',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('input', () => {
- it('renders multiline plain text input', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'plain_text_input',
- multiline: true,
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'text',
- multiline: true,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders plain text input', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'plain_text_input',
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'text',
- multiline: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders multi users select', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'multi_users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select users',
- emoji: true,
- },
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- null,
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders static select', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'static_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select an item',
- emoji: true,
- },
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- ],
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'select',
- props: {
- key: 1,
- children: [
- {
- component: 'option',
- props: {
- key: 0,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-0',
- },
- },
- {
- component: 'option',
- props: {
- key: 1,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-1',
- },
- },
- {
- component: 'option',
- props: {
- key: 2,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-2',
- },
- },
- ],
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select an item',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders datepicker', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders linear scale', () => {
- const payload = [
- {
- type: 'input',
- element: {
- type: 'linear_scale',
- maxValue: 2,
- },
- label: {
- type: 'plain_text',
- text: 'Label',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'input-group',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Label',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'linear-scale',
- props: {
- key: 1,
- children: [
- {
- component: 'linear-scale-point',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '0',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- {
- component: 'linear-scale-point',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '1',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- {
- component: 'linear-scale-point',
- props: {
- key: 2,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '2',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- ],
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('conditional', () => {
- it('renders when conditions match', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['rocket.chat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(conditionalParse(blocks)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders when no conditions are set', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['rocket.chat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(parse(blocks)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('does not render when conditions match', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['livechat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(conditionalParse(blocks)).toStrictEqual([]);
- });
-});
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserContextualBar.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserContextualBar.ts
deleted file mode 100644
index abab07551b..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserContextualBar.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { ActionsBlock } from '../../blocks/layout/ActionsBlock';
-import type { ContextBlock } from '../../blocks/layout/ContextBlock';
-import type { DividerBlock } from '../../blocks/layout/DividerBlock';
-import type { ImageBlock } from '../../blocks/layout/ImageBlock';
-import type { InputBlock } from '../../blocks/layout/InputBlock';
-import type { SectionBlock } from '../../blocks/layout/SectionBlock';
-import { SurfaceRenderer } from '../SurfaceRenderer';
-
-type ContextualBarSurfaceLayoutBlock =
- | ActionsBlock
- | ContextBlock
- | DividerBlock
- | ImageBlock
- | InputBlock
- | SectionBlock;
-
-export abstract class UiKitParserContextualBar<
- OutputElement
-> extends SurfaceRenderer {
- public constructor() {
- super(['actions', 'context', 'divider', 'image', 'input', 'section']);
- }
-}
-
-export type ContextualBarSurfaceLayout = ContextualBarSurfaceLayoutBlock[];
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserMessage.spec.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserMessage.spec.ts
deleted file mode 100644
index 30049de1dc..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserMessage.spec.ts
+++ /dev/null
@@ -1,1465 +0,0 @@
-import { uiKitMessage, UiKitParserMessage } from '../..';
-import { BlockContext } from '../BlockContext';
-
-class TestParser extends UiKitParserMessage {
- plain_text = (element: any, context: any, index: any): any => ({
- component: 'text',
- props: {
- key: index,
- children: element.text,
- emoji: element.emoji,
- block: context === BlockContext.BLOCK,
- },
- });
-
- mrkdwn = (element: any, context: any, index: any): any => ({
- component: 'markdown',
- props: {
- key: index,
- children: element.text,
- verbatim: Boolean(element.verbatim),
- block: context === BlockContext.BLOCK,
- },
- });
-
- divider = (_element: any, context: any, index: any): any => ({
- component: 'divider',
- props: {
- key: index,
- block: context === BlockContext.BLOCK,
- },
- });
-
- section = (element: any, context: any, index: any): any => {
- let key = 0;
- return {
- component: 'section',
- props: {
- key: index,
- children: [
- ...(element.text
- ? [this.text(element.text, BlockContext.SECTION, key++)]
- : []),
- ...(element.fields?.map((field: any) =>
- this.text(field, BlockContext.SECTION, key++)
- ) ?? []),
- ...(element.accessory
- ? [
- this.renderAccessories(
- element.accessory,
- BlockContext.SECTION,
- undefined,
- key++
- ),
- ]
- : []),
- ],
- block: context === BlockContext.BLOCK,
- },
- };
- };
-
- actions = (element: any, context: any, index: any): any => ({
- component: 'actions',
- props: {
- key: index,
- children: element.elements.map((element: any, key: number) =>
- this.renderActions(element, BlockContext.ACTION, undefined, key)
- ),
- block: context === BlockContext.BLOCK,
- },
- });
-
- context = (element: any, context: any, index: any): any => ({
- component: 'context',
- props: {
- key: index,
- children: element.elements.map((element: any, key: number) =>
- this.renderContext(element, BlockContext.CONTEXT, undefined, key)
- ),
- block: context === BlockContext.BLOCK,
- },
- });
-
- button = (element: any, context: any, index: any): any => ({
- component: 'button',
- props: {
- key: index,
- children: element.text
- ? [this.text(element.text, BlockContext.SECTION, 0)]
- : [],
- ...(element.url && { href: element.url }),
- ...(element.value && { value: element.value }),
- variant: element.style ?? 'normal',
- block: context === BlockContext.BLOCK,
- },
- });
-
- image = (element: any, context: any, index: any): any => {
- if (context === BlockContext.BLOCK) {
- let key = 0;
- return {
- component: 'image-container',
- props: {
- key: index,
- children: [
- {
- component: 'image',
- props: {
- key: key++,
- src: element.imageUrl,
- alt: element.altText,
- block: false,
- },
- },
- ...(element.title
- ? [this.plainText(element.title, -1, key++)]
- : []),
- ],
- block: true,
- },
- };
- }
-
- return {
- component: 'image',
- props: {
- key: index,
- src: element.imageUrl,
- alt: element.altText,
- block: false,
- },
- };
- };
-
- overflow = (element: any, _context: any, index: any): any => ({
- component: 'menu',
- props: {
- key: index,
- children: element.options.map((option: any, key: any) => ({
- component: 'menu-item',
- props: {
- key,
- children: [
- this.text(option.text, -1, 0),
- ...(option.description
- ? [this.plainText(option.description, -1, 1)]
- : []),
- ],
- value: option.value,
- ...(option.url && { url: option.url }),
- },
- })),
- },
- });
-
- datePicker = (element: any, _context: any, index: any): any => ({
- component: 'input',
- props: {
- key: index,
- type: 'date',
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- ...(element.initialDate && { defaultValue: element.initialDate }),
- },
- });
-
- staticSelect = (element: any, _context: any, index: any): any => ({
- component: 'select',
- props: {
- key: index,
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- children: element.options.map((option: any, key: any) => ({
- component: 'option',
- props: {
- key,
- children: this.text(option.text, -1, 0),
- value: option.value,
- ...(option.description && {
- description: this.text(option.description, -1, 0),
- }),
- },
- })),
- ...(element.initialOption && {
- defaultValue: element.options.find(
- (option: any) => option.value === element.initialOption.value
- )?.value,
- }),
- },
- });
-
- multiStaticSelect = (element: any, _context: any, index: any): any => ({
- component: 'select',
- props: {
- key: index,
- ...(element.placeholder && {
- placeholder: this.text(element.placeholder, -1, 0),
- }),
- multiple: true,
- children: element.options.map((option: any, key: any) => ({
- component: 'option',
- props: {
- key,
- children: this.text(option.text, -1, 0),
- value: option.value,
- ...(option.description && {
- description: this.text(option.description, -1, 0),
- }),
- },
- })),
- ...(element.initialOptions && {
- defaultValue: element.options
- .filter((option: any) =>
- element.initialOptions.some(
- (initialOption: any) => option.value === initialOption.value
- )
- )
- .map((option: any) => option.value),
- }),
- },
- });
-}
-
-const parser = new TestParser();
-const parse = uiKitMessage(parser);
-
-const conditionalParse = uiKitMessage(parser, {
- engine: 'rocket.chat',
-});
-
-describe('divider', () => {
- it('renders', () => {
- const payload = [
- {
- type: 'divider',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'divider',
- props: {
- key: 0,
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('section', () => {
- it('renders text as plain_text', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('render text as mrkdwn', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and ',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children:
- 'This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and ',
- verbatim: false,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders text fields', () => {
- const payload = [
- {
- type: 'section',
- fields: [
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 1,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 2,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 3,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 4,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as button', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with a button.',
- },
- accessory: {
- type: 'button',
- text: {
- type: 'plain_text',
- text: 'Click Me',
- emoji: true,
- },
- value: 'click_me_123',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with a button.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'button',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Click Me',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'click_me_123',
- variant: 'normal',
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as image', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with an accessory image.',
- },
- accessory: {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with an accessory image.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 1,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as overflow menu', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'This is a section block with an overflow menu.',
- },
- accessory: {
- type: 'overflow',
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-3',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-4',
- },
- ],
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'This is a section block with an overflow menu.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'menu',
- props: {
- key: 1,
- children: [
- {
- component: 'menu-item',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-0',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 1,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-1',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 2,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-2',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 3,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-3',
- },
- },
- {
- component: 'menu-item',
- props: {
- key: 4,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'value-4',
- },
- },
- ],
- },
- },
- ],
- },
- },
- ]);
- });
-
- it('renders accessory as datepicker', () => {
- const payload = [
- {
- type: 'section',
- text: {
- type: 'mrkdwn',
- text: 'Pick a date for the deadline.',
- },
- accessory: {
- type: 'datepicker',
- initial_date: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- block: true,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: 'Pick a date for the deadline.',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- },
- },
- ]);
- });
-});
-
-describe('image', () => {
- it('renders with title', () => {
- const payload = [
- {
- type: 'image',
- title: {
- type: 'plain_text',
- text: 'I Need a Marg',
- emoji: true,
- },
- imageUrl:
- 'https://assets3.thrillist.com/v1/image/1682388/size/tl-horizontal_main.jpg',
- altText: 'marg',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'image-container',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://assets3.thrillist.com/v1/image/1682388/size/tl-horizontal_main.jpg',
- alt: 'marg',
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 1,
- children: 'I Need a Marg',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders with no title', () => {
- const payload = [
- {
- type: 'image',
- imageUrl:
- 'https://i1.wp.com/thetempest.co/wp-content/uploads/2017/08/The-wise-words-of-Michael-Scott-Imgur-2.jpg?w=1024&ssl=1',
- altText: 'inspiration',
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'image-container',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://i1.wp.com/thetempest.co/wp-content/uploads/2017/08/The-wise-words-of-Michael-Scott-Imgur-2.jpg?w=1024&ssl=1',
- alt: 'inspiration',
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('actions', () => {
- it('renders all selects', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a conversation',
- emoji: true,
- },
- },
- {
- type: 'channels_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a channel',
- emoji: true,
- },
- },
- {
- type: 'users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a user',
- emoji: true,
- },
- },
- {
- type: 'static_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select an item',
- emoji: true,
- },
- options: [
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-0',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-1',
- },
- {
- text: {
- type: 'plain_text',
- text: '*this is plain_text text*',
- emoji: true,
- },
- value: 'value-2',
- },
- ],
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- null,
- null,
- null,
- {
- component: 'select',
- props: {
- key: 3,
- children: [
- {
- component: 'option',
- props: {
- key: 0,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-0',
- },
- },
- {
- component: 'option',
- props: {
- key: 1,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-1',
- },
- },
- {
- component: 'option',
- props: {
- key: 2,
- children: {
- component: 'text',
- props: {
- key: 0,
- children: '*this is plain_text text*',
- emoji: true,
- block: false,
- },
- },
- value: 'value-2',
- },
- },
- ],
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select an item',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders filtered conversations select', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select private conversation',
- emoji: true,
- },
- filter: {
- include: ['private'],
- },
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [null],
- block: true,
- },
- },
- ]);
- });
-
- it('renders selects with initial options', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'conversations_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a conversation',
- emoji: true,
- },
- initialConversation: 'D123',
- },
- {
- type: 'users_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a user',
- emoji: true,
- },
- initialUser: 'U123',
- },
- {
- type: 'channels_select',
- placeholder: {
- type: 'plain_text',
- text: 'Select a channel',
- emoji: true,
- },
- initialChannel: 'C123',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [null, null, null],
- block: true,
- },
- },
- ]);
- });
-
- it('renders button', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'button',
- text: {
- type: 'plain_text',
- text: 'Click Me',
- emoji: true,
- },
- value: 'click_me_123',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- {
- component: 'button',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Click Me',
- emoji: true,
- block: false,
- },
- },
- ],
- value: 'click_me_123',
- variant: 'normal',
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders datepicker', () => {
- const payload = [
- {
- type: 'actions',
- elements: [
- {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- {
- type: 'datepicker',
- initialDate: '1990-04-28',
- placeholder: {
- type: 'plain_text',
- text: 'Select a date',
- emoji: true,
- },
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'actions',
- props: {
- key: 0,
- children: [
- {
- component: 'input',
- props: {
- key: 0,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- {
- component: 'input',
- props: {
- key: 1,
- type: 'date',
- defaultValue: '1990-04-28',
- placeholder: {
- component: 'text',
- props: {
- key: 0,
- children: 'Select a date',
- emoji: true,
- block: false,
- },
- },
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('context', () => {
- it('renders plain text', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'plain_text',
- text: 'Author: K A Applegate',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'Author: K A Applegate',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders mrkdwn', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'mrkdwn',
- text: '*Cat* has approved this message.',
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'image',
- props: {
- key: 0,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'markdown',
- props: {
- key: 1,
- children: '*Cat* has approved this message.',
- verbatim: false,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders text and images', () => {
- const payload = [
- {
- type: 'context',
- elements: [
- {
- type: 'mrkdwn',
- text: '*This* is :smile: markdown',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'image',
- imageUrl:
- 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- altText: 'cute cat',
- },
- {
- type: 'plain_text',
- text: 'Author: K A Applegate',
- emoji: true,
- },
- ],
- },
- ];
- expect(parse(payload)).toStrictEqual([
- {
- component: 'context',
- props: {
- key: 0,
- children: [
- {
- component: 'markdown',
- props: {
- key: 0,
- children: '*This* is :smile: markdown',
- verbatim: false,
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 1,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 2,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'image',
- props: {
- key: 3,
- src: 'https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg',
- alt: 'cute cat',
- block: false,
- },
- },
- {
- component: 'text',
- props: {
- key: 4,
- children: 'Author: K A Applegate',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-});
-
-describe('conditional', () => {
- it('renders when conditions match', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['rocket.chat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(conditionalParse(blocks)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('renders when no conditions are set', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['rocket.chat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(parse(blocks)).toStrictEqual([
- {
- component: 'section',
- props: {
- key: 0,
- children: [
- {
- component: 'text',
- props: {
- key: 0,
- children: 'This is a plain text section block.',
- emoji: true,
- block: false,
- },
- },
- ],
- block: true,
- },
- },
- ]);
- });
-
- it('does not render when conditions match', () => {
- const blocks = [
- {
- type: 'conditional',
- when: {
- engine: ['livechat'],
- },
- render: [
- {
- type: 'section',
- text: {
- type: 'plain_text',
- text: 'This is a plain text section block.',
- emoji: true,
- },
- },
- ],
- },
- ];
-
- expect(conditionalParse(blocks)).toStrictEqual([]);
- });
-});
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserMessage.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserMessage.ts
deleted file mode 100644
index 739f7db5f3..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserMessage.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import type { ActionsBlock } from '../../blocks/layout/ActionsBlock';
-import type { CalloutBlock } from '../../blocks/layout/CalloutBlock';
-import type { ContextBlock } from '../../blocks/layout/ContextBlock';
-import type { DividerBlock } from '../../blocks/layout/DividerBlock';
-import type { ImageBlock } from '../../blocks/layout/ImageBlock';
-import type { PreviewBlock } from '../../blocks/layout/PreviewBlock';
-import type { SectionBlock } from '../../blocks/layout/SectionBlock';
-import type { VideoConferenceBlock } from '../../blocks/layout/VideoConferenceBlock';
-import { SurfaceRenderer } from '../SurfaceRenderer';
-
-type MessageSurfaceLayoutBlock =
- | ActionsBlock
- | ContextBlock
- | DividerBlock
- | ImageBlock
- | SectionBlock
- | VideoConferenceBlock
- | PreviewBlock
- | CalloutBlock;
-
-export abstract class UiKitParserMessage extends SurfaceRenderer<
- OutputElement,
- MessageSurfaceLayoutBlock
-> {
- public constructor() {
- super([
- 'actions',
- 'context',
- 'divider',
- 'image',
- 'section',
- 'preview',
- 'video_conf',
- 'callout',
- ]);
- }
-}
-
-export type MessageSurfaceLayout = MessageSurfaceLayoutBlock[];
diff --git a/packages/ui-kit/src/rendering/surfaces/UiKitParserModal.spec.ts b/packages/ui-kit/src/rendering/surfaces/UiKitParserModal.spec.ts
deleted file mode 100644
index bbf9acb843..0000000000
--- a/packages/ui-kit/src/rendering/surfaces/UiKitParserModal.spec.ts
+++ /dev/null
@@ -1,1950 +0,0 @@
-import type { PlainText, OverflowElement } from '../..';
-import { uiKitModal, UiKitParserModal } from '../..';
-import { BlockContext } from '../BlockContext';
-
-class TestParser extends UiKitParserModal