vanilla-jui 1.4.5 → 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/index.d.ts +1273 -1896
- package/dist/index.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +21 -2
- package/src/components/accordion.ts +297 -216
- package/src/components/flow.ts +222 -258
- package/src/components/form.ts +44 -102
- package/src/components/menu.ts +268 -356
- package/src/components/modal.ts +181 -641
- package/src/components/offcanvas.ts +225 -106
- package/src/components/pagination.ts +296 -326
- package/src/components/sticky.ts +55 -54
- package/src/components/swiper.ts +237 -247
- package/src/components/tabs.ts +278 -271
- package/src/components/toc.ts +42 -46
- package/src/core/Component.ts +69 -47
- package/src/css/accordion.css +2 -2
- package/src/css/animation.css +1 -5
- package/src/css/avatar.css +1 -1
- package/src/css/badge.css +1 -1
- package/src/css/breadcrumb.css +9 -10
- package/src/css/button.css +1 -1
- package/src/css/card.css +2 -2
- package/src/css/color.css +974 -1002
- package/src/css/color_p3.css +974 -1004
- package/src/css/components.css +1 -1
- package/src/css/content.css +72 -63
- package/src/css/drop.css +1 -1
- package/src/css/editor.css +14 -14
- package/src/css/flow.css +4 -14
- package/src/css/font.css +5 -4
- package/src/css/form.css +76 -52
- package/src/css/gradient.css +299 -222
- package/src/css/icon.css +57 -57
- package/src/css/index.css +1 -1
- package/src/css/layout.css +13 -10
- package/src/css/loading.css +60 -12
- package/src/css/menu.css +262 -188
- package/src/css/modal.css +1 -1
- package/src/css/offcanvas.css +9 -13
- package/src/css/pagination.css +5 -1
- package/src/css/popup.css +1 -1
- package/src/css/skeleton.css +3 -2
- package/src/css/status.css +2 -3
- package/src/css/swiper.css +1 -1
- package/src/css/table.css +1 -1
- package/src/css/tabs.css +12 -11
- package/src/css/tag.css +1 -1
- package/src/css/theme-palette.css +19 -5
- package/src/css/themes/default/accordion.css +61 -61
- package/src/css/themes/default/avatar.css +54 -54
- package/src/css/themes/default/badge.css +62 -62
- package/src/css/themes/default/breadcrumb.css +23 -23
- package/src/css/themes/default/button.css +203 -203
- package/src/css/themes/default/content.css +53 -53
- package/src/css/themes/default/drop.css +10 -10
- package/src/css/themes/default/editor.css +9 -9
- package/src/css/themes/default/index.css +1 -1
- package/src/css/themes/default/loading.css +26 -20
- package/src/css/themes/default/menu.css +75 -11
- package/src/css/themes/default/modal.css +32 -36
- package/src/css/themes/default/pagination.css +7 -7
- package/src/css/themes/default/popup.css +6 -6
- package/src/css/themes/default/swiper.css +32 -32
- package/src/css/themes/default/table.css +16 -16
- package/src/css/themes/default/tabs.css +30 -30
- package/src/css/themes/default/tag.css +71 -71
- package/src/css/themes/default/theme-palette.css +11 -11
- package/src/css/themes/default/tip.css +42 -42
- package/src/css/themes/default/toast.css +60 -60
- package/src/css/themes/default/toolbar.css +23 -29
- package/src/css/themes/default/tooltip.css +43 -13
- package/src/css/themes/index.css +1 -1
- package/src/css/tip.css +2 -2
- package/src/css/toast.css +3 -3
- package/src/css/tokens.css +12 -17
- package/src/css/toolbar.css +9 -10
- package/src/css/tooltip.css +3 -2
- package/src/index.ts +22 -19
- package/src/{components → primitives}/drop.ts +58 -49
- package/src/{components → primitives}/icons.ts +1 -1
- package/src/primitives/loading.ts +23 -0
- package/src/primitives/parabola.ts +388 -0
- package/src/primitives/popup.ts +61 -0
- package/src/{components → primitives}/theme.ts +88 -57
- package/src/{components → primitives}/toast.ts +18 -25
- package/src/{components → primitives}/tooltip.ts +100 -25
- package/src/utilities/browser.ts +23 -49
- package/src/utilities/class-name.ts +5 -0
- package/src/utilities/dom.ts +14 -32
- package/src/utilities/function.ts +4 -0
- package/src/utilities/http.ts +7 -7
- package/src/utilities/id.ts +57 -0
- package/src/utilities/object.ts +5 -0
- package/src/utilities/timer.ts +38 -0
- package/src/utilities/types.ts +420 -0
- package/src/{components → validation}/validator.ts +64 -53
- package/src/components/parabola.ts +0 -335
- package/src/utilities/cache.ts +0 -57
- package/src/utilities/core.ts +0 -614
- package/src/utilities/storage.ts +0 -46
package/src/components/toc.ts
CHANGED
|
@@ -4,14 +4,12 @@ import Component, {
|
|
|
4
4
|
type ComponentDOM,
|
|
5
5
|
type ComponentRuntime,
|
|
6
6
|
} from '../core/Component.ts';
|
|
7
|
-
import {
|
|
8
|
-
type ResolveSchema,
|
|
9
|
-
randomId,
|
|
10
|
-
resolveProps,
|
|
11
|
-
} from '../utilities/core.ts';
|
|
7
|
+
import { joinClasses } from '../utilities/class-name.ts';
|
|
12
8
|
import { type DOMReference, all, requireContainer } from '../utilities/dom.ts';
|
|
9
|
+
import { randomId } from '../utilities/id.ts';
|
|
10
|
+
import { type ResolveSchema, resolveProps } from '../utilities/types.ts';
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
interface TocClassNames {
|
|
15
13
|
toc: string;
|
|
16
14
|
list: string;
|
|
17
15
|
link: string;
|
|
@@ -19,36 +17,38 @@ export interface TocClassNames {
|
|
|
19
17
|
levelPrefix: string;
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
type TocClassNameConfig = Partial<TocClassNames>;
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
interface TocItem {
|
|
25
23
|
id: string;
|
|
26
24
|
text: string;
|
|
27
25
|
level: number;
|
|
28
26
|
element: HTMLHeadingElement;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
interface TocCurrent {
|
|
32
30
|
index: number;
|
|
33
31
|
item: TocItem | null;
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
container?: DOMReference;
|
|
34
|
+
interface TocProps extends Record<string, unknown> {
|
|
38
35
|
target?: DOMReference;
|
|
39
36
|
headings?: string;
|
|
40
37
|
offset?: number;
|
|
41
38
|
className?: TocClassNameConfig;
|
|
42
|
-
|
|
39
|
+
onChange?:
|
|
40
|
+
| ((item: TocItem | null, index: number, toc: TocInstance) => void)
|
|
41
|
+
| null;
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
interface ResolvedTocProps extends Record<string, unknown> {
|
|
46
|
-
container: DOMReference;
|
|
47
45
|
target: DOMReference;
|
|
48
46
|
headings: string;
|
|
49
47
|
offset: number;
|
|
50
48
|
className: TocClassNames;
|
|
51
|
-
|
|
49
|
+
onChange:
|
|
50
|
+
| ((item: TocItem | null, index: number, toc: TocInstance) => void)
|
|
51
|
+
| null;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
interface TocState extends Record<string, unknown> {
|
|
@@ -58,7 +58,6 @@ interface TocState extends Record<string, unknown> {
|
|
|
58
58
|
|
|
59
59
|
interface TocDOM extends ComponentDOM {
|
|
60
60
|
root: HTMLElement | null;
|
|
61
|
-
container: Element | null;
|
|
62
61
|
target: Element | null;
|
|
63
62
|
list: HTMLElement | null;
|
|
64
63
|
headings: HTMLHeadingElement[];
|
|
@@ -75,6 +74,13 @@ interface TocScrollOptions {
|
|
|
75
74
|
updateHash?: boolean;
|
|
76
75
|
}
|
|
77
76
|
|
|
77
|
+
type TocInstance = Component<ResolvedTocProps, TocState, TocDOM> & {
|
|
78
|
+
runtime: TocRuntime;
|
|
79
|
+
build(): TocInstance;
|
|
80
|
+
refresh(): TocInstance;
|
|
81
|
+
activate(index: number): TocInstance;
|
|
82
|
+
};
|
|
83
|
+
|
|
78
84
|
const DEFAULT_CLASS_NAMES: TocClassNames = {
|
|
79
85
|
toc: 'j-toc',
|
|
80
86
|
list: 'toc-list',
|
|
@@ -84,14 +90,12 @@ const DEFAULT_CLASS_NAMES: TocClassNames = {
|
|
|
84
90
|
};
|
|
85
91
|
|
|
86
92
|
const TOC_PROPS_SCHEMA = {
|
|
87
|
-
container: { default: null },
|
|
88
93
|
target: { default: '.j-content' },
|
|
89
94
|
headings: { default: 'h2, h3', type: 'string' },
|
|
90
95
|
offset: {
|
|
91
96
|
default: 80,
|
|
92
97
|
type: 'number',
|
|
93
|
-
|
|
94
|
-
message: 'expects a positive number or 0.',
|
|
98
|
+
min: 0,
|
|
95
99
|
},
|
|
96
100
|
className: {
|
|
97
101
|
default: DEFAULT_CLASS_NAMES,
|
|
@@ -101,7 +105,7 @@ const TOC_PROPS_SCHEMA = {
|
|
|
101
105
|
...(value && typeof value === 'object' ? value : {}),
|
|
102
106
|
}),
|
|
103
107
|
},
|
|
104
|
-
|
|
108
|
+
onChange: { default: null, types: ['function', 'null'] },
|
|
105
109
|
} satisfies ResolveSchema<TocProps>;
|
|
106
110
|
|
|
107
111
|
const ACTIVE_OFFSET_TOLERANCE = 1;
|
|
@@ -109,12 +113,11 @@ const ACTIVE_OFFSET_TOLERANCE = 1;
|
|
|
109
113
|
function normalizeProps(input: TocProps): ResolvedTocProps {
|
|
110
114
|
const props = resolveProps(input, TOC_PROPS_SCHEMA, 'Toc.props');
|
|
111
115
|
return {
|
|
112
|
-
container: props.container as DOMReference,
|
|
113
116
|
target: props.target as DOMReference,
|
|
114
117
|
headings: props.headings as string,
|
|
115
118
|
offset: props.offset as number,
|
|
116
119
|
className: props.className as TocClassNames,
|
|
117
|
-
|
|
120
|
+
onChange: props.onChange as ResolvedTocProps['onChange'],
|
|
118
121
|
};
|
|
119
122
|
}
|
|
120
123
|
|
|
@@ -138,18 +141,17 @@ function normalizeHeading(element: HTMLHeadingElement, index: number): TocItem {
|
|
|
138
141
|
*
|
|
139
142
|
* 扫描内容区域内的标题,生成锚点列表,并随页面滚动更新 active 状态。
|
|
140
143
|
*/
|
|
141
|
-
|
|
144
|
+
class Toc extends Component<ResolvedTocProps, TocState, TocDOM> {
|
|
142
145
|
declare runtime: TocRuntime;
|
|
143
146
|
|
|
144
147
|
/**
|
|
145
148
|
* 创建 Toc 实例。
|
|
146
149
|
* @param {object} [input={}] Toc 配置。
|
|
147
150
|
*/
|
|
148
|
-
constructor(
|
|
149
|
-
const
|
|
150
|
-
super(
|
|
151
|
+
constructor(props: TocProps = {}) {
|
|
152
|
+
const settings = normalizeProps(props);
|
|
153
|
+
super(settings);
|
|
151
154
|
|
|
152
|
-
this.dom.container = null;
|
|
153
155
|
this.dom.target = null;
|
|
154
156
|
this.dom.list = null;
|
|
155
157
|
this.dom.headings = [];
|
|
@@ -177,21 +179,16 @@ export class Toc extends Component<ResolvedTocProps, TocState, TocDOM> {
|
|
|
177
179
|
if (this.runtime.built) return this;
|
|
178
180
|
|
|
179
181
|
this.init(this.props);
|
|
180
|
-
this.dom.container = requireContainer(
|
|
181
|
-
this.props.container,
|
|
182
|
-
'Toc.container'
|
|
183
|
-
);
|
|
184
182
|
this.dom.target = requireContainer(this.props.target, 'Toc.target');
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
this.dom.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
this.dom.container.appendChild(root);
|
|
183
|
+
this.dom.list = jsx('div', {
|
|
184
|
+
className: this.props.className.list,
|
|
185
|
+
'data-toc-list': 'root',
|
|
186
|
+
}) as HTMLElement;
|
|
187
|
+
this.dom.root = jsx('nav', {
|
|
188
|
+
className: this.props.className.toc,
|
|
189
|
+
'data-toc': 'root',
|
|
190
|
+
children: this.dom.list,
|
|
191
|
+
}) as HTMLElement;
|
|
195
192
|
|
|
196
193
|
this.runtime.built = true;
|
|
197
194
|
this.refresh();
|
|
@@ -259,7 +256,7 @@ export class Toc extends Component<ResolvedTocProps, TocState, TocDOM> {
|
|
|
259
256
|
`${this.props.className.levelPrefix}${item.level}`,
|
|
260
257
|
];
|
|
261
258
|
if (active) classes.push(this.props.className.active);
|
|
262
|
-
return classes
|
|
259
|
+
return joinClasses(...classes);
|
|
263
260
|
}
|
|
264
261
|
|
|
265
262
|
private buildLink(item: TocItem, index: number): HTMLAnchorElement {
|
|
@@ -302,8 +299,8 @@ export class Toc extends Component<ResolvedTocProps, TocState, TocDOM> {
|
|
|
302
299
|
link.className = this.linkClassName(items[i], active);
|
|
303
300
|
});
|
|
304
301
|
|
|
305
|
-
if (typeof this.props.
|
|
306
|
-
this.props.
|
|
302
|
+
if (typeof this.props.onChange === 'function') {
|
|
303
|
+
this.props.onChange(current, index, this);
|
|
307
304
|
}
|
|
308
305
|
}
|
|
309
306
|
|
|
@@ -368,11 +365,10 @@ export class Toc extends Component<ResolvedTocProps, TocState, TocDOM> {
|
|
|
368
365
|
*/
|
|
369
366
|
protected onDestroy(): void {
|
|
370
367
|
this.cleanup.events.clear();
|
|
371
|
-
|
|
368
|
+
this.dom.root?.remove();
|
|
372
369
|
|
|
373
370
|
this.runtime.built = false;
|
|
374
371
|
this.runtime.ticking = false;
|
|
375
|
-
this.dom.container = null;
|
|
376
372
|
this.dom.target = null;
|
|
377
373
|
this.dom.list = null;
|
|
378
374
|
this.dom.headings = [];
|
|
@@ -380,6 +376,6 @@ export class Toc extends Component<ResolvedTocProps, TocState, TocDOM> {
|
|
|
380
376
|
}
|
|
381
377
|
}
|
|
382
378
|
|
|
383
|
-
export function createToc(props: TocProps = {}):
|
|
379
|
+
export function createToc(props: TocProps = {}): TocInstance {
|
|
384
380
|
return new Toc(props);
|
|
385
381
|
}
|
package/src/core/Component.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createDeepStore, flushSync } from 'vanilla-signal';
|
|
2
2
|
|
|
3
3
|
import { createEventManager } from '../utilities/events.ts';
|
|
4
|
+
import { isPlainObject } from '../utilities/object.ts';
|
|
4
5
|
|
|
5
6
|
export type ComponentProps = Record<string, unknown>;
|
|
6
7
|
export type ComponentState = Record<string, unknown>;
|
|
@@ -13,14 +14,16 @@ export interface ComponentRuntime {
|
|
|
13
14
|
destroyed: boolean;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
export
|
|
17
|
+
export type ComponentCache = unknown;
|
|
18
|
+
|
|
19
|
+
export interface ComponentReCreateOptions {
|
|
17
20
|
force?: boolean;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
export type ComponentLifecycleEvent =
|
|
21
24
|
| 'init'
|
|
22
|
-
| '
|
|
23
|
-
| '
|
|
25
|
+
| 'beforeReCreate'
|
|
26
|
+
| 'afterReCreate'
|
|
24
27
|
| 'destroy';
|
|
25
28
|
export type ComponentEventName = string;
|
|
26
29
|
export type ComponentListener = (...args: unknown[]) => void;
|
|
@@ -56,12 +59,6 @@ export interface ComponentCleanupRegistry {
|
|
|
56
59
|
[key: string]: unknown;
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
function isPlainObject(value: unknown): value is ComponentProps {
|
|
60
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
61
|
-
const proto = Object.getPrototypeOf(value);
|
|
62
|
-
return proto === Object.prototype || proto === null;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
62
|
/**
|
|
66
63
|
* 轻量级组件基类,集成 vanilla-signal 响应式状态和插件系统
|
|
67
64
|
* 为所有 UI 组件提供统一的状态管理、生命周期钩子和插件支持
|
|
@@ -70,6 +67,7 @@ export default class Component<
|
|
|
70
67
|
TProps extends ComponentProps = ComponentProps,
|
|
71
68
|
TState extends ComponentState = ComponentState,
|
|
72
69
|
TDOM extends ComponentDOM = ComponentDOM,
|
|
70
|
+
TCache = ComponentCache,
|
|
73
71
|
> {
|
|
74
72
|
/** 全局插件注册表,所有新创建的组件实例会自动安装这些插件 */
|
|
75
73
|
static globalPlugins = new Map<string, ComponentPlugin<Component>>();
|
|
@@ -80,6 +78,9 @@ export default class Component<
|
|
|
80
78
|
/** DOM 引用容器,存储根元素及其他 DOM 节点引用 */
|
|
81
79
|
dom: TDOM;
|
|
82
80
|
|
|
81
|
+
/** 实例缓存容器,存储组件运行时派生数据 */
|
|
82
|
+
cache: TCache;
|
|
83
|
+
|
|
83
84
|
/** 已安装的插件映射表 */
|
|
84
85
|
plugins: Map<ComponentPlugin<unknown>, ComponentCleanup>;
|
|
85
86
|
|
|
@@ -105,6 +106,9 @@ export default class Component<
|
|
|
105
106
|
/** DOM 引用容器,存储根元素及其他 DOM 节点引用 */
|
|
106
107
|
this.dom = { root: null } as TDOM;
|
|
107
108
|
|
|
109
|
+
/** 实例缓存容器,存储组件运行时派生数据 */
|
|
110
|
+
this.cache = {} as TCache;
|
|
111
|
+
|
|
108
112
|
/** 已安装的插件映射表 */
|
|
109
113
|
this.plugins = new Map();
|
|
110
114
|
|
|
@@ -114,8 +118,8 @@ export default class Component<
|
|
|
114
118
|
/** 内部事件监听器注册表,用于生命周期和自定义事件 */
|
|
115
119
|
this._listeners = {
|
|
116
120
|
init: [], // 初始化完成事件
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
beforeReCreate: [], // 重新实例化前事件
|
|
122
|
+
afterReCreate: [], // 重新实例化后事件
|
|
119
123
|
destroy: [], // 销毁事件
|
|
120
124
|
};
|
|
121
125
|
|
|
@@ -129,23 +133,6 @@ export default class Component<
|
|
|
129
133
|
this.installGlobalPlugins();
|
|
130
134
|
}
|
|
131
135
|
|
|
132
|
-
/**
|
|
133
|
-
* 获取组件的根 DOM 元素
|
|
134
|
-
* @returns {HTMLElement|null} 根 DOM 元素或 null
|
|
135
|
-
*/
|
|
136
|
-
get root(): Element | null {
|
|
137
|
-
return this.dom?.root || null;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* 设置组件的根 DOM 元素
|
|
142
|
-
* @param {HTMLElement} value - 要设置的根 DOM 元素
|
|
143
|
-
*/
|
|
144
|
-
set root(value: Element | null) {
|
|
145
|
-
if (!this.dom) this.dom = { root: null } as TDOM;
|
|
146
|
-
this.dom.root = value;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
136
|
/**
|
|
150
137
|
* 安装实例插件
|
|
151
138
|
* 插件可以是函数形式 plugin(instance, options) 或对象形式 { install(instance, options) }
|
|
@@ -169,7 +156,7 @@ export default class Component<
|
|
|
169
156
|
|
|
170
157
|
/**
|
|
171
158
|
* 注册事件监听器
|
|
172
|
-
* 用于监听组件生命周期事件(init、
|
|
159
|
+
* 用于监听组件生命周期事件(init、beforeReCreate、afterReCreate、destroy)或自定义事件
|
|
173
160
|
* @param {string} event - 事件名称
|
|
174
161
|
* @param {Function} callback - 事件回调函数
|
|
175
162
|
* @returns {Component} 返回当前实例,支持链式调用
|
|
@@ -283,39 +270,57 @@ export default class Component<
|
|
|
283
270
|
throw new Error('Component.setState: expects a plain object patch.');
|
|
284
271
|
}
|
|
285
272
|
|
|
273
|
+
const normalizedPatch = this.normalizeStatePatch(patch as Partial<TState>);
|
|
274
|
+
if (!isPlainObject(normalizedPatch)) {
|
|
275
|
+
throw new Error('Component.setState: expects a plain object patch.');
|
|
276
|
+
}
|
|
277
|
+
this.validateStatePatch(normalizedPatch);
|
|
278
|
+
|
|
286
279
|
flushSync(() => {
|
|
287
|
-
for (const [k, v] of Object.entries(
|
|
280
|
+
for (const [k, v] of Object.entries(normalizedPatch)) {
|
|
288
281
|
if (!this.state) return;
|
|
289
282
|
this.state[k as keyof TState] = v as TState[keyof TState];
|
|
290
283
|
}
|
|
291
284
|
});
|
|
285
|
+
this.afterSetState(normalizedPatch);
|
|
292
286
|
return this;
|
|
293
287
|
}
|
|
294
288
|
|
|
295
289
|
/**
|
|
296
|
-
*
|
|
297
|
-
* 合并新的属性配置,触发
|
|
298
|
-
* 子类可以重写
|
|
290
|
+
* 根据新的 props 重新创建组件实例并触发生命周期
|
|
291
|
+
* 合并新的属性配置,触发 beforeReCreate 和 afterReCreate 事件
|
|
292
|
+
* 子类可以重写 onReCreate 方法实现自定义重建前逻辑
|
|
299
293
|
* @param {Object} [propsPatch={}] - 要合并的属性补丁对象
|
|
300
294
|
* @param {Object} [options] - 更新选项
|
|
301
295
|
* @param {boolean} [options.force=false] - 是否强制更新(由子类处理)
|
|
302
|
-
* @returns {Component}
|
|
296
|
+
* @returns {Component} 返回新创建的实例
|
|
303
297
|
* @throws {Error} 如果组件已被销毁则抛出异常
|
|
304
298
|
*/
|
|
305
|
-
|
|
299
|
+
reCreate(
|
|
306
300
|
propsPatch: Partial<TProps> | null | undefined = {},
|
|
307
|
-
{ force = false }:
|
|
301
|
+
{ force = false }: ComponentReCreateOptions = {}
|
|
308
302
|
): this {
|
|
309
303
|
if (this.runtime.destroyed)
|
|
310
|
-
throw new Error('Component.
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
304
|
+
throw new Error('Component.reCreate: instance destroyed');
|
|
305
|
+
|
|
306
|
+
if (!isPlainObject(propsPatch)) return this;
|
|
307
|
+
|
|
308
|
+
const nextProps = Object.assign({}, this.props, propsPatch);
|
|
309
|
+
this.emit('beforeReCreate', propsPatch, { force });
|
|
310
|
+
if (typeof this.onReCreate === 'function')
|
|
311
|
+
this.onReCreate(propsPatch, { force });
|
|
312
|
+
|
|
313
|
+
const nextInstance = this.createInstance(nextProps);
|
|
314
|
+
this.destroy();
|
|
315
|
+
nextInstance.emit('afterReCreate', propsPatch, { force });
|
|
316
|
+
return nextInstance;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
protected createInstance(props: TProps): this {
|
|
320
|
+
const ComponentConstructor = this.constructor as new (
|
|
321
|
+
props: TProps
|
|
322
|
+
) => this;
|
|
323
|
+
return new ComponentConstructor(props);
|
|
319
324
|
}
|
|
320
325
|
|
|
321
326
|
/**
|
|
@@ -343,13 +348,30 @@ export default class Component<
|
|
|
343
348
|
this.cleanup.plugins.clear();
|
|
344
349
|
this.cleanup.events.clear();
|
|
345
350
|
this.dom = { root: null } as TDOM;
|
|
351
|
+
this.cache = {} as TCache;
|
|
346
352
|
this.state = null;
|
|
347
353
|
}
|
|
348
354
|
|
|
349
355
|
protected onInit?(props: TProps): void;
|
|
350
|
-
protected
|
|
356
|
+
protected onReCreate?(
|
|
351
357
|
propsPatch: Partial<TProps> | null | undefined,
|
|
352
|
-
options: Required<
|
|
358
|
+
options: Required<ComponentReCreateOptions>
|
|
353
359
|
): void;
|
|
360
|
+
protected normalizeStatePatch(patch: Partial<TState>): Partial<TState> {
|
|
361
|
+
return patch;
|
|
362
|
+
}
|
|
363
|
+
protected validateStatePatch(patch: Partial<TState>): void {
|
|
364
|
+
if (!this.state) return;
|
|
365
|
+
for (const key of Object.keys(patch)) {
|
|
366
|
+
const stateKey = String(key);
|
|
367
|
+
const exists = Object.hasOwn(this.state as object, stateKey);
|
|
368
|
+
if (!exists) {
|
|
369
|
+
throw new Error(
|
|
370
|
+
`Component.setState: "${stateKey}" is not a supported state key.`
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
protected afterSetState(_patch: Partial<TState>): void {}
|
|
354
376
|
protected onDestroy?(): void;
|
|
355
377
|
}
|
package/src/css/accordion.css
CHANGED
package/src/css/animation.css
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
@layer animation {
|
|
2
|
-
|
|
3
2
|
/* none */
|
|
4
3
|
.animate-none {
|
|
5
4
|
animation: none;
|
|
@@ -22,7 +21,6 @@
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
@keyframes animate-ping {
|
|
25
|
-
|
|
26
24
|
75%,
|
|
27
25
|
100% {
|
|
28
26
|
transform: scale(2);
|
|
@@ -47,7 +45,6 @@
|
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
@keyframes animate-bounce {
|
|
50
|
-
|
|
51
48
|
0%,
|
|
52
49
|
100% {
|
|
53
50
|
transform: translateY(-25%);
|
|
@@ -100,7 +97,6 @@
|
|
|
100
97
|
}
|
|
101
98
|
|
|
102
99
|
@keyframes animate-shake {
|
|
103
|
-
|
|
104
100
|
0%,
|
|
105
101
|
100% {
|
|
106
102
|
transform: translateX(0);
|
|
@@ -204,4 +200,4 @@
|
|
|
204
200
|
transform: translateY(0);
|
|
205
201
|
}
|
|
206
202
|
}
|
|
207
|
-
}
|
|
203
|
+
}
|
package/src/css/avatar.css
CHANGED
package/src/css/badge.css
CHANGED
package/src/css/breadcrumb.css
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
@layer components {
|
|
2
|
-
|
|
3
2
|
.j-breadcrumb {
|
|
4
3
|
font-size: var(--breadcrumb-font-size);
|
|
5
4
|
color: var(--breadcrumb-fg);
|
|
@@ -12,8 +11,8 @@
|
|
|
12
11
|
height: var(--breadcrumb-icon-size);
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
.j-breadcrumb>ol,
|
|
16
|
-
.j-breadcrumb>ul {
|
|
14
|
+
.j-breadcrumb > ol,
|
|
15
|
+
.j-breadcrumb > ul {
|
|
17
16
|
display: flex;
|
|
18
17
|
flex-wrap: wrap;
|
|
19
18
|
justify-content: flex-start;
|
|
@@ -22,8 +21,8 @@
|
|
|
22
21
|
padding: 0;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
.j-breadcrumb>ol li,
|
|
26
|
-
.j-breadcrumb>ul li {
|
|
24
|
+
.j-breadcrumb > ol li,
|
|
25
|
+
.j-breadcrumb > ul li {
|
|
27
26
|
display: flex;
|
|
28
27
|
align-items: center;
|
|
29
28
|
justify-content: center;
|
|
@@ -33,20 +32,20 @@
|
|
|
33
32
|
padding-inline-start: 0;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
.j-breadcrumb li+li::before {
|
|
35
|
+
.j-breadcrumb li + li::before {
|
|
37
36
|
color: var(--breadcrumb-divider-fg);
|
|
38
37
|
content: '/';
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
.j-breadcrumb.is-dot li+li::before {
|
|
40
|
+
.j-breadcrumb.is-dot li + li::before {
|
|
42
41
|
content: '•';
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
.j-breadcrumb.is-arrow li+li::before {
|
|
44
|
+
.j-breadcrumb.is-arrow li + li::before {
|
|
46
45
|
content: '>';
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
.j-breadcrumb.is-dash li+li::before {
|
|
48
|
+
.j-breadcrumb.is-dash li + li::before {
|
|
50
49
|
content: '–';
|
|
51
50
|
}
|
|
52
51
|
|
|
@@ -80,4 +79,4 @@
|
|
|
80
79
|
.j-breadcrumb.is-right ol {
|
|
81
80
|
justify-content: flex-end;
|
|
82
81
|
}
|
|
83
|
-
}
|
|
82
|
+
}
|
package/src/css/button.css
CHANGED
package/src/css/card.css
CHANGED
|
@@ -141,11 +141,11 @@
|
|
|
141
141
|
padding: var(--vertical-card-footer-padding, var(--s4));
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
.j-card .card-content
|
|
144
|
+
.j-card .card-content + .card-footer {
|
|
145
145
|
padding-top: 0;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
.j-card .card-footer:has(.j-button-group) {
|
|
149
149
|
padding-top: 4px;
|
|
150
150
|
}
|
|
151
|
-
}
|
|
151
|
+
}
|