Skip to content

Commit

Permalink
[duoyun-ui] Fixed <dy-form> dup change event
Browse files Browse the repository at this point in the history
  • Loading branch information
mantou132 committed Jan 25, 2024
1 parent 2140dd2 commit 34d4585
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 59 deletions.
2 changes: 1 addition & 1 deletion packages/duoyun-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "duoyun-ui",
"version": "1.1.16",
"version": "1.1.17",
"description": "A lightweight desktop UI component library, implemented using Gem",
"keywords": [
"frontend",
Expand Down
27 changes: 14 additions & 13 deletions packages/duoyun-ui/src/elements/date-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const style = createCSSSheet(css`
.calendar.hidden {
visibility: hidden;
}
.calendar::part(no-highlight-cell):hover {
.calendar::part(no-highlight-cell) {
border-radius: ${theme.smallRound};
}
.calendar::part(start-highlight-cell) {
Expand All @@ -86,15 +86,17 @@ const style = createCSSSheet(css`
grid: auto-flow / 1fr 1fr 1fr;
}
.item {
display: flex;
align-items: center;
justify-content: center;
outline: 1px solid transparent;
outline-offset: -0.5em;
position: relative;
display: grid;
place-items: center;
border-radius: ${theme.smallRound};
}
.item.highlight {
z-index: 1;
outline-color: ${theme.highlightColor};
.item.highlight::after {
content: '';
position: absolute;
border-radius: inherit;
inset: 0.5em;
border: 1px solid ${theme.highlightColor};
}
.item:hover {
background: ${theme.hoverBackgroundColor};
Expand All @@ -110,9 +112,8 @@ const style = createCSSSheet(css`
flex-direction: column;
}
.time {
display: flex;
align-items: center;
justify-content: center;
display: grid;
place-items: center;
height: 3em;
}
.timepanel {
Expand Down Expand Up @@ -243,7 +244,7 @@ export class DuoyunDatePanelElement extends GemElement<State> {
default:
return html`
<dy-action-text @click=${() => this.setState({ mode: 'day' })}>
${this.#currentPosition.format('YYYY-MM-DD')}
${this.#currentPosition.format('YYYY')}
</dy-action-text>
`;
}
Expand Down
21 changes: 8 additions & 13 deletions packages/duoyun-ui/src/elements/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,43 +285,38 @@ export class DuoyunFormItemElement extends GemElement<FormItemState> {
constructor() {
super();
this.addEventListener('change', (evt: CustomEvent) => {
if (!this.name) {
evt.stopPropagation();
}
evt.stopPropagation();
if (this.#type === 'slot') {
this.#change(evt.detail);
this.#itemchange(evt.detail);
}
});
}

#change = (value: number | string | any[] | any) => {
#itemchange = (value: number | string | any[] | any) => {
if (this.name) {
this.itemchange({ name: this.name, value });
}
};

#onChange = (evt: CustomEvent<any>) => {
evt.stopPropagation();
this.#change(evt.detail);
this.#itemchange(evt.detail);
};

#onCheckboxChange = (evt: CustomEvent<boolean>) => {
evt.stopPropagation();
this.#change(this.value ? (evt.detail ? this.value : '') : evt.detail);
this.#itemchange(this.value ? (evt.detail ? this.value : '') : evt.detail);
};

#onTextChangeWithIndex = (evt: CustomEvent<string>, index: number) => {
evt.stopPropagation();
const value = (this.value || []) as string[];
this.#change([...value.slice(0, index), evt.detail, ...value.slice(index + 1)]);
this.#itemchange([...value.slice(0, index), evt.detail, ...value.slice(index + 1)]);
};

#onTextCleanWithIndex = async (index: number) => {
this.#change(((this.value || []) as string[]).filter((_, i) => i !== index));
this.#itemchange(((this.value || []) as string[]).filter((_, i) => i !== index));
};

#onTextAdd = async () => {
this.#change([...((this.value || []) as string[]), '']);
this.#itemchange([...((this.value || []) as string[]), '']);
};

mounted = () => {
Expand Down
39 changes: 21 additions & 18 deletions packages/duoyun-ui/src/elements/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { mediaQuery } from '@mantou/gem/helper/mediaquery';
import { theme } from '../lib/theme';
import { locale } from '../lib/locale';
import { hotkeys } from '../lib/hotkeys';
import { setBodyInert } from '../lib/utils';
import { DyPromise, setBodyInert } from '../lib/utils';
import { commonAnimationOptions, fadeIn, fadeOut, slideInUp } from '../lib/animations';

import './button';
Expand Down Expand Up @@ -183,27 +183,30 @@ export class DuoyunModalElement extends GemElement {

// Cannot be used for dynamic forms
// 错误必须处理,不然会被默认通过 Toast 显示
static async open<T = Element>(options: ModalOptions & ModalOpenOptions<T>) {
static open<T = Element>(options: ModalOptions & ModalOpenOptions<T>) {
const modal = new this({ ...options, open: true });
const restoreInert = setBodyInert(modal);
document.body.append(modal);
// bubble close event close modal
return new Promise<T>((res, rej) => {
const getBodyEle = () => {
const ele = modal.bodyRef.element?.children[0] as any;
return ele instanceof HTMLSlotElement ? ele.assignedElements()[0] : ele;
};
modal.addEventListener('close', async () => {
const ele = getBodyEle();
await options.prepareClose?.(ele);
rej(ele);
});
modal.addEventListener('ok', async () => {
const ele = getBodyEle();
await options.prepareOk?.(ele);
res(ele);
});
}).finally(async () => {
return DyPromise.new<T, { modal: DuoyunModalElement }>(
(res, rej) => {
const getBodyEle = () => {
const ele = modal.bodyRef.element?.children[0] as any;
return ele instanceof HTMLSlotElement ? ele.assignedElements()[0] : ele;
};
modal.addEventListener('close', async () => {
const ele = getBodyEle();
await options.prepareClose?.(ele);
rej(ele);
});
modal.addEventListener('ok', async () => {
const ele = getBodyEle();
await options.prepareOk?.(ele);
res(ele);
});
},
{ modal },
).finally(async () => {
restoreInert();
await modal.#closeAnimate();
modal.remove();
Expand Down
1 change: 1 addition & 0 deletions packages/duoyun-ui/src/elements/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import './use';

const style = createCSSSheet(css`
:host(:where(:not([hidden]))) {
cursor: default;
display: inline-flex;
align-items: center;
justify-content: center;
Expand Down
58 changes: 48 additions & 10 deletions packages/duoyun-ui/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,17 +176,25 @@ export function throttle<T extends (...args: any) => any>(
};
}

export function debounce<T extends (...args: any) => any>(fn: T, wait = 500) {
export function debounce<T extends (...args: any) => any>(
fn: T,
wait = 500,
{ leading = false }: { leading?: boolean } = {},
) {
let timer = 0;
let result: any = undefined;
return (...rest: Parameters<T>) => {
if (!timer) {
timer = window.setTimeout(() => {
timer = 0;
}, wait);
result = fn(...(rest as any));
}
return result;
return function (...args: Parameters<T>) {
return new Promise<Awaited<ReturnType<typeof fn>>>((resolve, reject) => {
clearTimeout(timer);
timer = window.setTimeout(
() => {
timer = window.setTimeout(() => (timer = 0), wait);
Promise.resolve(fn(...(args as any)))
.then(resolve)
.catch(reject);
},
leading && !timer ? 0 : wait,
);
});
};
}

Expand Down Expand Up @@ -393,3 +401,33 @@ export function createCacheStore<T extends Record<string, any>>(
export function isRemoteIcon(icon: string | Element | DocumentFragment): icon is string {
return typeof icon === 'string' && !!icon.trim().match(/^(http|[./])/);
}

/**
* Pass additional fields
*
* not support async function
*/
export class DyPromise<T, E extends Record<string, unknown>> extends Promise<T> {
static new<T, E extends Record<string, unknown>>(
executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void,
props: E,
) {
const instance = new DyPromise<T, E>(executor);
return Object.assign(instance, props);
}
then<TResult1 = T, TResult2 = never>(
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,
) {
const result = super.then<TResult1, TResult2>(onfulfilled, onrejected);
return Object.assign(result, this) as unknown as DyPromise<TResult1 | TResult2, E> & E;
}
catch<TResult>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null) {
const result = super.catch(onrejected);
return Object.assign(result, this) as unknown as DyPromise<TResult | T, E> & E;
}
finally(onfinally?: (() => void) | null | undefined) {
const result = super.finally(onfinally);
return Object.assign(result, this) as unknown as DyPromise<T, E> & E;
}
}
4 changes: 2 additions & 2 deletions packages/duoyun-ui/src/patterns/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,11 @@ const style = createCSSSheet(
const consoleStyle = createCSSSheet(css`
::selection,
::target-text {
color: white;
color: ${theme.backgroundColor};
background: ${theme.primaryColor};
}
::highlight(search) {
color: white;
color: ${theme.backgroundColor};
background: ${theme.informativeColor};
}
:where(:root) {
Expand Down
7 changes: 5 additions & 2 deletions packages/duoyun-ui/src/patterns/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { StyleObject, createCSSSheet, css, styleMap } from '@mantou/gem/lib/util
import { history } from '@mantou/gem/lib/history';

import { icons } from '../lib/icons';
import { blockContainer } from '../lib/styles';
import { blockContainer, focusStyle } from '../lib/styles';
import { readProp } from '../lib/utils';
import { theme } from '../lib/theme';
import { Drawer } from '../elements/drawer';
import { Modal, ModalOpenOptions, ModalOptions } from '../elements/modal';
import { DuoyunWaitElement, waitLoading } from '../elements/wait';
Expand All @@ -27,7 +28,7 @@ type FormItemProps<T = unknown> = {
required?: boolean;
rules?: DuoyunFormItemElement['rules'];

slot?: TemplateResult;
slot?: TemplateResult | HTMLElement | HTMLElement[];
};

export type FormItem<T = unknown> =
Expand All @@ -50,6 +51,7 @@ const style = createCSSSheet(css`
display: flex;
align-items: center;
gap: 1px;
border-radius: ${theme.normalRound};
}
summary dy-use {
width: 1.2em;
Expand All @@ -68,6 +70,7 @@ const style = createCSSSheet(css`
*/
@customElement('dy-pat-form')
@adoptedStyle(blockContainer)
@adoptedStyle(focusStyle)
@adoptedStyle(style)
export class DyPatFormElement<T = Record<string, unknown>> extends GemElement<T> {
@refobject formRef: RefObject<DuoyunFormElement>;
Expand Down
9 changes: 9 additions & 0 deletions packages/gem-book/src/website/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ document.body.append(book);

const style = document.createElement('style');
style.textContent = css`
::selection,
::target-text {
color: ${defaultTheme.backgroundColor};
background: ${defaultTheme.primaryColor};
}
::highlight(search) {
color: ${defaultTheme.backgroundColor};
background: ${defaultTheme.noteColor};
}
:where(html) {
height: 100%;
overflow: hidden;
Expand Down

0 comments on commit 34d4585

Please sign in to comment.