Skip to content

Commit

Permalink
Merge pull request #143 from 563316158/master
Browse files Browse the repository at this point in the history
feat(marquee): add 'fixed' property for marquee
  • Loading branch information
FriedRiceNoodles authored Aug 17, 2024
2 parents eb32972 + d728fdb commit e2cc95a
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 17 deletions.
12 changes: 12 additions & 0 deletions docs/example/Marquee/demos/fixedUsage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* title: 短文案固定
* description: 通过 `fixed` 属性可以控制,短文案固定、长文案滚动效果。
*/

import { Marquee } from '@banana-ui/react';

export default function BasicUsage() {
const content = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';

return <Marquee fixed content={content} />;
}
2 changes: 2 additions & 0 deletions docs/example/Marquee/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ demo:
<code src="./demos/duration.tsx"></code>
<code src="./demos/pauseWhenHover.tsx"></code>
<code src="./demos/customStyle.tsx"></code>
<code src="./demos/fixedUsage.tsx"></code>

## 属性 - Attributes & Properties

Expand All @@ -28,6 +29,7 @@ demo:
| color | 跑马灯的文本颜色 | `string` | '' |
| duration | 滚动时长(单位:s) | `number` | 20 |
| pauseWhenHover <br /> (pause-when-hover) | 鼠标悬停时是否暂停 | `boolean` | false |
| fixed | 短文案固定 | `boolean` | false |

## CSS Parts

Expand Down
7 changes: 7 additions & 0 deletions packages/banana-react/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @banana/banana-react

## 1.19.4

### Patch Changes

- Updated dependencies
- @banana-ui/banana@1.19.4

## 1.19.3

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/banana-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@banana-ui/react",
"version": "1.19.3",
"version": "1.19.4",
"description": "React components for Banana UI",
"keywords": [
"web components",
Expand Down
6 changes: 6 additions & 0 deletions packages/banana/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# banana-ui

## 1.19.4

### Patch Changes

- add fixed for marquee

## 1.19.3

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/banana/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@banana-ui/banana",
"version": "1.19.3",
"version": "1.19.4",
"description": "An UI library of web components can be used in any framework",
"keywords": [
"web components",
Expand Down
19 changes: 17 additions & 2 deletions packages/banana/src/marquee/index.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,27 @@ export default [
.marquee {
overflow: hidden;
background-color: var(--banana-marquee-background-color);
display: flex;
flex-direction: row;
align-items: center;
}
.content {
.content-normal {
overflow: hidden;
display: inline-block;
flex: 0 0 auto;
white-space: nowrap;
animation: marquee var(--banana-marquee-duration) linear infinite;
transform: translateX(var(--banana-marquee-width, 100%));
}
.content-fixed {
overflow: hidden;
display: inline-block;
flex: 0 0 auto;
white-space: nowrap;
transform: translateX(0);
}
@media (any-hover: hover) {
Expand All @@ -31,7 +46,7 @@ export default [
@keyframes marquee {
0% {
transform: translateX(0);
transform: translateX(var(--banana-marquee-width, 100%));
}
100% {
Expand Down
38 changes: 38 additions & 0 deletions packages/banana/src/marquee/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,42 @@ describe('b-marquee', () => {
expect(animationPlayState3).to.equal('running');
});
});

describe('custom fixed', () => {
it('pauses animation when content width is less than marquee width', async () => {
const element = await fixture<BMarquee>(html`<b-marquee fixed content="short content"></b-marquee>`);

// Simulate content width being less than marquee width
element._marquee!.getBoundingClientRect = () => ({ width: 100 } as DOMRect);
element._content!.getBoundingClientRect = () => ({ width: 50 } as DOMRect);

// 强制调用私有方法
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(element as any)?.firstUpdated();
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(element as any)?._calculateWidth();

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
expect((element as any)._isNormal).to.equal(false);
expect(element.style.getPropertyValue('--banana-marquee-width')).to.equal('100px');
});

it('resumes animation when content width is greater than marquee width', async () => {
const element = await fixture<BMarquee>(html`<b-marquee fixed content="a very very long content"></b-marquee>`);

// Simulate content width being greater than marquee width
element._marquee!.getBoundingClientRect = () => ({ width: 100 } as DOMRect);
element._content!.getBoundingClientRect = () => ({ width: 200 } as DOMRect);

// 强制调用私有方法
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(element as any)?.firstUpdated();
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(element as any)?._calculateWidth();

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
expect((element as any)._isNormal).to.equal(true);
expect(element.style.getPropertyValue('--banana-marquee-width')).to.equal('100px');
});
});
});
66 changes: 57 additions & 9 deletions packages/banana/src/marquee/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { CSSResultGroup, html, LitElement, PropertyValueMap } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { customElement, property, query, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import styles from './index.styles';

@customElement('b-marquee')
export default class BMarquee extends LitElement {
static styles?: CSSResultGroup = styles;
private resizeObserver: ResizeObserver | undefined;

connectedCallback() {
super.connectedCallback();
}

disconnectedCallback() {
super.disconnectedCallback();
// 停止观察元素的尺寸变化
this._marquee && this.resizeObserver?.unobserve(this._marquee);
}

@property()
Expand All @@ -28,6 +31,46 @@ export default class BMarquee extends LitElement {
@property({ type: Boolean, attribute: 'pause-when-hover' })
pauseWhenHover = false;

@property({ type: Boolean, reflect: true })
fixed = false;

// 判断是否是 normal还是fixed (fixed为true时,才生效)
@state()
_isNormal = true;

@query('.marquee')
_marquee: HTMLDivElement | undefined;

@query('.content')
_content: HTMLDivElement | undefined;

firstUpdated() {
this._setBananaMarqueeWidth();

// 观察元素的尺寸变化
if (this._marquee) {
this.resizeObserver = new ResizeObserver(() => this._calculateWidth());

this.resizeObserver?.observe(this._marquee);
}
}

private _calculateWidth() {
// marquee的宽度变化了 重新设置marquee的宽度
this._setBananaMarqueeWidth();

if (this._marquee && this._content && this.fixed) {
const marqueeWidth = this._marquee.getBoundingClientRect().width;
const contentWidth = this._content.getBoundingClientRect().width;

this._isNormal = contentWidth > marqueeWidth;
}
}

private _setBananaMarqueeWidth() {
this.style.setProperty('--banana-marquee-width', `${this._marquee!.getBoundingClientRect().width}px`);
}

protected willUpdate(_changedProperties: PropertyValueMap<this>): void {
if (_changedProperties.has('color')) {
const color = this.color ?? '';
Expand All @@ -41,15 +84,20 @@ export default class BMarquee extends LitElement {
}

render() {
const marqueeClass = classMap({
marquee: true,
'marquee--pause-when-hover': this.pauseWhenHover,
});

const contentClass = classMap({
content: true,
'content-normal': this._isNormal,
'content-fixed': !this._isNormal,
});

return html`
<div
part="base"
class=${classMap({
marquee: true,
'marquee--pause-when-hover': this.pauseWhenHover,
})}
>
<div part="content" class="content">${this.content}</div>
<div part="base" class=${marqueeClass}>
<div part="content" class=${contentClass}>${this.content}</div>
</div>
`;
}
Expand Down
8 changes: 4 additions & 4 deletions packages/banana/src/select/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ describe('b-select', () => {
element.open = true;
const clearIcon = element.shadowRoot?.querySelector('.clear-icon-container');
// mouse event
clearIcon.dispatchEvent(new MouseEvent('click'));
clearIcon?.dispatchEvent(new MouseEvent('click'));
expect(element.value).to.equal('');
// should close the listbox.
expect(element.open).to.equal(false);
Expand All @@ -390,7 +390,7 @@ describe('b-select', () => {
`);
multipleElement.open = true;
const multipleClearIcon = multipleElement.shadowRoot?.querySelector('.clear-icon-container');
multipleClearIcon.dispatchEvent(new MouseEvent('click'));
multipleClearIcon?.dispatchEvent(new MouseEvent('click'));
expect(multipleElement.value).to.deep.equal([]);
// should close the listbox.
expect(multipleElement.open).to.equal(false);
Expand All @@ -406,7 +406,7 @@ describe('b-select', () => {
`);
element.open = true;
const clearIcon = element.shadowRoot?.querySelector('.clear-icon-container');
clearIcon.dispatchEvent(new MouseEvent('click'));
clearIcon?.dispatchEvent(new MouseEvent('click'));
expect(element.open).to.equal(true);
});
});
Expand Down Expand Up @@ -553,7 +553,7 @@ describe('b-select', () => {
await element.updateComplete;

const clearIcon = element.shadowRoot?.querySelector('.clear-icon-container');
clearIcon.dispatchEvent(new MouseEvent('click'));
clearIcon?.dispatchEvent(new MouseEvent('click'));

await element.updateComplete;

Expand Down
2 changes: 2 additions & 0 deletions public/Marquee/fixedUsage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<b-marquee fixed
content="Lorem ipsum dolor sit amet, consectetur adipiscing elit."></b-marquee>

0 comments on commit e2cc95a

Please sign in to comment.