@ioca/react 1.5.23 → 1.5.24

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.
@@ -0,0 +1,36 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+
4
+ const AsyncContent = (props) => {
5
+ const { load, loader } = props;
6
+ const [state, setState] = useState({ status: "loading" });
7
+ useEffect(() => {
8
+ let cancelled = false;
9
+ setState({ status: "loading" });
10
+ load()
11
+ .then((module) => {
12
+ if (!cancelled) {
13
+ setState({ status: "loaded", Component: module.default });
14
+ }
15
+ })
16
+ .catch((error) => {
17
+ if (!cancelled) {
18
+ setState({ status: "error", error });
19
+ }
20
+ });
21
+ return () => {
22
+ cancelled = true;
23
+ };
24
+ }, [load]);
25
+ switch (state.status) {
26
+ case "loaded":
27
+ return jsx(state.Component, {});
28
+ case "error":
29
+ return null;
30
+ case "loading":
31
+ default:
32
+ return loader ?? null;
33
+ }
34
+ };
35
+
36
+ export { AsyncContent as default };
@@ -21,11 +21,17 @@ const isSameTabs = (prev, next) => prev.length === next.length &&
21
21
  const getParsedTabs = (items, children) => {
22
22
  const contents = new Map();
23
23
  if (!items) {
24
+ const lazyLoaders = new Map();
24
25
  const tabs = Children.map(children, (node, i) => {
25
26
  const { key, props: nodeProps } = node;
26
27
  const { title, children: tabChildren, content, keepDOM, closable, } = nodeProps;
27
28
  const tabKey = String(key ?? i);
28
- contents.set(tabKey, tabChildren ?? content);
29
+ if (typeof content === "function") {
30
+ lazyLoaders.set(tabKey, { load: content });
31
+ }
32
+ else {
33
+ contents.set(tabKey, tabChildren ?? content);
34
+ }
29
35
  return {
30
36
  key: tabKey,
31
37
  title,
@@ -36,16 +42,23 @@ const getParsedTabs = (items, children) => {
36
42
  return {
37
43
  tabs,
38
44
  contents,
45
+ lazyLoaders,
39
46
  keys: new Set(tabs.map((tab) => String(tab.key))),
40
47
  };
41
48
  }
49
+ const lazyLoaders = new Map();
42
50
  const tabs = items.map((item, i) => {
43
51
  if (["string", "number"].includes(typeof item)) {
44
52
  const key = String(item);
45
53
  return { key, title: item };
46
54
  }
47
55
  const key = String(item.key ?? i);
48
- contents.set(key, item.content);
56
+ if (typeof item.content === "function") {
57
+ lazyLoaders.set(key, { load: item.content });
58
+ }
59
+ else {
60
+ contents.set(key, item.content);
61
+ }
49
62
  const { content, ...rest } = item;
50
63
  return {
51
64
  ...rest,
@@ -55,6 +68,7 @@ const getParsedTabs = (items, children) => {
55
68
  return {
56
69
  tabs,
57
70
  contents,
71
+ lazyLoaders,
58
72
  keys: new Set(tabs.map((tab) => String(tab.key))),
59
73
  };
60
74
  };
@@ -1,14 +1,15 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import classNames from 'classnames';
3
3
  import { useRef, useState, useMemo, useEffect, useImperativeHandle } from 'react';
4
4
  import { useIntersectionObserver, useSize } from '../../js/hooks.js';
5
+ import AsyncContent from './async-content.js';
5
6
  import TabsContents from './contents.js';
6
7
  import { defaultRenderMore, getParsedTabs, isSameTabs, emptyBarStyle } from './helper.js';
7
8
  import Item from './item.js';
8
9
  import TabsNavs from './navs.js';
9
10
 
10
11
  const Tabs = ((props) => {
11
- const { ref, active, tabs: items, type = "default", prepend, append, children, className, vertical, toggable, navsJustify = "start", navsClass, bar = true, hideMore, barClass, renderMore = defaultRenderMore, onTabChange, ...rest } = props;
12
+ const { ref, active, tabs: items, type = "default", prepend, append, children, className, vertical, toggable, loader, navsJustify = "start", navsClass, bar = true, hideMore, barClass, renderMore = defaultRenderMore, onTabChange, ...rest } = props;
12
13
  const navRefs = useRef([]);
13
14
  const navsRef = useRef(null);
14
15
  const contentsRef = useRef(new Map());
@@ -34,6 +35,9 @@ const Tabs = ((props) => {
34
35
  const nextContents = new Map(parsedTabs.contents);
35
36
  const sourceTabs = parsedTabs.tabs;
36
37
  const sourceKeys = parsedTabs.keys;
38
+ parsedTabs.lazyLoaders.forEach((lazyLoader, key) => {
39
+ nextContents.set(key, jsx(AsyncContent, { load: lazyLoader.load, loader: loader }));
40
+ });
37
41
  hiddenSourceKeysRef.current.forEach((key) => {
38
42
  if (!sourceKeys.has(key)) {
39
43
  hiddenSourceKeysRef.current.delete(key);
@@ -60,7 +64,12 @@ const Tabs = ((props) => {
60
64
  open(currentTabs[i].key ?? `${i}`);
61
65
  return;
62
66
  }
63
- contentsRef.current.set(tkey, tab.content);
67
+ if (typeof tab.content === "function") {
68
+ contentsRef.current.set(tkey, jsx(AsyncContent, { load: tab.content, loader: loader }));
69
+ }
70
+ else {
71
+ contentsRef.current.set(tkey, tab.content);
72
+ }
64
73
  const { content, ...rest } = tab;
65
74
  setTabs((ts) => {
66
75
  const nextTabs = [...ts];
package/lib/index.js CHANGED
@@ -5942,6 +5942,38 @@ const Swiper = ((props) => {
5942
5942
  });
5943
5943
  Swiper.Item = Item$1;
5944
5944
 
5945
+ const AsyncContent = (props) => {
5946
+ const { load, loader } = props;
5947
+ const [state, setState] = useState({ status: "loading" });
5948
+ useEffect(() => {
5949
+ let cancelled = false;
5950
+ setState({ status: "loading" });
5951
+ load()
5952
+ .then((module) => {
5953
+ if (!cancelled) {
5954
+ setState({ status: "loaded", Component: module.default });
5955
+ }
5956
+ })
5957
+ .catch((error) => {
5958
+ if (!cancelled) {
5959
+ setState({ status: "error", error });
5960
+ }
5961
+ });
5962
+ return () => {
5963
+ cancelled = true;
5964
+ };
5965
+ }, [load]);
5966
+ switch (state.status) {
5967
+ case "loaded":
5968
+ return jsx(state.Component, {});
5969
+ case "error":
5970
+ return null;
5971
+ case "loading":
5972
+ default:
5973
+ return loader ?? null;
5974
+ }
5975
+ };
5976
+
5945
5977
  const TabsContents = (props) => {
5946
5978
  const { tabs, activeKey, cachedTabKeySet, getContent } = props;
5947
5979
  return (jsx("div", { className: "i-tab-contents", children: tabs.map((tab, i) => {
@@ -5973,11 +6005,17 @@ const isSameTabs = (prev, next) => prev.length === next.length &&
5973
6005
  const getParsedTabs = (items, children) => {
5974
6006
  const contents = new Map();
5975
6007
  if (!items) {
6008
+ const lazyLoaders = new Map();
5976
6009
  const tabs = Children.map(children, (node, i) => {
5977
6010
  const { key, props: nodeProps } = node;
5978
6011
  const { title, children: tabChildren, content, keepDOM, closable, } = nodeProps;
5979
6012
  const tabKey = String(key ?? i);
5980
- contents.set(tabKey, tabChildren ?? content);
6013
+ if (typeof content === "function") {
6014
+ lazyLoaders.set(tabKey, { load: content });
6015
+ }
6016
+ else {
6017
+ contents.set(tabKey, tabChildren ?? content);
6018
+ }
5981
6019
  return {
5982
6020
  key: tabKey,
5983
6021
  title,
@@ -5988,16 +6026,23 @@ const getParsedTabs = (items, children) => {
5988
6026
  return {
5989
6027
  tabs,
5990
6028
  contents,
6029
+ lazyLoaders,
5991
6030
  keys: new Set(tabs.map((tab) => String(tab.key))),
5992
6031
  };
5993
6032
  }
6033
+ const lazyLoaders = new Map();
5994
6034
  const tabs = items.map((item, i) => {
5995
6035
  if (["string", "number"].includes(typeof item)) {
5996
6036
  const key = String(item);
5997
6037
  return { key, title: item };
5998
6038
  }
5999
6039
  const key = String(item.key ?? i);
6000
- contents.set(key, item.content);
6040
+ if (typeof item.content === "function") {
6041
+ lazyLoaders.set(key, { load: item.content });
6042
+ }
6043
+ else {
6044
+ contents.set(key, item.content);
6045
+ }
6001
6046
  const { content, ...rest } = item;
6002
6047
  return {
6003
6048
  ...rest,
@@ -6007,6 +6052,7 @@ const getParsedTabs = (items, children) => {
6007
6052
  return {
6008
6053
  tabs,
6009
6054
  contents,
6055
+ lazyLoaders,
6010
6056
  keys: new Set(tabs.map((tab) => String(tab.key))),
6011
6057
  };
6012
6058
  };
@@ -6038,7 +6084,7 @@ const TabsNavs = (props) => {
6038
6084
  var TabsNavs$1 = memo(TabsNavs);
6039
6085
 
6040
6086
  const Tabs = ((props) => {
6041
- const { ref, active, tabs: items, type = "default", prepend, append, children, className, vertical, toggable, navsJustify = "start", navsClass, bar = true, hideMore, barClass, renderMore = defaultRenderMore, onTabChange, ...rest } = props;
6087
+ const { ref, active, tabs: items, type = "default", prepend, append, children, className, vertical, toggable, loader, navsJustify = "start", navsClass, bar = true, hideMore, barClass, renderMore = defaultRenderMore, onTabChange, ...rest } = props;
6042
6088
  const navRefs = useRef([]);
6043
6089
  const navsRef = useRef(null);
6044
6090
  const contentsRef = useRef(new Map());
@@ -6064,6 +6110,9 @@ const Tabs = ((props) => {
6064
6110
  const nextContents = new Map(parsedTabs.contents);
6065
6111
  const sourceTabs = parsedTabs.tabs;
6066
6112
  const sourceKeys = parsedTabs.keys;
6113
+ parsedTabs.lazyLoaders.forEach((lazyLoader, key) => {
6114
+ nextContents.set(key, jsx(AsyncContent, { load: lazyLoader.load, loader: loader }));
6115
+ });
6067
6116
  hiddenSourceKeysRef.current.forEach((key) => {
6068
6117
  if (!sourceKeys.has(key)) {
6069
6118
  hiddenSourceKeysRef.current.delete(key);
@@ -6090,7 +6139,12 @@ const Tabs = ((props) => {
6090
6139
  open(currentTabs[i].key ?? `${i}`);
6091
6140
  return;
6092
6141
  }
6093
- contentsRef.current.set(tkey, tab.content);
6142
+ if (typeof tab.content === "function") {
6143
+ contentsRef.current.set(tkey, jsx(AsyncContent, { load: tab.content, loader: loader }));
6144
+ }
6145
+ else {
6146
+ contentsRef.current.set(tkey, tab.content);
6147
+ }
6094
6148
  const { content, ...rest } = tab;
6095
6149
  setTabs((ts) => {
6096
6150
  const nextTabs = [...ts];
@@ -1,10 +1,12 @@
1
- import { ForwardRefExoticComponent, Ref, ReactNode, RefObject, CSSProperties } from 'react';
1
+ import { ForwardRefExoticComponent, Ref, ReactNode, ComponentType, RefObject, CSSProperties } from 'react';
2
2
  import Item from './item.js';
3
3
 
4
4
  interface ITabItem {
5
5
  key?: string;
6
6
  title?: ReactNode;
7
- content?: ReactNode;
7
+ content?: ReactNode | (() => Promise<{
8
+ default: ComponentType<any>;
9
+ }>);
8
10
  closable?: boolean;
9
11
  keepDOM?: boolean;
10
12
  intersecting?: boolean;
@@ -28,6 +30,7 @@ interface ITabs {
28
30
  children?: ReactNode;
29
31
  style?: CSSProperties;
30
32
  renderMore?: (moreTabs: ITabItem[]) => ReactNode;
33
+ loader?: ReactNode;
31
34
  onTabChange?: (to?: string, from?: string) => void;
32
35
  }
33
36
  interface RefTabs {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ioca/react",
3
- "version": "1.5.23",
3
+ "version": "1.5.24",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",