@fto-consult/expo-ui 6.78.2 → 6.79.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/package.json +2 -2
- package/src/AppEntry/index.js +2 -16
- package/src/components/Dialog/AppBarDialog.js +0 -14
- package/src/components/Dialog/Dialog.js +1 -1
- package/src/components/Dialog/DialogActions.js +2 -12
- package/src/components/Dialog/DialogContent.js +0 -4
- package/src/components/Dialog/DialogFooter.js +2 -12
- package/src/components/Dialog/DialogTitle.js +2 -12
- package/src/components/Dropdown/index.js +3 -0
- package/src/components/Fab/Group.js +1 -1
- package/src/components/Grid/Grid.js +1 -1
- package/src/components/List/Common.js +0 -1
- package/src/components/SimpleSelect/index.js +1 -1
- package/src/context/Provider.js +22 -1
- package/src/screens/Help/openLibraries.js +1 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fto-consult/expo-ui",
|
3
|
-
"version": "6.
|
3
|
+
"version": "6.79.0",
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
5
5
|
"main": "main",
|
6
6
|
"scripts": {
|
@@ -71,7 +71,7 @@
|
|
71
71
|
"@expo/html-elements": "^0.5.1",
|
72
72
|
"@expo/vector-icons": "^13.0.0",
|
73
73
|
"@faker-js/faker": "^8.0.2",
|
74
|
-
"@fto-consult/common": "^3.
|
74
|
+
"@fto-consult/common": "^3.64.3",
|
75
75
|
"@pchmn/expo-material3-theme": "^1.3.1",
|
76
76
|
"@react-native-async-storage/async-storage": "1.18.2",
|
77
77
|
"@react-native-community/datetimepicker": "7.2.0",
|
package/src/AppEntry/index.js
CHANGED
@@ -42,7 +42,7 @@ import { StyleSheet } from "react-native";
|
|
42
42
|
import Logo from "$ecomponents/Logo";
|
43
43
|
import AppEntryRootView from "./RootView";
|
44
44
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
45
|
-
|
45
|
+
|
46
46
|
|
47
47
|
|
48
48
|
let MAX_BACK_COUNT = 1;
|
@@ -73,19 +73,7 @@ function App({init:initApp,initialRouteName:appInitialRouteName,children}) {
|
|
73
73
|
hasCallInitApp : false,
|
74
74
|
});
|
75
75
|
React.useEffect(() => {
|
76
|
-
|
77
|
-
const triggerKeyboardToggle = (status)=>{
|
78
|
-
APP.trigger(APP.EVENTS.KEYBOARD_DID_TOGGLE,{shown:status,status,visible:status,hide : !status});
|
79
|
-
}
|
80
|
-
const keyBoardDidShow = ()=>{
|
81
|
-
APP.trigger(APP.EVENTS.KEYBOARD_DID_SHOW);
|
82
|
-
triggerKeyboardToggle(true);
|
83
|
-
},keyBoardDidHide = ()=>{
|
84
|
-
APP.trigger(APP.EVENTS.KEYBOARD_DID_HIDE);
|
85
|
-
triggerKeyboardToggle(false);
|
86
|
-
}
|
87
|
-
const keyBoardDidShowListener = Keyboard.addListener("keyboardDidShow",keyBoardDidShow);
|
88
|
-
const keyBoardDidHideListener = Keyboard.addListener("keyboardDidHide",keyBoardDidHide);
|
76
|
+
|
89
77
|
const loadResources = ()=>{
|
90
78
|
return new Promise((resolve)=>{
|
91
79
|
loadFonts(FontsIconsFilter).catch((e)=>{
|
@@ -226,8 +214,6 @@ function App({init:initApp,initialRouteName:appInitialRouteName,children}) {
|
|
226
214
|
});
|
227
215
|
APP.on(APP.EVENTS.BACK_BUTTON,backAction);
|
228
216
|
return () => {
|
229
|
-
keyBoardDidShowListener && keyBoardDidShowListener.remove && keyBoardDidShowListener.remove();
|
230
|
-
keyBoardDidHideListener && keyBoardDidHideListener.remove && keyBoardDidHideListener.remove();
|
231
217
|
APP.off(APP.EVENTS.BACK_BUTTON,backAction);
|
232
218
|
if(subscription && subscription.remove){
|
233
219
|
subscription.remove();
|
@@ -6,20 +6,6 @@ import {isIos,isAndroid,isWeb} from "$cplatform";
|
|
6
6
|
|
7
7
|
const AppBarDialogComponent = React.forwardRef((props,ref)=>{
|
8
8
|
const {actions,responsive,isFullScreen,fullScreen,actionsProps,...rest} = props;
|
9
|
-
const forceRender = React.useForceRender();
|
10
|
-
React.useEffect(()=>{
|
11
|
-
const onResize = ()=>{
|
12
|
-
return;
|
13
|
-
forceRender();
|
14
|
-
}
|
15
|
-
if(responsive){
|
16
|
-
APP.on(APP.EVENTS.RESIZE_PAGE,onResize);
|
17
|
-
}
|
18
|
-
return ()=>{
|
19
|
-
APP.off(APP.EVENTS.RESIZE_PAGE,onResize);
|
20
|
-
}
|
21
|
-
},[]);
|
22
|
-
|
23
9
|
if(responsive && !isFullScreen() || (typeof fullScreen =='boolean' && !fullScreen)){
|
24
10
|
return null;
|
25
11
|
}
|
@@ -163,7 +163,7 @@ const DialogComponent = React.forwardRef((props,ref)=>{
|
|
163
163
|
const maxHeight = getMaxHeight(),maxWidth = getMaxWidth();
|
164
164
|
const backgroundColor = theme.surfaceBackgroundColor;
|
165
165
|
borderRadius = fullScreen || !(isMobileNative() || isMobileMedia()) || isPreloader ? 0 : typeof borderRadius =='number'? borderRadius : 5*theme.roundness;
|
166
|
-
const fullScreenStyle = fullScreen ? {width:dimensions.width,height:dimensions.height,marginHorizontal:0,paddingHorizontal:0}: {
|
166
|
+
const fullScreenStyle = fullScreen ? {width:dimensions.width,minHeight:MIN_HEIGHT,/*height:dimensions.height*/height:"100%",marginHorizontal:0,paddingHorizontal:0}: {
|
167
167
|
maxWidth,
|
168
168
|
maxHeight,
|
169
169
|
borderRadius,
|
@@ -7,20 +7,10 @@ import {renderActions} from "./utils";
|
|
7
7
|
import View from "$ecomponents/View";
|
8
8
|
import { StyleSheet } from "react-native";
|
9
9
|
import DialogActions from "./RNPDialogActions";
|
10
|
+
import {usePageDimensions} from "$cdimensions/utils";
|
10
11
|
|
11
12
|
const DialogActionsComponent = React.forwardRef(({actions,isAlert,onAlertRequestClose,testID,containerProps,actionMutator,actionProps,cancelButton,responsive,isFullScreen,fullScreen,actionsProps,menuProps,...rest},ref)=>{
|
12
|
-
|
13
|
-
React.useEffect(()=>{
|
14
|
-
const onResize = ()=>{
|
15
|
-
forceRender();
|
16
|
-
}
|
17
|
-
if(responsive){
|
18
|
-
APP.on(APP.EVENTS.RESIZE_PAGE,onResize);
|
19
|
-
}
|
20
|
-
return ()=>{
|
21
|
-
APP.off(APP.EVENTS.RESIZE_PAGE,onResize);
|
22
|
-
}
|
23
|
-
},[])
|
13
|
+
usePageDimensions();
|
24
14
|
if(responsive && isFullScreen() || fullScreen){
|
25
15
|
return null;
|
26
16
|
}
|
@@ -1,11 +1,7 @@
|
|
1
1
|
import KeyboardAvoidingView from "../KeyboardAvoidingView";
|
2
2
|
import React from "$react";
|
3
|
-
import { useWindowDimensions } from "react-native";
|
4
3
|
|
5
4
|
const DialogContentComponent = ({isPreloader,title,children,isFullScreen,...props})=>{
|
6
5
|
return children;
|
7
|
-
const isFull = isFullScreen();
|
8
|
-
return React.useMemo(()=>children,[isPreloader,title,children]);
|
9
|
-
return isPreloader || !isFull ? content : <KeyboardAvoidingView testID="RN_DialogKeybaordAvoidingView">{content}</KeyboardAvoidingView>
|
10
6
|
}
|
11
7
|
export default DialogContentComponent;
|
@@ -2,20 +2,10 @@ import React from "$react";
|
|
2
2
|
import {defaultObj} from "$cutils";;
|
3
3
|
import View from "$ecomponents/View";
|
4
4
|
import { StyleSheet } from "react-native";
|
5
|
+
import {usePageDimensions} from "$cdimensions/utils";
|
5
6
|
|
6
7
|
const DialogFullPageFooter = React.forwardRef(({responsive,containerProps,children,isFullScreen,fullScreen,...rest},ref)=>{
|
7
|
-
|
8
|
-
React.useEffect(()=>{
|
9
|
-
const onResize = ()=>{
|
10
|
-
forceRender();
|
11
|
-
}
|
12
|
-
if(responsive){
|
13
|
-
APP.on(APP.EVENTS.RESIZE_PAGE,onResize);
|
14
|
-
}
|
15
|
-
return ()=>{
|
16
|
-
APP.off(APP.EVENTS.RESIZE_PAGE,onResize);
|
17
|
-
}
|
18
|
-
},[])
|
8
|
+
usePageDimensions();
|
19
9
|
if(responsive && !isFullScreen() || (typeof fullScreen =='boolean' && !fullScreen) || !React.isValidElement(children)){
|
20
10
|
return null;
|
21
11
|
}
|
@@ -5,20 +5,10 @@ import {isNonNullString,defaultObj} from "$cutils";
|
|
5
5
|
import View from "$ecomponents/View";
|
6
6
|
import theme from "$theme";
|
7
7
|
import { StyleSheet } from "react-native";
|
8
|
+
import {usePageDimensions} from "$cdimensions/utils";
|
8
9
|
|
9
10
|
const DialogTitleComponent = React.forwardRef(({responsive,containerProps,title,titleProps,isFullScreen,fullScreen,...rest},ref)=>{
|
10
|
-
|
11
|
-
React.useEffect(()=>{
|
12
|
-
const onResize = ()=>{
|
13
|
-
forceRender();
|
14
|
-
}
|
15
|
-
if(responsive){
|
16
|
-
APP.on(APP.EVENTS.RESIZE_PAGE,onResize);
|
17
|
-
}
|
18
|
-
return ()=>{
|
19
|
-
APP.off(APP.EVENTS.RESIZE_PAGE,onResize);
|
20
|
-
}
|
21
|
-
},[])
|
11
|
+
usePageDimensions();
|
22
12
|
if(responsive && isFullScreen() || fullScreen || !React.isValidElement(title,true)){
|
23
13
|
return null;
|
24
14
|
}
|
@@ -646,6 +646,9 @@ class DropdownComponent extends AppComponent {
|
|
646
646
|
selectedText : this.getSelectedText(newSelected,selectedValuesKeys)
|
647
647
|
});
|
648
648
|
}
|
649
|
+
isVisible(){
|
650
|
+
return this.state.visible;
|
651
|
+
}
|
649
652
|
getBackgroundColor(){
|
650
653
|
return theme.surfaceBackground;
|
651
654
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { FAB} from 'react-native-paper';
|
2
2
|
import React from "$react";
|
3
|
-
import {StyleSheet
|
3
|
+
import {StyleSheet} from "react-native";
|
4
4
|
import {defaultStr,isNonNullString,isObj,defaultObj} from "$cutils";
|
5
5
|
import PropTypes from "prop-types";
|
6
6
|
import {MENU_ICON} from "$ecomponents/Icon";
|
@@ -8,7 +8,6 @@ import {isMobileMedia} from "$cplatform/dimensions";
|
|
8
8
|
import BackToTop from "$ecomponents/BackToTop";
|
9
9
|
import {FlatList,StyleSheet,View} from "react-native";
|
10
10
|
import Label from "$ecomponents/Label";
|
11
|
-
import { useWindowDimensions,Dimensions } from "react-native";
|
12
11
|
import { useList,useGetNumColumns } from "./hooks";
|
13
12
|
|
14
13
|
const CommonListComponent = React.forwardRef((props,ref)=>{
|
@@ -194,7 +194,7 @@ const SimpleSelect = React.forwardRef((props,ref)=>{
|
|
194
194
|
}
|
195
195
|
}
|
196
196
|
};
|
197
|
-
const dimensions = Dimensions.get("window")
|
197
|
+
const dimensions = Dimensions.get("window");
|
198
198
|
let contentContainerHeight = dimensions.height - defaultDecimal(layout?.top) - defaultDecimal(layout?.height)-20;
|
199
199
|
contentContainerHeight = Math.max(contentContainerHeight,200);
|
200
200
|
let marginTop = 0;
|
package/src/context/Provider.js
CHANGED
@@ -25,6 +25,7 @@ import {isMobileNative} from "$cplatform";
|
|
25
25
|
import notify from "$cnotify";
|
26
26
|
import {showPrompt} from "$ecomponents/Dialog/confirm";
|
27
27
|
import {SWRConfig} from "$swr";
|
28
|
+
import {Keyboard } from 'react-native';
|
28
29
|
|
29
30
|
Object.map(Utils,(v,i)=>{
|
30
31
|
if(typeof v =='function' && typeof window !='undefined' && window && !window[i]){
|
@@ -269,7 +270,7 @@ const Provider = ({children,getTableData,handleHelpScreen,navigation,swrConfig,a
|
|
269
270
|
})
|
270
271
|
}
|
271
272
|
|
272
|
-
|
273
|
+
const isKeyboardShownRef = React.useRef(false);
|
273
274
|
const {screens} = navigation;
|
274
275
|
navigation.screens = React.useMemo(()=>{
|
275
276
|
const r = prepareScreens({
|
@@ -290,14 +291,34 @@ const Provider = ({children,getTableData,handleHelpScreen,navigation,swrConfig,a
|
|
290
291
|
screensRef.current[sanitizedName] = new Date();
|
291
292
|
activeScreenRef.current = sanitizedName;
|
292
293
|
}
|
294
|
+
///la fonction de rappel lorsque le composant est monté
|
295
|
+
const triggerKeyboardToggle = (status)=>{
|
296
|
+
APP.trigger(APP.EVENTS.KEYBOARD_DID_TOGGLE,{shown:status,status,visible:status,hide : !status});
|
297
|
+
}
|
298
|
+
const keyBoardDidShow = ()=>{
|
299
|
+
isKeyboardShownRef.current = true;
|
300
|
+
APP.trigger(APP.EVENTS.KEYBOARD_DID_SHOW);
|
301
|
+
triggerKeyboardToggle(true);
|
302
|
+
},keyBoardDidHide = ()=>{
|
303
|
+
isKeyboardShownRef.current = false;
|
304
|
+
APP.trigger(APP.EVENTS.KEYBOARD_DID_HIDE);
|
305
|
+
triggerKeyboardToggle(false);
|
306
|
+
}
|
307
|
+
const keyBoardDidShowListener = Keyboard.addListener("keyboardDidShow",keyBoardDidShow);
|
308
|
+
const keyBoardDidHideListener = Keyboard.addListener("keyboardDidHide",keyBoardDidHide);
|
293
309
|
APP.on(APP.EVENTS.SCREEN_FOCUS,onScreenFocus);
|
294
310
|
return ()=>{
|
311
|
+
keyBoardDidShowListener?.remove && keyBoardDidShowListener.remove();
|
312
|
+
keyBoardDidHideListener?.remove && keyBoardDidHideListener.remove();
|
295
313
|
APP.off(APP.EVENTS.SCREEN_FOCUS,onScreenFocus);
|
296
314
|
}
|
297
315
|
},[]);
|
316
|
+
const isKeyboardShown = ()=> typeof Keyboard.isVisible =="function" && Keyboard.isVisible() || isKeyboardShownRef.current;
|
298
317
|
return <ExpoUIContext.Provider
|
299
318
|
value={{
|
300
319
|
...props,
|
320
|
+
isKeyboardShown, //permet de déterminer si le clavier est visible
|
321
|
+
isKeyboardVisible : isKeyboardShown,
|
301
322
|
handleHelpScreen,
|
302
323
|
navigation,
|
303
324
|
parseMangoQueries,
|
@@ -1 +1 @@
|
|
1
|
-
module.exports = {"@fto-consult/expo-ui":{"name":"@fto-consult/expo-ui","version":"6.
|
1
|
+
module.exports = {"@fto-consult/expo-ui":{"name":"@fto-consult/expo-ui","version":"6.78.2","repository":{"type":"git","url":"git+https://github.com/borispipo/expo-ui.git"},"homepage":"https://github.com/borispipo/expo-ui#readme"},"@babel/plugin-proposal-export-namespace-from":{"version":"7.18.9","url":"https://babel.dev/docs/en/next/babel-plugin-proposal-export-namespace-from","license":"MIT"},"@emotion/native":{"version":"11.11.0","url":"https://emotion.sh","license":"MIT"},"@emotion/react":{"version":"11.11.1","url":"https://github.com/emotion-js/emotion/tree/main/packages/react","license":"MIT"},"@expo/html-elements":{"version":"0.5.1","url":"https://github.com/expo/expo/tree/main/packages/html-elements","license":"MIT"},"@expo/metro-config":{"version":"0.10.7","url":"https://github.com/expo/expo.git","license":"MIT"},"@expo/vector-icons":{"version":"13.0.0","url":"https://expo.github.io/vector-icons","license":"MIT"},"@expo/webpack-config":{"version":"19.0.0","url":"https://github.com/expo/expo-cli.git","license":"MIT"},"@faker-js/faker":{"version":"8.0.2","url":"https://github.com/faker-js/faker.git","license":"MIT"},"@fto-consult/common":{"version":"3.63.2","url":"https://github.com/borispipo/common#readme","license":"ISC"},"@pchmn/expo-material3-theme":{"version":"1.3.1","url":"https://github.com/pchmn/expo-material3-theme#readme","license":"MIT"},"@react-native-async-storage/async-storage":{"version":"1.18.2","url":"https://github.com/react-native-async-storage/async-storage#readme","license":"MIT"},"@react-native-community/datetimepicker":{"version":"7.2.0","url":"https://github.com/react-native-community/datetimepicker#readme","license":"MIT"},"@react-native-community/netinfo":{"version":"9.3.10","url":"https://github.com/react-native-netinfo/react-native-netinfo#readme","license":"MIT"},"@react-native/assets-registry":{"version":"0.72.0","url":"git@github.com:facebook/react-native.git","license":"MIT"},"@react-navigation/native":{"version":"6.1.9","url":"https://reactnavigation.org","license":"MIT"},"@react-navigation/native-stack":{"version":"6.9.17","url":"https://github.com/software-mansion/react-native-screens#readme","license":"MIT"},"@react-navigation/stack":{"version":"6.3.20","url":"https://reactnavigation.org/docs/stack-navigator/","license":"MIT"},"@shopify/flash-list":{"version":"1.4.3","url":"https://shopify.github.io/flash-list/","license":"MIT"},"apexcharts":{"version":"3.44.0","url":"https://apexcharts.com","license":"MIT"},"babel-plugin-inline-dotenv":{"version":"1.7.0","url":"https://github.com/brysgo/babel-plugin-inline-dotenv#readme","license":"ISC"},"babel-plugin-module-resolver":{"version":"5.0.0","url":"https://github.com/tleunen/babel-plugin-module-resolver.git","license":"MIT"},"expo":{"version":"49.0.18","url":"https://github.com/expo/expo/tree/main/packages/expo","license":"MIT"},"expo-camera":{"version":"13.4.4","url":"https://docs.expo.dev/versions/latest/sdk/camera/","license":"MIT"},"expo-clipboard":{"version":"4.3.1","url":"https://docs.expo.dev/versions/latest/sdk/clipboard","license":"MIT"},"expo-font":{"version":"11.4.0","url":"https://docs.expo.dev/versions/latest/sdk/font/","license":"MIT"},"expo-image-picker":{"version":"14.3.2","url":"https://docs.expo.dev/versions/latest/sdk/imagepicker/","license":"MIT"},"expo-linking":{"version":"5.0.2","url":"https://docs.expo.dev/versions/latest/sdk/linking","license":"MIT"},"expo-sharing":{"version":"11.5.0","url":"https://docs.expo.dev/versions/latest/sdk/sharing/","license":"MIT"},"expo-sqlite":{"version":"11.3.3","url":"https://docs.expo.dev/versions/latest/sdk/sqlite/","license":"MIT"},"expo-status-bar":{"version":"1.6.0","url":"https://docs.expo.dev/versions/latest/sdk/status-bar/","license":"MIT"},"expo-system-ui":{"version":"2.4.0","url":"https://docs.expo.dev/versions/latest/sdk/system-ui","license":"MIT"},"expo-web-browser":{"version":"12.3.2","url":"https://docs.expo.dev/versions/latest/sdk/webbrowser/","license":"MIT"},"file-saver":{"version":"2.0.5","url":"https://github.com/eligrey/FileSaver.js#readme","license":"MIT"},"fs-extra":{"version":"11.1.1","url":"https://github.com/jprichardson/node-fs-extra","license":"MIT"},"google-libphonenumber":{"version":"3.2.33","url":"https://ruimarinho.github.io/google-libphonenumber/","license":"(MIT AND Apache-2.0)"},"htmlparser2-without-node-native":{"version":"3.9.2","url":"git://github.com/fb55/htmlparser2.git","license":"MIT"},"is-plain-obj":{"version":"4.1.0","license":"MIT"},"js-base64":{"version":"3.7.5","license":"BSD-3-Clause"},"pdfmake":{"version":"0.2.8","url":"http://pdfmake.org","license":"MIT"},"process":{"version":"0.11.10","url":"git://github.com/shtylman/node-process.git","license":"MIT"},"prop-types":{"version":"15.8.1","url":"https://facebook.github.io/react/","license":"MIT"},"react":{"version":"18.2.0","url":"https://reactjs.org/","license":"MIT"},"react-content-loader":{"version":"6.2.1","url":"https://github.com/danilowoz/react-content-loader","license":"MIT"},"react-dom":{"version":"18.2.0","url":"https://reactjs.org/","license":"MIT"},"react-native":{"version":"0.72.6","license":"MIT"},"react-native-big-list":{"version":"1.6.1","url":"https://marcocesarato.github.io/react-native-big-list-docs/","license":"GPL-3.0-or-later"},"react-native-blob-util":{"version":"0.18.6","url":"https://github.com/RonRadtke/react-native-blob-util","license":"MIT"},"react-native-gesture-handler":{"version":"2.12.1","url":"https://github.com/software-mansion/react-native-gesture-handler#readme","license":"MIT"},"react-native-get-random-values":{"version":"1.9.0","license":"MIT"},"react-native-iphone-x-helper":{"version":"1.3.1","url":"https://github.com/ptelad/react-native-iphone-x-helper#readme","license":"MIT"},"react-native-mime-types":{"version":"2.4.0","license":"MIT"},"react-native-paper":{"version":"5.11.1","url":"https://callstack.github.io/react-native-paper","license":"MIT"},"react-native-paper-dates":{"version":"0.20.4","url":"https://github.com/web-ridge/react-native-paper-dates#readme","license":"MIT"},"react-native-reanimated":{"version":"3.3.0","url":"https://github.com/software-mansion/react-native-reanimated#readme","license":"MIT"},"react-native-safe-area-context":{"version":"4.6.3","url":"https://github.com/th3rdwave/react-native-safe-area-context#readme","license":"MIT"},"react-native-screens":{"version":"3.22.1","url":"https://github.com/software-mansion/react-native-screens#readme","license":"MIT"},"react-native-svg":{"version":"13.9.0","url":"https://github.com/react-native-community/react-native-svg","license":"MIT"},"react-native-web":{"version":"0.19.9","url":"git://github.com/necolas/react-native-web.git","license":"MIT"},"react-native-webview":{"version":"13.2.2","url":"https://github.com/react-native-webview/react-native-webview#readme","license":"MIT"},"react-virtuoso":{"version":"4.6.2","url":"https://virtuoso.dev/","license":"MIT"},"sharp-cli":{"version":"2.1.0","url":"https://github.com/vseventer/sharp-cli","license":"MIT"},"tippy.js":{"version":"6.3.7","url":"https://atomiks.github.io/tippyjs/","license":"MIT"},"websql":{"version":"2.0.3","url":"git://github.com/nolanlawson/node-websql.git","license":"Apache-2.0"},"xlsx":{"version":"0.18.5","url":"https://sheetjs.com/","license":"Apache-2.0"}};
|