Skip to content

Commit

Permalink
Closed #88
Browse files Browse the repository at this point in the history
  • Loading branch information
mantou132 committed Dec 15, 2023
1 parent 3daba6a commit fccd360
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 29 deletions.
21 changes: 21 additions & 0 deletions packages/duoyun-ui/docs/en/02-elements/segmented.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# `<dy-segmented>`

## Example

<gbp-example name="dy-segmented" direction="column" src="https://jspm.dev/duoyun-ui/elements/segmented">

```json
[
{
"value": 0,
"options": [{ "label": "Item" }, { "label": "Item 2" }, { "label": "Item 3" }],
"@change": "(evt) => evt.target.value = evt.detail"
}
]
```

</gbp-example>

## API

<gbp-api src="/src/elements/segmented.ts"></gbp-api>
17 changes: 13 additions & 4 deletions packages/duoyun-ui/docs/en/02-elements/tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@

## Example

<gbp-example
name="dy-tabs"
props='{"style": "width: 240px", "center": true, "value": 0, "data": [{"tab": "Tab 1"}, {"tab": "Tab 2"}, {"tab": "Tab 3"}], "@change": "(evt) => evt.target.value = evt.detail"}'
src="https://jspm.dev/duoyun-ui/elements/tabs"></gbp-example>
<gbp-example name="dy-tabs" src="https://jspm.dev/duoyun-ui/elements/tabs">

```json
{
"style": "width: 240px",
"center": true,
"value": 0,
"items": [{ "label": "Tab 1" }, { "label": "Tab 2" }, { "label": "Tab 3" }],
"@change": "(evt) => evt.target.value = evt.detail"
}
```

</gbp-example>

## API

Expand Down
21 changes: 21 additions & 0 deletions packages/duoyun-ui/docs/zh/02-elements/segmented.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# `<dy-segmented>`

## Example

<gbp-example name="dy-segmented" direction="column" src="https://jspm.dev/duoyun-ui/elements/segmented">

```json
[
{
"value": 0,
"options": [{ "label": "Item" }, { "label": "Item 2" }, { "label": "Item 3" }],
"@change": "(evt) => evt.target.value = evt.detail"
}
]
```

</gbp-example>

## API

<gbp-api src="/src/elements/segmented.ts"></gbp-api>
17 changes: 13 additions & 4 deletions packages/duoyun-ui/docs/zh/02-elements/tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@

## Example

<gbp-example
name="dy-tabs"
props='{"style": "width: 240px", "center": true, "value": 0, "data": [{"tab": "Tab 1"}, {"tab": "Tab 2"}, {"tab": "Tab 3"}], "@change": "(evt) => evt.target.value = evt.detail"}'
src="https://jspm.dev/duoyun-ui/elements/tabs"></gbp-example>
<gbp-example name="dy-tabs" src="https://jspm.dev/duoyun-ui/elements/tabs">

```json
{
"style": "width: 240px",
"center": true,
"value": 0,
"items": [{ "label": "Tab 1" }, { "label": "Tab 2" }, { "label": "Tab 3" }],
"@change": "(evt) => evt.target.value = evt.detail"
}
```

</gbp-example>

## API

Expand Down
6 changes: 3 additions & 3 deletions packages/duoyun-ui/src/elements/radio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ export const groupStyle = createCSSSheet(css`
}
`);

export type Option = {
export interface Option<T = any> {
label: string | TemplateResult;
value?: any;
};
value?: T;
}

/**
* @customElement dy-radio-group
Expand Down
122 changes: 122 additions & 0 deletions packages/duoyun-ui/src/elements/segmented.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { GemElement, html } from '@mantou/gem/lib/element';
import {
Emitter,
adoptedStyle,
boolattribute,
customElement,
emitter,
part,
property,
} from '@mantou/gem/lib/decorators';
import { classMap, createCSSSheet, css, partMap } from '@mantou/gem/lib/utils';

import { commonHandle } from '../lib/hotkeys';
import { theme } from '../lib/theme';

import type { Option } from './radio';

import './use';

const style = createCSSSheet(css`
:host(:where(:not([hidden]))) {
display: flex;
cursor: default;
user-select: none;
font-size: 0.875em;
line-height: 1.2;
border-radius: ${theme.normalRound};
background: ${theme.hoverBackgroundColor};
padding: 2px;
}
:host([small]) {
font-size: 0.75em;
}
:host([disabled]) {
cursor: not-allowed;
}
:host([disabled]) .segment * {
opacity: 0.5;
}
.segment {
width: 0;
flex-grow: 1;
display: flex;
justify-content: center;
gap: 0.3em;
padding: calc(0.5em - 1px) 1em;
border-radius: inherit;
min-width: 5em;
}
:host(:where(:not([disabled]))) .segment:hover {
background: ${theme.borderColor};
}
:host .segment.current {
background: ${theme.backgroundColor};
}
.icon {
flex-shrink: 0;
width: 1.2em;
}
.label {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
`);

export interface SegmentedOption<T = any> extends Option<T> {
icon?: string | Element | DocumentFragment;
}

/**
* @customElement dy-segmented
*/
@customElement('dy-segmented')
@adoptedStyle(style)
export class DuoyunSegmentedElement extends GemElement {
@part static segment: string;
@part static currentSegment: string;
@part static icon: string;

@boolattribute disabled: boolean;
@boolattribute small: boolean;

@property options?: SegmentedOption[];
@property value?: any;
@emitter change: Emitter<any>;

constructor() {
super({ delegatesFocus: true });
this.internals.role = 'group';
}

#onClick = (v: any) => {
if (this.disabled) return;
this.change(v);
};

render = () => {
if (!this.options) return html``;
return html`
${this.options.map(({ value, label, icon }, index) => {
const isCurrent = (value ?? index) === this.value;
return html`
<div
role="radio"
tabindex="0"
class=${classMap({ segment: true, current: isCurrent })}
part=${partMap({
[DuoyunSegmentedElement.segment]: true,
[DuoyunSegmentedElement.currentSegment]: isCurrent,
})}
@keydown=${commonHandle}
@click=${() => this.#onClick(value ?? index)}
>
${icon ? html`<dy-use part=${DuoyunSegmentedElement.icon} class="icon" .element=${icon}></dy-use>` : ''}
<span class="label">${label}</span>
</div>
`;
})}
`;
};
}
17 changes: 6 additions & 11 deletions packages/duoyun-ui/src/elements/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ const style = createCSSSheet(css`
height: 100%;
}
`);

export interface TabItem<T = any> {
tab: string | TemplateResult;
label: string | TemplateResult;
value?: T;
icon?: string | Element | DocumentFragment;
getContent?: () => string | TemplateResult;
Expand All @@ -103,16 +104,10 @@ export class DuoyunTabsElement extends GemElement {
@boolattribute center: boolean;
@attribute orientation: 'horizontal' | 'vertical';

/**@deprecated */
@property data?: TabItem[];
@property items?: TabItem[];
@property value?: any;
@emitter change: Emitter<any>;

get #items() {
return this.items || this.data;
}

get #orientation() {
return this.orientation || 'horizontal';
}
Expand All @@ -123,12 +118,12 @@ export class DuoyunTabsElement extends GemElement {
}

render = () => {
if (!this.#items) return html``;
if (!this.items) return html``;
let currentContent: TemplateResult | string = '';
return html`
<div part=${DuoyunTabsElement.tabs} class="tabs">
${this.#items.map(({ value, tab, icon, getContent }, index) => {
const isCurrent: boolean = (value ?? index) === this.value;
${this.items.map(({ value, label, icon, getContent }, index) => {
const isCurrent = (value ?? index) === this.value;
if (isCurrent) currentContent = getContent?.() || '';
return html`
<div
Expand All @@ -138,7 +133,7 @@ export class DuoyunTabsElement extends GemElement {
@click=${() => this.change(value ?? index)}
>
${icon ? html`<dy-use part=${DuoyunTabsElement.icon} class="icon" .element=${icon}></dy-use>` : ''}
<span tabindex="0" @keydown=${commonHandle}>${tab}</span>
<span tabindex="0" @keydown=${commonHandle}>${label}</span>
${isCurrent
? html`
<dy-divider
Expand Down
20 changes: 13 additions & 7 deletions packages/gem-book/src/plugins/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@ customElements.whenDefined('gem-book').then(() => {
return '#'.repeat(headingLevel + this.#headingLevel - 1);
};

#renderCode = (s?: string) => {
return s ? `\`${s.replace(/\|/g, '\\|').replace(/\n/g, ' ')}\`` : '';
#renderCode = (s = '', deprecated?: boolean) => {
if (!s) return '';
const code = `\`${s.replace(/\|/g, '\\|').replace(/\n/g, ' ')}\``;
return deprecated ? `~~${code}~~` : code;
};

#renderTable = <T>(list: T[], headers: string[], fields: ((data: T) => string)[]) => {
Expand Down Expand Up @@ -139,7 +141,7 @@ customElements.whenDefined('gem-book').then(() => {
staticProperties,
['Property', 'Type'].concat(constructorParams.some((e) => e.description) ? 'Description' : []),
[
({ name }) => this.#renderCode(name),
({ name, deprecated }) => this.#renderCode(name, deprecated),
({ type }) => this.#renderCode(type),
({ description = '' }) => description.replaceAll('\n', '<br>'),
],
Expand All @@ -151,7 +153,7 @@ customElements.whenDefined('gem-book').then(() => {
staticMethods,
['Method', 'Type'].concat(constructorParams.some((e) => e.description) ? 'Description' : []),
[
({ name }) => this.#renderCode(name),
({ name, deprecated }) => this.#renderCode(name, deprecated),
({ type }) => this.#renderCode(type),
({ description = '' }) => description.replaceAll('\n', '<br>'),
],
Expand All @@ -165,7 +167,8 @@ customElements.whenDefined('gem-book').then(() => {
innerWidth > 600 && constructorParams.some((e) => e.description) ? 'Description' : [],
),
[
({ name, attribute }) => this.#renderCode(name) + (attribute ? `(${this.#renderCode(attribute)})` : ''),
({ name, attribute, deprecated }) =>
this.#renderCode(name, deprecated) + (attribute ? `(${this.#renderCode(attribute)})` : ''),
({ reactive }) => (reactive ? 'Yes' : ''),
({ type }) => this.#renderCode(type),
({ description = '' }) => description.replaceAll('\n', '<br>'),
Expand All @@ -179,7 +182,7 @@ customElements.whenDefined('gem-book').then(() => {
methods.filter(({ event }) => !event),
['Method', 'Type'].concat(constructorParams.some((e) => e.description) ? 'Description' : []),
[
({ name }) => this.#renderCode(name),
({ name, deprecated }) => this.#renderCode(name, deprecated),
({ type }) => this.#renderCode(type),
({ description = '' }) => description.replaceAll('\n', '<br>'),
],
Expand All @@ -205,7 +208,10 @@ customElements.whenDefined('gem-book').then(() => {
this.#renderTable(
exports.filter(({ kindName }) => kindName === 'FunctionDeclaration' || kindName === 'ClassDeclaration'),
['Name', 'Description'],
[({ name }) => this.#renderCode(name), ({ description = '' }) => description.replaceAll('\n', '<br>')],
[
({ name, deprecated }) => this.#renderCode(name, deprecated),
({ description = '' }) => description.replaceAll('\n', '<br>'),
],
),
);
};
Expand Down

0 comments on commit fccd360

Please sign in to comment.