@fukict/basic 0.1.0
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/LICENSE +21 -0
- package/dist/component-class/fukict.d.ts +207 -0
- package/dist/component-class/fukict.d.ts.map +1 -0
- package/dist/component-class/fukict.js +299 -0
- package/dist/component-class/fukict.js.map +1 -0
- package/dist/component-class/index.d.ts +5 -0
- package/dist/component-class/index.d.ts.map +1 -0
- package/dist/component-class/index.js +5 -0
- package/dist/component-class/index.js.map +1 -0
- package/dist/component-class/slot.d.ts +9 -0
- package/dist/component-class/slot.d.ts.map +1 -0
- package/dist/component-class/slot.js +46 -0
- package/dist/component-class/slot.js.map +1 -0
- package/dist/component-function/define.d.ts +36 -0
- package/dist/component-function/define.d.ts.map +1 -0
- package/dist/component-function/define.js +23 -0
- package/dist/component-function/define.js.map +1 -0
- package/dist/component-function/index.d.ts +6 -0
- package/dist/component-function/index.d.ts.map +1 -0
- package/dist/component-function/index.js +5 -0
- package/dist/component-function/index.js.map +1 -0
- package/dist/dom/attributes.d.ts +36 -0
- package/dist/dom/attributes.d.ts.map +1 -0
- package/dist/dom/attributes.js +113 -0
- package/dist/dom/attributes.js.map +1 -0
- package/dist/dom/element.d.ts +22 -0
- package/dist/dom/element.d.ts.map +1 -0
- package/dist/dom/element.js +98 -0
- package/dist/dom/element.js.map +1 -0
- package/dist/dom/events.d.ts +14 -0
- package/dist/dom/events.d.ts.map +1 -0
- package/dist/dom/events.js +18 -0
- package/dist/dom/events.js.map +1 -0
- package/dist/dom/index.d.ts +10 -0
- package/dist/dom/index.d.ts.map +1 -0
- package/dist/dom/index.js +14 -0
- package/dist/dom/index.js.map +1 -0
- package/dist/dom/node.d.ts +22 -0
- package/dist/dom/node.d.ts.map +1 -0
- package/dist/dom/node.js +30 -0
- package/dist/dom/node.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-runtime.d.ts +10 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +9 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/metadata.d.ts +14 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +14 -0
- package/dist/metadata.js.map +1 -0
- package/dist/renderer/attributes.d.ts +15 -0
- package/dist/renderer/attributes.d.ts.map +1 -0
- package/dist/renderer/attributes.js +61 -0
- package/dist/renderer/attributes.js.map +1 -0
- package/dist/renderer/create.d.ts +30 -0
- package/dist/renderer/create.d.ts.map +1 -0
- package/dist/renderer/create.js +223 -0
- package/dist/renderer/create.js.map +1 -0
- package/dist/renderer/diff/children.d.ts +12 -0
- package/dist/renderer/diff/children.d.ts.map +1 -0
- package/dist/renderer/diff/children.js +55 -0
- package/dist/renderer/diff/children.js.map +1 -0
- package/dist/renderer/diff/class.d.ts +8 -0
- package/dist/renderer/diff/class.d.ts.map +1 -0
- package/dist/renderer/diff/class.js +38 -0
- package/dist/renderer/diff/class.js.map +1 -0
- package/dist/renderer/diff/element.d.ts +14 -0
- package/dist/renderer/diff/element.d.ts.map +1 -0
- package/dist/renderer/diff/element.js +34 -0
- package/dist/renderer/diff/element.js.map +1 -0
- package/dist/renderer/diff/fragment.d.ts +13 -0
- package/dist/renderer/diff/fragment.d.ts.map +1 -0
- package/dist/renderer/diff/fragment.js +32 -0
- package/dist/renderer/diff/fragment.js.map +1 -0
- package/dist/renderer/diff/function.d.ts +9 -0
- package/dist/renderer/diff/function.d.ts.map +1 -0
- package/dist/renderer/diff/function.js +58 -0
- package/dist/renderer/diff/function.js.map +1 -0
- package/dist/renderer/diff/helpers.d.ts +19 -0
- package/dist/renderer/diff/helpers.d.ts.map +1 -0
- package/dist/renderer/diff/helpers.js +194 -0
- package/dist/renderer/diff/helpers.js.map +1 -0
- package/dist/renderer/diff/index.d.ts +18 -0
- package/dist/renderer/diff/index.d.ts.map +1 -0
- package/dist/renderer/diff/index.js +103 -0
- package/dist/renderer/diff/index.js.map +1 -0
- package/dist/renderer/diff/props.d.ts +18 -0
- package/dist/renderer/diff/props.d.ts.map +1 -0
- package/dist/renderer/diff/props.js +99 -0
- package/dist/renderer/diff/props.js.map +1 -0
- package/dist/renderer/index.d.ts +26 -0
- package/dist/renderer/index.d.ts.map +1 -0
- package/dist/renderer/index.js +93 -0
- package/dist/renderer/index.js.map +1 -0
- package/dist/renderer/mount.d.ts +30 -0
- package/dist/renderer/mount.d.ts.map +1 -0
- package/dist/renderer/mount.js +209 -0
- package/dist/renderer/mount.js.map +1 -0
- package/dist/types/class.d.ts +88 -0
- package/dist/types/class.d.ts.map +1 -0
- package/dist/types/class.js +2 -0
- package/dist/types/class.js.map +1 -0
- package/dist/types/context.d.ts +36 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +9 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/core.d.ts +124 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +15 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/dom-attributes.d.ts +236 -0
- package/dist/types/dom-attributes.d.ts.map +1 -0
- package/dist/types/dom-attributes.js +2 -0
- package/dist/types/dom-attributes.js.map +1 -0
- package/dist/types/events.d.ts +13 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +7 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/jsx.d.ts +215 -0
- package/dist/types/jsx.d.ts.map +1 -0
- package/dist/types/jsx.js +2 -0
- package/dist/types/jsx.js.map +1 -0
- package/dist/utils/context.d.ts +31 -0
- package/dist/utils/context.d.ts.map +1 -0
- package/dist/utils/context.js +80 -0
- package/dist/utils/context.js.map +1 -0
- package/dist/utils/dom-helpers.d.ts +29 -0
- package/dist/utils/dom-helpers.d.ts.map +1 -0
- package/dist/utils/dom-helpers.js +53 -0
- package/dist/utils/dom-helpers.js.map +1 -0
- package/dist/vnode.d.ts +28 -0
- package/dist/vnode.d.ts.map +1 -0
- package/dist/vnode.js +68 -0
- package/dist/vnode.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Fukict Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { Ref, Slots } from '../types/class.js';
|
|
2
|
+
import type { VNode, VNodeChild } from '../types/core.js';
|
|
3
|
+
import type { FukictDetachAttribute, FukictRefAttribute, FukictSlotAttribute } from '../types/dom-attributes.js';
|
|
4
|
+
/**
|
|
5
|
+
* Component children props
|
|
6
|
+
* Note: TypeScript sees children as VNodeChild during JSX compilation,
|
|
7
|
+
* but Babel transforms them to VNode[] at runtime
|
|
8
|
+
*/
|
|
9
|
+
export interface BaseProps {
|
|
10
|
+
children?: VNodeChild | VNodeChild[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Complete props type for Fukict components (including all fukict attributes)
|
|
14
|
+
*/
|
|
15
|
+
export type FukictComponentProps<P extends Record<string, any>> = P & BaseProps & FukictRefAttribute & FukictSlotAttribute & FukictDetachAttribute;
|
|
16
|
+
/**
|
|
17
|
+
* Fukict class component base class
|
|
18
|
+
*
|
|
19
|
+
* @example Basic usage with self-update
|
|
20
|
+
* ```ts
|
|
21
|
+
* class Counter extends Fukict<{ initial: number }> {
|
|
22
|
+
* private count: number;
|
|
23
|
+
*
|
|
24
|
+
* constructor(props, children) {
|
|
25
|
+
* super(props, children);
|
|
26
|
+
* this.count = props.initial;
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* increment() {
|
|
30
|
+
* this.count++;
|
|
31
|
+
* // Self-update: manually trigger re-render
|
|
32
|
+
* this.update();
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* render() {
|
|
36
|
+
* return <div on:click={() => this.increment()}>{this.count}</div>;
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @example Custom update logic
|
|
42
|
+
* ```ts
|
|
43
|
+
* class OptimizedComponent extends Fukict<{ data: string }> {
|
|
44
|
+
* update(newProps) {
|
|
45
|
+
* // Custom logic: skip update if data hasn't changed
|
|
46
|
+
* if (newProps.data === this.props.data) return;
|
|
47
|
+
* super.update(newProps);
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare abstract class Fukict<P extends Record<string, any> = {}, S extends Slots = Slots> {
|
|
53
|
+
/**
|
|
54
|
+
* Component type marker for Babel plugin
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
static readonly __COMPONENT_TYPE__: "class";
|
|
58
|
+
/**
|
|
59
|
+
* Unique component instance ID (for debugging)
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
readonly __id__: number;
|
|
63
|
+
/**
|
|
64
|
+
* Component name (for debugging)
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
readonly __name__: string;
|
|
68
|
+
/**
|
|
69
|
+
* Component props (readonly)
|
|
70
|
+
* Automatically includes optional children property and fukict attributes
|
|
71
|
+
*/
|
|
72
|
+
protected readonly props: FukictComponentProps<P>;
|
|
73
|
+
/**
|
|
74
|
+
* Component slots (extracted by renderer)
|
|
75
|
+
*
|
|
76
|
+
* Note: Slots are not available when component is manually instantiated
|
|
77
|
+
* or in detached rendering mode (fukict:detach).
|
|
78
|
+
*/
|
|
79
|
+
protected slots: S;
|
|
80
|
+
/**
|
|
81
|
+
* Refs map (shared with framework and user)
|
|
82
|
+
*/
|
|
83
|
+
readonly refs: Map<string | symbol, Ref>;
|
|
84
|
+
/**
|
|
85
|
+
* Current rendered VNode (component's internal render result)
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
__vnode__: VNode | null;
|
|
89
|
+
/**
|
|
90
|
+
* Wrapper VNode (ClassComponentVNode that wraps this instance in parent's tree)
|
|
91
|
+
* Used for context traversal - child can access parent's context via __wrapper__
|
|
92
|
+
* @internal
|
|
93
|
+
*/
|
|
94
|
+
__wrapper__: VNode | null;
|
|
95
|
+
/**
|
|
96
|
+
* Parent DOM container
|
|
97
|
+
* @internal
|
|
98
|
+
*/
|
|
99
|
+
__container__: Element | null;
|
|
100
|
+
/**
|
|
101
|
+
* Component placeholder (in container mode)
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
__placeholder__: Comment | null;
|
|
105
|
+
/**
|
|
106
|
+
* Lifecycle execution flags (prevent re-entrant calls during lifecycle)
|
|
107
|
+
* @internal
|
|
108
|
+
*/
|
|
109
|
+
__inUpdating__: boolean;
|
|
110
|
+
__inMounting__: boolean;
|
|
111
|
+
__inUnmounting__: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Constructor
|
|
114
|
+
*/
|
|
115
|
+
constructor(props: FukictComponentProps<P>);
|
|
116
|
+
/**
|
|
117
|
+
* Render method (must be implemented by subclass)
|
|
118
|
+
*/
|
|
119
|
+
abstract render(): VNode;
|
|
120
|
+
/**
|
|
121
|
+
* Provide context value at current component level
|
|
122
|
+
*
|
|
123
|
+
* Only available in Class Components. Context is stored on VNode tree
|
|
124
|
+
* with no global state. Lower-level contexts override parent contexts.
|
|
125
|
+
*
|
|
126
|
+
* @param key - Context key (Symbol or string)
|
|
127
|
+
* @param value - Context value (will be wrapped in Proxy for immutability)
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* import { THEME_CONTEXT, type ThemeContext } from './contexts';
|
|
132
|
+
*
|
|
133
|
+
* class App extends Fukict {
|
|
134
|
+
* mounted() {
|
|
135
|
+
* this.provideContext<ThemeContext>(THEME_CONTEXT, {
|
|
136
|
+
* mode: 'dark',
|
|
137
|
+
* color: '#000',
|
|
138
|
+
* });
|
|
139
|
+
* }
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
protected provideContext<T>(key: string | symbol, value: T): void;
|
|
144
|
+
/**
|
|
145
|
+
* Get context value from current or parent contexts
|
|
146
|
+
*
|
|
147
|
+
* Traverses up the VNode tree to find context. Returns default value
|
|
148
|
+
* if context not found.
|
|
149
|
+
*
|
|
150
|
+
* Search order:
|
|
151
|
+
* 1. Current component's __vnode__.__context__ (if component provided its own context)
|
|
152
|
+
* 2. Parent component's context (via __wrapper__.__parentInstance__)
|
|
153
|
+
*
|
|
154
|
+
* @param key - Context key (Symbol or string)
|
|
155
|
+
* @param defaultValue - Default value if context not found
|
|
156
|
+
* @returns Context value (or default)
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { THEME_CONTEXT, type ThemeContext } from './contexts';
|
|
161
|
+
*
|
|
162
|
+
* class Button extends Fukict {
|
|
163
|
+
* render() {
|
|
164
|
+
* const theme = this.getContext<ThemeContext>(
|
|
165
|
+
* THEME_CONTEXT,
|
|
166
|
+
* { mode: 'light', color: '#fff' }
|
|
167
|
+
* );
|
|
168
|
+
* return <button style={`background: ${theme.color}`}>Click me</button>;
|
|
169
|
+
* }
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
protected getContext<T>(key: string | symbol, defaultValue?: T): T | undefined;
|
|
174
|
+
/**
|
|
175
|
+
* Update component (props-driven update with built-in diff)
|
|
176
|
+
*
|
|
177
|
+
* Can be overridden by user for custom update logic.
|
|
178
|
+
* Called by renderer when parent updates props.
|
|
179
|
+
* Skipped when component is detached (fukict:detach).
|
|
180
|
+
*
|
|
181
|
+
* @param newProps - New props (optional, defaults to current props for self-update)
|
|
182
|
+
*/
|
|
183
|
+
update(newProps?: FukictComponentProps<P>): void;
|
|
184
|
+
/**
|
|
185
|
+
* Lifecycle: called after component is mounted
|
|
186
|
+
*/
|
|
187
|
+
mounted?(): void;
|
|
188
|
+
/**
|
|
189
|
+
* Lifecycle: called before component is unmounted
|
|
190
|
+
*/
|
|
191
|
+
beforeUnmount?(): void;
|
|
192
|
+
/**
|
|
193
|
+
* Lifecycle: called after component is updated
|
|
194
|
+
*/
|
|
195
|
+
updated?(prevProps: FukictComponentProps<P>): void;
|
|
196
|
+
/**
|
|
197
|
+
* Mount component (called by renderer or manually)
|
|
198
|
+
* @internal
|
|
199
|
+
*/
|
|
200
|
+
mount(container: Element, placeholder?: Comment): void;
|
|
201
|
+
/**
|
|
202
|
+
* Unmount component (called by renderer)
|
|
203
|
+
* @internal
|
|
204
|
+
*/
|
|
205
|
+
unmount(): void;
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=fukict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fukict.d.ts","sourceRoot":"","sources":["../../src/component-class/fukict.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EACV,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAMpC;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,GACjE,SAAS,GACT,kBAAkB,GAClB,mBAAmB,GACnB,qBAAqB,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,8BAAsB,MAAM,CAC1B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EAClC,CAAC,SAAS,KAAK,GAAG,KAAK;IAEvB;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAG,OAAO,CAAU;IAEtD;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAElD;;;;;OAKG;IACH,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;IAEnB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;IAEzC;;;OAGG;IACH,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IAExB;;;;OAIG;IACH,WAAW,EAAE,KAAK,GAAG,IAAI,CAAC;IAE1B;;;OAGG;IACH,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;IAE9B;;;OAGG;IACH,eAAe,EAAE,OAAO,GAAG,IAAI,CAAC;IAEhC;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;OAEG;gBACS,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAoB1C;;OAEG;IACH,QAAQ,CAAC,MAAM,IAAI,KAAK;IAExB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,SAAS,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAkBjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,SAAS,CAAC,UAAU,CAAC,CAAC,EACpB,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,YAAY,CAAC,EAAE,CAAC,GACf,CAAC,GAAG,SAAS;IA4BhB;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,IAAI;IA2ChD;;OAEG;IACH,OAAO,CAAC,IAAI,IAAI;IAEhB;;OAEG;IACH,aAAa,CAAC,IAAI,IAAI;IAEtB;;OAEG;IACH,OAAO,CAAC,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,IAAI;IAElD;;;OAGG;IACH,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI;IA8BtD;;;OAGG;IACH,OAAO,IAAI,IAAI;CAiBhB"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fukict/basic - Fukict Class Component Base
|
|
3
|
+
*/
|
|
4
|
+
import { createRealNode } from '../renderer/create.js';
|
|
5
|
+
import { diff, removeNode } from '../renderer/diff/index.js';
|
|
6
|
+
import { activate } from '../renderer/mount.js';
|
|
7
|
+
import { createImmutableProxy, getParentContext } from '../utils/context.js';
|
|
8
|
+
// Global component instance counter for unique IDs
|
|
9
|
+
let componentIdCounter = 0;
|
|
10
|
+
/**
|
|
11
|
+
* Fukict class component base class
|
|
12
|
+
*
|
|
13
|
+
* @example Basic usage with self-update
|
|
14
|
+
* ```ts
|
|
15
|
+
* class Counter extends Fukict<{ initial: number }> {
|
|
16
|
+
* private count: number;
|
|
17
|
+
*
|
|
18
|
+
* constructor(props, children) {
|
|
19
|
+
* super(props, children);
|
|
20
|
+
* this.count = props.initial;
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* increment() {
|
|
24
|
+
* this.count++;
|
|
25
|
+
* // Self-update: manually trigger re-render
|
|
26
|
+
* this.update();
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* render() {
|
|
30
|
+
* return <div on:click={() => this.increment()}>{this.count}</div>;
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Custom update logic
|
|
36
|
+
* ```ts
|
|
37
|
+
* class OptimizedComponent extends Fukict<{ data: string }> {
|
|
38
|
+
* update(newProps) {
|
|
39
|
+
* // Custom logic: skip update if data hasn't changed
|
|
40
|
+
* if (newProps.data === this.props.data) return;
|
|
41
|
+
* super.update(newProps);
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export class Fukict {
|
|
47
|
+
/**
|
|
48
|
+
* Component type marker for Babel plugin
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
static __COMPONENT_TYPE__ = 'class';
|
|
52
|
+
/**
|
|
53
|
+
* Unique component instance ID (for debugging)
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
__id__;
|
|
57
|
+
/**
|
|
58
|
+
* Component name (for debugging)
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
__name__;
|
|
62
|
+
/**
|
|
63
|
+
* Component props (readonly)
|
|
64
|
+
* Automatically includes optional children property and fukict attributes
|
|
65
|
+
*/
|
|
66
|
+
props;
|
|
67
|
+
/**
|
|
68
|
+
* Component slots (extracted by renderer)
|
|
69
|
+
*
|
|
70
|
+
* Note: Slots are not available when component is manually instantiated
|
|
71
|
+
* or in detached rendering mode (fukict:detach).
|
|
72
|
+
*/
|
|
73
|
+
slots;
|
|
74
|
+
/**
|
|
75
|
+
* Refs map (shared with framework and user)
|
|
76
|
+
*/
|
|
77
|
+
refs;
|
|
78
|
+
/**
|
|
79
|
+
* Current rendered VNode (component's internal render result)
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
__vnode__;
|
|
83
|
+
/**
|
|
84
|
+
* Wrapper VNode (ClassComponentVNode that wraps this instance in parent's tree)
|
|
85
|
+
* Used for context traversal - child can access parent's context via __wrapper__
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
__wrapper__;
|
|
89
|
+
/**
|
|
90
|
+
* Parent DOM container
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
__container__;
|
|
94
|
+
/**
|
|
95
|
+
* Component placeholder (in container mode)
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
98
|
+
__placeholder__;
|
|
99
|
+
/**
|
|
100
|
+
* Lifecycle execution flags (prevent re-entrant calls during lifecycle)
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
__inUpdating__;
|
|
104
|
+
__inMounting__;
|
|
105
|
+
__inUnmounting__;
|
|
106
|
+
/**
|
|
107
|
+
* Constructor
|
|
108
|
+
*/
|
|
109
|
+
constructor(props) {
|
|
110
|
+
this.__id__ = ++componentIdCounter;
|
|
111
|
+
this.__name__ = this.constructor.name;
|
|
112
|
+
this.props = props;
|
|
113
|
+
this.slots = {};
|
|
114
|
+
// Initialize instance fields (avoid field initializers for better memory efficiency)
|
|
115
|
+
this.refs = new Map();
|
|
116
|
+
this.__vnode__ = null;
|
|
117
|
+
this.__wrapper__ = null;
|
|
118
|
+
this.__container__ = null;
|
|
119
|
+
this.__placeholder__ = null;
|
|
120
|
+
this.__inUpdating__ = false;
|
|
121
|
+
this.__inMounting__ = false;
|
|
122
|
+
this.__inUnmounting__ = false;
|
|
123
|
+
// Note: Do NOT call render() here!
|
|
124
|
+
// render() will be called in mount() after subclass constructor completes
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Provide context value at current component level
|
|
128
|
+
*
|
|
129
|
+
* Only available in Class Components. Context is stored on VNode tree
|
|
130
|
+
* with no global state. Lower-level contexts override parent contexts.
|
|
131
|
+
*
|
|
132
|
+
* @param key - Context key (Symbol or string)
|
|
133
|
+
* @param value - Context value (will be wrapped in Proxy for immutability)
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* import { THEME_CONTEXT, type ThemeContext } from './contexts';
|
|
138
|
+
*
|
|
139
|
+
* class App extends Fukict {
|
|
140
|
+
* mounted() {
|
|
141
|
+
* this.provideContext<ThemeContext>(THEME_CONTEXT, {
|
|
142
|
+
* mode: 'dark',
|
|
143
|
+
* color: '#000',
|
|
144
|
+
* });
|
|
145
|
+
* }
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
provideContext(key, value) {
|
|
150
|
+
if (!this.__vnode__) {
|
|
151
|
+
console.warn(`[Fukict] Cannot provide context in component "${this.__name__}": __vnode__ is null. ` +
|
|
152
|
+
`Make sure to call provideContext() after component is mounted.`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!this.__vnode__.__context__) {
|
|
156
|
+
this.__vnode__.__context__ = {
|
|
157
|
+
__parent__: getParentContext(this.__vnode__),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
this.__vnode__.__context__[key] = createImmutableProxy(value);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get context value from current or parent contexts
|
|
164
|
+
*
|
|
165
|
+
* Traverses up the VNode tree to find context. Returns default value
|
|
166
|
+
* if context not found.
|
|
167
|
+
*
|
|
168
|
+
* Search order:
|
|
169
|
+
* 1. Current component's __vnode__.__context__ (if component provided its own context)
|
|
170
|
+
* 2. Parent component's context (via __wrapper__.__parentInstance__)
|
|
171
|
+
*
|
|
172
|
+
* @param key - Context key (Symbol or string)
|
|
173
|
+
* @param defaultValue - Default value if context not found
|
|
174
|
+
* @returns Context value (or default)
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* import { THEME_CONTEXT, type ThemeContext } from './contexts';
|
|
179
|
+
*
|
|
180
|
+
* class Button extends Fukict {
|
|
181
|
+
* render() {
|
|
182
|
+
* const theme = this.getContext<ThemeContext>(
|
|
183
|
+
* THEME_CONTEXT,
|
|
184
|
+
* { mode: 'light', color: '#fff' }
|
|
185
|
+
* );
|
|
186
|
+
* return <button style={`background: ${theme.color}`}>Click me</button>;
|
|
187
|
+
* }
|
|
188
|
+
* }
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
getContext(key, defaultValue) {
|
|
192
|
+
// First, check if this component has its own context
|
|
193
|
+
if (this.__vnode__ && this.__vnode__.__context__) {
|
|
194
|
+
let currentContext = this.__vnode__.__context__;
|
|
195
|
+
// Traverse up the chain starting from current component
|
|
196
|
+
while (currentContext) {
|
|
197
|
+
if (key in currentContext) {
|
|
198
|
+
return currentContext[key];
|
|
199
|
+
}
|
|
200
|
+
currentContext = currentContext.__parent__;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// If not found in own context chain, look in parent component
|
|
204
|
+
if (this.__wrapper__) {
|
|
205
|
+
const parentInstance = this.__wrapper__.__parentInstance__;
|
|
206
|
+
if (parentInstance) {
|
|
207
|
+
// Recursively search in parent
|
|
208
|
+
return parentInstance.getContext(key, defaultValue);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return defaultValue;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Update component (props-driven update with built-in diff)
|
|
215
|
+
*
|
|
216
|
+
* Can be overridden by user for custom update logic.
|
|
217
|
+
* Called by renderer when parent updates props.
|
|
218
|
+
* Skipped when component is detached (fukict:detach).
|
|
219
|
+
*
|
|
220
|
+
* @param newProps - New props (optional, defaults to current props for self-update)
|
|
221
|
+
*/
|
|
222
|
+
update(newProps) {
|
|
223
|
+
// Prevent re-entrant update during lifecycle hooks
|
|
224
|
+
if (this.__inUpdating__ || this.__inMounting__ || this.__inUnmounting__) {
|
|
225
|
+
console.warn(`[Fukict] Component "${this.__name__}" tried to update during lifecycle execution. ` +
|
|
226
|
+
`This is not allowed and the update was ignored. ` +
|
|
227
|
+
`Do not call update() or trigger parent updates in mounted/updated/beforeUnmount hooks.`);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
this.__inUpdating__ = true;
|
|
231
|
+
const prevProps = this.props;
|
|
232
|
+
// Update props (use current props if not provided)
|
|
233
|
+
if (newProps !== undefined) {
|
|
234
|
+
this.props = newProps;
|
|
235
|
+
}
|
|
236
|
+
// Re-render
|
|
237
|
+
const newVNode = this.render();
|
|
238
|
+
// Preserve context from old VNode to new VNode
|
|
239
|
+
if (this.__vnode__?.__context__) {
|
|
240
|
+
newVNode.__context__ = this.__vnode__.__context__;
|
|
241
|
+
}
|
|
242
|
+
// Built-in diff and patch
|
|
243
|
+
if (this.__vnode__ && this.__container__) {
|
|
244
|
+
diff(this.__vnode__, newVNode, this.__container__);
|
|
245
|
+
}
|
|
246
|
+
this.__vnode__ = newVNode;
|
|
247
|
+
// Call lifecycle hook (protected from re-entry)
|
|
248
|
+
if (this.updated) {
|
|
249
|
+
this.updated(prevProps);
|
|
250
|
+
}
|
|
251
|
+
this.__inUpdating__ = false;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Mount component (called by renderer or manually)
|
|
255
|
+
* @internal
|
|
256
|
+
*/
|
|
257
|
+
mount(container, placeholder) {
|
|
258
|
+
this.__placeholder__ = placeholder || null;
|
|
259
|
+
this.__container__ = placeholder?.parentElement || container;
|
|
260
|
+
this.__inMounting__ = true;
|
|
261
|
+
// First render (if not already rendered)
|
|
262
|
+
if (!this.__vnode__) {
|
|
263
|
+
this.__vnode__ = this.render();
|
|
264
|
+
}
|
|
265
|
+
if (!this.__vnode__) {
|
|
266
|
+
this.__inMounting__ = false;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// 1. Create real DOM for instance.__vnode__ (pass this for fukict:ref)
|
|
270
|
+
createRealNode(this.__vnode__, this);
|
|
271
|
+
// 2. Recursively activate nested components in instance.__vnode__
|
|
272
|
+
activate({
|
|
273
|
+
vnode: this.__vnode__,
|
|
274
|
+
...(placeholder ? { placeholder } : { container }),
|
|
275
|
+
onMounted: () => {
|
|
276
|
+
this.__inMounting__ = false;
|
|
277
|
+
// 3. Trigger mounted() hook (protected from re-entry)
|
|
278
|
+
this.mounted?.();
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Unmount component (called by renderer)
|
|
284
|
+
* @internal
|
|
285
|
+
*/
|
|
286
|
+
unmount() {
|
|
287
|
+
this.__inUnmounting__ = true;
|
|
288
|
+
this.beforeUnmount?.();
|
|
289
|
+
removeNode(this.__vnode__, this.__container__);
|
|
290
|
+
for (const ref of this.refs.values()) {
|
|
291
|
+
ref.current = null;
|
|
292
|
+
}
|
|
293
|
+
this.refs.clear();
|
|
294
|
+
this.__vnode__ = null;
|
|
295
|
+
this.__container__ = null;
|
|
296
|
+
this.__inUnmounting__ = false;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=fukict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fukict.js","sourceRoot":"","sources":["../../src/component-class/fukict.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/component-class/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/component-class/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Slots } from '../types/class';
|
|
2
|
+
import type { VNodeChild } from '../types/core';
|
|
3
|
+
/** Extract slots from children
|
|
4
|
+
*
|
|
5
|
+
* @param children - Child nodes
|
|
6
|
+
* @returns Slots object or undefined
|
|
7
|
+
*/
|
|
8
|
+
export declare function extractSlots(children?: VNodeChild[]): Slots;
|
|
9
|
+
//# sourceMappingURL=slot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot.d.ts","sourceRoot":"","sources":["../../src/component-class/slot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAqBhD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,GAAG,KAAK,CAwB3D"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compose slots by adding a slot to the slots object
|
|
3
|
+
*
|
|
4
|
+
* @param slots - Slots object to modify
|
|
5
|
+
* @param key - Slot name
|
|
6
|
+
* @param slot - Slot content to add
|
|
7
|
+
*/
|
|
8
|
+
function composeSlots(slots, key, slot) {
|
|
9
|
+
if (!slots)
|
|
10
|
+
return;
|
|
11
|
+
if (!slots[key]) {
|
|
12
|
+
slots[key] = slot;
|
|
13
|
+
}
|
|
14
|
+
else if (Array.isArray(slots[key])) {
|
|
15
|
+
slots[key].push(slot);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
slots[key] = [slots[key], slot];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Extract slots from children
|
|
22
|
+
*
|
|
23
|
+
* @param children - Child nodes
|
|
24
|
+
* @returns Slots object or undefined
|
|
25
|
+
*/
|
|
26
|
+
export function extractSlots(children) {
|
|
27
|
+
if (!children)
|
|
28
|
+
return {};
|
|
29
|
+
const slots = {};
|
|
30
|
+
for (const child of children) {
|
|
31
|
+
// Skip null/undefined
|
|
32
|
+
if (typeof child === 'undefined' || child === null)
|
|
33
|
+
continue;
|
|
34
|
+
// Text nodes or non-VNode - add to default slot
|
|
35
|
+
if (typeof child !== 'object' ||
|
|
36
|
+
!('type' in child) ||
|
|
37
|
+
!child.__slot_name__) {
|
|
38
|
+
composeSlots(slots, 'default', child);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// With slot's name, it's a named slot
|
|
42
|
+
composeSlots(slots, child.__slot_name__, child);
|
|
43
|
+
}
|
|
44
|
+
return slots;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=slot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot.js","sourceRoot":"","sources":["../../src/component-class/slot.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,KAAY,EAAE,GAAW,EAAE,IAAgB;IAC/D,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAChB,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACpB,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACrC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,QAAuB;IAClD,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEzB,MAAM,KAAK,GAAU,EAAE,CAAC;IAExB,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,sBAAsB;QACtB,IAAI,OAAO,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QAE7D,gDAAgD;QAChD,IACE,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;YAClB,CAAC,KAAK,CAAC,aAAa,EACpB,CAAC;YACD,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;YACtC,SAAS;QACX,CAAC;QAED,sCAAsC;QACtC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fukict/basic - Function Component Helper
|
|
3
|
+
*
|
|
4
|
+
* Helper function for type inference in function components
|
|
5
|
+
*/
|
|
6
|
+
import type { FukictSlotAttribute } from '../types';
|
|
7
|
+
import type { VNode, VNodeChild } from '../types/core.js';
|
|
8
|
+
/**
|
|
9
|
+
* Props type for function component with children support
|
|
10
|
+
* Children can have fukict:slot attribute
|
|
11
|
+
*/
|
|
12
|
+
export type FunctionComponentProps<P = {}> = P & FukictSlotAttribute & {
|
|
13
|
+
children?: VNodeChild | VNodeChild[];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Function component type with props and children
|
|
17
|
+
*/
|
|
18
|
+
export type FunctionComponent<P = {}> = (props: FunctionComponentProps<P>) => VNode | null;
|
|
19
|
+
/**
|
|
20
|
+
* Define a function component with type inference
|
|
21
|
+
*
|
|
22
|
+
* This is a no-op helper function that provides better TypeScript type inference.
|
|
23
|
+
* It doesn't change the runtime behavior, just helps with types.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const Greeting = defineFukict<{ name: string }>((props) => {
|
|
28
|
+
* return h('div', null, [`Hello, ${props.name}!`]);
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @param fn - Function component
|
|
33
|
+
* @returns The same function with better types and __COMPONENT_TYPE__ marker
|
|
34
|
+
*/
|
|
35
|
+
export declare function defineFukict<P = {}>(fn: FunctionComponent<P>): FunctionComponent<P>;
|
|
36
|
+
//# sourceMappingURL=define.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/component-function/define.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE1D;;;GAGG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAC5C,mBAAmB,GAAG;IACpB,QAAQ,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC;CACtC,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,GAAG,EAAE,IAAI,CACtC,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAC7B,KAAK,GAAG,IAAI,CAAC;AAElB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,EAAE,EACjC,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,GACvB,iBAAiB,CAAC,CAAC,CAAC,CAKtB"}
|