airx 0.3.1 → 0.4.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.
@@ -42,7 +42,7 @@ export interface Instance<E extends AbstractElement = AbstractElement> {
42
42
  element?: AirxElement;
43
43
  beforeElement?: AirxElement;
44
44
  signalWatcher?: signal.Watcher;
45
- childrenRender?: AirxComponentRender;
45
+ componentReturnValue?: AirxComponentRender | AirxElement;
46
46
  needReRender?: boolean;
47
47
  elementNamespace?: string;
48
48
  context: InnerAirxComponentContext<E>;
@@ -1,6 +1,6 @@
1
- import * as CSS from 'csstype';
2
- import { Signal } from 'signal-polyfill';
3
- import { AirxChildren } from './element';
1
+ import type * as CSS from 'csstype';
2
+ import type { Signal } from 'signal-polyfill';
3
+ import type { AirxComponentRender, AirxChildren } from './element';
4
4
  export interface Events {
5
5
  onCopy: ClipboardEvent;
6
6
  onCut: ClipboardEvent;
@@ -1145,25 +1145,29 @@ interface IntrinsicElementAttributesMap {
1145
1145
  use: SVGAttributes;
1146
1146
  view: SVGAttributes;
1147
1147
  }
1148
- export type ReservedProps = {
1149
- children?: AirxChildren;
1148
+ export interface RefAttributes {
1149
+ ref?: Signal.State<any | undefined> | ((ele: any) => void);
1150
+ }
1151
+ export interface ReservedAttributes {
1150
1152
  key?: string | number | symbol;
1151
- ref?: Signal.State<any | undefined>;
1152
- };
1153
+ children?: AirxChildren;
1154
+ }
1153
1155
  export type NativeElements = {
1154
- [K in keyof IntrinsicElementAttributesMap]: IntrinsicElementAttributesMap[K] & ReservedProps;
1156
+ [K in keyof IntrinsicElementAttributesMap]: IntrinsicElementAttributesMap[K] & ReservedAttributes & RefAttributes;
1155
1157
  };
1156
1158
  declare global {
1157
1159
  namespace JSX {
1158
- interface ElementAttributesProperty {
1160
+ type ElementClass = never;
1161
+ interface Element extends AirxComponentRender {
1159
1162
  }
1160
1163
  interface ElementChildrenAttribute {
1161
- children: AirxChildren;
1164
+ children: {};
1162
1165
  }
1163
1166
  interface IntrinsicElements extends NativeElements {
1164
- [name: string]: any;
1165
1167
  }
1166
- type IntrinsicAttributes = ReservedProps;
1168
+ interface IntrinsicAttributes {
1169
+ key?: string | number | symbol;
1170
+ }
1167
1171
  }
1168
1172
  }
1169
1173
  export {};
@@ -15,7 +15,7 @@ export interface AirxElement<P = any> {
15
15
  props: Props & P;
16
16
  [symbol.airxElementSymbol]: true;
17
17
  }
18
- export type AirxChildren = null | string | number | boolean | undefined | AirxElement | Array<AirxChildren>;
18
+ export type AirxChildren = null | string | number | boolean | undefined | AirxElement | Array<AirxChildren> | AirxComponentRender;
19
19
  /**
20
20
  * 函数式组件接收自己的 props,并返回一个 AirxElement
21
21
  */
@@ -90,9 +90,13 @@
90
90
  */
91
91
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
92
  function createElement(type, props, ...children) {
93
- const localChildren = children.length > 0
94
- ? children
95
- : props.children;
93
+ const localChildren = [];
94
+ if (children.length > 0) {
95
+ localChildren.push(...children);
96
+ }
97
+ else if (props && props.children) {
98
+ localChildren.push(props.children);
99
+ }
96
100
  return {
97
101
  type,
98
102
  props: {
@@ -393,10 +397,16 @@
393
397
  if ('ref' in instance.memoProps) {
394
398
  context.onMounted(() => {
395
399
  const ref = instance.memoProps.ref;
396
- // 如果组件有自己的 dom 并且 ref 为 state
397
- if (instance.domRef && isState(ref)) {
398
- ref.set(instance.domRef);
399
- return () => ref.set(undefined);
400
+ // 如果组件有自己的 dom
401
+ if (instance.domRef) {
402
+ if (isState(ref)) {
403
+ ref.set(instance.domRef);
404
+ return () => ref.set(undefined);
405
+ }
406
+ if (typeof ref === 'function') {
407
+ ref(instance.domRef);
408
+ return () => ref(undefined);
409
+ }
400
410
  }
401
411
  });
402
412
  }
@@ -461,22 +471,7 @@
461
471
  }
462
472
  // airx 组件
463
473
  if (typeof element?.type === 'function') {
464
- if (instance.signalWatcher == null) {
465
- // Watch 是惰性的,只有当 Signal 被读取时才会触发 --!
466
- const signalWatcher = createWatch(async () => {
467
- instance.needReRender = true;
468
- onUpdateRequire?.(instance);
469
- queueMicrotask(() => {
470
- signalWatcher.watch();
471
- const paddings = signalWatcher.getPending();
472
- for (const padding of paddings)
473
- padding.get();
474
- });
475
- });
476
- instance.signalWatcher = signalWatcher;
477
- instance.context.addDisposer(() => signalWatcher.unwatch());
478
- }
479
- if (instance.childrenRender == null) {
474
+ if (instance.componentReturnValue == null) {
480
475
  const component = element.type;
481
476
  const beforeContext = globalContext.current;
482
477
  globalContext.current = instance.context.getSafeContext();
@@ -487,32 +482,58 @@
487
482
  catch (error) {
488
483
  componentReturnValue = createErrorRender(error);
489
484
  }
490
- if (typeof componentReturnValue !== 'function') {
491
- const error = new Error('Component must return a render function');
492
- componentReturnValue = createErrorRender(error.message);
493
- }
494
485
  // restore context
495
486
  globalContext.current = beforeContext;
496
- instance.childrenRender = componentReturnValue;
497
- const childrenComputed = createComputed(() => {
498
- try {
499
- return instance.childrenRender();
500
- }
501
- catch (error) {
502
- return createErrorRender(error)();
487
+ instance.componentReturnValue = componentReturnValue;
488
+ // static function component
489
+ if (isValidElement(componentReturnValue)) {
490
+ const elements = childrenAsElements(componentReturnValue);
491
+ reconcileChildren(pluginContext, instance, elements);
492
+ }
493
+ // reaction function component
494
+ if (typeof componentReturnValue === 'function') {
495
+ if (instance.signalWatcher == null) {
496
+ // Watch 是惰性的,只有当 Signal 被读取时才会触发 --!
497
+ const signalWatcher = createWatch(async () => {
498
+ instance.needReRender = true;
499
+ onUpdateRequire?.(instance);
500
+ queueMicrotask(() => {
501
+ signalWatcher.watch();
502
+ const paddings = signalWatcher.getPending();
503
+ for (const padding of paddings)
504
+ padding.get();
505
+ });
506
+ });
507
+ instance.signalWatcher = signalWatcher;
508
+ instance.context.addDisposer(() => signalWatcher.unwatch());
503
509
  }
504
- });
505
- instance.signalWatcher.watch(childrenComputed);
506
- const children = childrenComputed.get();
507
- reconcileChildren(pluginContext, instance, childrenAsElements(children));
510
+ const childrenComputed = createComputed(() => {
511
+ try {
512
+ if (typeof componentReturnValue === 'function') {
513
+ return componentReturnValue();
514
+ }
515
+ }
516
+ catch (error) {
517
+ return createErrorRender(error)();
518
+ }
519
+ });
520
+ instance.signalWatcher.watch(childrenComputed);
521
+ const children = childrenComputed.get();
522
+ reconcileChildren(pluginContext, instance, childrenAsElements(children));
523
+ }
508
524
  }
509
525
  if (instance.needReRender) {
510
526
  let children;
511
527
  try {
512
- // 如果是由于父组件导致的子组件渲染
513
- // 直接使用 childrenComputed.get() 将读取到缓存值
514
- // 因此这里使用 childrenRender 来更新 children 的值
515
- children = instance.childrenRender();
528
+ if (isValidElement(instance.componentReturnValue)) {
529
+ children = instance.componentReturnValue;
530
+ }
531
+ else {
532
+ // 如果是由于父组件导致的子组件渲染
533
+ // 直接使用 childrenComputed.get() 将读取到缓存值
534
+ // 因此这里使用 childrenRender 来更新 children 的值
535
+ children = instance.componentReturnValue();
536
+ }
516
537
  }
517
538
  catch (error) {
518
539
  children = createErrorRender(error)();