@jobber/components 4.24.2-JOB-69677.2 → 4.24.3-pre.4
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/dist/Autocomplete/Autocomplete.d.ts +6 -2
- package/dist/Autocomplete/index.js +9 -7
- package/dist/DatePicker/index.js +1 -1
- package/dist/{DatePicker-38b0c40b.js → DatePicker-940cdb21.js} +28 -1
- package/dist/InputDate/index.js +1 -1
- package/dist/RadioGroup/RadioOption.d.ts +16 -30
- package/dist/RadioGroup/index.js +1 -1
- package/dist/{RadioGroup-8e76d20b.js → RadioGroup-67a5f560.js} +3 -5
- package/dist/RecurringSelect/index.js +1 -1
- package/package.json +2 -2
|
@@ -3,7 +3,7 @@ import { XOR } from "ts-xor";
|
|
|
3
3
|
import { GroupOption, Option } from "./Option";
|
|
4
4
|
import { FormFieldProps } from "../FormField";
|
|
5
5
|
type OptionCollection = XOR<Option[], GroupOption[]>;
|
|
6
|
-
interface AutocompleteProps extends Pick<FormFieldProps, "
|
|
6
|
+
interface AutocompleteProps extends Pick<FormFieldProps, "size" | "onBlur" | "onFocus" | "invalid" | "name" | "validations"> {
|
|
7
7
|
/**
|
|
8
8
|
* Initial options to show when user first focuses the Autocomplete
|
|
9
9
|
*/
|
|
@@ -40,5 +40,9 @@ interface AutocompleteProps extends Pick<FormFieldProps, "inputRef" | "invalid"
|
|
|
40
40
|
*/
|
|
41
41
|
readonly placeholder: string;
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Max statements disabled here to make room for the
|
|
45
|
+
* debounce functions.
|
|
46
|
+
*/
|
|
47
|
+
export declare function Autocomplete({ initialOptions, value, allowFreeForm, size, invalid, debounce: debounceRate, onChange, getOptions, placeholder, onBlur, onFocus, name, validations, }: AutocompleteProps): JSX.Element;
|
|
44
48
|
export {};
|
|
@@ -145,14 +145,16 @@ function useRepositionMenu(attachTo, visible = false) {
|
|
|
145
145
|
return Object.assign(Object.assign({}, popper), { menuRef, setMenuRef, targetWidth });
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Max statements disabled here to make room for the
|
|
150
|
+
* debounce functions.
|
|
151
|
+
*/
|
|
152
|
+
// eslint-disable-next-line max-statements
|
|
153
|
+
function Autocomplete({ initialOptions = [], value, allowFreeForm = true, size = undefined, invalid, debounce: debounceRate = 300, onChange, getOptions, placeholder, onBlur, onFocus, name, validations, }) {
|
|
154
|
+
var _a;
|
|
153
155
|
const [options, setOptions] = React.useState(initialOptions);
|
|
154
156
|
const [menuVisible, setMenuVisible] = React.useState(false);
|
|
155
|
-
const [inputText, setInputText] = React.useState((
|
|
157
|
+
const [inputText, setInputText] = React.useState((_a = value === null || value === void 0 ? void 0 : value.label) !== null && _a !== void 0 ? _a : "");
|
|
156
158
|
const autocompleteRef = React.useRef(null);
|
|
157
159
|
const delayedSearch = debounce__default["default"](updateSearch, debounceRate);
|
|
158
160
|
React.useEffect(() => {
|
|
@@ -164,7 +166,7 @@ function Autocomplete(_a) {
|
|
|
164
166
|
updateInput((_a = value === null || value === void 0 ? void 0 : value.label) !== null && _a !== void 0 ? _a : "");
|
|
165
167
|
}, [value]);
|
|
166
168
|
return (React__default["default"].createElement("div", { className: styles.autocomplete, ref: autocompleteRef },
|
|
167
|
-
React__default["default"].createElement(InputText.InputText,
|
|
169
|
+
React__default["default"].createElement(InputText.InputText, { autocomplete: false, size: size, invalid: invalid, value: inputText, onChange: handleInputChange, placeholder: placeholder, onFocus: handleInputFocus, onBlur: handleInputBlur, name: name, validations: validations }),
|
|
168
170
|
menuVisible && (React__default["default"].createElement(Menu, { attachTo: autocompleteRef, visible: menuVisible && options.length > 0, options: options, selectedOption: value, onOptionSelect: handleMenuChange }))));
|
|
169
171
|
function updateInput(newText) {
|
|
170
172
|
setInputText(newText);
|
package/dist/DatePicker/index.js
CHANGED
|
@@ -68,6 +68,7 @@ function useFocusOnSelectedDate() {
|
|
|
68
68
|
function DatePicker({ onChange, onMonthChange, activator, inline, selected, readonly = false, disabled = false, fullWidth = false, smartAutofocus = true, maxDate, minDate, highlightDates, }) {
|
|
69
69
|
const { ref, focusOnSelectedDate } = useFocusOnSelectedDate();
|
|
70
70
|
const [open, setOpen] = React.useState(false);
|
|
71
|
+
const { datePickerRef } = useDatePickerFocus(ref, open, inline);
|
|
71
72
|
const wrapperClassName = classnames__default["default"](styles.datePickerWrapper, {
|
|
72
73
|
// react-datepicker uses this class name to not close the date picker when
|
|
73
74
|
// the activator is clicked
|
|
@@ -87,7 +88,7 @@ function DatePicker({ onChange, onMonthChange, activator, inline, selected, read
|
|
|
87
88
|
React.useEffect(focusOnSelectedDate, [open]);
|
|
88
89
|
}
|
|
89
90
|
return (React__default["default"].createElement("div", { className: wrapperClassName, ref: ref },
|
|
90
|
-
React__default["default"].createElement(ReactDatePicker__default["default"], { calendarClassName: datePickerClassNames, showPopperArrow: false, selected: selected, inline: inline, disabled: disabled, readOnly: readonly, onChange: handleChange, maxDate: maxDate, minDate: minDate, useWeekdaysShort: true, customInput: React__default["default"].createElement(DatePickerActivator, { activator: activator, fullWidth: fullWidth }), renderCustomHeader: props => React__default["default"].createElement(DatePickerCustomHeader, Object.assign({}, props)), onCalendarOpen: handleCalendarOpen, onCalendarClose: handleCalendarClose, dateFormat: ["P", "PP", "PPP", "MMM dd yyyy", "MMMM dd yyyy"], highlightDates: highlightDates, onMonthChange: onMonthChange })));
|
|
91
|
+
React__default["default"].createElement(ReactDatePicker__default["default"], { calendarClassName: datePickerClassNames, showPopperArrow: false, selected: selected, inline: inline, disabled: disabled, readOnly: readonly, enableTabLoop: false, onChange: handleChange, maxDate: maxDate, minDate: minDate, ref: datePickerRef, useWeekdaysShort: true, customInput: React__default["default"].createElement(DatePickerActivator, { activator: activator, fullWidth: fullWidth }), renderCustomHeader: props => React__default["default"].createElement(DatePickerCustomHeader, Object.assign({}, props)), onCalendarOpen: handleCalendarOpen, onCalendarClose: handleCalendarClose, dateFormat: ["P", "PP", "PPP", "MMM dd yyyy", "MMMM dd yyyy"], highlightDates: highlightDates, onMonthChange: onMonthChange })));
|
|
91
92
|
/**
|
|
92
93
|
* The onChange callback on ReactDatePicker returns a Date and an Event, but
|
|
93
94
|
* the onChange in our interface only provides the Date. Simplifying the code
|
|
@@ -106,5 +107,31 @@ function DatePicker({ onChange, onMonthChange, activator, inline, selected, read
|
|
|
106
107
|
setOpen(false);
|
|
107
108
|
}
|
|
108
109
|
}
|
|
110
|
+
function useDatePickerFocus(ref, open, inline) {
|
|
111
|
+
const datePickerRef = React.useRef(null);
|
|
112
|
+
const handleTabbing = (event) => {
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
var _a;
|
|
115
|
+
if (event.key === "Tab" &&
|
|
116
|
+
ref.current &&
|
|
117
|
+
!ref.current.contains(document.activeElement)) {
|
|
118
|
+
(_a = datePickerRef.current) === null || _a === void 0 ? void 0 : _a.setOpen(false);
|
|
119
|
+
}
|
|
120
|
+
}, 0);
|
|
121
|
+
};
|
|
122
|
+
React.useEffect(() => {
|
|
123
|
+
var _a;
|
|
124
|
+
if (!inline && open) {
|
|
125
|
+
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.addEventListener("keydown", handleTabbing);
|
|
126
|
+
}
|
|
127
|
+
return () => {
|
|
128
|
+
var _a;
|
|
129
|
+
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("keydown", handleTabbing);
|
|
130
|
+
};
|
|
131
|
+
}, [open, ref, inline, handleTabbing]);
|
|
132
|
+
return {
|
|
133
|
+
datePickerRef,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
109
136
|
|
|
110
137
|
exports.DatePicker = DatePicker;
|
package/dist/InputDate/index.js
CHANGED
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var omit = require('lodash/omit');
|
|
6
6
|
var React = require('react');
|
|
7
7
|
var FormField = require('../FormField-090113ec.js');
|
|
8
|
-
var DatePicker = require('../DatePicker-
|
|
8
|
+
var DatePicker = require('../DatePicker-940cdb21.js');
|
|
9
9
|
require('../tslib.es6-5b8768b7.js');
|
|
10
10
|
require('uuid');
|
|
11
11
|
require('react-hook-form');
|
|
@@ -1,48 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PropsWithChildren } from "react";
|
|
2
2
|
import { XOR } from "ts-xor";
|
|
3
|
-
interface
|
|
4
|
-
/**
|
|
5
|
-
* The value of the radio button.
|
|
6
|
-
*/
|
|
3
|
+
interface BaseRadioOptions {
|
|
7
4
|
readonly value: string | number;
|
|
8
|
-
/**
|
|
9
|
-
* Disables the radio button.
|
|
10
|
-
*/
|
|
11
5
|
readonly disabled?: boolean;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
readonly description?: string;
|
|
6
|
+
}
|
|
7
|
+
interface RadioOptionsWithDescription extends BaseRadioOptions {
|
|
16
8
|
/**
|
|
17
9
|
* The label to appear beside the radio button.
|
|
18
10
|
*/
|
|
19
|
-
|
|
11
|
+
label: string;
|
|
20
12
|
/**
|
|
21
|
-
*
|
|
22
|
-
* not provided, or associated additional content with the radio button if
|
|
23
|
-
* `label` is provided.
|
|
24
|
-
*
|
|
25
|
-
* Prefer using `label` and `description` over adding child elements if the
|
|
26
|
-
* content of either would be text.
|
|
13
|
+
* Further description of the label.
|
|
27
14
|
*/
|
|
28
|
-
|
|
15
|
+
description?: string;
|
|
29
16
|
}
|
|
30
|
-
|
|
31
|
-
readonly children: ReactNode;
|
|
32
|
-
}
|
|
33
|
-
interface WithRequiredLabel extends BaseRadioOptionProps {
|
|
34
|
-
readonly label: string;
|
|
35
|
-
}
|
|
36
|
-
type RadioOptionProps = XOR<WithRequiredChildren, WithRequiredLabel>;
|
|
17
|
+
type RadioOptionProps = XOR<RadioOptionsWithDescription, PropsWithChildren<BaseRadioOptions>>;
|
|
37
18
|
/**
|
|
38
19
|
* For rendering props only. To make updates to
|
|
39
20
|
* the real RadioOption, look at InternalRadioOption
|
|
40
21
|
*/
|
|
41
|
-
export declare function RadioOption({ children }: RadioOptionProps): JSX.Element;
|
|
42
|
-
interface
|
|
22
|
+
export declare function RadioOption({ children }: PropsWithChildren<RadioOptionProps>): JSX.Element;
|
|
23
|
+
interface BaseInternalRadioOptions extends BaseRadioOptions {
|
|
43
24
|
readonly name: string;
|
|
44
25
|
readonly checked: boolean;
|
|
45
26
|
onChange(newValue: string | number): void;
|
|
46
27
|
}
|
|
47
|
-
|
|
28
|
+
interface InternalRadioOptionsWithDescription extends BaseInternalRadioOptions {
|
|
29
|
+
label: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
}
|
|
32
|
+
type InternalRadioOptionProps = XOR<InternalRadioOptionsWithDescription, PropsWithChildren<BaseInternalRadioOptions>>;
|
|
33
|
+
export declare function InternalRadioOption({ value, name, label, description, disabled, checked, children, onChange, }: PropsWithChildren<InternalRadioOptionProps>): JSX.Element;
|
|
48
34
|
export {};
|
package/dist/RadioGroup/index.js
CHANGED
|
@@ -9,8 +9,8 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
9
9
|
|
|
10
10
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
11
11
|
|
|
12
|
-
var css_248z = "._5P8wEHDUdKY- {\n display: -ms-inline-flexbox;\n display: inline-flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n\n._08ZPdlE98Ko- {\n /* Hide checkbox on UI but not screen readers and still allow focus state */\n position: absolute;\n left: -999vw;\n}\n\n.-PUoLXltVlQ- {\n display: -ms-inline-flexbox;\n display: inline-flex;\n font-size: calc((16px * 1) * 0.875);\n font-size: calc(calc(16px * 1) * 0.875);\n font-size: var(--typography--fontSize-base);\n cursor: pointer;\n -ms-flex-align: start;\n align-items: flex-start;\n}\n\n._08ZPdlE98Ko- + .-PUoLXltVlQ-::before {\n content: \"\";\n display: block;\n width: calc(16px * 1);\n width: var(--space-base);\n height: calc(16px * 1);\n height: var(--space-base);\n box-sizing: border-box;\n margin: calc(16px / 8) calc(16px / 2) 0 0;\n margin: var(--space-smallest) var(--space-small) 0 0;\n border: calc(16px / 8) solid rgb(125, 176, 14);\n border: var(--border-thick) solid var(--color-interactive);\n border-radius: 100%;\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n transition: all 200ms;\n transition: all var(--timing-base);\n -ms-flex-negative: 0;\n flex-shrink: 0;\n}\n\n._08ZPdlE98Ko-:focus + .-PUoLXltVlQ-:before {\n box-shadow: 0px 0px calc(16px / 4) calc(16px / 8)\n rgb(231, 213, 87);\n box-shadow: var(--shadow-focus);\n}\n\n._08ZPdlE98Ko-:focus:checked + .-PUoLXltVlQ-:before {\n box-shadow: 0px 0px 0px calc(16px / 16) rgb(81, 114, 9),\n 0px 0px calc(16px / 4) calc(16px / 8)\n rgb(231, 213, 87);\n box-shadow: 0px 0px 0px var(--space-minuscule) var(--color-interactive--hover),\n var(--shadow-focus);\n}\n\n._08ZPdlE98Ko-:checked + .-PUoLXltVlQ-::before {\n box-shadow: 0px 0px 0px calc(16px / 16) rgb(81, 114, 9);\n box-shadow: 0px 0px 0px var(--space-minuscule) var(--color-interactive--hover);\n border-color: rgb(81, 114, 9);\n border-color: var(--color-interactive--hover);\n border-width: calc(16px / 4);\n border-width: var(--border-thicker);\n background-color: rgb(125, 176, 14);\n background-color: var(--color-interactive);\n}\n\n._08ZPdlE98Ko-[disabled] + .-PUoLXltVlQ- {\n color: rgb(181, 181, 181);\n color: var(--color-disabled);\n cursor: not-allowed;\n}\n\n._08ZPdlE98Ko-[disabled] + .-PUoLXltVlQ-::before {\n border-color: rgb(225, 225, 225);\n border-color: var(--color-disabled--secondary);\n}\n\n._08ZPdlE98Ko-[disabled]:checked + .-PUoLXltVlQ-::before {\n box-shadow: 0px 0px 0px calc(16px / 16) rgb(181, 181, 181);\n box-shadow: 0px 0px 0px var(--space-minuscule) var(--color-disabled);\n border-color: rgb(181, 181, 181);\n border-color: var(--color-grey);\n background-color: rgb(225, 225, 225);\n background-color: var(--color-disabled--secondary);\n}\n\n._8r6qT-6S9EI
|
|
13
|
-
var styles = {"radioGroup":"_5P8wEHDUdKY-","input":"_08ZPdlE98Ko-","label":"-PUoLXltVlQ-","description":"_8r6qT-6S9EI-"
|
|
12
|
+
var css_248z = "._5P8wEHDUdKY- {\n display: -ms-inline-flexbox;\n display: inline-flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n\n._08ZPdlE98Ko- {\n /* Hide checkbox on UI but not screen readers and still allow focus state */\n position: absolute;\n left: -999vw;\n}\n\n.-PUoLXltVlQ- {\n display: -ms-inline-flexbox;\n display: inline-flex;\n font-size: calc((16px * 1) * 0.875);\n font-size: calc(calc(16px * 1) * 0.875);\n font-size: var(--typography--fontSize-base);\n cursor: pointer;\n -ms-flex-align: start;\n align-items: flex-start;\n}\n\n._08ZPdlE98Ko- + .-PUoLXltVlQ-::before {\n content: \"\";\n display: block;\n width: calc(16px * 1);\n width: var(--space-base);\n height: calc(16px * 1);\n height: var(--space-base);\n box-sizing: border-box;\n margin: calc(16px / 8) calc(16px / 2) 0 0;\n margin: var(--space-smallest) var(--space-small) 0 0;\n border: calc(16px / 8) solid rgb(125, 176, 14);\n border: var(--border-thick) solid var(--color-interactive);\n border-radius: 100%;\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n transition: all 200ms;\n transition: all var(--timing-base);\n -ms-flex-negative: 0;\n flex-shrink: 0;\n}\n\n._08ZPdlE98Ko-:focus + .-PUoLXltVlQ-:before {\n box-shadow: 0px 0px calc(16px / 4) calc(16px / 8)\n rgb(231, 213, 87);\n box-shadow: var(--shadow-focus);\n}\n\n._08ZPdlE98Ko-:focus:checked + .-PUoLXltVlQ-:before {\n box-shadow: 0px 0px 0px calc(16px / 16) rgb(81, 114, 9),\n 0px 0px calc(16px / 4) calc(16px / 8)\n rgb(231, 213, 87);\n box-shadow: 0px 0px 0px var(--space-minuscule) var(--color-interactive--hover),\n var(--shadow-focus);\n}\n\n._08ZPdlE98Ko-:checked + .-PUoLXltVlQ-::before {\n box-shadow: 0px 0px 0px calc(16px / 16) rgb(81, 114, 9);\n box-shadow: 0px 0px 0px var(--space-minuscule) var(--color-interactive--hover);\n border-color: rgb(81, 114, 9);\n border-color: var(--color-interactive--hover);\n border-width: calc(16px / 4);\n border-width: var(--border-thicker);\n background-color: rgb(125, 176, 14);\n background-color: var(--color-interactive);\n}\n\n._08ZPdlE98Ko-[disabled] + .-PUoLXltVlQ- {\n color: rgb(181, 181, 181);\n color: var(--color-disabled);\n cursor: not-allowed;\n}\n\n._08ZPdlE98Ko-[disabled] + .-PUoLXltVlQ-::before {\n border-color: rgb(225, 225, 225);\n border-color: var(--color-disabled--secondary);\n}\n\n._08ZPdlE98Ko-[disabled]:checked + .-PUoLXltVlQ-::before {\n box-shadow: 0px 0px 0px calc(16px / 16) rgb(181, 181, 181);\n box-shadow: 0px 0px 0px var(--space-minuscule) var(--color-disabled);\n border-color: rgb(181, 181, 181);\n border-color: var(--color-grey);\n background-color: rgb(225, 225, 225);\n background-color: var(--color-disabled--secondary);\n}\n\n._8r6qT-6S9EI- {\n margin-bottom: calc(16px / 2);\n margin-bottom: var(--space-small);\n padding-left: calc(16px * 1.5);\n padding-left: var(--space-large);\n}\n\n._08ZPdlE98Ko-[disabled] + .-PUoLXltVlQ- + ._8r6qT-6S9EI- > p {\n color: rgb(181, 181, 181);\n color: var(--color-disabled);\n}\n";
|
|
13
|
+
var styles = {"radioGroup":"_5P8wEHDUdKY-","input":"_08ZPdlE98Ko-","label":"-PUoLXltVlQ-","description":"_8r6qT-6S9EI-"};
|
|
14
14
|
styleInject_es.styleInject(css_248z);
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -22,13 +22,11 @@ function RadioOption({ children }) {
|
|
|
22
22
|
}
|
|
23
23
|
function InternalRadioOption({ value, name, label, description, disabled, checked, children, onChange, }) {
|
|
24
24
|
const inputId = `${value.toString()}_${uuid.v1()}`;
|
|
25
|
-
const shouldRenderIndependentChildren = label && children;
|
|
26
25
|
return (React__default["default"].createElement("div", null,
|
|
27
26
|
React__default["default"].createElement("input", { onChange: handleChange, type: "radio", name: name, value: value, disabled: disabled, checked: checked, id: inputId, className: styles.input, "aria-describedby": description ? `${inputId}_description` : undefined }),
|
|
28
27
|
React__default["default"].createElement("label", { className: styles.label, htmlFor: inputId }, label ? label : children),
|
|
29
28
|
description && (React__default["default"].createElement("div", { className: styles.description, id: `${inputId}_description` },
|
|
30
|
-
React__default["default"].createElement(Text.Text, { variation: "subdued", size: "small" }, description)))
|
|
31
|
-
shouldRenderIndependentChildren && (React__default["default"].createElement("div", { className: styles.children, id: `${inputId}_children` }, children))));
|
|
29
|
+
React__default["default"].createElement(Text.Text, { variation: "subdued", size: "small" }, description)))));
|
|
32
30
|
function handleChange() {
|
|
33
31
|
onChange(value);
|
|
34
32
|
}
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var uuid = require('uuid');
|
|
7
7
|
var styleInject_es = require('../style-inject.es-9d2f5f4e.js');
|
|
8
|
-
var RadioGroup = require('../RadioGroup-
|
|
8
|
+
var RadioGroup = require('../RadioGroup-67a5f560.js');
|
|
9
9
|
var Text = require('../Text-e7ed0974.js');
|
|
10
10
|
require('classnames');
|
|
11
11
|
require('../Typography-fd6f932a.js');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components",
|
|
3
|
-
"version": "4.24.
|
|
3
|
+
"version": "4.24.3-pre.4+f00e5e03",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"> 1%",
|
|
84
84
|
"IE 10"
|
|
85
85
|
],
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "f00e5e03b772ed91cc48ebe14a664cb4ee6116a1"
|
|
87
87
|
}
|