@nocobase/plugin-mobile-client 0.10.0-alpha.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.
Files changed (183) hide show
  1. package/client.d.ts +4 -0
  2. package/client.js +30 -0
  3. package/docs/en-US/index.md +7 -0
  4. package/docs/en-US/installation.md +13 -0
  5. package/docs/en-US/tabs.json +14 -0
  6. package/docs/en-US/usage.md +1 -0
  7. package/docs/zh-CN/index.md +7 -0
  8. package/docs/zh-CN/installation.md +13 -0
  9. package/docs/zh-CN/tabs.json +14 -0
  10. package/docs/zh-CN/usage.md +2 -0
  11. package/lib/client/configuration/App.d.ts +2 -0
  12. package/lib/client/configuration/App.js +40 -0
  13. package/lib/client/configuration/Interface.d.ts +2 -0
  14. package/lib/client/configuration/Interface.js +20 -0
  15. package/lib/client/configuration/index.d.ts +2 -0
  16. package/lib/client/configuration/index.js +27 -0
  17. package/lib/client/core/bridge/index.d.ts +2 -0
  18. package/lib/client/core/bridge/index.js +17 -0
  19. package/lib/client/core/bridge/injects.d.ts +13 -0
  20. package/lib/client/core/bridge/injects.js +13 -0
  21. package/lib/client/core/bridge/native-call.d.ts +1 -0
  22. package/lib/client/core/bridge/native-call.js +24 -0
  23. package/lib/client/core/index.d.ts +3 -0
  24. package/lib/client/core/index.js +46 -0
  25. package/lib/client/core/schema/common/index.d.ts +1 -0
  26. package/lib/client/core/schema/common/index.js +16 -0
  27. package/lib/client/core/schema/common/page.d.ts +16 -0
  28. package/lib/client/core/schema/common/page.js +23 -0
  29. package/lib/client/core/schema/components/container/Container.Designer.d.ts +2 -0
  30. package/lib/client/core/schema/components/container/Container.Designer.js +138 -0
  31. package/lib/client/core/schema/components/container/Container.d.ts +5 -0
  32. package/lib/client/core/schema/components/container/Container.js +150 -0
  33. package/lib/client/core/schema/components/container/index.d.ts +1 -0
  34. package/lib/client/core/schema/components/container/index.js +16 -0
  35. package/lib/client/core/schema/components/header/Header.Designer.d.ts +2 -0
  36. package/lib/client/core/schema/components/header/Header.Designer.js +72 -0
  37. package/lib/client/core/schema/components/header/Header.d.ts +10 -0
  38. package/lib/client/core/schema/components/header/Header.js +85 -0
  39. package/lib/client/core/schema/components/header/index.d.ts +1 -0
  40. package/lib/client/core/schema/components/header/index.js +16 -0
  41. package/lib/client/core/schema/components/index.d.ts +6 -0
  42. package/lib/client/core/schema/components/index.js +71 -0
  43. package/lib/client/core/schema/components/menu/Menu.Designer.d.ts +2 -0
  44. package/lib/client/core/schema/components/menu/Menu.Designer.js +81 -0
  45. package/lib/client/core/schema/components/menu/Menu.Item.d.ts +6 -0
  46. package/lib/client/core/schema/components/menu/Menu.Item.js +129 -0
  47. package/lib/client/core/schema/components/menu/Menu.d.ts +7 -0
  48. package/lib/client/core/schema/components/menu/Menu.js +88 -0
  49. package/lib/client/core/schema/components/menu/MenuBlockInitializer.d.ts +2 -0
  50. package/lib/client/core/schema/components/menu/MenuBlockInitializer.js +51 -0
  51. package/lib/client/core/schema/components/menu/index.d.ts +2 -0
  52. package/lib/client/core/schema/components/menu/index.js +27 -0
  53. package/lib/client/core/schema/components/menu/schema.d.ts +17 -0
  54. package/lib/client/core/schema/components/menu/schema.js +24 -0
  55. package/lib/client/core/schema/components/page/Page.Designer.d.ts +2 -0
  56. package/lib/client/core/schema/components/page/Page.Designer.js +160 -0
  57. package/lib/client/core/schema/components/page/Page.d.ts +5 -0
  58. package/lib/client/core/schema/components/page/Page.js +157 -0
  59. package/lib/client/core/schema/components/page/index.d.ts +1 -0
  60. package/lib/client/core/schema/components/page/index.js +16 -0
  61. package/lib/client/core/schema/components/settings/Settings.Designer.d.ts +2 -0
  62. package/lib/client/core/schema/components/settings/Settings.Designer.js +37 -0
  63. package/lib/client/core/schema/components/settings/Settings.d.ts +6 -0
  64. package/lib/client/core/schema/components/settings/Settings.js +43 -0
  65. package/lib/client/core/schema/components/settings/SettingsBlockInitializer.d.ts +2 -0
  66. package/lib/client/core/schema/components/settings/SettingsBlockInitializer.js +51 -0
  67. package/lib/client/core/schema/components/settings/index.d.ts +2 -0
  68. package/lib/client/core/schema/components/settings/index.js +27 -0
  69. package/lib/client/core/schema/components/tab-bar/TabBar.Item.d.ts +6 -0
  70. package/lib/client/core/schema/components/tab-bar/TabBar.Item.js +80 -0
  71. package/lib/client/core/schema/components/tab-bar/TabBar.d.ts +6 -0
  72. package/lib/client/core/schema/components/tab-bar/TabBar.js +138 -0
  73. package/lib/client/core/schema/components/tab-bar/index.d.ts +1 -0
  74. package/lib/client/core/schema/components/tab-bar/index.js +16 -0
  75. package/lib/client/core/schema/components/tab-bar/schema.d.ts +18 -0
  76. package/lib/client/core/schema/components/tab-bar/schema.js +25 -0
  77. package/lib/client/core/schema/helpers/index.d.ts +67 -0
  78. package/lib/client/core/schema/helpers/index.js +49 -0
  79. package/lib/client/core/schema/hooks/index.d.ts +1 -0
  80. package/lib/client/core/schema/hooks/index.js +16 -0
  81. package/lib/client/core/schema/hooks/useSchemaPatch.d.ts +3 -0
  82. package/lib/client/core/schema/hooks/useSchemaPatch.js +61 -0
  83. package/lib/client/core/schema/index.d.ts +3 -0
  84. package/lib/client/core/schema/index.js +38 -0
  85. package/lib/client/core/schema/initializers/BlockInitializers.d.ts +147 -0
  86. package/lib/client/core/schema/initializers/BlockInitializers.js +79 -0
  87. package/lib/client/core/schema/initializers/index.d.ts +1 -0
  88. package/lib/client/core/schema/initializers/index.js +16 -0
  89. package/lib/client/core/schema/scopes/grid-card.d.ts +15 -0
  90. package/lib/client/core/schema/scopes/grid-card.js +45 -0
  91. package/lib/client/core/schema/scopes/index.d.ts +1 -0
  92. package/lib/client/core/schema/scopes/index.js +16 -0
  93. package/lib/client/devices/iOS6.d.ts +5 -0
  94. package/lib/client/devices/iOS6.js +32 -0
  95. package/lib/client/devices/index.d.ts +2 -0
  96. package/lib/client/devices/index.js +43 -0
  97. package/lib/client/index.d.ts +3 -0
  98. package/lib/client/index.js +47 -0
  99. package/lib/client/locale/en-US.d.ts +2 -0
  100. package/lib/client/locale/en-US.js +9 -0
  101. package/lib/client/locale/index.d.ts +4 -0
  102. package/lib/client/locale/index.js +43 -0
  103. package/lib/client/locale/zh-CN.d.ts +32 -0
  104. package/lib/client/locale/zh-CN.js +39 -0
  105. package/lib/client/router/Application.d.ts +3 -0
  106. package/lib/client/router/Application.js +129 -0
  107. package/lib/client/router/InterfaceProvider.d.ts +4 -0
  108. package/lib/client/router/InterfaceProvider.js +29 -0
  109. package/lib/client/router/InterfaceRouter.d.ts +6 -0
  110. package/lib/client/router/InterfaceRouter.js +58 -0
  111. package/lib/client/router/RouteSwitchProvider.d.ts +2 -0
  112. package/lib/client/router/RouteSwitchProvider.js +59 -0
  113. package/lib/client/router/index.d.ts +2 -0
  114. package/lib/client/router/index.js +27 -0
  115. package/lib/index.d.ts +1 -0
  116. package/lib/index.js +13 -0
  117. package/lib/server/index.d.ts +1 -0
  118. package/lib/server/index.js +13 -0
  119. package/lib/server/plugin.d.ts +10 -0
  120. package/lib/server/plugin.js +57 -0
  121. package/lib/server/routes.d.ts +34 -0
  122. package/lib/server/routes.js +41 -0
  123. package/package.json +28 -0
  124. package/server.d.ts +4 -0
  125. package/server.js +30 -0
  126. package/src/client/configuration/App.tsx +23 -0
  127. package/src/client/configuration/Interface.tsx +11 -0
  128. package/src/client/configuration/index.ts +2 -0
  129. package/src/client/core/bridge/index.ts +2 -0
  130. package/src/client/core/bridge/injects.ts +14 -0
  131. package/src/client/core/bridge/native-call.ts +23 -0
  132. package/src/client/core/index.tsx +45 -0
  133. package/src/client/core/schema/common/index.ts +1 -0
  134. package/src/client/core/schema/common/page.ts +16 -0
  135. package/src/client/core/schema/components/container/Container.Designer.tsx +88 -0
  136. package/src/client/core/schema/components/container/Container.tsx +135 -0
  137. package/src/client/core/schema/components/container/index.ts +1 -0
  138. package/src/client/core/schema/components/header/Header.Designer.tsx +39 -0
  139. package/src/client/core/schema/components/header/Header.tsx +49 -0
  140. package/src/client/core/schema/components/header/index.ts +1 -0
  141. package/src/client/core/schema/components/index.ts +6 -0
  142. package/src/client/core/schema/components/menu/Menu.Designer.tsx +46 -0
  143. package/src/client/core/schema/components/menu/Menu.Item.tsx +97 -0
  144. package/src/client/core/schema/components/menu/Menu.tsx +82 -0
  145. package/src/client/core/schema/components/menu/MenuBlockInitializer.tsx +20 -0
  146. package/src/client/core/schema/components/menu/index.ts +2 -0
  147. package/src/client/core/schema/components/menu/schema.ts +17 -0
  148. package/src/client/core/schema/components/page/Page.Designer.tsx +106 -0
  149. package/src/client/core/schema/components/page/Page.tsx +132 -0
  150. package/src/client/core/schema/components/page/index.ts +1 -0
  151. package/src/client/core/schema/components/settings/Settings.Designer.tsx +22 -0
  152. package/src/client/core/schema/components/settings/Settings.tsx +25 -0
  153. package/src/client/core/schema/components/settings/SettingsBlockInitializer.tsx +20 -0
  154. package/src/client/core/schema/components/settings/index.ts +2 -0
  155. package/src/client/core/schema/components/tab-bar/TabBar.Item.tsx +67 -0
  156. package/src/client/core/schema/components/tab-bar/TabBar.tsx +108 -0
  157. package/src/client/core/schema/components/tab-bar/index.ts +1 -0
  158. package/src/client/core/schema/components/tab-bar/schema.ts +18 -0
  159. package/src/client/core/schema/helpers/index.ts +38 -0
  160. package/src/client/core/schema/hooks/index.ts +1 -0
  161. package/src/client/core/schema/hooks/useSchemaPatch.ts +24 -0
  162. package/src/client/core/schema/index.ts +3 -0
  163. package/src/client/core/schema/initializers/BlockInitializers.ts +81 -0
  164. package/src/client/core/schema/initializers/index.ts +1 -0
  165. package/src/client/core/schema/scopes/grid-card.ts +35 -0
  166. package/src/client/core/schema/scopes/index.ts +1 -0
  167. package/src/client/devices/iOS6.tsx +24 -0
  168. package/src/client/devices/index.tsx +27 -0
  169. package/src/client/index.tsx +33 -0
  170. package/src/client/locale/en-US.ts +5 -0
  171. package/src/client/locale/index.ts +23 -0
  172. package/src/client/locale/zh-CN.ts +33 -0
  173. package/src/client/router/Application.tsx +114 -0
  174. package/src/client/router/InterfaceProvider.tsx +11 -0
  175. package/src/client/router/InterfaceRouter.tsx +48 -0
  176. package/src/client/router/RouteSwitchProvider.tsx +31 -0
  177. package/src/client/router/index.ts +2 -0
  178. package/src/index.ts +1 -0
  179. package/src/server/collections/.gitkeep +0 -0
  180. package/src/server/index.ts +1 -0
  181. package/src/server/plugin.ts +25 -0
  182. package/src/server/routes.ts +38 -0
  183. package/types.d.ts +0 -0
@@ -0,0 +1,106 @@
1
+ import { GeneralSchemaDesigner, SchemaSettings, useDesignable } from '@nocobase/client';
2
+ import React from 'react';
3
+ import { generateNTemplate, useTranslation } from '../../../../locale';
4
+ import { useField, useFieldSchema } from '@formily/react';
5
+ import { findGridSchema } from '../../helpers';
6
+ import { uid } from '@formily/shared';
7
+ import { Button } from 'antd';
8
+ import { MenuOutlined } from '@ant-design/icons';
9
+
10
+ export const PageDesigner = (props) => {
11
+ const { showBack } = props;
12
+ const { t } = useTranslation();
13
+ const fieldSchema = useFieldSchema();
14
+ const { dn } = useDesignable();
15
+ const headerSchema = fieldSchema?.properties?.['header'];
16
+ const tabsSchema = fieldSchema?.properties?.['tabs'];
17
+ const field = useField();
18
+ const schemaSettingsProps = {
19
+ dn,
20
+ field,
21
+ fieldSchema,
22
+ };
23
+
24
+ return (
25
+ <SchemaSettings
26
+ title={
27
+ <Button
28
+ style={{
29
+ borderColor: 'rgb(241, 139, 98)',
30
+ color: 'rgb(241, 139, 98)',
31
+ }}
32
+ icon={<MenuOutlined />}
33
+ type="dashed"
34
+ >
35
+ {t('Page configuration')}
36
+ </Button>
37
+ }
38
+ {...schemaSettingsProps}
39
+ >
40
+ <SchemaSettings.SwitchItem
41
+ checked={!!headerSchema}
42
+ title={t('Enable Header')}
43
+ onChange={async (v) => {
44
+ if (v) {
45
+ await dn.insertAfterBegin({
46
+ type: 'void',
47
+ name: 'header',
48
+ 'x-component': 'MHeader',
49
+ 'x-designer': 'MHeader.Designer',
50
+ 'x-component-props': {
51
+ title: fieldSchema.parent['x-component-props']?.name,
52
+ showBack,
53
+ },
54
+ });
55
+ } else {
56
+ await dn.remove(headerSchema);
57
+ }
58
+ dn.refresh();
59
+ }}
60
+ />
61
+ <SchemaSettings.SwitchItem
62
+ checked={!!tabsSchema}
63
+ title={t('Enable Tabs')}
64
+ onChange={async (v) => {
65
+ if (v) {
66
+ const gridSchema = findGridSchema(fieldSchema);
67
+ if (gridSchema) {
68
+ return dn.remove(gridSchema).then(() => {
69
+ return dn.insertBeforeEnd({
70
+ type: 'void',
71
+ name: 'tabs',
72
+ 'x-component': 'Tabs',
73
+ 'x-component-props': {},
74
+ 'x-initializer': 'TabPaneInitializers',
75
+ 'x-initializer-props': {
76
+ gridInitializer: 'MBlockInitializers',
77
+ },
78
+ properties: {
79
+ tab1: {
80
+ type: 'void',
81
+ title: generateNTemplate('Untitled'),
82
+ 'x-component': 'Tabs.TabPane',
83
+ 'x-designer': 'Tabs.Designer',
84
+ 'x-component-props': {},
85
+ properties: {
86
+ grid: {
87
+ ...gridSchema,
88
+ 'x-uid': uid(),
89
+ },
90
+ },
91
+ },
92
+ },
93
+ });
94
+ });
95
+ }
96
+ } else {
97
+ const gridSchema = findGridSchema(tabsSchema.properties[Object.keys(tabsSchema.properties)[0]]);
98
+ if (gridSchema) {
99
+ return dn.remove(tabsSchema).then(() => dn.insertBeforeEnd(gridSchema, {}));
100
+ }
101
+ }
102
+ }}
103
+ />
104
+ </SchemaSettings>
105
+ );
106
+ };
@@ -0,0 +1,132 @@
1
+ import { css, cx } from '@emotion/css';
2
+ import { RecursionField, useFieldSchema } from '@formily/react';
3
+ import { ActionBarProvider, SortableItem, TabsContextProvider, useDesigner } from '@nocobase/client';
4
+ import { TabsProps } from 'antd';
5
+ import React, { useCallback, useMemo } from 'react';
6
+ import { useSearchParams } from 'react-router-dom';
7
+ import { countGridCol } from '../../helpers';
8
+ import { PageDesigner } from './Page.Designer';
9
+
10
+ const globalActionCSS = css`
11
+ #nb-position-container > & {
12
+ height: 49px;
13
+ border-top: 1px solid #f0f2f5;
14
+ margin-bottom: 0px !important;
15
+ padding: 0 var(--nb-spacing);
16
+ align-items: center;
17
+ overflow-x: auto;
18
+ background: #ffffff;
19
+ z-index: 100;
20
+ }
21
+ `;
22
+
23
+ const InternalPage: React.FC = (props) => {
24
+ const Designer = useDesigner();
25
+ const fieldSchema = useFieldSchema();
26
+ const [searchParams, setSearchParams] = useSearchParams();
27
+ const tabsSchema = fieldSchema.properties?.['tabs'];
28
+ // Only support globalActions in page
29
+ const onlyInPage = fieldSchema.root === fieldSchema.parent;
30
+ let hasGlobalActions = false;
31
+ if (!tabsSchema) {
32
+ hasGlobalActions = countGridCol(fieldSchema.properties['grid'], 2) === 1;
33
+ } else if (searchParams.has('tab') && tabsSchema.properties?.[searchParams.get('tab')]) {
34
+ hasGlobalActions = countGridCol(tabsSchema.properties[searchParams.get('tab')]?.properties?.['grid'], 2) === 1;
35
+ } else if (tabsSchema.properties) {
36
+ const schema = Object.values(tabsSchema.properties).sort((t1, t2) => t1['x-index'] - t2['x-index'])[0];
37
+ if (schema) {
38
+ setTimeout(() => {
39
+ setSearchParams([['tab', schema.name.toString()]]);
40
+ });
41
+ }
42
+ }
43
+
44
+ const onTabsChange = useCallback<TabsProps['onChange']>(
45
+ (key) => {
46
+ setSearchParams([['tab', key]]);
47
+ },
48
+ [setSearchParams],
49
+ );
50
+
51
+ const GlobalActionProvider = useMemo(() => {
52
+ if (hasGlobalActions) {
53
+ return ActionBarProvider;
54
+ }
55
+ return (props) => <>{props.children}</>;
56
+ }, [hasGlobalActions]);
57
+
58
+ return (
59
+ <GlobalActionProvider
60
+ container={hasGlobalActions && onlyInPage ? document.getElementById('nb-position-container') : null}
61
+ forceProps={{
62
+ layout: 'one-column',
63
+ className: globalActionCSS,
64
+ }}
65
+ >
66
+ <SortableItem
67
+ eid="nb-mobile-scroll-wrapper"
68
+ className={cx(
69
+ 'nb-mobile-page',
70
+ css`
71
+ background: #f0f2f5;
72
+ display: flex;
73
+ flex-direction: column;
74
+ width: 100%;
75
+ height: 100%;
76
+ overflow-x: hidden;
77
+ overflow-y: auto;
78
+ padding-bottom: var(--nb-spacing);
79
+ `,
80
+ )}
81
+ >
82
+ <Designer {...fieldSchema?.['x-designer-props']}></Designer>
83
+ <div
84
+ style={{
85
+ paddingBottom: tabsSchema ? null : 'var(--nb-spacing)',
86
+ }}
87
+ className={cx(
88
+ 'nb-mobile-page-header',
89
+ css`
90
+ & > .ant-tabs > .ant-tabs-nav {
91
+ background: #fff;
92
+ padding: 0 var(--nb-spacing);
93
+ }
94
+ display: flex;
95
+ flex-direction: column;
96
+ `,
97
+ )}
98
+ >
99
+ <RecursionField
100
+ schema={fieldSchema}
101
+ filterProperties={(s) => {
102
+ return 'MHeader' === s['x-component'];
103
+ }}
104
+ ></RecursionField>
105
+ <TabsContextProvider deep={false} activeKey={searchParams.get('tab')} onChange={onTabsChange}>
106
+ <RecursionField
107
+ schema={fieldSchema}
108
+ filterProperties={(s) => {
109
+ return 'Tabs' === s['x-component'];
110
+ }}
111
+ ></RecursionField>
112
+ </TabsContextProvider>
113
+ </div>
114
+
115
+ {!tabsSchema && (
116
+ <RecursionField
117
+ schema={fieldSchema}
118
+ filterProperties={(s) => {
119
+ return s['x-component'] !== 'MHeader';
120
+ }}
121
+ ></RecursionField>
122
+ )}
123
+ </SortableItem>
124
+ </GlobalActionProvider>
125
+ );
126
+ };
127
+
128
+ export const MPage = InternalPage as unknown as typeof InternalPage & {
129
+ Designer: typeof PageDesigner;
130
+ };
131
+ MPage.Designer = PageDesigner;
132
+ MPage.displayName = 'MPage';
@@ -0,0 +1 @@
1
+ export * from './Page';
@@ -0,0 +1,22 @@
1
+ import { GeneralSchemaDesigner, SchemaSettings } from '@nocobase/client';
2
+ import React from 'react';
3
+ import { useTranslation } from '../../../../locale';
4
+
5
+ export const SettingsDesigner = () => {
6
+ const { t } = useTranslation();
7
+
8
+ return (
9
+ <GeneralSchemaDesigner>
10
+ <SchemaSettings.Remove
11
+ key="remove"
12
+ removeParentsIfNoChildren
13
+ confirm={{
14
+ title: t('Delete settings block'),
15
+ }}
16
+ breakRemoveOn={{
17
+ 'x-component': 'Grid',
18
+ }}
19
+ />
20
+ </GeneralSchemaDesigner>
21
+ );
22
+ };
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import { SettingsMenu, SortableItem, useDesigner } from '@nocobase/client';
3
+ import { SettingsDesigner } from './Settings.Designer';
4
+ import { css, cx } from '@emotion/css';
5
+ export const InternalSettings = () => {
6
+ const Designer = useDesigner();
7
+ return (
8
+ <SortableItem
9
+ className={cx(
10
+ 'nb-mobile-setting',
11
+ css`
12
+ margin-bottom: var(--nb-spacing);
13
+ `,
14
+ )}
15
+ >
16
+ <Designer />
17
+ <SettingsMenu redirectUrl="/mobile" />
18
+ </SortableItem>
19
+ );
20
+ };
21
+ export const MSettings = InternalSettings as unknown as typeof InternalSettings & {
22
+ Designer: typeof SettingsDesigner;
23
+ };
24
+
25
+ MSettings.Designer = SettingsDesigner;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { SettingOutlined } from '@ant-design/icons';
3
+ import { SchemaInitializer } from '@nocobase/client';
4
+
5
+ export const MSettingsBlockInitializer = (props) => {
6
+ const { insert } = props;
7
+ return (
8
+ <SchemaInitializer.Item
9
+ icon={<SettingOutlined />}
10
+ onClick={async () => {
11
+ insert({
12
+ type: 'void',
13
+ 'x-component': 'MSettings',
14
+ 'x-designer': 'MSettings.Designer',
15
+ 'x-component-props': {},
16
+ });
17
+ }}
18
+ />
19
+ );
20
+ };
@@ -0,0 +1,2 @@
1
+ export * from './Settings';
2
+ export * from './SettingsBlockInitializer';
@@ -0,0 +1,67 @@
1
+ import React, { useEffect, useMemo } from 'react';
2
+ import { TabBar, TabBarItemProps } from 'antd-mobile';
3
+ import { GeneralSchemaDesigner, SchemaSettings, SortableItem, useDesigner } from '@nocobase/client';
4
+ import { useTranslation } from '../../../../locale';
5
+ import { Schema, useField, useFieldSchema } from '@formily/react';
6
+ import { useSchemaPatch } from '../../hooks';
7
+ import { css, cx } from '@emotion/css';
8
+ import { tabItemSchema } from './schema';
9
+
10
+ const InternalItem: React.FC<TabBarItemProps> = () => {
11
+ // NOTE: nothing to do
12
+ // return <TabBar.Item {...props}></TabBar.Item>;
13
+ const Designer = useDesigner();
14
+ return (
15
+ <SortableItem
16
+ className={cx(
17
+ 'nb-mobile-tab-bar-item',
18
+ css`
19
+ position: absolute !important;
20
+ width: 100%;
21
+ height: 100%;
22
+ top: 0;
23
+ left: 0;
24
+ `,
25
+ )}
26
+ >
27
+ <Designer />
28
+ </SortableItem>
29
+ );
30
+ };
31
+
32
+ export const Designer = () => {
33
+ const { t } = useTranslation();
34
+ const fieldSchema = useFieldSchema();
35
+ const { onUpdateComponentProps } = useSchemaPatch();
36
+ const field = useField();
37
+ const tabItems = Object.keys(fieldSchema.parent.properties).length;
38
+
39
+ return (
40
+ <GeneralSchemaDesigner>
41
+ <SchemaSettings.ModalItem
42
+ title={t('Edit info')}
43
+ initialValues={field.componentProps}
44
+ schema={tabItemSchema}
45
+ onSubmit={onUpdateComponentProps}
46
+ ></SchemaSettings.ModalItem>
47
+ {tabItems > 1 ? (
48
+ <SchemaSettings.Remove
49
+ key="remove"
50
+ removeParentsIfNoChildren
51
+ confirm={{
52
+ title: t('Delete tab item?'),
53
+ }}
54
+ breakRemoveOn={{
55
+ 'x-component': 'MTabBar',
56
+ }}
57
+ ></SchemaSettings.Remove>
58
+ ) : null}
59
+ </GeneralSchemaDesigner>
60
+ );
61
+ };
62
+
63
+ export const TabBarItem = InternalItem as unknown as typeof InternalItem & {
64
+ Designer: typeof Designer;
65
+ };
66
+
67
+ TabBarItem.Designer = Designer;
@@ -0,0 +1,108 @@
1
+ import { TabBar } from 'antd-mobile';
2
+ import { TabBarItem } from './TabBar.Item';
3
+ import React, { useCallback } from 'react';
4
+ import { useFieldSchema } from '@formily/react';
5
+ import {
6
+ DndContext,
7
+ Icon,
8
+ SchemaComponent,
9
+ SchemaInitializer,
10
+ SortableItem,
11
+ useCompile,
12
+ useDesignable,
13
+ } from '@nocobase/client';
14
+ import { useTranslation } from '../../../../locale';
15
+ import { css, cx } from '@emotion/css';
16
+ import { uid } from '@formily/shared';
17
+ import { useNavigate, useParams } from 'react-router-dom';
18
+ import { tabItemSchema } from './schema';
19
+ import { PageSchema } from '../../common';
20
+
21
+ export const InternalTabBar: React.FC = (props) => {
22
+ const fieldSchema = useFieldSchema();
23
+ const { designable } = useDesignable();
24
+ const { t } = useTranslation();
25
+ const { insertBeforeEnd } = useDesignable();
26
+ const navigate = useNavigate();
27
+ const params = useParams<{ name: string }>();
28
+ const compile = useCompile();
29
+
30
+ const onAddTab = useCallback((values: any) => {
31
+ return insertBeforeEnd({
32
+ type: 'void',
33
+ 'x-component': 'MTabBar.Item',
34
+ 'x-component-props': values,
35
+ 'x-designer': 'MTabBar.Item.Designer',
36
+ properties: {
37
+ [uid()]: PageSchema,
38
+ },
39
+ });
40
+ }, []);
41
+
42
+ return (
43
+ <SortableItem
44
+ className={cx(
45
+ 'nb-mobile-tab-bar',
46
+ css`
47
+ position: relative;
48
+ width: 100%;
49
+ display: flex;
50
+ align-items: center;
51
+ `,
52
+ )}
53
+ >
54
+ <DndContext>
55
+ <TabBar
56
+ activeKey={params.name}
57
+ onChange={(key) => {
58
+ if (key === 'add-tab') {
59
+ return;
60
+ }
61
+ navigate(`/mobile/${key}`);
62
+ }}
63
+ safeArea
64
+ className={cx(
65
+ css`
66
+ width: 100%;
67
+ `,
68
+ )}
69
+ >
70
+ {fieldSchema.mapProperties((schema, name) => {
71
+ const cp = schema['x-component-props'];
72
+ return (
73
+ <TabBar.Item
74
+ {...cp}
75
+ key={`tab_${schema['x-uid']}`}
76
+ title={
77
+ <>
78
+ {compile(cp.title)}
79
+ <SchemaComponent schema={schema} name={name} />
80
+ </>
81
+ }
82
+ icon={cp.icon ? <Icon type={cp.icon} /> : undefined}
83
+ ></TabBar.Item>
84
+ );
85
+ })}
86
+ {designable && (!fieldSchema.properties || Object.keys(fieldSchema.properties).length < 5) ? (
87
+ <TabBar.Item
88
+ className={css`
89
+ .adm-tab-bar-item-icon {
90
+ height: auto;
91
+ }
92
+ `}
93
+ icon={<SchemaInitializer.ActionModal title={t('Add tab')} onSubmit={onAddTab} schema={tabItemSchema} />}
94
+ key="add-tab"
95
+ ></TabBar.Item>
96
+ ) : null}
97
+ </TabBar>
98
+ </DndContext>
99
+ </SortableItem>
100
+ );
101
+ };
102
+
103
+ export const MTabBar = InternalTabBar as unknown as typeof InternalTabBar & {
104
+ Item: typeof TabBarItem;
105
+ };
106
+
107
+ MTabBar.Item = TabBarItem;
108
+ MTabBar.displayName = 'MTabBar';
@@ -0,0 +1 @@
1
+ export * from './TabBar';
@@ -0,0 +1,18 @@
1
+ export const tabItemSchema = {
2
+ properties: {
3
+ title: {
4
+ type: 'string',
5
+ title: `{{ t('Title') }}`,
6
+ required: true,
7
+ 'x-component': 'Input',
8
+ 'x-decorator': 'FormItem',
9
+ },
10
+ icon: {
11
+ required: true,
12
+ 'x-decorator': 'FormItem',
13
+ 'x-component': 'IconPicker',
14
+ title: `{{ t('Icon') }}`,
15
+ 'x-component-props': {},
16
+ },
17
+ },
18
+ };
@@ -0,0 +1,38 @@
1
+ import { ISchema, Schema } from '@formily/react';
2
+ import { uid } from '@formily/shared';
3
+ export const gridItemWrap = (schema: ISchema) => {
4
+ return {
5
+ type: 'void',
6
+ 'x-component': 'MGrid.Item',
7
+ properties: {
8
+ [schema.name || uid()]: schema,
9
+ },
10
+ };
11
+ };
12
+
13
+ export const findSchema = (schema: Schema, component: string) => {
14
+ const gridSchema = schema.reduceProperties(
15
+ (schema, next) => schema || (next['x-component'] === component && next),
16
+ ) as Schema;
17
+ return gridSchema;
18
+ };
19
+ export const findGridSchema = (schema: Schema) => {
20
+ return findSchema(schema, 'Grid');
21
+ };
22
+
23
+ const allowComponents = ['Grid', 'Grid.Row'];
24
+ const plusComponent = ['Grid.Col'];
25
+ export const countGridCol = (schema: Schema, countToStop?: number) => {
26
+ if (!schema) return 0;
27
+ let count = 0;
28
+ if (plusComponent.includes(schema['x-component'])) {
29
+ count += 1;
30
+ }
31
+ if (typeof countToStop === 'number' && count >= countToStop) return count;
32
+ if (allowComponents.includes(schema['x-component'])) {
33
+ schema.mapProperties((schema) => {
34
+ count += countGridCol(schema, countToStop);
35
+ });
36
+ }
37
+ return count;
38
+ };
@@ -0,0 +1 @@
1
+ export * from './useSchemaPatch';
@@ -0,0 +1,24 @@
1
+ import { useField, useFieldSchema } from '@formily/react';
2
+ import { useDesignable } from '@nocobase/client';
3
+ import _ from 'lodash';
4
+ import { useCallback } from 'react';
5
+
6
+ export const useSchemaPatch = () => {
7
+ const { dn } = useDesignable();
8
+ const fieldSchema = useFieldSchema();
9
+ const field = useField();
10
+
11
+ const onUpdateComponentProps = useCallback((data) => {
12
+ _.set(fieldSchema, 'x-component-props', data);
13
+ field.componentProps = { ...field.componentProps, ...data };
14
+ dn.emit('patch', {
15
+ schema: {
16
+ ['x-uid']: fieldSchema['x-uid'],
17
+ 'x-component-props': fieldSchema['x-component-props'],
18
+ },
19
+ });
20
+ dn.refresh();
21
+ }, []);
22
+
23
+ return { onUpdateComponentProps };
24
+ };
@@ -0,0 +1,3 @@
1
+ export * from './initializers';
2
+ export * from './components';
3
+ export * from './scopes';
@@ -0,0 +1,81 @@
1
+ import { gridRowColWrap } from '@nocobase/client';
2
+ import { generateNTemplate } from '../../../locale';
3
+
4
+ // 页面里添加区块
5
+ export const MBlockInitializers = {
6
+ title: '{{t("Add block")}}',
7
+ icon: 'PlusOutlined',
8
+ wrap: gridRowColWrap,
9
+ items: [
10
+ {
11
+ key: 'dataBlocks',
12
+ type: 'itemGroup',
13
+ title: '{{t("Data blocks")}}',
14
+ children: [
15
+ {
16
+ key: 'GridCard',
17
+ type: 'item',
18
+ title: '{{t("Grid Card")}}',
19
+ component: 'GridCardBlockInitializer',
20
+ },
21
+ {
22
+ key: 'table',
23
+ type: 'item',
24
+ title: '{{t("Table")}}',
25
+ component: 'TableBlockInitializer',
26
+ },
27
+ {
28
+ key: 'form',
29
+ type: 'item',
30
+ title: '{{t("Form")}}',
31
+ component: 'FormBlockInitializer',
32
+ },
33
+ {
34
+ key: 'details',
35
+ type: 'item',
36
+ title: '{{t("Details")}}',
37
+ component: 'DetailsBlockInitializer',
38
+ },
39
+ {
40
+ key: 'calendar',
41
+ type: 'item',
42
+ title: '{{t("Calendar")}}',
43
+ component: 'CalendarBlockInitializer',
44
+ },
45
+ {
46
+ key: 'mapBlock',
47
+ type: 'item',
48
+ title: generateNTemplate('Map'),
49
+ component: 'MapBlockInitializer',
50
+ },
51
+ ],
52
+ },
53
+ {
54
+ key: 'otherBlocks',
55
+ type: 'itemGroup',
56
+ title: '{{t("Other blocks")}}',
57
+ children: [
58
+ {
59
+ key: 'menu',
60
+ type: 'item',
61
+ title: generateNTemplate('Menu'),
62
+ component: 'MMenuBlockInitializer',
63
+ sort: 100,
64
+ },
65
+ {
66
+ key: 'markdown',
67
+ type: 'item',
68
+ title: '{{t("Markdown")}}',
69
+ component: 'MarkdownBlockInitializer',
70
+ },
71
+ {
72
+ key: 'settings',
73
+ type: 'item',
74
+ title: generateNTemplate('Settings'),
75
+ component: 'MSettingsBlockInitializer',
76
+ sort: 100,
77
+ },
78
+ ],
79
+ },
80
+ ],
81
+ };
@@ -0,0 +1 @@
1
+ export * from './BlockInitializers';