compelem 0.28.1 → 0.28.2
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/.agents/skills/compelem-usage/SKILL.md +303 -0
- package/README.md +35 -20
- package/dist/CompElem.d.ts +107 -0
- package/dist/IComponent.d.ts +71 -0
- package/dist/config.d.ts +10 -0
- package/dist/constants.d.ts +64 -0
- package/dist/decorator/Decorator.d.ts +35 -0
- package/dist/decorator/index.d.ts +32 -0
- package/dist/decorators/computed.d.ts +9 -0
- package/dist/decorators/csscope.d.ts +14 -0
- package/dist/decorators/debounced.d.ts +1 -0
- package/dist/decorators/emits.d.ts +14 -0
- package/dist/decorators/event.d.ts +7 -0
- package/dist/decorators/onced.d.ts +1 -0
- package/dist/decorators/prop.d.ts +8 -0
- package/dist/decorators/query.d.ts +8 -0
- package/dist/decorators/state.d.ts +14 -0
- package/dist/decorators/tag.d.ts +7 -0
- package/dist/decorators/throttled.d.ts +1 -0
- package/dist/decorators/watch.d.ts +9 -0
- package/dist/devtools.d.ts +38 -0
- package/dist/directive/index.d.ts +11 -0
- package/dist/directives/Bind.d.ts +5 -0
- package/dist/directives/Classes.d.ts +6 -0
- package/dist/directives/ForEach.d.ts +7 -0
- package/dist/directives/Html.d.ts +6 -0
- package/dist/directives/IfElse.d.ts +7 -0
- package/dist/directives/IfTrue.d.ts +7 -0
- package/dist/directives/Model.d.ts +16 -0
- package/dist/directives/Show.d.ts +9 -0
- package/dist/directives/Slot.d.ts +7 -0
- package/dist/directives/Styles.d.ts +7 -0
- package/dist/directives/When.d.ts +22 -0
- package/dist/events/event.d.ts +22 -0
- package/dist/events/extends.d.ts +4 -0
- package/dist/helpers.d.ts +18 -0
- package/dist/index.cjs.js +7 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.esm.js +7 -0
- package/dist/reactive.d.ts +34 -0
- package/dist/render/CssTemplate.d.ts +11 -0
- package/dist/render/Template.d.ts +27 -0
- package/dist/render/TemplateMeta.d.ts +17 -0
- package/dist/render/UpdatePoint.d.ts +32 -0
- package/dist/render/UpdatePointMeta.d.ts +28 -0
- package/dist/render/render.d.ts +53 -0
- package/dist/transition/index.d.ts +62 -0
- package/dist/types.d.ts +197 -0
- package/dist/utils.d.ts +19 -0
- package/dist/viewTransition.d.ts +10 -0
- package/dist-dev/compelem.umd.js +6262 -0
- package/dist-dev/devtools.d.ts +38 -0
- package/dist-dev/index.cjs.js +6258 -0
- package/dist-dev/index.esm.js +6177 -0
- package/llms.txt +92 -0
- package/package.json +47 -8
- package/CHANGELOG.md +0 -1
- package/index.js +0 -7
- /package/{CompElem.d.ts → dist-dev/CompElem.d.ts} +0 -0
- /package/{IComponent.d.ts → dist-dev/IComponent.d.ts} +0 -0
- /package/{config.d.ts → dist-dev/config.d.ts} +0 -0
- /package/{constants.d.ts → dist-dev/constants.d.ts} +0 -0
- /package/{decorator → dist-dev/decorator}/Decorator.d.ts +0 -0
- /package/{decorator → dist-dev/decorator}/index.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/computed.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/csscope.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/debounced.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/emits.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/event.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/onced.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/prop.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/query.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/state.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/tag.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/throttled.d.ts +0 -0
- /package/{decorators → dist-dev/decorators}/watch.d.ts +0 -0
- /package/{directive → dist-dev/directive}/index.d.ts +0 -0
- /package/{directives → dist-dev/directives}/Bind.d.ts +0 -0
- /package/{directives → dist-dev/directives}/Classes.d.ts +0 -0
- /package/{directives → dist-dev/directives}/ForEach.d.ts +0 -0
- /package/{directives → dist-dev/directives}/Html.d.ts +0 -0
- /package/{directives → dist-dev/directives}/IfElse.d.ts +0 -0
- /package/{directives → dist-dev/directives}/IfTrue.d.ts +0 -0
- /package/{directives → dist-dev/directives}/Model.d.ts +0 -0
- /package/{directives → dist-dev/directives}/Show.d.ts +0 -0
- /package/{directives → dist-dev/directives}/Slot.d.ts +0 -0
- /package/{directives → dist-dev/directives}/Styles.d.ts +0 -0
- /package/{directives → dist-dev/directives}/When.d.ts +0 -0
- /package/{events → dist-dev/events}/event.d.ts +0 -0
- /package/{events → dist-dev/events}/extends.d.ts +0 -0
- /package/{helpers.d.ts → dist-dev/helpers.d.ts} +0 -0
- /package/{index.d.ts → dist-dev/index.d.ts} +0 -0
- /package/{reactive.d.ts → dist-dev/reactive.d.ts} +0 -0
- /package/{render → dist-dev/render}/CssTemplate.d.ts +0 -0
- /package/{render → dist-dev/render}/Template.d.ts +0 -0
- /package/{render → dist-dev/render}/TemplateMeta.d.ts +0 -0
- /package/{render → dist-dev/render}/UpdatePoint.d.ts +0 -0
- /package/{render → dist-dev/render}/UpdatePointMeta.d.ts +0 -0
- /package/{render → dist-dev/render}/render.d.ts +0 -0
- /package/{transition → dist-dev/transition}/index.d.ts +0 -0
- /package/{types.d.ts → dist-dev/types.d.ts} +0 -0
- /package/{utils.d.ts → dist-dev/utils.d.ts} +0 -0
- /package/{viewTransition.d.ts → dist-dev/viewTransition.d.ts} +0 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# compelem Usage Skill
|
|
2
|
+
|
|
3
|
+
This skill provides guidance for AI agents working with the **compelem** WebComponent library.
|
|
4
|
+
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
**Version:** 0.28.1
|
|
8
|
+
**Package:** `compelem`
|
|
9
|
+
**Author:** holyhigh2
|
|
10
|
+
**Docs:** `AGENTS.md` (this repo)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Installation & Imports
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import {
|
|
18
|
+
CompElem, tag, prop, state, computed, watch, emits,
|
|
19
|
+
csscope, Csscope, css, h,
|
|
20
|
+
forEach, ifElse, model, show, classes, styles,
|
|
21
|
+
bind, slot, html, transition, when,
|
|
22
|
+
createRef, defineComponents, startViewTransition
|
|
23
|
+
} from "compelem";
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Component Skeleton
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
@emits('change')
|
|
32
|
+
@tag("my-counter")
|
|
33
|
+
export class MyCounter extends CompElem {
|
|
34
|
+
@prop({ type: Number, model: true }) value = 0;
|
|
35
|
+
@prop label: string;
|
|
36
|
+
@state count = 0;
|
|
37
|
+
|
|
38
|
+
@computed
|
|
39
|
+
get doubled() { return this.count * 2 }
|
|
40
|
+
|
|
41
|
+
@watch('count', { immediate: true })
|
|
42
|
+
onCount(nv: number, ov: number) { console.log(nv, ov) }
|
|
43
|
+
|
|
44
|
+
@csscope(Csscope.INNER)
|
|
45
|
+
static get css() {
|
|
46
|
+
return css`button{ color: var(--c, black); }`
|
|
47
|
+
}
|
|
48
|
+
get cssVars() { return { c: this.count > 9 ? 'red' : 'black' } }
|
|
49
|
+
|
|
50
|
+
mounted() {
|
|
51
|
+
this.emit('change', { value: this.count })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
render(): Template {
|
|
55
|
+
return h`<div>
|
|
56
|
+
<span>${this.label}: ${this.count}</span>
|
|
57
|
+
<button @click="${() => this.count++}">+1</button>
|
|
58
|
+
${forEach(this.items, it => it.id, it => h`<li key=${it.id}>${it.name}</li>`)}
|
|
59
|
+
${ifElse(this.count > 5, () => h`<b>big</b>`, () => h`<i>small</i>`)}
|
|
60
|
+
</div>`
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Key Decorators
|
|
68
|
+
|
|
69
|
+
| Decorator | Purpose | Key Options |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `@tag(name, immediate?)` | Register component | `immediate=true` → auto `customElements.define` |
|
|
72
|
+
| `@prop(options?)` | External input (read-only) | `type`, `model`, `attribute`, `hasChanged`, `converter` |
|
|
73
|
+
| `@state(options?)` | Internal reactive state | `shallow`, `prop` (init from prop), `hasChanged` |
|
|
74
|
+
| `@computed` | Cached getter | Must be non-static getter |
|
|
75
|
+
| `@watch(source, options?)` | React to changes | `immediate`, `deep`, `once` |
|
|
76
|
+
| `@emits(...names)` | Declare events | Supports `'update:*'` wildcard |
|
|
77
|
+
| `@csscope(...scopes)` | Style scopes | `INNER`, `HOST`, `GLOBAL` |
|
|
78
|
+
| `@event(name, target?)` | Non-view events | Window/document/element events |
|
|
79
|
+
| `@query(selector, cache?)` | ShadowDOM query | `QueryCache.ONCE` for single query |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Template Syntax (`h` tag function)
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
h`<div @click="${handler}" .value="${v}" ?disabled="${d}" *r="${r}">`
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
| Prefix | Meaning |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `@` | Event listener |
|
|
92
|
+
| `.` | Component prop (type-safe) |
|
|
93
|
+
| `?` | Boolean attribute toggle |
|
|
94
|
+
| `*` | Evaluate then set (supports `:camel/:kebab/:snake`) |
|
|
95
|
+
| `key=${id}` | For `forEach` items |
|
|
96
|
+
| `ref="${refObj}"` | DOM reference via `createRef()` |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Built-in Directives
|
|
101
|
+
|
|
102
|
+
| Directive | Position | Example |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `bind(obj)` | TAG | `<div ${bind(obj)}>` |
|
|
105
|
+
| `show(cond, cb?)` | TAG | `<div ${show(visible)}>` |
|
|
106
|
+
| `model(val, prop?, modelProp?)` | TAG | `<input ${model(val)}>` |
|
|
107
|
+
| `classes(obj\|arr\|str)` | TAG | `<div ${classes({active: true})}>` |
|
|
108
|
+
| `styles(obj\|str)` | TAG | `<div ${styles({color: 'red'})}>` |
|
|
109
|
+
| `forEach(arr, keyFn, tmpl)` | TEXT/SLOT | `${forEach(list, i=>i.id, i=>h\`<li key=${i.id}>\`)}` |
|
|
110
|
+
| `ifTrue(cond, tmpl)` | TEXT/SLOT | `${ifTrue(show, () => h\`<span>\`)}` |
|
|
111
|
+
| `ifElse(cond, ifT, elseT)` | TEXT/SLOT | `${ifElse(c, t, f)}` |
|
|
112
|
+
| `when(val, cases)` | TEXT/SLOT | `${when(x, [[v=>v>0, t], ['default', f]])}` |
|
|
113
|
+
| `slot(tmpl, name?)` | SLOT | Dynamic slot content |
|
|
114
|
+
| `html(str)` | TAG/TEXT/SLOT | Raw HTML injection |
|
|
115
|
+
| `transition(name, inner, opts?)` | TEXT/SLOT | Animation on structural changes |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Lifecycle Hooks
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
propsReady(props) // After props set, before render
|
|
123
|
+
render() // Return Template | null
|
|
124
|
+
beforeMount() // Before first mount
|
|
125
|
+
mounted() // After first mount
|
|
126
|
+
shouldUpdate(changed) // Return false to skip update
|
|
127
|
+
beforeDestroyed() // Before destroy
|
|
128
|
+
destroyed() // After destroy
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Instance Members (Read-only)
|
|
134
|
+
|
|
135
|
+
- `rootComponent`, `parentComponent`, `wrapperComponent`
|
|
136
|
+
- `renderRoot` / `renderRoots`, `shadowRoot`
|
|
137
|
+
- `slots`, `slotHooks`
|
|
138
|
+
- `cssSheets`, `globalCssSheet`
|
|
139
|
+
- `attrs`, `props`
|
|
140
|
+
- `isMounted`, `isDestroyed`
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Instance Methods
|
|
145
|
+
|
|
146
|
+
- `emit(evName, arg?, event?)` — Fire component event
|
|
147
|
+
- `nextTick(cbk)` — After DOM update
|
|
148
|
+
- `forceUpdate()` — Force re-render
|
|
149
|
+
- `updateProps(props, force?)` — Batch update props
|
|
150
|
+
- `insertStyleSheet(sheet)` — Dynamic CSS
|
|
151
|
+
- `destroy()` — Cleanup component
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Dynamic CSS Variables
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
get cssVars() {
|
|
159
|
+
return {
|
|
160
|
+
primaryColor: this.theme === 'dark' ? '#fff' : '#000',
|
|
161
|
+
spacing: `${this.size}px`
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Generates: --primary-color, --spacing
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Event System
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
// Native events
|
|
173
|
+
<div @click="${handler}">
|
|
174
|
+
<div @resize="${handler}"> // Element resize
|
|
175
|
+
<div @outside.mousedown="${h}"> // Click outside
|
|
176
|
+
<div @mutate.attr="${h}"> // MutationObserver
|
|
177
|
+
|
|
178
|
+
// Component events (must @emits first)
|
|
179
|
+
<my-comp @change="${handler}"> // Receives custom data
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Modifiers:** `.stop` `.prevent` `.self` `.left` `.right` `.ctrl` `.alt` `.esc` `.debounce:100` `.throttle:100` `.once`
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Dev/Prod Builds (package.json exports)
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
"exports": {
|
|
190
|
+
".": {
|
|
191
|
+
"import": { "default": "dist/index.esm.js" },
|
|
192
|
+
"require": { "default": "dist/index.cjs.js" },
|
|
193
|
+
"development": { "default": "dist-dev/index.esm.js" },
|
|
194
|
+
"production": { "default": "dist/index.prod.esm.js" }
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
- `npm run prod` → `dist/index.prod.esm.js` (minified, no dev code)
|
|
200
|
+
- `npm run dev` → `dist-dev/index.esm.js` (with devtools hints, warnings)
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Common Patterns
|
|
205
|
+
|
|
206
|
+
### Two-way Binding (model prop)
|
|
207
|
+
```ts
|
|
208
|
+
@prop({ type: String, model: true }) value = '';
|
|
209
|
+
// Parent: <my-input .value="${val}" @update:value="${v => val = v}">
|
|
210
|
+
// Or: <my-input ${model(val)}>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Dynamic Slots
|
|
214
|
+
```ts
|
|
215
|
+
render() {
|
|
216
|
+
return h`<div>
|
|
217
|
+
${slot(args => h`<span>${args.title}</span>`, 'header')}
|
|
218
|
+
<slot></slot>
|
|
219
|
+
</div>`
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### View Transitions (SPA routing)
|
|
224
|
+
```ts
|
|
225
|
+
await startViewTransition(() => {
|
|
226
|
+
router.navigate('/new-page')
|
|
227
|
+
})
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Register Multiple Components
|
|
231
|
+
```ts
|
|
232
|
+
import { defineComponents } from 'compelem';
|
|
233
|
+
// After all @tag components are imported:
|
|
234
|
+
defineComponents()
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Debugging Tips
|
|
240
|
+
|
|
241
|
+
1. **DevTools hint**: Set `window.__COMPELEM_DEVTOOLS_NO_HINT__ = true` to silence
|
|
242
|
+
2. **React/Vue interop**: Add `emit-native` attr to convert events to CustomEvent
|
|
243
|
+
3. **No-view components**: `render()` returns `null` → no Shadow DOM, only HOST/GLOBAL styles
|
|
244
|
+
4. **Prop mutation**: Dev mode throws if you assign to `@prop` directly; use `model: true` or `emit('update:xxx')`
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## TypeScript Config
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"compilerOptions": {
|
|
253
|
+
"experimentalDecorators": true,
|
|
254
|
+
"useDefineForClassFields": false,
|
|
255
|
+
"module": "ESNext",
|
|
256
|
+
"moduleResolution": "bundler",
|
|
257
|
+
"target": "ES2017",
|
|
258
|
+
"lib": ["ES2017", "DOM", "DOM.Iterable"]
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## File Structure Reference
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
src/
|
|
269
|
+
├── index.ts # Main exports
|
|
270
|
+
├── CompElem.ts # Base component class
|
|
271
|
+
├── config.ts # Global config (setDefaults)
|
|
272
|
+
├── devtools.ts # DevTools integration
|
|
273
|
+
├── decorators/ # All decorators
|
|
274
|
+
├── directives/ # Built-in directives
|
|
275
|
+
├── render/ # Template engine
|
|
276
|
+
├── events/ # Event system
|
|
277
|
+
├── transition/ # Animation system
|
|
278
|
+
└── types.ts # All option types
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Anti-Patterns to Avoid
|
|
284
|
+
|
|
285
|
+
| ❌ Don't | ✅ Do |
|
|
286
|
+
|---|---|
|
|
287
|
+
| Assign to `@prop` inside component | Use `@prop({model:true})` or `emit('update:xxx')` |
|
|
288
|
+
| Use `@csscope` on non-static getter | Use on `static get css()` only |
|
|
289
|
+
| Forget `@emits` before `emit()` | Declare all events with `@emits` |
|
|
290
|
+
| Use `model` with dynamic paths | Use static property paths only |
|
|
291
|
+
| Duplicate `key` in `forEach` | Ensure unique keys |
|
|
292
|
+
| Use `@query` on no-view component | Use `render()` returning Template |
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Quick Commands
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
npm run prod # Build production (dist/index.prod.esm.js)
|
|
300
|
+
npm run dev # Build development (dist-dev/index.esm.js)
|
|
301
|
+
npm run lint # ESLint check
|
|
302
|
+
npx tsc --noEmit # Type check
|
|
303
|
+
```
|
package/README.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="./assets/logo-dark.svg">
|
|
4
|
+
<img src="./assets/logo.svg" alt="compelem" width="120" height="120">
|
|
5
|
+
</picture>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<h1 align="center">compelem</h1>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<em>Component + Element · A Web Components MVVM library</em>
|
|
12
|
+
</p>
|
|
13
|
+
<p align="center">
|
|
14
|
+
<img src="https://img.shields.io/npm/v/compelem" alt="npm">
|
|
15
|
+
<img src="https://img.shields.io/badge/license-MIT-blue" alt="license">
|
|
16
|
+
<img src="https://img.shields.io/badge/TypeScript-ready-3178C6" alt="ts">
|
|
17
|
+
</p>
|
|
3
18
|
一个现代化、响应式、快速、轻量的WebComponent开发库。为开发者提供丰富、灵活、可扩展的声明式接口
|
|
4
19
|
|
|
5
20
|
## 概览
|
|
@@ -291,23 +306,23 @@ CompElem 组件既可以在 CompElem 环境内调用,也可以直接在原生
|
|
|
291
306
|
|
|
292
307
|
> 创建流程
|
|
293
308
|
|
|
294
|
-
| 功能 |
|
|
295
|
-
| ------------------------------------------------------------ |
|
|
296
|
-
| 1. 创建组件实例,完成类属性默认值设置(prop/state/...) |
|
|
297
|
-
| 2. 初始化类全局样式(仅一次)及 实例样式(产生 styles 数组) |
|
|
298
|
-
| 3. 创建 shadowRoot 并挂载组件样式 |
|
|
299
|
-
| 4. 执行装饰器 create 回调 |
|
|
300
|
-
| 5. 绑定 parentComponent
|
|
301
|
-
| 6. 验证及初始化 props |
|
|
302
|
-
| 7. 初始化 states |
|
|
303
|
-
| 8. @computed |
|
|
304
|
-
| 9. @watch(immediate) |
|
|
305
|
-
| 10. 渲染 render 及依赖绑定 |
|
|
306
|
-
| 11. 绑定 renderRoot 及 renderRoots |
|
|
307
|
-
| 12. 初始化插槽 slots |
|
|
308
|
-
| 13. 执行装饰器 beforeMount 回调 ,如 @query
|
|
309
|
-
| 14. 初始化动态 css |
|
|
310
|
-
| 15. 执行装饰器 mounted 回调 |
|
|
309
|
+
| 功能 | 生命周期 |
|
|
310
|
+
| ------------------------------------------------------------ | ----------- |
|
|
311
|
+
| 1. 创建组件实例,完成类属性默认值设置(prop/state/...) | |
|
|
312
|
+
| 2. 初始化类全局样式(仅一次)及 实例样式(产生 styles 数组) | |
|
|
313
|
+
| 3. 创建 shadowRoot 并挂载组件样式 | |
|
|
314
|
+
| 4. 执行装饰器 create 回调 | constructor |
|
|
315
|
+
| 5. 绑定 parentComponent | |
|
|
316
|
+
| 6. 验证及初始化 props | propsReady |
|
|
317
|
+
| 7. 初始化 states | |
|
|
318
|
+
| 8. @computed | |
|
|
319
|
+
| 9. @watch(immediate) | |
|
|
320
|
+
| 10. 渲染 render 及依赖绑定 | render |
|
|
321
|
+
| 11. 绑定 renderRoot 及 renderRoots | |
|
|
322
|
+
| 12. 初始化插槽 slots | |
|
|
323
|
+
| 13. 执行装饰器 beforeMount 回调 ,如 @query | beforeMount |
|
|
324
|
+
| 14. 初始化动态 css | mounted |
|
|
325
|
+
| 15. 执行装饰器 mounted 回调 | |
|
|
311
326
|
|
|
312
327
|
> 更新流程【普通】
|
|
313
328
|
|
|
@@ -420,7 +435,6 @@ return h` <l-tooltip>
|
|
|
420
435
|
| when | TEXT/SLOT | 多条件分支,支持 switch/ifelse 两种模式 | ` ...>${when(condition,{c1:()=>h``,c2:...})}<... ` |
|
|
421
436
|
| slot | SLOT | 动态插槽 | ` ...>${slot((args) => h``)}<... ` |
|
|
422
437
|
| html | TAG/TEXT/SLOT | 向指定元素/文本位置插入HTML内容 | `<div a="b" ${html('<b>1</b>')}> ...>${html('<b>1</b>')}<...` |
|
|
423
|
-
| transition | TEXT/SLOT | 为内层结构指令的切换添加过渡动画,支持JS钩子。通常使用 `<transition>` 伪标签 | `${transition('fade', ifElse(...), {mode:'out-in'})}` |
|
|
424
438
|
|
|
425
439
|
## 过渡动画 Transition
|
|
426
440
|
|
|
@@ -711,4 +725,5 @@ setDefaults({
|
|
|
711
725
|
## 扩展
|
|
712
726
|
- [VSCode](https://marketplace.visualstudio.com/items?itemName=holyhigh2.compelem-vscode) - 为h函数和css片段提供语法加亮/智能提示/诊断等功能
|
|
713
727
|
- [Vite-css](https://www.npmjs.com/package/vite-plugin-compelem-css) - 用于在导入scss/css文件时直接转换为CssTemplate
|
|
728
|
+
- [Vite-scss](https://www.npmjs.com/package/vite-plugin-compelem-scss) - 用于在css``模板中支持scss语法
|
|
714
729
|
- [Vite-comments](https://www.npmjs.com/package/vite-plugin-compelem-strip-comments) - 用于支持h``模板中的html注释
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { IComponent } from "./IComponent";
|
|
2
|
+
import { CssTemplate } from "./render/CssTemplate";
|
|
3
|
+
import { Template } from "./render/Template";
|
|
4
|
+
import { UpdatePoint } from "./render/UpdatePoint";
|
|
5
|
+
import { TplFn } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* CompElem基类,意为组件元素。提供了基本内置属性及生命周期等必备接口
|
|
8
|
+
* 每个组件都需要继承自该类
|
|
9
|
+
*
|
|
10
|
+
* @author holyhigh2
|
|
11
|
+
*/
|
|
12
|
+
export declare class CompElem<T = HTMLElement> extends HTMLElement implements IComponent<T> {
|
|
13
|
+
#private;
|
|
14
|
+
__data_: Record<string, any>;
|
|
15
|
+
__updateTree: Array<UpdatePoint>;
|
|
16
|
+
__updateSubViewDeps: Map<string, Set<UpdatePoint>>;
|
|
17
|
+
_cssUpdateInNextTick: boolean;
|
|
18
|
+
_cssVarOldValueMap: Record<string, string | number>;
|
|
19
|
+
_watchUpdateSetInNextTick: Set<Function>;
|
|
20
|
+
_watchUpdateArgsInNextTick: Map<Function, Record<string, any>>;
|
|
21
|
+
_computedUpdateSetInNextTick: Set<Function>;
|
|
22
|
+
_subComponentEventSn: number;
|
|
23
|
+
_subComponentEventMap: Map<number, Record<string, Function>>;
|
|
24
|
+
get [Symbol.toStringTag](): string;
|
|
25
|
+
get cid(): number;
|
|
26
|
+
get attrs(): Record<string, string>;
|
|
27
|
+
get props(): Record<string, any>;
|
|
28
|
+
get renderRoot(): T | undefined;
|
|
29
|
+
get renderRoots(): HTMLElement[];
|
|
30
|
+
get parentComponent(): CompElem | undefined;
|
|
31
|
+
get wrapperComponent(): CompElem | undefined;
|
|
32
|
+
get slots(): Record<string, Array<Node>>;
|
|
33
|
+
get slotHooks(): Record<string, (...args: any[]) => Template>;
|
|
34
|
+
get cssSheets(): CSSStyleSheet[];
|
|
35
|
+
get isMounted(): boolean;
|
|
36
|
+
get cssVars(): Record<string, string | number | undefined>;
|
|
37
|
+
__inited: boolean;
|
|
38
|
+
__thisRef: WeakRef<any>;
|
|
39
|
+
__superComp: Function;
|
|
40
|
+
constructor(...args: any[]);
|
|
41
|
+
insertStyleSheet(sheet: CssTemplate | CSSStyleSheet): CSSStyleSheet | null;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the root component in the parent chain, or itself if it's the top-level component.
|
|
44
|
+
*/
|
|
45
|
+
get rootComponent(): CompElem;
|
|
46
|
+
connectedCallback(): void;
|
|
47
|
+
disconnectedCallback(): void;
|
|
48
|
+
beforeDestroyed(): void;
|
|
49
|
+
destroyed(): void;
|
|
50
|
+
get isDestroyed(): boolean;
|
|
51
|
+
destroy(): void;
|
|
52
|
+
setup(): void;
|
|
53
|
+
propsReady(props: Record<string, any>): void;
|
|
54
|
+
render(): Template | null;
|
|
55
|
+
beforeMount(): void;
|
|
56
|
+
mounted(): void;
|
|
57
|
+
slotChange(slot: HTMLSlotElement, name: string): void;
|
|
58
|
+
attributeChangedCallback(attributeName: string, oldValue: string | null, newValue: string | null): void;
|
|
59
|
+
/**
|
|
60
|
+
* 是否需要更新,可获取变更属性
|
|
61
|
+
* 返回true时更新
|
|
62
|
+
*/
|
|
63
|
+
shouldUpdate(changed: Record<string, any>): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 1. 调用render
|
|
66
|
+
* 2. 更新@query/all
|
|
67
|
+
* 3. 更新ref
|
|
68
|
+
* 4. 更新prop到attr的映射
|
|
69
|
+
* @param changed
|
|
70
|
+
*/
|
|
71
|
+
updated(changed: Record<string, any>): void;
|
|
72
|
+
/**
|
|
73
|
+
* 由监控变量调用
|
|
74
|
+
* @param stateKey
|
|
75
|
+
* @param ov
|
|
76
|
+
* @param rootStateKey 如果是对象内部属性变更,会返回根属性名
|
|
77
|
+
* @returns
|
|
78
|
+
*/
|
|
79
|
+
_notify(nv: any | undefined, ov: any, chain: string[], subNewValue?: any, subOldValue?: any): void;
|
|
80
|
+
requestUpdate(nv: any, ov: any, chain: string[], subNewValue?: any, subOldValue?: any): void;
|
|
81
|
+
updateProps(props: Record<string, any>, force?: boolean): void;
|
|
82
|
+
_initProps(props: Record<string, any>, attrs?: Record<string, any>): void;
|
|
83
|
+
/**
|
|
84
|
+
* 绑定slot标签,render时调用
|
|
85
|
+
*/
|
|
86
|
+
_bindSlot(slot: HTMLSlotElement, name: string, props: Record<string, any>): void;
|
|
87
|
+
_updateSlot(name: string, propName?: string, value?: any): void;
|
|
88
|
+
_asyncDirectives: WeakMap<TplFn, any>;
|
|
89
|
+
renderAsync(cbk: TplFn, ...args: any[]): void;
|
|
90
|
+
_regSubViewDeps(props: string[], up: UpdatePoint): void;
|
|
91
|
+
_getPrivateData(): Record<string, any>;
|
|
92
|
+
/**
|
|
93
|
+
* 发出组件事件
|
|
94
|
+
* @param evName 事件名称
|
|
95
|
+
* @param args 自定义参数
|
|
96
|
+
*/
|
|
97
|
+
emit(evName: string, arg?: Record<string, any>, event?: Event): void;
|
|
98
|
+
/**
|
|
99
|
+
* 下一帧执行
|
|
100
|
+
* @param cbk
|
|
101
|
+
*/
|
|
102
|
+
nextTick(cbk: () => void): void;
|
|
103
|
+
/**
|
|
104
|
+
* 强制更新一次视图
|
|
105
|
+
*/
|
|
106
|
+
forceUpdate(): void;
|
|
107
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { CssTemplate } from "./render/CssTemplate";
|
|
2
|
+
import { Template } from "./render/Template";
|
|
3
|
+
/**
|
|
4
|
+
* 组件接口
|
|
5
|
+
* 定义组件属性、生命周期及方法
|
|
6
|
+
* @author holyhigh2
|
|
7
|
+
*/
|
|
8
|
+
export interface IComponent<T = HTMLElement> {
|
|
9
|
+
get cid(): number;
|
|
10
|
+
get attrs(): Record<string, string>;
|
|
11
|
+
get props(): Record<string, any>;
|
|
12
|
+
get renderRoot(): T | undefined;
|
|
13
|
+
get renderRoots(): HTMLElement[];
|
|
14
|
+
get rootComponent(): HTMLElement | undefined;
|
|
15
|
+
get parentComponent(): HTMLElement | undefined;
|
|
16
|
+
get wrapperComponent(): HTMLElement | undefined;
|
|
17
|
+
get slots(): Record<string, Array<Node>>;
|
|
18
|
+
get slotHooks(): Record<string, (...args: any[]) => Template>;
|
|
19
|
+
get cssSheets(): CSSStyleSheet[];
|
|
20
|
+
get isMounted(): boolean;
|
|
21
|
+
get cssVars(): Record<string, string | number | undefined>;
|
|
22
|
+
propsReady(props: Record<string, any>): void;
|
|
23
|
+
render(): Template | null;
|
|
24
|
+
beforeMount(): void;
|
|
25
|
+
mounted(): void;
|
|
26
|
+
connectedCallback(): void;
|
|
27
|
+
disconnectedCallback(): void;
|
|
28
|
+
beforeDestroyed(): void;
|
|
29
|
+
destroyed(): void;
|
|
30
|
+
shouldUpdate(changed: Record<string, any>): boolean;
|
|
31
|
+
updated(changed: Record<string, any>): void;
|
|
32
|
+
slotChange(slot: HTMLSlotElement, slotName: string): void;
|
|
33
|
+
attributeChangedCallback(attributeName: string, oldValue: string | null, newValue: string | null): void;
|
|
34
|
+
/**
|
|
35
|
+
* 初始化组件实例,完成响应属性及参数绑定、执行计算属性及立即执行的监视器、视图等等。
|
|
36
|
+
* 除非想创建一个全局响应分发器,否则不应该调用该方法
|
|
37
|
+
*/
|
|
38
|
+
setup(): void;
|
|
39
|
+
/**
|
|
40
|
+
* 抛出自定义事件
|
|
41
|
+
* @param evName 事件名称
|
|
42
|
+
* @param args 自定义参数
|
|
43
|
+
*/
|
|
44
|
+
emit(evName: string, arg: Record<string, any>, event?: Event): void;
|
|
45
|
+
/**
|
|
46
|
+
* 创建下一帧执行的逻辑
|
|
47
|
+
* @param cbk
|
|
48
|
+
*/
|
|
49
|
+
nextTick(cbk: () => void): void;
|
|
50
|
+
/**
|
|
51
|
+
* 强制更新视图
|
|
52
|
+
*/
|
|
53
|
+
forceUpdate(): void;
|
|
54
|
+
/**
|
|
55
|
+
* 请求指定路径更新
|
|
56
|
+
* @param nv new value
|
|
57
|
+
* @param ov old value
|
|
58
|
+
* @param chain path segment
|
|
59
|
+
*/
|
|
60
|
+
requestUpdate(nv: any, ov: any, chain: string[], subNewValue?: any, subOldValue?: any): void;
|
|
61
|
+
/**
|
|
62
|
+
* 向组件插入样式表,没有shadowDOM的组件调用无效
|
|
63
|
+
* @param sheet
|
|
64
|
+
*/
|
|
65
|
+
insertStyleSheet(sheet: CssTemplate | CSSStyleSheet): CSSStyleSheet | null;
|
|
66
|
+
/**
|
|
67
|
+
* 对于组件应用于原生环境或其他相似环境没有父组件但需要更新属性时调用
|
|
68
|
+
* @param props {属性名:值} 对象
|
|
69
|
+
*/
|
|
70
|
+
updateProps(props: Record<string, any>): void;
|
|
71
|
+
}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DefaultProps } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* 设置全局/组件默认属性
|
|
4
|
+
* @param options
|
|
5
|
+
*/
|
|
6
|
+
export declare function setDefaults(options: DefaultProps): void;
|
|
7
|
+
export declare function getBaseSheets(ctor: Function): CSSStyleSheet[];
|
|
8
|
+
export declare const getDefaultCss: () => CSSStyleSheet[];
|
|
9
|
+
export declare const getGlobalDefaultProps: () => Record<string, any>;
|
|
10
|
+
export declare const getComponentDefaultProps: () => Record<string, any>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CompElem } from "./CompElem";
|
|
2
|
+
import { DecoratorWrapper } from "./decorator";
|
|
3
|
+
import { CssTemplate } from "./render/CssTemplate";
|
|
4
|
+
import { Constructor, Getter, PropOption, StateOption, TplFn } from "./types";
|
|
5
|
+
export declare const SLOT_NAME_DEFAULT = "default";
|
|
6
|
+
/**
|
|
7
|
+
* 共享内容
|
|
8
|
+
*/
|
|
9
|
+
export declare const EXP_KEY: RegExp;
|
|
10
|
+
export declare enum CollectorType {
|
|
11
|
+
RENDER = 1,
|
|
12
|
+
COMPUTED = 2,
|
|
13
|
+
DIRECTIVE = 3
|
|
14
|
+
}
|
|
15
|
+
export declare enum Mode {
|
|
16
|
+
Prod = "prod",
|
|
17
|
+
Dev = "dev"
|
|
18
|
+
}
|
|
19
|
+
export declare const PropTypeMap: Record<string, Constructor<any>>;
|
|
20
|
+
export interface CompiledWatchMeta {
|
|
21
|
+
rootMap: Map<string, string[]>;
|
|
22
|
+
watchKeysDeep: string[] | undefined;
|
|
23
|
+
watchDeepUpdateMap: Record<string, Set<Function>>;
|
|
24
|
+
watchUpdateMap: Record<string, Set<Function>>;
|
|
25
|
+
onceMap: Map<string, boolean>;
|
|
26
|
+
}
|
|
27
|
+
export declare const DefinitionCompEventMap: Map<Function, Record<string, any>[]>;
|
|
28
|
+
export declare const DefinitionCompEmitMap: WeakMap<Function, Set<string>>;
|
|
29
|
+
export declare const DefinitionTagMap: Record<string, string>;
|
|
30
|
+
export declare const DefinitionComponentMap: Record<string, Function>;
|
|
31
|
+
export declare const DefinitionComputedMap: WeakMap<Function, Record<string, Getter>>;
|
|
32
|
+
export declare const DefinitionStateMap: WeakMap<Function, Record<string, StateOption>>;
|
|
33
|
+
export declare const DefinitionPropMap: WeakMap<Function, Record<string, PropOption>>;
|
|
34
|
+
export declare const DefinitionModelMap: WeakMap<Function, string[]>;
|
|
35
|
+
export declare const DefinitionDecoratorMap: Map<Function, DecoratorWrapper[]>;
|
|
36
|
+
export declare const ObservedAttrsMap: Map<Function, Set<string>>;
|
|
37
|
+
export declare const ViewDepMap: Map<Function, Set<string>>;
|
|
38
|
+
export declare const WatchKeysOnceMap: WeakMap<Function, Map<string, boolean>>;
|
|
39
|
+
export declare const WatchKeysDeepListMap: WeakMap<Function, string[]>;
|
|
40
|
+
export declare const WatchKeyRootMap: WeakMap<Function, Map<string, string[]>>;
|
|
41
|
+
export declare const WatchUpdateMap: WeakMap<Function, Record<string, Set<Function>>>;
|
|
42
|
+
export declare const WatchDeepUpdateMap: WeakMap<Function, Record<string, Set<Function>>>;
|
|
43
|
+
export declare const WatchImmediateListMap: WeakMap<Function, Record<string, Set<Function>>>;
|
|
44
|
+
export declare const CompiledWatchMetaMap: WeakMap<Function, CompiledWatchMeta | null>;
|
|
45
|
+
export declare const StateShallowKeySetMap: WeakMap<Function, Set<string>>;
|
|
46
|
+
export declare const PropShallowKeySetMap: WeakMap<Function, Set<string>>;
|
|
47
|
+
export declare const HasChangedPropOrStateMap: WeakMap<Function, Map<string, Function>>;
|
|
48
|
+
export declare const ComputedMapCache: WeakMap<Function, Record<string, Getter>>;
|
|
49
|
+
export declare const ComputedUpdateDepsMap: WeakMap<Function, Map<string, Set<Function>>>;
|
|
50
|
+
export declare const CssUpdateDepsMap: WeakMap<Function, Set<string>>;
|
|
51
|
+
export declare const CssTemplateCacheMap: WeakMap<TemplateStringsArray, CssTemplate>;
|
|
52
|
+
export declare const CssStyleSheetCacheMap: WeakMap<TemplateStringsArray, CSSStyleSheet>;
|
|
53
|
+
export declare const CssScopeCacheMap: WeakMap<Function, Map<string, CSSStyleSheet[]>>;
|
|
54
|
+
export declare const CssTemplateSheetMap: WeakMap<CssTemplate, CSSStyleSheet>;
|
|
55
|
+
export declare const CssVarKeyCacheMap: WeakMap<Function, Map<string, string>>;
|
|
56
|
+
export declare const DirectiveScopeMap: Map<Function, string[]>;
|
|
57
|
+
export declare const ComponentDynamicCssUpdaterMap: WeakMap<CompElem<any>, Map<Function, CSSStyleSheet>>;
|
|
58
|
+
export declare const ComponentUninitializedSubComponentPropMap: WeakMap<CompElem<any>, Map<Node, Record<string, any>>>;
|
|
59
|
+
export declare const ComponentUninitializedSlotFunctionMap: WeakMap<Node, Record<string, TplFn>>;
|
|
60
|
+
export declare const ComponentUninitializedWrapperComponentMap: WeakMap<Node, CompElem<any>>;
|
|
61
|
+
export declare const PATH_SEPARATOR = ".";
|
|
62
|
+
export declare const PROP_NAME_SLOTS = "slots";
|
|
63
|
+
export declare const DATA_KEY = "__data_";
|
|
64
|
+
export declare const PLACEHOLDER = "\u27EC\u010A\u27ED";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CompElem } from "../CompElem";
|
|
2
|
+
export declare enum DecoratorType {
|
|
3
|
+
CLASS = "class",
|
|
4
|
+
FIELD = "field",
|
|
5
|
+
METHOD = "method"
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* 用于构造装饰器
|
|
9
|
+
* @author holyhigh2
|
|
10
|
+
*/
|
|
11
|
+
export declare abstract class Decorator {
|
|
12
|
+
/**
|
|
13
|
+
* 优先级,越大越先执行
|
|
14
|
+
*/
|
|
15
|
+
static get priority(): number;
|
|
16
|
+
/**
|
|
17
|
+
* 装饰器使用范围,超出范围会报错
|
|
18
|
+
*/
|
|
19
|
+
abstract get targets(): Array<DecoratorType>;
|
|
20
|
+
/**
|
|
21
|
+
* 构造会传递自定义参数
|
|
22
|
+
* @param args 自定义参数
|
|
23
|
+
*/
|
|
24
|
+
created(component: CompElem, ...args: any[]): void;
|
|
25
|
+
/**
|
|
26
|
+
* 执行时机与组件一致
|
|
27
|
+
* @param component 组件实例
|
|
28
|
+
* @param setReactive 为实例设置响应属性,注意,仅是设置到了instance.reactiveData中并非this.key。如需实现this访问,可自行定义组件的properties
|
|
29
|
+
* @param args 装饰器函数参数
|
|
30
|
+
*/
|
|
31
|
+
beforeMount(component: CompElem, setReactive: (key: string, value: any) => any, ...args: any[]): void;
|
|
32
|
+
mounted(component: CompElem, setReactive: (key: string, value: any) => any, ...args: any[]): void;
|
|
33
|
+
updated(component: CompElem, changed: Record<string, any>): void;
|
|
34
|
+
beforeDestroy(component: CompElem, ...args: any[]): void;
|
|
35
|
+
}
|