Skip to content

Commit

Permalink
feat: added KScrollbar component (#379)
Browse files Browse the repository at this point in the history
  • Loading branch information
baiwusanyu-c committed Dec 28, 2023
1 parent 807b491 commit 6e56664
Show file tree
Hide file tree
Showing 28 changed files with 418 additions and 75 deletions.
23 changes: 12 additions & 11 deletions components/Divider/__test__/divider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { afterEach, expect, test, describe, beforeEach } from 'vitest';
import KDivider from '../src';
import KDividerContent from './fixture/divider.content.slot.test.svelte';

let host: HTMLElement;
let host;

const initHost = () => {
host = document.createElement('div');
host = globalThis.document.createElement('div');
host.setAttribute('id', 'host');
document.body.appendChild(host);
globalThis.document.body.appendChild(host);
};
beforeEach(() => {
initHost();
Expand All @@ -26,7 +26,7 @@ describe('Test: KDivider', () => {
}
});
expect(instance).toBeTruthy();
expect((host as HTMLElement)!.innerHTML.includes('k-divider--test')).toBeTruthy();
expect(host!.innerHTML.includes('k-divider--test')).toBeTruthy();
expect(host.innerHTML).matchSnapshot();
});

Expand All @@ -38,10 +38,10 @@ describe('Test: KDivider', () => {
}
});
expect(instance).toBeTruthy();
expect((host as HTMLElement)!.innerHTML.includes('k-divider--horizontal')).toBeTruthy();
expect(host!.innerHTML.includes('k-divider--horizontal')).toBeTruthy();
instance.$set({ direction: 'vertical' });
await tick();
expect((host as HTMLElement)!.innerHTML.includes('k-divider--vertical')).toBeTruthy();
expect(host!.innerHTML.includes('k-divider--vertical')).toBeTruthy();
expect(host.innerHTML).matchSnapshot();
});

Expand All @@ -53,10 +53,10 @@ describe('Test: KDivider', () => {
}
});
expect(instance).toBeTruthy();
expect((host as HTMLElement)!.innerHTML.includes('b-red')).toBeTruthy();
expect(host!.innerHTML.includes('b-red')).toBeTruthy();
instance.$set({ borderColor: 'b-blue' });
await tick();
expect((host as HTMLElement)!.innerHTML.includes('b-blue')).toBeTruthy();
expect(host!.innerHTML.includes('b-blue')).toBeTruthy();
expect(host.innerHTML).matchSnapshot();
});

Expand All @@ -69,17 +69,18 @@ describe('Test: KDivider', () => {
}
});
expect(instance).toBeTruthy();
expect((host as HTMLElement)!.innerHTML.includes('k-divider--horizontal__solid')).toBeTruthy();
expect(host!.innerHTML.includes('k-divider--horizontal__solid')).toBeTruthy();
instance.$set({ borderStyle: 'dotted' });
await tick();
expect((host as HTMLElement)!.innerHTML.includes('k-divider--horizontal__dotted')).toBeTruthy();
expect(host!.innerHTML.includes('k-divider--horizontal__dotted')).toBeTruthy();
instance.$set({ direction: 'vertical', borderStyle: 'dashed' });
await tick();
expect((host as HTMLElement)!.innerHTML.includes('k-divider--vertical__dashed')).toBeTruthy();
expect(host!.innerHTML.includes('k-divider--vertical__dashed')).toBeTruthy();
expect(host.innerHTML).matchSnapshot();
});

test('slots: content', async () => {
//@ts-ignore
const instance = new KDividerContent({
target: host
});
Expand Down
10 changes: 5 additions & 5 deletions components/Dropdown/__test__/__snapshots__/dropdown.spec.ts.snap

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions components/Dropdown/__test__/dropdown.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ describe('Test: KDropdown', () => {
await fireEvent.click(btn);
await tick();
await vi.advanceTimersByTimeAsync(300);
expect(host!.innerHTML.includes('ikun-scroll-bar')).toBeTruthy();
expect(host!.innerHTML.includes('style="max-height: 10px;"')).toBeTruthy();
expect(host!.innerHTML.includes('k-scrollbar')).toBeTruthy();
expect(host!.innerHTML.includes('max-height: 10px')).toBeTruthy();
expect(host!.innerHTML.includes('白发三千丈')).toBeTruthy();
expect(host.innerHTML).matchSnapshot();
});
Expand All @@ -80,6 +80,7 @@ describe('Test: KDropdown', () => {
const instance = new KDropdownChange({
target: host
});
// @ts-ignore
instance.$on('change', (v) => {
mockFn();
show = v.detail;
Expand Down Expand Up @@ -175,6 +176,7 @@ describe('Test: KDropdown', () => {
const instance = new KDropdownItemCommand({
target: host
});
// @ts-ignore
instance.$on('command', (v) => {
mockFn();
value = v.detail;
Expand Down
1 change: 1 addition & 0 deletions components/Dropdown/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"dependencies": {
"@ikun-ui/icon": "workspace:*",
"@ikun-ui/popover": "workspace:*",
"@ikun-ui/scrollbar": "workspace:*",
"@ikun-ui/utils": "workspace:*",
"baiwusanyu-utils": "^1.0.16",
"clsx": "^2.0.0"
Expand Down
22 changes: 4 additions & 18 deletions components/Dropdown/src/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import type { KDropdownProps } from './types';
import { KPopover } from '@ikun-ui/popover';
import { createEventDispatcher, setContext } from 'svelte';
import { KScrollbar } from '@ikun-ui/scrollbar/src/index.js';
export let placement: KDropdownProps['placement'] = 'bottom';
// hover click manual
Expand Down Expand Up @@ -61,7 +62,7 @@
const prefixCls = getPrefixCls('dropdown');
$: cnames = clsx(prefixCls, cls);
$: itmeCls = clsx(`${prefixCls}-item-container`, 'ikun-scroll-bar');
$: itmeCls = clsx(`${prefixCls}-item-container`);
</script>

<KPopover
Expand All @@ -77,22 +78,7 @@
<button class={cnames} {...$$restProps} {role} {tabindex} {...attrs} slot="triggerEl">
<slot />
</button>
<div slot="contentEl" class={itmeCls} style:max-height={maxHeight}>
<KScrollbar slot="contentEl" cls={itmeCls} css={`max-height: ${maxHeight}`}>
<slot name="dropdown" />
</div>
</KScrollbar>
</KPopover>

<style>
:global(.ikun-scroll-bar::-webkit-scrollbar-track-piece) {
background: transparent;
}
:global(.ikun-scroll-bar::-webkit-scrollbar) {
width: 6px;
}
:global(.ikun-scroll-bar::-webkit-scrollbar-thumb) {
background: var(--ikun-light-800);
border-radius: 20px;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Test: KScrollbar > basic render 1`] = `"<div class=\\"k-scrollbar k-scrollbar--test\\" style=\\"--k-scrollbar--thumb__radius: 50px; --k-scrollbar--thumb: red; --k-scrollbar__h: 10px; --k-scrollbar__w: 10px; --k-scrollbar--track__radius: 50px; --k-scrollbar--track: green;\\"></div>"`;
exports[`Test: KScrollbar > props: cls 1`] = `"<div class=\\"k-scrollbar k-scrollbar--test\\" style=\\"--k-scrollbar--thumb__radius: 20px; --k-scrollbar--thumb: var(--ikun-light-800); --k-scrollbar__h: 6px; --k-scrollbar__w: 6px; --k-scrollbar--track__radius: 20px; --k-scrollbar--track: transparent;\\"></div>"`;
49 changes: 49 additions & 0 deletions components/Scrollbar/__test__/scrollbar.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import KScrollbar from '../src';

let host;

const initHost = () => {
host = globalThis.document.createElement('div');
host.setAttribute('id', 'host');
globalThis.document.body.appendChild(host);
};
beforeEach(() => {
initHost();
vi.useFakeTimers();
});
afterEach(() => {
host.remove();
vi.useRealTimers();
});

describe('Test: KScrollbar', () => {
test('props: cls', async () => {
const instance = new KScrollbar({
target: host,
props: {
cls: 'k-scrollbar--test'
}
});
expect(instance).toBeTruthy();
expect(host!.innerHTML.includes('k-scrollbar--test')).toBeTruthy();
expect(host.innerHTML).matchSnapshot();
});

test('basic render', async () => {
const instance = new KScrollbar({
target: host,
props: {
cls: 'k-scrollbar--test',
width: '10px',
height: '10px',
thumbBackground: 'red',
thumbRadius: '50px',
trackRadius: '50px',
trackBackground: 'green'
}
});
expect(instance).toBeTruthy();
expect(host.innerHTML).matchSnapshot();
});
});
48 changes: 48 additions & 0 deletions components/Scrollbar/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@ikun-ui/scrollbar",
"version": "0.1.0",
"type": "module",
"main": "src/index.ts",
"types": "src/index.d.ts",
"svelte": "src/index.ts",
"keywords": [
"svelte",
"svelte3",
"web component",
"component",
"react",
"vue",
"svelte-kit",
"dx"
],
"files": [
"dist",
"package.json"
],
"scripts": {
"build": "npm run build:js && npm run build:svelte",
"build:js": "tsc -p . --outDir dist/ --rootDir src/",
"build:svelte": "svelte-strip strip src/ dist",
"publish:pre": "node ../../scripts/pre-publish.js",
"publish:npm": "pnpm run publish:pre && pnpm publish --no-git-checks --access public"
},
"publishConfig": {
"access": "public",
"main": "dist/index.js",
"module": "dist/index.js",
"svelte": "dist/index.js",
"types": "dist/index.d.ts"
},
"dependencies": {
"@ikun-ui/icon": "workspace:*",
"@ikun-ui/utils": "workspace:*",
"baiwusanyu-utils": "^1.0.16",
"clsx": "^2.0.0"
},
"devDependencies": {
"@tsconfig/svelte": "^5.0.2",
"svelte-strip": "^2.0.0",
"tslib": "^2.6.2",
"typescript": "^5.3.2"
}
}
60 changes: 60 additions & 0 deletions components/Scrollbar/src/index.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script lang="ts">
import { getPrefixCls } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import type { KScrollbarProps } from './types';
import { genCSSVariable, scrollDefaultProps } from './utils';
export let css: KScrollbarProps['css'] = scrollDefaultProps.css;
export let trackBackground: KScrollbarProps['trackBackground'] =
scrollDefaultProps.trackBackground;
export let trackRadius: KScrollbarProps['trackRadius'] = scrollDefaultProps.trackRadius;
export let width: KScrollbarProps['width'] = scrollDefaultProps.width;
export let height: KScrollbarProps['height'] = scrollDefaultProps.height;
export let thumbBackground: KScrollbarProps['thumbBackground'] =
scrollDefaultProps.thumbBackground;
export let thumbRadius: KScrollbarProps['thumbRadius'] = scrollDefaultProps.thumbRadius;
export let cls: KScrollbarProps['cls'] = scrollDefaultProps.cls;
export let attrs: KScrollbarProps['attrs'] = scrollDefaultProps.attrs;
let style = css;
$: {
style = genCSSVariable({
css,
trackBackground,
trackRadius,
width,
height,
thumbBackground,
thumbRadius,
cls,
attrs
});
}
let element: HTMLDivElement | null = null;
export function getElm() {
return element;
}
const prefixCls = getPrefixCls('scrollbar');
$: cnames = clsx(prefixCls, cls);
</script>

<div class={cnames} bind:this={element} {...$$restProps} {...attrs} {style}>
<slot />
</div>

<style>
:global(.k-scrollbar::-webkit-scrollbar-track-piece) {
background: var(--k-scrollbar--track);
border-radius: var(--k-scrollbar--track__radius);
}
:global(.k-scrollbar::-webkit-scrollbar) {
width: var(--k-scrollbar__w);
height: var(--k-scrollbar__h);
}
:global(.k-scrollbar::-webkit-scrollbar-thumb) {
background: var(--k-scrollbar--thumb);
border-radius: var(--k-scrollbar--thumb__radius);
}
</style>
5 changes: 5 additions & 0 deletions components/Scrollbar/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="./types" />
import Scrollbar from './index.svelte';
export { Scrollbar as KScrollbar };
export { scrollDefaultProps, genCSSVariable } from './utils';
export default Scrollbar;
13 changes: 13 additions & 0 deletions components/Scrollbar/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/// <reference types="svelte" />
import type { ClassValue } from 'clsx';
export type KScrollbarProps = {
css: string;
trackBackground: string;
trackRadius: string;
width: string;
height: string;
thumbBackground: string;
thumbRadius: string;
cls: ClassValue;
attrs: Record<string, string>;
};
34 changes: 34 additions & 0 deletions components/Scrollbar/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { KScrollbarProps } from './types';

export const scrollDefaultProps: KScrollbarProps = {
css: '',
trackBackground: 'transparent',
trackRadius: '20px',
width: '6px',
height: '6px',
thumbBackground: 'var(--ikun-light-800)',
thumbRadius: '20px',
cls: undefined,
attrs: {}
};

export const genCSSVariable = (props: KScrollbarProps) => {
const cssVariable = {
['--k-scrollbar--track']: props.trackBackground,
['--k-scrollbar--track__radius']: props.trackRadius,
['--k-scrollbar__w']: props.width,
['--k-scrollbar__h']: props.height,
['--k-scrollbar--thumb']: props.thumbBackground,
['--k-scrollbar--thumb__radius']: props.thumbRadius
};

let style = props.css;
Object.keys(cssVariable).forEach((k) => {
const value = cssVariable[k as keyof typeof cssVariable];
if (value) {
style = `${k}: ${value};${style}`;
}
});

return style;
};
11 changes: 11 additions & 0 deletions components/Scrollbar/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",

"compilerOptions": {
"noImplicitAny": true,
"strict": true,
"declaration": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.svelte"],
"exclude": ["node_modules/*", "**/*.spec.ts"]
}
Loading

0 comments on commit 6e56664

Please sign in to comment.