@nutui/nutui-react 1.3.16-beta.0 → 1.4.0-beta.1
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/CHANGELOG.md +10 -0
- package/dist/esm/ActionSheet.js +1 -1
- package/dist/esm/Cell.js +4 -12
- package/dist/esm/ConfigProvider.js +18 -4
- package/dist/esm/Empty.js +3 -3
- package/dist/esm/Progress.js +1 -1
- package/dist/esm/SearchBar.js +3 -3
- package/dist/esm/TabbarItem.js +1 -9
- package/dist/esm/types/src/packages/cell/cell.d.ts +0 -2
- package/dist/esm/types/src/packages/configprovider/configprovider.d.ts +2 -0
- package/dist/esm/types/src/packages/{formitem/useForm.d.ts → form/useForm.taro.d.ts} +0 -0
- package/dist/esm/types/src/packages/signature/demo.d.ts +1 -0
- package/dist/esm/types/src/packages/tabbaritem/tabbaritem.d.ts +0 -1
- package/dist/locales/base.js +1 -1
- package/dist/locales/en-US.js +1 -1
- package/dist/locales/id-ID.js +1 -1
- package/dist/locales/zh-CN.js +1 -1
- package/dist/locales/zh-TW.js +1 -1
- package/dist/locales/zh-UG.js +1 -1
- package/dist/nutui.react.es.js +6773 -2518
- package/dist/nutui.react.umd.js +6760 -2505
- package/dist/packages/actionsheet/actionsheet.scss +29 -13
- package/dist/packages/address/address.scss +46 -18
- package/dist/packages/animatingnumbers/countup.scss +10 -1
- package/dist/packages/audio/audio.scss +17 -4
- package/dist/packages/backtop/backtop.scss +4 -3
- package/dist/packages/badge/badge.scss +2 -2
- package/dist/packages/barrage/barrage.scss +13 -6
- package/dist/packages/button/button.scss +56 -0
- package/dist/packages/calendar/calendar.scss +8 -7
- package/dist/packages/card/card.scss +1 -1
- package/dist/packages/cascader/cascader.scss +21 -12
- package/dist/packages/cell/cell.scss +9 -3
- package/dist/packages/cellgroup/cellgroup.scss +2 -2
- package/dist/packages/checkbox/checkbox.scss +1 -1
- package/dist/packages/circleprogress/circleprogress.scss +1 -1
- package/dist/packages/collapseitem/collapseitem.scss +52 -18
- package/dist/packages/dialog/dialog.scss +1 -1
- package/dist/packages/divider/divider.scss +9 -0
- package/dist/packages/elevator/elevator.scss +8 -4
- package/dist/packages/empty/empty.scss +5 -2
- package/dist/packages/fixednav/fixednav.scss +8 -0
- package/dist/packages/formitem/formitem.scss +1 -1
- package/dist/packages/griditem/griditem.scss +9 -4
- package/dist/packages/image/image.scss +2 -2
- package/dist/packages/indicator/indicator.scss +7 -0
- package/dist/packages/infiniteloading/infiniteloading.scss +12 -8
- package/dist/packages/input/input.scss +24 -4
- package/dist/packages/inputnumber/inputnumber.scss +9 -8
- package/dist/packages/menu/menu.scss +2 -3
- package/dist/packages/menuitem/menuitem.scss +3 -2
- package/dist/packages/navbar/navbar.scss +25 -5
- package/dist/packages/noticebar/noticebar.scss +14 -8
- package/dist/packages/numberkeyboard/numberkeyboard.scss +28 -6
- package/dist/packages/overlay/overlay.scss +25 -0
- package/dist/packages/pagination/pagination.scss +19 -8
- package/dist/packages/picker/picker.scss +46 -21
- package/dist/packages/popup/popup.scss +6 -2
- package/dist/packages/progress/progress.scss +10 -0
- package/dist/packages/pulltorefresh/pulltorefresh.scss +9 -1
- package/dist/packages/radio/radio.scss +9 -6
- package/dist/packages/radiogroup/radiogroup.scss +49 -0
- package/dist/packages/range/range.scss +4 -4
- package/dist/packages/row/row.scss +16 -0
- package/dist/packages/searchbar/searchbar.scss +20 -6
- package/dist/packages/shortpassword/shortpassword.scss +23 -12
- package/dist/packages/sidenavbar/sidenavbar.scss +20 -2
- package/dist/packages/sidenavbaritem/sidenavbaritem.scss +13 -5
- package/dist/packages/signature/signature.scss +16 -0
- package/dist/packages/step/step.scss +48 -2
- package/dist/packages/subsidenavbar/subsidenavbar.scss +4 -4
- package/dist/packages/switch/switch.scss +14 -0
- package/dist/packages/tabbar/tabbar.scss +1 -1
- package/dist/packages/tabbaritem/tabbaritem.scss +4 -3
- package/dist/packages/table/table.scss +21 -10
- package/dist/packages/tabpane/tabpane.scss +3 -2
- package/dist/packages/tabs/tabs.scss +18 -6
- package/dist/packages/textarea/textarea.scss +2 -2
- package/dist/packages/timedetail/timedetail.scss +8 -5
- package/dist/packages/timepannel/timepannel.scss +4 -4
- package/dist/packages/timeselect/timeselect.scss +27 -13
- package/dist/packages/uploader/uploader.scss +23 -7
- package/dist/packages/virtuallist/virtuallist.scss +15 -3
- package/dist/style.css +1 -1
- package/dist/style.es.js +1 -1
- package/dist/styles/font/config.json +1 -1
- package/dist/styles/theme-dark.scss +18 -0
- package/dist/styles/theme-default.scss +28 -0
- package/dist/styles/themes/default.scss +1 -0
- package/dist/styles/variables.scss +103 -96
- package/dist/types/index.d.ts +2 -3
- package/package.json +4 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
# v1.4.0
|
|
2
|
+
`2022-12-21`
|
|
3
|
+
|
|
4
|
+
* :sparkles: feat: 新增动态主题定制能力 (#546) @oasis-cloud
|
|
5
|
+
* :sparkles: feat: 新增 input 组件对小程序特性的支持 (#542) @simpleStyle
|
|
6
|
+
* :sparkles: feat: 删除 react-router-dom 依赖,涉及的 to 属性不再支持 (#550) @oasis-cloud
|
|
7
|
+
* :bug: fix: 修复 searchBar 组件 onSearch 方法。 (#549) @xiaoyatong
|
|
8
|
+
* :bug: fix: 修复 noticbar 垂直滚动延迟问题 (#545) @vickyYe
|
|
9
|
+
|
|
10
|
+
|
|
1
11
|
# v1.3.15
|
|
2
12
|
`2022-12-14`
|
|
3
13
|
|
package/dist/esm/ActionSheet.js
CHANGED
|
@@ -41,7 +41,7 @@ var ActionSheet = function ActionSheet(props) {
|
|
|
41
41
|
rest = _objectWithoutProperties(_defaultProps$props, _excluded);
|
|
42
42
|
var b = cn('actionsheet');
|
|
43
43
|
var isHighlight = function isHighlight(item) {
|
|
44
|
-
return props.chooseTagValue && props.chooseTagValue === item[props.optionTag || 'name'] ? props.color : '
|
|
44
|
+
return props.chooseTagValue && props.chooseTagValue === item[props.optionTag || 'name'] ? props.color : '$dark1';
|
|
45
45
|
};
|
|
46
46
|
var cancelActionSheet = function cancelActionSheet() {
|
|
47
47
|
onCancel && onCancel();
|
package/dist/esm/Cell.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
2
2
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
-
var _excluded = ["children", "
|
|
3
|
+
var _excluded = ["children", "onClick", "title", "subTitle", "desc", "descTextAlign", "isLink", "icon", "roundRadius", "url", "replace", "center", "size", "className", "iconSlot", "linkSlot", "iconClassPrefix", "iconFontClassName"];
|
|
4
4
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
5
5
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
6
6
|
import React__default from 'react';
|
|
7
|
-
import { useHistory } from 'react-router-dom';
|
|
8
7
|
import { c as cn } from './bem-893ad28d.js';
|
|
9
8
|
import Icon from './Icon.js';
|
|
10
9
|
import { C as ComponentDefaults } from './typings-1c5f2628.js';
|
|
@@ -25,13 +24,11 @@ var defaultProps = _objectSpread(_objectSpread({}, ComponentDefaults), {}, {
|
|
|
25
24
|
className: '',
|
|
26
25
|
iconSlot: null,
|
|
27
26
|
linkSlot: null,
|
|
28
|
-
click: function click(event) {},
|
|
29
27
|
onClick: function onClick(event) {}
|
|
30
28
|
});
|
|
31
29
|
var Cell = function Cell(props) {
|
|
32
30
|
var _defaultProps$props = _objectSpread(_objectSpread({}, defaultProps), props),
|
|
33
31
|
children = _defaultProps$props.children,
|
|
34
|
-
click = _defaultProps$props.click,
|
|
35
32
|
onClick = _defaultProps$props.onClick,
|
|
36
33
|
title = _defaultProps$props.title,
|
|
37
34
|
subTitle = _defaultProps$props.subTitle,
|
|
@@ -41,7 +38,6 @@ var Cell = function Cell(props) {
|
|
|
41
38
|
icon = _defaultProps$props.icon,
|
|
42
39
|
roundRadius = _defaultProps$props.roundRadius,
|
|
43
40
|
url = _defaultProps$props.url,
|
|
44
|
-
to = _defaultProps$props.to,
|
|
45
41
|
replace = _defaultProps$props.replace,
|
|
46
42
|
center = _defaultProps$props.center,
|
|
47
43
|
size = _defaultProps$props.size,
|
|
@@ -52,13 +48,9 @@ var Cell = function Cell(props) {
|
|
|
52
48
|
iconFontClassName = _defaultProps$props.iconFontClassName,
|
|
53
49
|
rest = _objectWithoutProperties(_defaultProps$props, _excluded);
|
|
54
50
|
var b = cn('cell');
|
|
55
|
-
var history = useHistory();
|
|
56
51
|
var handleClick = function handleClick(event) {
|
|
57
|
-
click(event);
|
|
58
52
|
onClick(event);
|
|
59
|
-
if (
|
|
60
|
-
history[replace ? 'replace' : 'push'](to);
|
|
61
|
-
} else if (url) {
|
|
53
|
+
if (url) {
|
|
62
54
|
replace ? window.location.replace(url) : window.location.href = url;
|
|
63
55
|
}
|
|
64
56
|
};
|
|
@@ -71,7 +63,7 @@ var Cell = function Cell(props) {
|
|
|
71
63
|
};
|
|
72
64
|
return React__default.createElement("div", _objectSpread({
|
|
73
65
|
className: "".concat(b({
|
|
74
|
-
clickable: !!
|
|
66
|
+
clickable: !!isLink,
|
|
75
67
|
center: center,
|
|
76
68
|
large: size === 'large'
|
|
77
69
|
}, [className]), " "),
|
|
@@ -97,7 +89,7 @@ var Cell = function Cell(props) {
|
|
|
97
89
|
alone: !title && !subTitle
|
|
98
90
|
}),
|
|
99
91
|
style: styles
|
|
100
|
-
}, desc) : null, !linkSlot &&
|
|
92
|
+
}, desc) : null, !linkSlot && isLink ? React__default.createElement(Icon, {
|
|
101
93
|
classPrefix: iconClassPrefix,
|
|
102
94
|
fontClassName: iconFontClassName,
|
|
103
95
|
name: "right",
|
|
@@ -3,7 +3,8 @@ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProper
|
|
|
3
3
|
var _excluded = ["children"];
|
|
4
4
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
5
5
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
6
|
-
import React__default, { createContext, useContext } from 'react';
|
|
6
|
+
import React__default, { createContext, useContext, useMemo } from 'react';
|
|
7
|
+
import _ from 'lodash';
|
|
7
8
|
var zhCN = {
|
|
8
9
|
save: '保存',
|
|
9
10
|
confirm: '确认',
|
|
@@ -152,20 +153,33 @@ var setDefaultConfig = function setDefaultConfig(config) {
|
|
|
152
153
|
var getDefaultConfig = function getDefaultConfig() {
|
|
153
154
|
return defaultConfigRef.current;
|
|
154
155
|
};
|
|
156
|
+
// 创建一个 Context 对象
|
|
157
|
+
var ConfigContext = createContext(null);
|
|
155
158
|
var useConfig = function useConfig() {
|
|
156
159
|
var _useContext;
|
|
157
160
|
return (_useContext = useContext(ConfigContext)) !== null && _useContext !== void 0 ? _useContext : getDefaultConfig();
|
|
158
161
|
};
|
|
159
|
-
|
|
160
|
-
var
|
|
162
|
+
function convertThemeVarsToCSSVars(themeVars) {
|
|
163
|
+
var cssVars = {};
|
|
164
|
+
Object.keys(themeVars).forEach(function (key) {
|
|
165
|
+
cssVars["--".concat(_.kebabCase(key))] = themeVars[key];
|
|
166
|
+
});
|
|
167
|
+
return cssVars;
|
|
168
|
+
}
|
|
161
169
|
var ConfigProvider = function ConfigProvider(props) {
|
|
162
170
|
var _defaultProps$props = _objectSpread(_objectSpread({}, defaultProps), props),
|
|
163
171
|
children = _defaultProps$props.children,
|
|
164
172
|
config = _objectWithoutProperties(_defaultProps$props, _excluded);
|
|
165
173
|
var parentConfig = useConfig();
|
|
174
|
+
var theme = config.theme || {};
|
|
175
|
+
var style = useMemo(function () {
|
|
176
|
+
return convertThemeVarsToCSSVars(theme);
|
|
177
|
+
}, [theme]);
|
|
166
178
|
return React__default.createElement(ConfigContext.Provider, {
|
|
167
179
|
value: _objectSpread(_objectSpread({}, parentConfig), config)
|
|
168
|
-
},
|
|
180
|
+
}, React__default.createElement("div", {
|
|
181
|
+
style: style
|
|
182
|
+
}, children));
|
|
169
183
|
};
|
|
170
184
|
ConfigProvider.defaultProps = defaultProps;
|
|
171
185
|
ConfigProvider.displayName = 'NutConfigProvider';
|
package/dist/esm/Empty.js
CHANGED
|
@@ -18,7 +18,7 @@ var defaultStatus = {
|
|
|
18
18
|
network: 'https://static-ftcms.jd.com/p/files/61a9e31de7dcdbcc0ce62734.png'
|
|
19
19
|
};
|
|
20
20
|
var defaultProps = {
|
|
21
|
-
description: '
|
|
21
|
+
description: '',
|
|
22
22
|
image: 'empty',
|
|
23
23
|
imageSize: '',
|
|
24
24
|
className: ''
|
|
@@ -26,7 +26,7 @@ var defaultProps = {
|
|
|
26
26
|
var Empty = function Empty(props) {
|
|
27
27
|
var _useConfig = useConfig(),
|
|
28
28
|
locale = _useConfig.locale;
|
|
29
|
-
defaultProps.description = locale.noData || defaultProps.description
|
|
29
|
+
// defaultProps.description = locale.noData || defaultProps.description
|
|
30
30
|
var _defaultProps$props = _objectSpread(_objectSpread({}, defaultProps), props),
|
|
31
31
|
image = _defaultProps$props.image,
|
|
32
32
|
imageSize = _defaultProps$props.imageSize,
|
|
@@ -73,7 +73,7 @@ var Empty = function Empty(props) {
|
|
|
73
73
|
style: imgStyle
|
|
74
74
|
}, imageNode), typeof description === 'string' ? React__default.createElement("div", {
|
|
75
75
|
className: b('description')
|
|
76
|
-
}, description) : {
|
|
76
|
+
}, description || locale.noData) : {
|
|
77
77
|
description: description
|
|
78
78
|
}, children));
|
|
79
79
|
};
|
package/dist/esm/Progress.js
CHANGED
|
@@ -167,7 +167,7 @@ var Progress = function Progress(props) {
|
|
|
167
167
|
}, textType === 'text' && React__default.createElement("span", {
|
|
168
168
|
className: classesTextInner,
|
|
169
169
|
style: {
|
|
170
|
-
color: textColor || '
|
|
170
|
+
color: textColor || '$title-color'
|
|
171
171
|
}
|
|
172
172
|
}, percentage, isShowPercentage ? '%' : ''), textType === 'icon' && React__default.createElement(Icon, {
|
|
173
173
|
classPrefix: iconClassPrefix,
|
package/dist/esm/SearchBar.js
CHANGED
|
@@ -193,7 +193,7 @@ var SearchBar = function SearchBar(props) {
|
|
|
193
193
|
if (actionText) {
|
|
194
194
|
return React__default.createElement("div", {
|
|
195
195
|
className: searchbarBem('action-text'),
|
|
196
|
-
onClick:
|
|
196
|
+
onClick: search
|
|
197
197
|
}, actionText);
|
|
198
198
|
}
|
|
199
199
|
return null;
|
|
@@ -207,8 +207,8 @@ var SearchBar = function SearchBar(props) {
|
|
|
207
207
|
onSearch && onSearch(value);
|
|
208
208
|
}
|
|
209
209
|
};
|
|
210
|
-
var
|
|
211
|
-
|
|
210
|
+
var search = function search() {
|
|
211
|
+
onSearch && onSearch(value);
|
|
212
212
|
};
|
|
213
213
|
var renderLabel = function renderLabel() {
|
|
214
214
|
if (label) {
|
package/dist/esm/TabbarItem.js
CHANGED
|
@@ -2,7 +2,6 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
3
3
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
4
4
|
import React__default, { useEffect } from 'react';
|
|
5
|
-
import { useHistory } from 'react-router-dom';
|
|
6
5
|
import { c as cn } from './bem-893ad28d.js';
|
|
7
6
|
import Icon from './Icon.js';
|
|
8
7
|
import { C as ComponentDefaults } from './typings-1c5f2628.js';
|
|
@@ -14,7 +13,6 @@ var defaultProps = _objectSpread(_objectSpread({}, ComponentDefaults), {}, {
|
|
|
14
13
|
tabTitle: '',
|
|
15
14
|
icon: '',
|
|
16
15
|
href: '',
|
|
17
|
-
to: '',
|
|
18
16
|
num: '',
|
|
19
17
|
active: false,
|
|
20
18
|
activeColor: '',
|
|
@@ -31,7 +29,6 @@ var TabbarItem = function TabbarItem(props) {
|
|
|
31
29
|
tabTitle = _defaultProps$props.tabTitle,
|
|
32
30
|
icon = _defaultProps$props.icon,
|
|
33
31
|
href = _defaultProps$props.href,
|
|
34
|
-
to = _defaultProps$props.to,
|
|
35
32
|
num = _defaultProps$props.num,
|
|
36
33
|
active = _defaultProps$props.active,
|
|
37
34
|
activeColor = _defaultProps$props.activeColor,
|
|
@@ -42,16 +39,11 @@ var TabbarItem = function TabbarItem(props) {
|
|
|
42
39
|
iconFontClassName = _defaultProps$props.iconFontClassName;
|
|
43
40
|
var b = cn('tabbar-item');
|
|
44
41
|
var bIcon = cn('tabbar-item__icon-box');
|
|
45
|
-
var history = useHistory();
|
|
46
42
|
useEffect(function () {
|
|
47
43
|
if (active && href) {
|
|
48
44
|
window.location.href = href;
|
|
49
|
-
return;
|
|
50
45
|
}
|
|
51
|
-
|
|
52
|
-
history.push(to);
|
|
53
|
-
}
|
|
54
|
-
}, [active, history, href, to]);
|
|
46
|
+
}, [active, href]);
|
|
55
47
|
return React__default.createElement("div", {
|
|
56
48
|
className: "".concat(b({
|
|
57
49
|
active: active
|
|
@@ -9,14 +9,12 @@ export interface CellProps extends BasicComponent {
|
|
|
9
9
|
icon: string;
|
|
10
10
|
roundRadius: string | number;
|
|
11
11
|
url: string;
|
|
12
|
-
to: string;
|
|
13
12
|
replace: boolean;
|
|
14
13
|
center: boolean;
|
|
15
14
|
size: string;
|
|
16
15
|
className: string;
|
|
17
16
|
iconSlot: ReactNode;
|
|
18
17
|
linkSlot: ReactNode;
|
|
19
|
-
click: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
|
20
18
|
onClick: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
|
21
19
|
}
|
|
22
20
|
export declare const Cell: FunctionComponent<Partial<CellProps> & Omit<React.HTMLAttributes<HTMLDivElement>, 'title'>>;
|
|
@@ -2,6 +2,8 @@ import React, { FunctionComponent } from 'react';
|
|
|
2
2
|
import { BaseLang } from '@/locales/base';
|
|
3
3
|
export interface ConfigProviderProps {
|
|
4
4
|
locale: BaseLang;
|
|
5
|
+
theme?: Record<string, string>;
|
|
6
|
+
[key: string]: any;
|
|
5
7
|
}
|
|
6
8
|
export declare const defaultConfigRef: {
|
|
7
9
|
current: ConfigProviderProps;
|
|
File without changes
|
package/dist/locales/base.js
CHANGED
package/dist/locales/en-US.js
CHANGED
package/dist/locales/id-ID.js
CHANGED
package/dist/locales/zh-CN.js
CHANGED
package/dist/locales/zh-TW.js
CHANGED
package/dist/locales/zh-UG.js
CHANGED