@geoinsight/react-components 0.1.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.
Files changed (41) hide show
  1. package/.babelrc.json +16 -0
  2. package/.storybook/main.js +11 -0
  3. package/.storybook/preview.js +43 -0
  4. package/README.md +26 -0
  5. package/dist/cjs/index.css +111 -0
  6. package/dist/cjs/index.js +15 -0
  7. package/dist/esm/index.css +111 -0
  8. package/dist/esm/index.js +12 -0
  9. package/package.json +44 -0
  10. package/rollup.config.js +40 -0
  11. package/src/components/accordion/index.css +40 -0
  12. package/src/components/accordion/index.stories.tsx +55 -0
  13. package/src/components/accordion/index.tsx +78 -0
  14. package/src/components/accordion/index.types.ts +44 -0
  15. package/src/components/button/index.css +80 -0
  16. package/src/components/button/index.stories.tsx +46 -0
  17. package/src/components/button/index.tsx +45 -0
  18. package/src/components/button/index.types.ts +41 -0
  19. package/src/components/input/index.css +30 -0
  20. package/src/components/input/index.stories.tsx +34 -0
  21. package/src/components/input/index.tsx +25 -0
  22. package/src/components/input/index.types.ts +29 -0
  23. package/src/components/text-area/index.css +53 -0
  24. package/src/components/text-area/index.stories.tsx +30 -0
  25. package/src/components/text-area/index.tsx +62 -0
  26. package/src/components/text-area/index.types.ts +37 -0
  27. package/src/decorators/withColorScheme.tsx +34 -0
  28. package/src/index.ts +2 -0
  29. package/src/stories/Introduction.stories.mdx +211 -0
  30. package/src/stories/assets/code-brackets.svg +1 -0
  31. package/src/stories/assets/colors.svg +1 -0
  32. package/src/stories/assets/comments.svg +1 -0
  33. package/src/stories/assets/direction.svg +1 -0
  34. package/src/stories/assets/flow.svg +1 -0
  35. package/src/stories/assets/plugin.svg +1 -0
  36. package/src/stories/assets/repo.svg +1 -0
  37. package/src/stories/assets/stackalt.svg +1 -0
  38. package/src/styles/variables.css +100 -0
  39. package/src/types/data-theme.d.ts +5 -0
  40. package/src/utils/themes.ts +1 -0
  41. package/tsconfig.json +21 -0
package/.babelrc.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "sourceType": "unambiguous",
3
+ "presets": [
4
+ [
5
+ "@babel/preset-env",
6
+ {
7
+ "targets": {
8
+ "chrome": 100
9
+ }
10
+ }
11
+ ],
12
+ "@babel/preset-typescript",
13
+ "@babel/preset-react"
14
+ ],
15
+ "plugins": []
16
+ }
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ "stories": ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
3
+ "addons": ["@storybook/addon-links", "@storybook/addon-essentials", "@storybook/addon-interactions", "@storybook/addon-mdx-gfm"],
4
+ "framework": {
5
+ name: "@storybook/react-webpack5",
6
+ options: {}
7
+ },
8
+ docs: {
9
+ autodocs: true
10
+ }
11
+ };
@@ -0,0 +1,43 @@
1
+ import "../src/styles/variables.css";
2
+
3
+ export const parameters = {
4
+ actions: { argTypesRegex: "^on[A-Z].*" },
5
+ controls: {
6
+ matchers: {
7
+ color: /(background|color)$/i,
8
+ date: /Date$/,
9
+ },
10
+ },
11
+ };
12
+
13
+ export const globalTypes = {
14
+ theme: {
15
+ name: 'Theme',
16
+ description: 'Global theme for components',
17
+ defaultValue: 'light',
18
+ toolbar: {
19
+ icon: 'circlehollow',
20
+ // Array of plain string values or MenuItem shape (see below)
21
+ items: ['light', 'dark'],
22
+ // Property that specifies if the name of the item will be displayed
23
+ showName: true,
24
+ // Change title based on selected value
25
+ dynamicTitle: true,
26
+ },
27
+ },
28
+ palette: {
29
+ name: 'Palette',
30
+ description: 'Global theme for components',
31
+ defaultValue: 'water',
32
+ toolbar: {
33
+ icon: 'circlehollow',
34
+ // Array of plain string values or MenuItem shape (see below)
35
+ items: ['water', 'forest', 'earth'],
36
+ // Property that specifies if the name of the item will be displayed
37
+ showName: true,
38
+ // Change title based on selected value
39
+ dynamicTitle: true,
40
+ },
41
+ },
42
+ }
43
+
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # Introduction
2
+ This library is used for Geoinsight, on their websites.
3
+
4
+ ## Install
5
+ Install with npm:
6
+ `npm install @geoinsight/react-components`
7
+
8
+ Install with yarn:
9
+ `yarn add @geoinsight/react-components`
10
+
11
+ ## Use
12
+ As an example:
13
+ `import { Button } from "@geoinsight/react-components";`
14
+
15
+ ## Docs
16
+ ### Basic components
17
+ #### Button
18
+ `<Button />`
19
+
20
+ #### Input
21
+ `<Input />`
22
+
23
+ #### TextArea
24
+ `<TextArea />`
25
+
26
+
@@ -0,0 +1,111 @@
1
+ .button {
2
+ align-items: center;
3
+ border-radius: var(--spacing-32);
4
+ border: none;
5
+ cursor: pointer;
6
+ display: flex;
7
+ justify-content: center;
8
+ gap: var(--spacing-8);
9
+ font-size: var(--font-size-16);
10
+ }
11
+
12
+ /*
13
+ .button--active {
14
+ background-color: var(--color-neutral-500) !important;
15
+ } */
16
+
17
+ .button:disabled {
18
+ cursor: unset;
19
+ opacity: 0.5;
20
+ pointer-events: none;
21
+ }
22
+
23
+ .button:hover {
24
+ background-color: var(--color-primary);
25
+ transition: var(--transition-bg-cubic-bezier);
26
+ }
27
+
28
+ .button__link {
29
+ background-color: unset !important;
30
+ color: var(--color-neutral-100);
31
+ text-decoration: underline transparent;
32
+ }
33
+
34
+ .button__link:hover {
35
+ color: var(--color-primary);
36
+ text-decoration: underline 0.1rem var(--color-primary);
37
+ text-underline-offset: var(--spacing-8);
38
+ transition: var(--transition-color-cubic-bezier),
39
+ var(--transition-text-decoration-cubic-bezier);
40
+ }
41
+
42
+ .button__primary {
43
+ background-color: var(--color-secondary);
44
+ border: 3px solid var(--color-primary);
45
+ }
46
+
47
+ .button__primary:hover {
48
+ box-shadow: 0 4px 4px 0 var(--color-neutral-400);
49
+ transition: var(--transition-bg-cubic-bezier), var(--transition-box-shadow-cubic-bezier);
50
+ }
51
+
52
+ .button__secondary {
53
+ background-color: var(--color-neutral-900);
54
+ border: 3px solid var(--color-primary);
55
+ color: var(--color-neutral-100);
56
+ }
57
+
58
+ .button__secondary:hover {
59
+ background-color: var(--color-primary);
60
+ }
61
+
62
+ .button__icon {
63
+ background-color: unset;
64
+ }
65
+
66
+ .button__icon:hover {
67
+ box-shadow: unset;
68
+ }
69
+
70
+ .button__small {
71
+ padding: var(--spacing-4);
72
+ }
73
+
74
+ .button__medium {
75
+ padding: var(--spacing-8) var(--spacing-24);
76
+ }
77
+
78
+ .button__large {
79
+ padding: var(--spacing-16);
80
+ }
81
+
82
+ .input-group {
83
+ display: flex;
84
+ flex-direction: column;
85
+ align-items: flex-start;
86
+ }
87
+
88
+ .input {
89
+ border-radius: var(--spacing-8);
90
+ border: 2px solid var(--color-primary);
91
+ color: var(--color-black);
92
+ padding: var(--spacing-16) var(--spacing-24);
93
+ }
94
+
95
+ .input:hover {
96
+ border: 3px solid var(--color-primary-700);
97
+ }
98
+
99
+ .input:focus {
100
+ border: 3px solid var(--color-primary-700);
101
+ outline: none;
102
+ }
103
+
104
+ .input--error {
105
+ border: 3px solid var(--color-danger);
106
+ }
107
+
108
+ .error {
109
+ font-size: 12px;
110
+ color: var(--color-danger);
111
+ }
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var clsx = require('clsx');
5
+
6
+ function Button({ children = "Click me", className = "", icon = undefined, isNewWindow = false, mode = "primary", size = "medium", as = "button", ...rest }) {
7
+ return as === "link" ? (jsxRuntime.jsxs("a", { ...(isNewWindow && { target: "_blank" }), className: clsx(className, "button", mode === "secondary" ? `button button__${mode}` : "button__link", `button__${size}`), ...rest, children: [children, icon] })) : (jsxRuntime.jsxs("button", { className: clsx(className, "button", `button__${mode}`, `button__${size}`), ...rest, children: [children, icon] }));
8
+ }
9
+
10
+ function Input({ className = "", classNameGroup = "", errorMessage = "", inputRef, styleGroup, ...rest }) {
11
+ return (jsxRuntime.jsxs("div", { className: `input-group ${classNameGroup}`, style: styleGroup, children: [jsxRuntime.jsx("input", { ref: inputRef, className: `input ${errorMessage ? "input--error" : ""} ${className}`, ...rest }), errorMessage && jsxRuntime.jsx("span", { className: "error", children: errorMessage })] }));
12
+ }
13
+
14
+ exports.Button = Button;
15
+ exports.Input = Input;
@@ -0,0 +1,111 @@
1
+ .button {
2
+ align-items: center;
3
+ border-radius: var(--spacing-32);
4
+ border: none;
5
+ cursor: pointer;
6
+ display: flex;
7
+ justify-content: center;
8
+ gap: var(--spacing-8);
9
+ font-size: var(--font-size-16);
10
+ }
11
+
12
+ /*
13
+ .button--active {
14
+ background-color: var(--color-neutral-500) !important;
15
+ } */
16
+
17
+ .button:disabled {
18
+ cursor: unset;
19
+ opacity: 0.5;
20
+ pointer-events: none;
21
+ }
22
+
23
+ .button:hover {
24
+ background-color: var(--color-primary);
25
+ transition: var(--transition-bg-cubic-bezier);
26
+ }
27
+
28
+ .button__link {
29
+ background-color: unset !important;
30
+ color: var(--color-neutral-100);
31
+ text-decoration: underline transparent;
32
+ }
33
+
34
+ .button__link:hover {
35
+ color: var(--color-primary);
36
+ text-decoration: underline 0.1rem var(--color-primary);
37
+ text-underline-offset: var(--spacing-8);
38
+ transition: var(--transition-color-cubic-bezier),
39
+ var(--transition-text-decoration-cubic-bezier);
40
+ }
41
+
42
+ .button__primary {
43
+ background-color: var(--color-secondary);
44
+ border: 3px solid var(--color-primary);
45
+ }
46
+
47
+ .button__primary:hover {
48
+ box-shadow: 0 4px 4px 0 var(--color-neutral-400);
49
+ transition: var(--transition-bg-cubic-bezier), var(--transition-box-shadow-cubic-bezier);
50
+ }
51
+
52
+ .button__secondary {
53
+ background-color: var(--color-neutral-900);
54
+ border: 3px solid var(--color-primary);
55
+ color: var(--color-neutral-100);
56
+ }
57
+
58
+ .button__secondary:hover {
59
+ background-color: var(--color-primary);
60
+ }
61
+
62
+ .button__icon {
63
+ background-color: unset;
64
+ }
65
+
66
+ .button__icon:hover {
67
+ box-shadow: unset;
68
+ }
69
+
70
+ .button__small {
71
+ padding: var(--spacing-4);
72
+ }
73
+
74
+ .button__medium {
75
+ padding: var(--spacing-8) var(--spacing-24);
76
+ }
77
+
78
+ .button__large {
79
+ padding: var(--spacing-16);
80
+ }
81
+
82
+ .input-group {
83
+ display: flex;
84
+ flex-direction: column;
85
+ align-items: flex-start;
86
+ }
87
+
88
+ .input {
89
+ border-radius: var(--spacing-8);
90
+ border: 2px solid var(--color-primary);
91
+ color: var(--color-black);
92
+ padding: var(--spacing-16) var(--spacing-24);
93
+ }
94
+
95
+ .input:hover {
96
+ border: 3px solid var(--color-primary-700);
97
+ }
98
+
99
+ .input:focus {
100
+ border: 3px solid var(--color-primary-700);
101
+ outline: none;
102
+ }
103
+
104
+ .input--error {
105
+ border: 3px solid var(--color-danger);
106
+ }
107
+
108
+ .error {
109
+ font-size: 12px;
110
+ color: var(--color-danger);
111
+ }
@@ -0,0 +1,12 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import clsx from 'clsx';
3
+
4
+ function Button({ children = "Click me", className = "", icon = undefined, isNewWindow = false, mode = "primary", size = "medium", as = "button", ...rest }) {
5
+ return as === "link" ? (jsxs("a", { ...(isNewWindow && { target: "_blank" }), className: clsx(className, "button", mode === "secondary" ? `button button__${mode}` : "button__link", `button__${size}`), ...rest, children: [children, icon] })) : (jsxs("button", { className: clsx(className, "button", `button__${mode}`, `button__${size}`), ...rest, children: [children, icon] }));
6
+ }
7
+
8
+ function Input({ className = "", classNameGroup = "", errorMessage = "", inputRef, styleGroup, ...rest }) {
9
+ return (jsxs("div", { className: `input-group ${classNameGroup}`, style: styleGroup, children: [jsx("input", { ref: inputRef, className: `input ${errorMessage ? "input--error" : ""} ${className}`, ...rest }), errorMessage && jsx("span", { className: "error", children: errorMessage })] }));
10
+ }
11
+
12
+ export { Button, Input };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@geoinsight/react-components",
3
+ "version": "0.1.0",
4
+ "description": "This library is the main UI component library for geoinsight",
5
+ "main": "dist/cjs/index.js",
6
+ "module": "dist/esm/index.js",
7
+ "author": "Geoinsight",
8
+ "license": "MIT",
9
+ "scripts": {
10
+ "build": "rollup -c rollup.config.js --bundleConfigAsCjs",
11
+ "storybook": "storybook dev -p 6006",
12
+ "build-storybook": "storybook build"
13
+ },
14
+ "dependencies": {
15
+ "@types/react": "^18.0.27",
16
+ "clsx": "^1.2.1",
17
+ "react": "^18.2.0",
18
+ "react-dom": "^18.2.0",
19
+ "react-icons": "^4.7.1",
20
+ "typescript": "^4.9.4"
21
+ },
22
+ "devDependencies": {
23
+ "@babel/core": "^7.20.12",
24
+ "@babel/preset-env": "^7.21.4",
25
+ "@babel/preset-react": "^7.18.6",
26
+ "@babel/preset-typescript": "^7.21.4",
27
+ "@rollup/plugin-commonjs": "^24.0.1",
28
+ "@rollup/plugin-node-resolve": "^15.0.1",
29
+ "@rollup/plugin-typescript": "^11.0.0",
30
+ "@storybook/addon-actions": "^7.0.7",
31
+ "@storybook/addon-essentials": "^7.0.7",
32
+ "@storybook/addon-interactions": "^7.0.7",
33
+ "@storybook/addon-links": "^7.0.7",
34
+ "@storybook/addon-mdx-gfm": "^7.0.7",
35
+ "@storybook/react": "^7.0.7",
36
+ "@storybook/react-webpack5": "^7.0.7",
37
+ "@storybook/testing-library": "^0.1.0",
38
+ "babel-loader": "^8.3.0",
39
+ "rollup": "^3.12.0",
40
+ "rollup-plugin-import-css": "^3.1.0",
41
+ "storybook": "^7.0.7",
42
+ "tslib": "^2.5.0"
43
+ }
44
+ }
@@ -0,0 +1,40 @@
1
+ // rollup.config.js
2
+ import resolve from "@rollup/plugin-node-resolve";
3
+ import commonjs from "@rollup/plugin-commonjs";
4
+ import typescript from "@rollup/plugin-typescript";
5
+ import pkg from "./package.json";
6
+ import css from "rollup-plugin-import-css";
7
+
8
+ export default [
9
+ {
10
+ input: "src/index.ts",
11
+ output: {
12
+ name: "mapinsight",
13
+ file: pkg.browser,
14
+ format: "umd",
15
+ },
16
+ plugins: [
17
+ resolve(),
18
+ commonjs(),
19
+ typescript({ tsconfig: "./tsconfig.json" }),
20
+ css()
21
+ ],
22
+ external: ["react", "react-dom"]
23
+ },
24
+
25
+ // CommonJS (for Node) and ES module (for bundlers) build.
26
+ // (We could have three entries in the configuration array
27
+ // instead of two, but it's quicker to generate multiple
28
+ // builds from a single configuration where possible, using
29
+ // an array for the `output` option, where we can specify
30
+ // `file` and `format` for each target)
31
+ {
32
+ input: "src/index.ts",
33
+ output: [
34
+ { file: pkg.main, format: "cjs" },
35
+ { file: pkg.module, format: "es" },
36
+ ],
37
+ plugins: [typescript({ tsconfig: "./tsconfig.json" }),
38
+ css()],
39
+ }
40
+ ];
@@ -0,0 +1,40 @@
1
+ .accordion {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--spacing-4)
5
+ }
6
+
7
+ .accordion__title {
8
+ border-radius: var(--spacing-8);
9
+ background-color: var(--color-neutral-700);
10
+ color: var(--color-neutral-100);
11
+ justify-content: flex-end;
12
+ gap: 8px;
13
+ padding: var(--spacing-8) var(--spacing-8) var(--spacing-8) var(--spacing-16);
14
+ }
15
+
16
+ .accordion__menu {
17
+ display: flex;
18
+ flex-direction: column;
19
+ gap: var(--spacing-4);
20
+ padding: 0 0 var(--spacing-8) var(--spacing-16);
21
+ }
22
+
23
+ .accordion__child {
24
+ border-radius: var(--spacing-8);
25
+ background-color: var(--color-neutral-200);
26
+ color: var(--color-neutral-900);
27
+ /* background: none !important; */
28
+ font-size: var(--font-size-14);
29
+ }
30
+
31
+ .accordion__child--active {
32
+ background-color: var(--color-neutral-500);
33
+ }
34
+
35
+ .accordion__check {
36
+ color: var(--color-neutral-500);
37
+ margin-right: calc(var(--spacing-24)*-1);
38
+ position: absolute;
39
+ right: 0;
40
+ }
@@ -0,0 +1,55 @@
1
+ import { ComponentStory, ComponentMeta } from "@storybook/react";
2
+ import { Accordion } from "./index";
3
+
4
+ // More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
5
+ export default {
6
+ title: "Example/Accordion",
7
+ component: Accordion,
8
+ // More on argTypes: https://storybook.js.org/docs/react/api/argtypes
9
+ argTypes: {
10
+ backgroundColor: { control: "color" },
11
+ },
12
+ } as ComponentMeta<typeof Accordion>;
13
+
14
+ // More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
15
+ const Template: ComponentStory<typeof Accordion> = (args) => (
16
+ <Accordion {...args} />
17
+ );
18
+
19
+ export const Primary = Template.bind({});
20
+ // More on args: https://storybook.js.org/docs/react/writing-stories/args
21
+ Primary.args = {
22
+ menu: {
23
+ water: {
24
+ label: "Water",
25
+ isExpanded: true,
26
+ dataTheme: "water",
27
+ children: [
28
+ {
29
+ id: "water_1",
30
+ label: "Water 1",
31
+ },
32
+ {
33
+ id: "water_2",
34
+ label: "Water 1",
35
+ },
36
+ ],
37
+ },
38
+ fire: {
39
+ label: "Fire",
40
+ dataTheme: "earth",
41
+ children: [
42
+ {
43
+ id: "fire_1",
44
+ label: "Fire 1",
45
+ },
46
+ {
47
+ id: "fire_2",
48
+ label: "Fire 2",
49
+ },
50
+ ],
51
+ },
52
+ },
53
+ defaultValue: "fire_1",
54
+ allExpanded: true
55
+ };
@@ -0,0 +1,78 @@
1
+ import { useState } from "react";
2
+ import Button from "../button";
3
+ import "./index.css";
4
+ import { TfiAngleUp, TfiAngleDown } from "react-icons/tfi";
5
+ import { BsCheckLg } from "react-icons/bs";
6
+ import { Accordion as AccordionProps } from "./index.types";
7
+
8
+ export function Accordion({
9
+ menu,
10
+ allExpanded,
11
+ defaultValue,
12
+ selectValue,
13
+ }: AccordionProps) {
14
+ const [toggle, setToggle] = useState<{ [key: string]: boolean | undefined }>(
15
+ Object.fromEntries(
16
+ Object.entries(menu).map(([key, { isExpanded = false }]) => [
17
+ key,
18
+ allExpanded !== undefined ? allExpanded : isExpanded,
19
+ ])
20
+ )
21
+ );
22
+ const [selected, setSelected] = useState<string>(defaultValue);
23
+
24
+ const handleToggle = (name: string) => {
25
+ setToggle((prev) => {
26
+ return { ...prev, [name]: !prev[name] };
27
+ });
28
+ };
29
+
30
+ return (
31
+ <div className={"accordion"}>
32
+ {Object.keys(menu).map((item) => (
33
+ <>
34
+ <Button
35
+ className={"accordion__title"}
36
+ data-theme={menu[item].dataTheme}
37
+ icon={toggle[item] ? <TfiAngleDown /> : <TfiAngleUp />}
38
+ handleClick={() => handleToggle(item)}
39
+ >
40
+ {menu[item].label}
41
+ </Button>
42
+ {toggle[item] && (
43
+ <div className="accordion__menu">
44
+ {menu[item].children.map((child) => (
45
+ <Button
46
+ mode="secondary"
47
+ data-theme={menu[item].dataTheme}
48
+ className={`accordion__child ${
49
+ child.id === selected &&
50
+ ` accordion__child--active`
51
+ }`}
52
+ handleClick={() => {
53
+ setSelected(child.id);
54
+ selectValue && selectValue(item, child);
55
+ }}
56
+ >
57
+ <>
58
+ {child.label}
59
+ {child.id === selected ? (
60
+ <BsCheckLg
61
+ className={"accordion__check"}
62
+ size={"1rem"}
63
+ />
64
+ ) : (
65
+ ""
66
+ )}
67
+ </>
68
+ </Button>
69
+ ))}
70
+ </div>
71
+ )}
72
+ </>
73
+ ))}
74
+ </div>
75
+ );
76
+ }
77
+
78
+ export default Accordion;
@@ -0,0 +1,44 @@
1
+ import {dataTheme} from "data-theme";
2
+
3
+ export interface Accordion {
4
+ /**
5
+ * What to put inside the menu
6
+ */
7
+ menu: layers;
8
+ /**
9
+ * Default value that is chosen. Must use on the of the children ids on the menu prop.
10
+ */
11
+ defaultValue: string;
12
+ /**
13
+ * Callback function for extra leg work outside the component. It takes two arguments:
14
+ * - item - parent ID.
15
+ * - object with the child ID and label.
16
+ */
17
+ selectValue?: (
18
+ parentId: string,
19
+ child: {
20
+ id: string;
21
+ label: string;
22
+ // field: string;
23
+ // tempValue: number;
24
+ // description: (value: number | string | undefined) => string;
25
+ // style: any;
26
+ }
27
+ ) => void;
28
+
29
+ allExpanded?: boolean;
30
+ }
31
+
32
+ export interface layer {
33
+ id: string;
34
+ label: string;
35
+ }
36
+
37
+ export interface layers {
38
+ [key: string]: {
39
+ label: string;
40
+ isExpanded?: boolean;
41
+ dataTheme?: dataTheme;
42
+ children: layer[];
43
+ };
44
+ }