Skip to content

Commit

Permalink
feat: added skeleton component
Browse files Browse the repository at this point in the history
feat: added skeleton component
  • Loading branch information
baiwusanyu-c committed Feb 29, 2024
2 parents d58ee08 + c0101dd commit 5cc6b6e
Show file tree
Hide file tree
Showing 22 changed files with 829 additions and 164 deletions.
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
engine-strict=true
resolution-mode=highest
registry=https://registry.npmmirror.com
32 changes: 32 additions & 0 deletions components/Skeleton/__test__/skeleton.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import KSkeleton 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: KSkeleton', () => {
test('props: cls', async () => {
const instance = new KSkeleton({
target: host,
props: {
cls: 'k-skeleton--test'
}
});
expect(instance).toBeTruthy();
expect(host!.innerHTML.includes('k-skeleton--test')).toBeTruthy();
expect(host.innerHTML).matchSnapshot();
});
});
48 changes: 48 additions & 0 deletions components/Skeleton/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@ikun-ui/skeleton",
"version": "0.2.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.18",
"clsx": "^2.0.0"
},
"devDependencies": {
"@tsconfig/svelte": "^5.0.2",
"svelte-strip": "^2.0.0",
"tslib": "^2.6.2",
"typescript": "^5.3.3"
}
}
29 changes: 29 additions & 0 deletions components/Skeleton/src/avatar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import { getPrefixCls } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import type { KSkeletonAvatarProps } from './types';
export let active: KSkeletonAvatarProps['active'] = false;
export let size: KSkeletonAvatarProps['size'] = 'md';
export let shape: KSkeletonAvatarProps['shape'] = 'circle';
export let cls: KSkeletonAvatarProps['cls'] = '';
export let attrs: KSkeletonAvatarProps['attrs'] = {};
const prefixCls = getPrefixCls('skeleton-avatar');
const prefixClsSke = getPrefixCls('skeleton');
const prefixClsContainer = getPrefixCls('skeleton-avatar-container');
$: containerCls = clsx(`${prefixClsContainer}--${size}`);
$: cnames = clsx(
prefixCls,
`${prefixCls}--${size}`,
`${prefixCls}--${shape}`,
{
[`${prefixClsSke}--active`]: active
},
cls
);
</script>

<div class={containerCls} {...$$restProps} {...attrs}>
<div class={cnames}></div>
</div>
32 changes: 32 additions & 0 deletions components/Skeleton/src/button.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts">
import { getPrefixCls } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import type { KSkeletonButtonProps } from './types';
export let active: KSkeletonButtonProps['active'] = false;
export let shape: KSkeletonButtonProps['shape'] = 'round';
export let block: KSkeletonButtonProps['block'] = false;
export let size: KSkeletonButtonProps['size'] = 'md';
export let cls: KSkeletonButtonProps['cls'] = '';
export let attrs: KSkeletonButtonProps['attrs'] = {};
const prefixCls = getPrefixCls('skeleton-button');
const prefixClsSke = getPrefixCls('skeleton');
$: cnames = clsx(
prefixCls,
{
[`${prefixCls}--${shape}--${size}`]: shape === 'circle'
},
{
[`${prefixCls}--${size}`]: !block && shape !== 'circle',
[`${prefixCls}--${shape}`]: shape !== 'circle',
[`${prefixCls}--block--${size}`]: block && shape !== 'circle'
},
{
[`${prefixClsSke}--active`]: active,
[`${prefixCls}-un--active`]: !active
},
cls
);
</script>

<button class={cnames} {...$$restProps} {...attrs}></button>
27 changes: 27 additions & 0 deletions components/Skeleton/src/image.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { getPrefixCls } from '@ikun-ui/utils';
import { KIcon } from '@ikun-ui/icon';
import { clsx } from 'clsx';
import type { KSkeletonImageProps } from './types';
export let active: KSkeletonImageProps['active'] = false;
export let cls: KSkeletonImageProps['cls'] = '';
export let attrs: KSkeletonImageProps['attrs'] = {};
const prefixCls = getPrefixCls('skeleton-image');
const prefixClsSke = getPrefixCls('skeleton');
$: cnames = clsx(
prefixCls,
{
[`${prefixClsSke}--active`]: active,
[`${prefixCls}-un--active`]: !active
},
cls
);
const iconCls = clsx(`${prefixCls}--icon`);
</script>

<div class={cnames} {...$$restProps} {...attrs}>
<slot>
<KIcon cls={iconCls} icon="i-carbon-image" width="50px" height="50px"></KIcon>
</slot>
</div>
82 changes: 82 additions & 0 deletions components/Skeleton/src/index.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<script lang="ts">
import { getPrefixCls } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import type {
KSkeletonAvatarProps,
KSkeletonParagraphProps,
KSkeletonProps,
KSkeletonTitleProps
} from './types';
import KSkeletonTitle from './title.svelte';
import KSkeletonParagraph from './paragraph.svelte';
import KSkeletonAvatar from './avatar.svelte';
import { isObject } from 'baiwusanyu-utils';
export let loading: KSkeletonProps['loading'] = false;
export let title: KSkeletonProps['title'] = true;
export let paragraph: KSkeletonProps['paragraph'] = true;
export let avatar: KSkeletonProps['avatar'] = false;
export let size: KSkeletonProps['size'] = 'md';
export let active: KSkeletonProps['active'] = false;
export let cls: KSkeletonProps['cls'] = '';
export let attrs: KSkeletonProps['attrs'] = {};
const prefixCls = getPrefixCls('skeleton');
$: avatarSize = isObject(avatar) ? (avatar as KSkeletonAvatarProps).size || size : size;
$: cnames = clsx(prefixCls, cls);
$: contentCls = clsx(`${prefixCls}-content--${avatarSize}`);
$: headerCls = clsx(`${prefixCls}-header`);
$: titleProps = isObject(title)
? {
size,
active,
...(title as KSkeletonTitleProps)
}
: {
size,
active
};
$: paragraphProps = isObject(paragraph)
? {
size,
active,
...(paragraph as KSkeletonParagraphProps)
}
: {
size,
active
};
$: avatarProps = isObject(avatar)
? {
size: avatarSize,
active,
...(avatar as KSkeletonAvatarProps)
}
: {
size: avatarSize,
active
};
</script>

<div class={cnames} {...$$restProps} {...attrs}>
{#if loading}
<slot name="skeleton">
<div class={headerCls}>
{#if avatar}
<KSkeletonAvatar {...avatarProps}></KSkeletonAvatar>
{/if}
{#if title}
<KSkeletonTitle {...titleProps}></KSkeletonTitle>
{/if}
</div>

<div class={contentCls}>
{#if paragraph}
<KSkeletonParagraph {...paragraphProps}></KSkeletonParagraph>
{/if}
</div>
</slot>
{:else}
<slot />
{/if}
</div>
14 changes: 14 additions & 0 deletions components/Skeleton/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// <reference types="./types" />
import Skeleton from './index.svelte';
import SkeletonTitle from './title.svelte';
import SkeletonParagraph from './paragraph.svelte';
import SkeletonButton from './button.svelte';
import SkeletonInput from './input.svelte';
import SkeletonImage from './image.svelte';
export { Skeleton as KSkeleton };
export { SkeletonTitle as KSkeletonTitle };
export { SkeletonParagraph as KSkeletonParagraph };
export { SkeletonButton as KSkeletonButton };
export { SkeletonInput as KSkeletonInput };
export { SkeletonImage as KSkeletonImage };
export default Skeleton;
26 changes: 26 additions & 0 deletions components/Skeleton/src/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts">
import { getPrefixCls } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import type { KSkeletonInputProps } from './types';
export let active: KSkeletonInputProps['active'] = false;
export let block: KSkeletonInputProps['block'] = false;
export let size: KSkeletonInputProps['size'] = 'md';
export let cls: KSkeletonInputProps['cls'] = '';
export let attrs: KSkeletonInputProps['attrs'] = {};
const prefixCls = getPrefixCls('skeleton-input');
const prefixClsSke = getPrefixCls('skeleton');
$: cnames = clsx(
prefixCls,
{
[`${prefixCls}--${size}`]: !block,
[`${prefixCls}--block--${size}`]: block
},
{
[`${prefixClsSke}--active`]: active
},
cls
);
</script>

<input class={cnames} {...$$restProps} {...attrs} readonly />
43 changes: 43 additions & 0 deletions components/Skeleton/src/paragraph.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang="ts">
import { getPrefixCls } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import type { KSkeletonParagraphProps } from './types';
import { isArray } from 'baiwusanyu-utils';
export let width: KSkeletonParagraphProps['width'] = undefined;
export let active: KSkeletonParagraphProps['active'] = false;
export let size: KSkeletonParagraphProps['size'] = 'md';
export let rows: KSkeletonParagraphProps['rows'] = 3;
export let cls: KSkeletonParagraphProps['cls'] = '';
export let attrs: KSkeletonParagraphProps['attrs'] = {};
const prefixCls = getPrefixCls('skeleton-paragraph');
const prefixClsSke = getPrefixCls('skeleton');
$: cnames = clsx(prefixCls, cls);
$: itemCls = clsx(`${prefixCls}--item`, `${prefixCls}--${size}`, {
[`${prefixClsSke}--active`]: active
});
let list: Array<{ width: string }> = [];
$: {
list = [];
for (let i = 0; i < rows!; i++) {
const item = { width: '100%' };
if (width && isArray(width) && (width as Array<number | string>)[i]) {
item.width = `${(width as Array<number | string>)[i]}px`;
} else if (i === rows! - 1 && width) {
item.width = `${width}px`;
} else if (i === rows! - 1 && !width) {
item.width = `60%`;
}
list.push(item);
}
}
</script>

<ul class={cnames} {...$$restProps} {...attrs}>
{#each list as item}
<li style:width={item.width} class={itemCls}></li>
{/each}
</ul>
27 changes: 27 additions & 0 deletions components/Skeleton/src/title.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { getPrefixCls } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import type { KSkeletonTitleProps } from './types';
export let width: KSkeletonTitleProps['width'] = undefined;
export let active: KSkeletonTitleProps['active'] = false;
export let size: KSkeletonTitleProps['size'] = 'md';
export let cls: KSkeletonTitleProps['cls'] = '';
export let attrs: KSkeletonTitleProps['attrs'] = {};
const prefixCls = getPrefixCls('skeleton-title');
const prefixClsSke = getPrefixCls('skeleton');
$: cnames = clsx(
prefixCls,
`${prefixCls}--${size}`,
{
[`${prefixClsSke}--active`]: active,
[`${prefixCls}-un--active`]: !active
},
cls
);
$: styleWidth = width === undefined || width === null ? '50%' : `${width}`;
</script>

<div class={cnames} style:width={styleWidth} {...$$restProps} {...attrs}></div>
Loading

0 comments on commit 5cc6b6e

Please sign in to comment.