@genesislcap/foundation-layout 9.0.1-alpha-b5c5eb7.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 (156) hide show
  1. package/README.md +916 -0
  2. package/dist/1.0.0.remoteEntry.js +1 -0
  3. package/dist/191.191.106ece7a41ded6731029.js +2 -0
  4. package/dist/191.9a61143c2afb6057ad1bae886d5d1a6e.js.map +1 -0
  5. package/dist/259.09c601e5288d875caab4df1e2354c0ea.js.map +1 -0
  6. package/dist/259.259.216fcad43e9a38888e08.js +2 -0
  7. package/dist/415.415.094780a1a1162c7e5f1c.js +3 -0
  8. package/dist/415.415.094780a1a1162c7e5f1c.js.LICENSE.txt +4 -0
  9. package/dist/415.fcfb4f02eaecbfa31fc322639f244245.js.map +1 -0
  10. package/dist/459.459.c9f0bb440eb1f041c99e.js +515 -0
  11. package/dist/459.cb5f5b49b4e8881992c420f3b1ca863d.js.map +1 -0
  12. package/dist/623.623.0e7e8f23454ee96ed9c8.js +3 -0
  13. package/dist/623.623.0e7e8f23454ee96ed9c8.js.LICENSE.txt +4 -0
  14. package/dist/623.e8f211473f9034c4157d362efb017821.js.map +1 -0
  15. package/dist/755.718e14af7194fb741f98580b24b2bb8f.js.map +1 -0
  16. package/dist/755.755.f93ee58c2b836a669ec4.js +2 -0
  17. package/dist/dashboard.json +1 -0
  18. package/dist/dts/index.d.ts +3 -0
  19. package/dist/dts/index.d.ts.map +1 -0
  20. package/dist/dts/index.federated.d.ts +1 -0
  21. package/dist/dts/index.federated.d.ts.map +1 -0
  22. package/dist/dts/main/index.d.ts +6 -0
  23. package/dist/dts/main/index.d.ts.map +1 -0
  24. package/dist/dts/main/layout-components.d.ts +42 -0
  25. package/dist/dts/main/layout-components.d.ts.map +1 -0
  26. package/dist/dts/main/layout-item.d.ts +70 -0
  27. package/dist/dts/main/layout-item.d.ts.map +1 -0
  28. package/dist/dts/main/layout-main.d.ts +186 -0
  29. package/dist/dts/main/layout-main.d.ts.map +1 -0
  30. package/dist/dts/main/layout-region.d.ts +70 -0
  31. package/dist/dts/main/layout-region.d.ts.map +1 -0
  32. package/dist/dts/styles/constants.d.ts +7 -0
  33. package/dist/dts/styles/constants.d.ts.map +1 -0
  34. package/dist/dts/styles/dragging.styles.d.ts +7 -0
  35. package/dist/dts/styles/dragging.styles.d.ts.map +1 -0
  36. package/dist/dts/styles/index.d.ts +4 -0
  37. package/dist/dts/styles/index.d.ts.map +1 -0
  38. package/dist/dts/styles/layout.styles.d.ts +8 -0
  39. package/dist/dts/styles/layout.styles.d.ts.map +1 -0
  40. package/dist/dts/utils/constants.d.ts +14 -0
  41. package/dist/dts/utils/constants.d.ts.map +1 -0
  42. package/dist/dts/utils/error.d.ts +13 -0
  43. package/dist/dts/utils/error.d.ts.map +1 -0
  44. package/dist/dts/utils/events.d.ts +38 -0
  45. package/dist/dts/utils/events.d.ts.map +1 -0
  46. package/dist/dts/utils/index.d.ts +7 -0
  47. package/dist/dts/utils/index.d.ts.map +1 -0
  48. package/dist/dts/utils/logger.d.ts +2 -0
  49. package/dist/dts/utils/logger.d.ts.map +1 -0
  50. package/dist/dts/utils/misc.d.ts +10 -0
  51. package/dist/dts/utils/misc.d.ts.map +1 -0
  52. package/dist/dts/utils/templates.d.ts +6 -0
  53. package/dist/dts/utils/templates.d.ts.map +1 -0
  54. package/dist/dts/utils/types.d.ts +63 -0
  55. package/dist/dts/utils/types.d.ts.map +1 -0
  56. package/dist/esm/index.federated.js +2 -0
  57. package/dist/esm/index.federated.js.map +1 -0
  58. package/dist/esm/index.js +3 -0
  59. package/dist/esm/index.js.map +1 -0
  60. package/dist/esm/main/index.js +6 -0
  61. package/dist/esm/main/index.js.map +1 -0
  62. package/dist/esm/main/layout-components.js +36 -0
  63. package/dist/esm/main/layout-components.js.map +1 -0
  64. package/dist/esm/main/layout-item.js +86 -0
  65. package/dist/esm/main/layout-item.js.map +1 -0
  66. package/dist/esm/main/layout-main.js +391 -0
  67. package/dist/esm/main/layout-main.js.map +1 -0
  68. package/dist/esm/main/layout-region.js +98 -0
  69. package/dist/esm/main/layout-region.js.map +1 -0
  70. package/dist/esm/main/main.css +17 -0
  71. package/dist/esm/styles/constants.js +16 -0
  72. package/dist/esm/styles/constants.js.map +1 -0
  73. package/dist/esm/styles/dragging.styles.js +116 -0
  74. package/dist/esm/styles/dragging.styles.js.map +1 -0
  75. package/dist/esm/styles/index.js +4 -0
  76. package/dist/esm/styles/index.js.map +1 -0
  77. package/dist/esm/styles/layout.styles.js +530 -0
  78. package/dist/esm/styles/layout.styles.js.map +1 -0
  79. package/dist/esm/utils/constants.js +14 -0
  80. package/dist/esm/utils/constants.js.map +1 -0
  81. package/dist/esm/utils/error.js +17 -0
  82. package/dist/esm/utils/error.js.map +1 -0
  83. package/dist/esm/utils/events.js +26 -0
  84. package/dist/esm/utils/events.js.map +1 -0
  85. package/dist/esm/utils/index.js +7 -0
  86. package/dist/esm/utils/index.js.map +1 -0
  87. package/dist/esm/utils/logger.js +3 -0
  88. package/dist/esm/utils/logger.js.map +1 -0
  89. package/dist/esm/utils/misc.js +24 -0
  90. package/dist/esm/utils/misc.js.map +1 -0
  91. package/dist/esm/utils/templates.js +11 -0
  92. package/dist/esm/utils/templates.js.map +1 -0
  93. package/dist/esm/utils/types.js +4 -0
  94. package/dist/esm/utils/types.js.map +1 -0
  95. package/dist/favicon.ico +0 -0
  96. package/dist/foundation-layout.api.json +1574 -0
  97. package/dist/foundation-layout.d.ts +478 -0
  98. package/dist/foundationLayout.8b94161c9f0d0d475d026a05513893c1.js.map +1 -0
  99. package/dist/index.ejs +23 -0
  100. package/dist/index.html +15 -0
  101. package/dist/info.ejs +13 -0
  102. package/dist/main.40c13c1585eb6fa5761a17ab29a7851e.js.map +1 -0
  103. package/dist/main.94f8a6853d484ec34632.js +2 -0
  104. package/dist/npm.consola.713.b1e4073e73c71572987a.js +2 -0
  105. package/dist/npm.consola.a0d3324d3e61dcc430c3029da5f4dcc7.js.map +1 -0
  106. package/dist/npm.genesis-community.248.9c9900001dbc5ba9c3ed.js +2 -0
  107. package/dist/npm.genesis-community.2e0cc159dabe113d6fb29bb505c1a0d4.js.map +1 -0
  108. package/dist/npm.microsoft.127.00f16f24d8da8fd89263.js +1469 -0
  109. package/dist/npm.microsoft.127.00f16f24d8da8fd89263.js.LICENSE.txt +14 -0
  110. package/dist/npm.microsoft.be43958facd28231e770c1307660f64d.js.map +1 -0
  111. package/dist/remoteEntry.js +2 -0
  112. package/dist/serve.json +3 -0
  113. package/dist/tsdoc-metadata.json +11 -0
  114. package/docs/.gitattributes +2 -0
  115. package/docs/api/foundation-layout.default_reload_buffer.md +18 -0
  116. package/docs/api/foundation-layout.foundationlayout.additem.md +38 -0
  117. package/docs/api/foundation-layout.foundationlayout.dragging.md +16 -0
  118. package/docs/api/foundation-layout.foundationlayout.getlayout.md +22 -0
  119. package/docs/api/foundation-layout.foundationlayout.layoutrequiredregistrations.md +37 -0
  120. package/docs/api/foundation-layout.foundationlayout.loadlayout.md +37 -0
  121. package/docs/api/foundation-layout.foundationlayout.md +44 -0
  122. package/docs/api/foundation-layout.foundationlayout.registereditems.md +26 -0
  123. package/docs/api/foundation-layout.foundationlayout.registeritem.md +42 -0
  124. package/docs/api/foundation-layout.foundationlayout.reloadbuffer.md +16 -0
  125. package/docs/api/foundation-layout.foundationlayoutcomponents.md +50 -0
  126. package/docs/api/foundation-layout.foundationlayoutitem.closable.md +16 -0
  127. package/docs/api/foundation-layout.foundationlayoutitem.md +35 -0
  128. package/docs/api/foundation-layout.foundationlayoutitem.registration.md +21 -0
  129. package/docs/api/foundation-layout.foundationlayoutitem.size.md +16 -0
  130. package/docs/api/foundation-layout.foundationlayoutitem.title.md +21 -0
  131. package/docs/api/foundation-layout.foundationlayoutregion.md +33 -0
  132. package/docs/api/foundation-layout.foundationlayoutregion.size.md +16 -0
  133. package/docs/api/foundation-layout.foundationlayoutregion.type.md +16 -0
  134. package/docs/api/foundation-layout.layoutemitevents.md +22 -0
  135. package/docs/api/foundation-layout.layoutreceiveevents.md +20 -0
  136. package/docs/api/foundation-layout.layoutreceiveeventsdetail.md +23 -0
  137. package/docs/api/foundation-layout.layoutregiontype.md +16 -0
  138. package/docs/api/foundation-layout.layoutregistrationerror._constructor_.md +23 -0
  139. package/docs/api/foundation-layout.layoutregistrationerror.md +23 -0
  140. package/docs/api/foundation-layout.layoutstyles.md +21 -0
  141. package/docs/api/foundation-layout.layouttemplate.md +21 -0
  142. package/docs/api/foundation-layout.layoutusageerror._constructor_.md +23 -0
  143. package/docs/api/foundation-layout.layoutusageerror.md +23 -0
  144. package/docs/api/foundation-layout.md +42 -0
  145. package/docs/api/foundation-layout.placement.md +18 -0
  146. package/docs/api/foundation-layout.registeredelementconfig.closable.md +14 -0
  147. package/docs/api/foundation-layout.registeredelementconfig.md +30 -0
  148. package/docs/api/foundation-layout.registeredelementconfig.registration.md +14 -0
  149. package/docs/api/foundation-layout.registeredelementconfig.size.md +14 -0
  150. package/docs/api/foundation-layout.registeredelementconfig.title.md +14 -0
  151. package/docs/api/foundation-layout.serialisedlayout.md +26 -0
  152. package/docs/api/index.md +12 -0
  153. package/docs/api-report.md +235 -0
  154. package/docs/img/foundation-layout-example.png +0 -0
  155. package/license.txt +46 -0
  156. package/package.json +80 -0
package/README.md ADDED
@@ -0,0 +1,916 @@
1
+ # Genesis Foundation UI App Layout
2
+
3
+ [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org/)
4
+ [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](https://www.typescriptlang.org/)
5
+
6
+ ### [API Docs](./docs/api/index.md)
7
+
8
+ ## Declarative HTML API
9
+
10
+ The following example shows the usage of the declarative API with `zero-charts` and the output that it produces.
11
+ ```html
12
+ <foundation-layout>
13
+ <foundation-layout-region>
14
+ <foundation-layout-item closable title="Pie">
15
+ <zero-charts
16
+ type="rose"
17
+ :config=${(x) => x.roseConfig}
18
+ :data=${(x) => x.roseData}
19
+ ></zero-charts>
20
+ </foundation-layout-item>
21
+ <foundation-layout-region type="vertical">
22
+ <foundation-layout-item title="Positions Area Chart">
23
+ <zero-charts type="area" :config=${(x) => x.areaConfig}>
24
+ <charts-datasource
25
+ resourceName="ALL_POSITIONS"
26
+ server-fields="INSTRUMENT_NAME QUANTITY"
27
+ charts-fields="type value"
28
+ isSnapshot="true"
29
+ ></charts-datasource>
30
+ </zero-charts>
31
+ </foundation-layout-item>
32
+ <foundation-layout-item title="Positions Column Chart">
33
+ <zero-charts type="column" :config=${(x) => x.columnConfig}>
34
+ <charts-datasource
35
+ resourceName="ALL_POSITIONS"
36
+ server-fields="INSTRUMENT_NAME QUANTITY"
37
+ charts-fields="type value"
38
+ isSnapshot="true"
39
+ ></charts-datasource>
40
+ </zero-charts>
41
+ </foundation-layout-item>
42
+ </foundation-layout-region>
43
+ </foundation-layout-region>
44
+ </foundation-layout>
45
+ ```
46
+
47
+ ![Example output of the declarative API with the zero charts](./docs/img/foundation-layout-example.png)
48
+
49
+ ## Set-up
50
+
51
+ ### Basic install
52
+
53
+ To enable this module in your application, follow the steps below.
54
+
55
+ 1. Add `@genesislcap/foundation-layout` as a dependency in your **package.json** file. Whenever you change the dependencies of your project, ensure you run the `$ npm run bootstrap` command again.
56
+
57
+ ```javascript
58
+ {
59
+ ...
60
+ "dependencies": {
61
+ "@genesislcap/foundation-layout": "latest"
62
+ },
63
+ ...
64
+ }
65
+ ```
66
+
67
+ 2. Register the layout with the design system. This is probably in a file called **components.ts**, located where you call `.register()` on the design system.
68
+
69
+ ```javascript
70
+ FoundationDesignSystem: registerFoundationDesignSystem().register(
71
+ // ...Other registrations
72
+ // add foundationLayoutComponents here
73
+ foundationLayoutComponents,
74
+ )
75
+ ```
76
+
77
+ - This registers the three custom elements for use in your application. The components will use the prefix of the design system as their prefix. For example, the root component will be `<foundation-layout>` in the `Foundation` design system, and `<zero-layout>` in the `Zero (alpha)` design system.
78
+
79
+ :::info
80
+ For the rest of this document, the components will be referred to with the `foundation-` prefix.
81
+ :::
82
+
83
+ ### Custom styling
84
+
85
+ The required class, template, and base styles are exported as part of the package, allowing a client to customise the styling of the layout system via design system extensions.
86
+
87
+ :::tip
88
+ All the customisable styles of the layout system are contained within the styles for [`<foundation-layout>`](./docs/api/foundation-layout.foundationlayout.md). So if you want to customise the styles in addition to setting the css variables, you only need to set the styles here.
89
+ :::
90
+
91
+ ### [Top Level Component `<foundation-layout>`](./docs/api/foundation-layout.foundationlayout.md)
92
+
93
+ Top level web component, which is used to initialise a custom layout
94
+
95
+ - **reload-buffer** : numerical attribute that controls the buffer between how long the layout is reloaded. The default
96
+ is 500ms. In this case, the layout is only reloaded if the child elements of the layout region are manipulated
97
+ once every 500ms. This is to stop the layout being reloaded over and over for every single item during initialisation.
98
+ The higher the value is, the more performant the component is - but the first load will appear to take longer.
99
+
100
+ ::tip
101
+ This only applies for usage with the declarative HTML API. When the layout first loads after this amount of time,
102
+ it emits an [event](#event).
103
+ :::
104
+
105
+ ### [Layout Regions](./docs/api/foundation-layout.foundationlayoutregion.md)
106
+
107
+ If you don't specify the `type` of the layout region, it defaults to `type="horizontal"`;
108
+
109
+ - **type**: `vertical`, `horizontal`, `tabs` (default `horizontal`).
110
+ - **size**: optional string parameter defining size, [see here](#sizing).
111
+
112
+ #### `<foundation-layout-region type="vertical">`
113
+
114
+ Indicates to the layout system that all immediate children are (by default) to be split equally within the available space of this
115
+ component using n-1 column split(s). Can be nested within other horizontal and vertical regions.
116
+
117
+ #### `<foundation-layout-region type="horizontal">`
118
+
119
+ Indicates to the layout system that all immediate children are (by default) to be split equally among the available space of this
120
+ component using n-1 row split(s). Can be nested within other horizontal and vertical regions.
121
+
122
+ #### `<foundation-layout-region type="tabs">`
123
+
124
+ Indicates to the layout system that all immediate children are to be added as tabs in the available space of this component,
125
+ with a tab for each child. The tabs are ordered according to which child the layout item is (e.g. the second `<foundation-layout-item>`
126
+ of the tab split is the second tab). The first child will be the one that is open by default. Can be nested within horizontal
127
+ and vertical regions, but cannot have more layout sections inside it.
128
+
129
+ ### [Layout Item `<foundation-layout-item>`](./docs/api/foundation-layout.foundationlayoutitem.md)
130
+
131
+ Wrapper component that lives inside a layout section and wraps the client content. All content must be inside a layout item,
132
+ otherwise a runtime error will be thrown when the layout attempts to render itself on screen.
133
+
134
+ - **title**: string defining the title of the pane that contains the content. Defaults to `Item x`, where `x` is the pane number.
135
+ - **closable**: boolean defining whether this element is closable - Default false.
136
+ - **size**: optional string parameter defining size, [see here](#sizing).
137
+ - **registration**: optional string, which manually sets the registered name for the pane - [see here](#dynamic-registration-and-adding-items). By default, each item that doesn't have the `registration` attribute set will be a string registered sequentially starting at `"1"`.
138
+
139
+ ### Sizing
140
+
141
+ The layout sections and layout item all have an _optional_ attribute:
142
+
143
+ - **size**: string defining the size. For rows, it specifies height. For columns, it specifies width. Has format `<number><size-unit>`.
144
+ Currently only supports units `fr` and `%`. Space is first proportionally allocated to items with sizeUnit `%`. If there is any space
145
+ left over (less than 100% allocated), then the remainder is allocated to the items with unit `fr` according to the fractional size.
146
+ If more than 100% is allocated, then an extra 50% is allocated to items with unit `fr` and is allocated to each item according to its
147
+ fractional size. All item sizes are then adjusted to bring the total back to 100%.
148
+
149
+ :::info
150
+ The size defines the size of the component _compared_ to the siblings _within_ the context of the component's parent.
151
+ :::
152
+
153
+ ## JavaScript API
154
+
155
+ The JavaScript API is [accessed through the methods on the root layout object](./docs/api/foundation-layout.foundationlayout.md) and allows for saving/loading the layout state, and dynamically adding items to the layout at runtime.
156
+
157
+ ### Dynamic registration and adding items
158
+
159
+ To have a pane displayed on the layout system, it must be *registered* with the layout system. When using the [declarative API](#declarative-html-api), the layout system takes care of this for you, but as you start to add items dynamically and then serialise the layout, you need to consider which panes are registered. See [this contained example](#contained-example), which allows the user to add pre-determined items to the layout dynamically.
160
+
161
+ :::tip
162
+ If you are only using the declarative API, and not using any dynamic integrations with JavaScript, then you shouldn't need to set the registration names of any items, as all the same items will be registered when you load a previously saved layout. If you are dynamically adding items as well, it is highly recommended to set the registration names of items manually. This makes it easier to figure out what is and is not registered.
163
+ * When using the declarative API, use the `registration` attribute on the `<foundation-layout-item>` component.
164
+ * When using the JavaScript API, set the `registration` optional parameter on the [registered element config](./docs/api/foundation-layout.registeredelementconfig.md).
165
+ :::
166
+
167
+ #### [Register Item](./docs/api/foundation-layout.foundationlayout.registeritem.md)
168
+
169
+ This API enables you to register an item at runtime, but it will not be displayed in the layout. This could be used to register components in anticipation of displaying them when loading a serialised layout - [see this example](#loading-serialised-layouts).
170
+
171
+ #### [Add Item](./docs/api/foundation-layout.foundationlayout.additem.md)
172
+
173
+ Add an item that has previously been registered with the layout.
174
+
175
+ #### [Layout Required Registrations](./docs/api/foundation-layout.foundationlayout.layoutrequiredregistrations.md)
176
+
177
+ Static function to read a layout config. It returns a list of all the required registrations required to load it in the layout system. [See this example](#loading-serialised-layouts).
178
+
179
+ #### [Get Current Registrations](./docs/api/foundation-layout.foundationlayout.registereditems.md)
180
+
181
+ Returns a list of all the items currently registered with the layout system.
182
+
183
+ :::tip
184
+ Use this function over `.layoutRequiredRegistrations(layout: SerialisedLayout)` to get the *current* registrations, because that will miss any items that are currently registered with the layout system, but which are not shown on the layout.
185
+ :::
186
+
187
+ ### Serialising layout
188
+
189
+ The JavaScript API can be used to save and load layout states. This only describes the state of the dynamic layout itself. It is the responsibility of any components contained within their layout to serialise their own state, if required.
190
+
191
+ #### [Get Layout](./docs/api/foundation-layout.foundationlayout.getlayout.md)
192
+
193
+ Get an object describing the current layout so that it can be restored at a later date. This does not save any data internally to the layout. It is up to the client to store this state where appropriate for later recall (browser local storage, persistence layer, etc.)
194
+
195
+ #### [Load Layout](./docs/api/foundation-layout.foundationlayout.loadlayout.md)
196
+
197
+ Loads a serialised layout. All items that are described in the config to load must already be registered with the layout system - using either the declarative or JavaScript API. If there are items missing (could be due either to missing items or to a mismatch of registered names) then a `LayoutUsageError` will be thrown containing the names of the missing items.
198
+
199
+ ## Events
200
+
201
+ ### [Emitted Events](./docs/api/foundation-layout.layoutemitevents.md)
202
+
203
+ Certain actions that are performed by the user interacting with the layout emit events. See the API document linked for the events and when they're emitted. Interacting with these events allows your client code to dynamically interact with the layout, such as enabling/disabling buttons to add items to the layout when they're removed/added.
204
+
205
+ ### [Received Events](./docs/api/foundation-layout.layoutreceiveevents.md)
206
+
207
+ Certain events are listened to by the container for each component, enabling the component to interact with the layout. For example, a component could emit an event to change the title of the containing window.
208
+ ```typescript
209
+ this.$emit(eventType, eventDetail)
210
+ ```
211
+ Each event requires a certain detail to process the event - see [the map of events to their required details](./docs/api/foundation-layout.layoutreceiveeventsdetail.md).
212
+
213
+ ## Contained elements
214
+
215
+ This section concerns the behaviour of elements inside the layout. If you are using simple elements or Genesis-supplied elements this section is less of a concern, but if you are building complex custom components yourself, you will need this information.
216
+
217
+ ### Element lifecycle
218
+
219
+ When an item is dragged around the layout, its lifecycle functions `connectedCallback` and `disconnectedCallback` are called.
220
+ It is important that the element accounts for this, such as caching data, or resizing correctly.
221
+
222
+ In the `@genesislcap/foundation-utils` package, there is a mix-in class `LifecycleMixin` which exposes two protected members `shouldRunConnect` and `shouldRunDisconnect`, which can be used to gate certain functionality. For example, if there are parts of `disconnectedCallback` that you don't want to run if the item is being dragged around the layout, you can gate it behind a `(!this.shouldRunDisconnect) return;` early return.
223
+
224
+ :::warning
225
+ At the very least, you must run `super` calls to the lifecycle methods, or else your custom element will not work correctly.
226
+ :::
227
+
228
+ ### Element cloning
229
+
230
+ To enable you to add multiple items from the same `registration`, the layout system clones elements to add to the layout.
231
+ This is the case both when items are added with `.addItem()`, and when they are added using the declarative API. Under the hood, this uses the Node [cloneNode](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode) api.
232
+ There are certain limitations to this function, especially when using custom elements with the shadow DOM. [See troubleshooting example](#binding-events-inline-in-the-declarative-api).
233
+
234
+ In the `@genesislcap/foundation-utils` package, there is a mix-in class `LifecycleMixin` which overrides the `cloneNode` API.
235
+
236
+ ```typescript
237
+ // Make a call to `deepClone` and manually clone children
238
+ override cloneNode(deep?: boolean): Node {
239
+ const thisClone = this.deepClone();
240
+ if (deep) {
241
+ Array.from(this.childNodes).forEach((child) => {
242
+ thisClone.appendChild(child.cloneNode(true));
243
+ });
244
+ }
245
+ return thisClone;
246
+ }
247
+
248
+ // Create a new element of the same name and copy over attributes
249
+ deepClone(): Node {
250
+ const copy = document.createElement(this.tagName.toLowerCase());
251
+ this.getAttributeNames().forEach((at) => copy.setAttribute(at, this.getAttribute(at)));
252
+ return copy;
253
+ }
254
+ ```
255
+
256
+ You can then extend the cloning functionality for your specific requirements. For example, our charts component needs to copy over `config` and `data` parameters.
257
+ ```typescript
258
+ export class G2PlotChart extends LifecycleMixin(FoundationElement) {
259
+ ...
260
+ override deepClone(): Node {
261
+ const copy = super.deepClone() as G2PlotChart;
262
+ copy.config = structuredClone(this.config);
263
+ copy.data = structuredClone(this.data);
264
+ return copy;
265
+ }
266
+ ...
267
+ }
268
+ ```
269
+ Some items you'll probably want to copy over are `eventListeners` and other non-attribute configuration elements on your custom element.
270
+
271
+ ## Examples
272
+
273
+ ### Simple example
274
+
275
+ Simple example with a vertical split and two items that will take up equal space.
276
+
277
+ ```html
278
+ <foundation-layout>
279
+ <foundation-layout-region type="horizontal">
280
+ <foundation-layout-item title="Component 1">
281
+ <!-- Content -->
282
+ </foundation-layout-item>
283
+ <foundation-layout-item title="Component 2">
284
+ <!-- Content -->
285
+ </foundation-layout-item>
286
+ </foundation-layout-region>
287
+ </foundation-layout>
288
+ ```
289
+
290
+ Will be rendered as:
291
+
292
+ ```
293
+ +-----------------------------------------------------+
294
+ | |
295
+ | Component 1 Contents |
296
+ | |
297
+ +-----------------------------------------------------+
298
+ | |
299
+ | Component 2 Contents |
300
+ | |
301
+ +-----------------------------------------------------+
302
+ ```
303
+
304
+ ### Nested example
305
+
306
+ A slightly more complicated example:
307
+
308
+ ```html
309
+ <foundation-layout>
310
+ <foundation-layout-region type="vertical">
311
+ <foundation-layout-item title="Component 1" size="25%" closable>
312
+ <!-- Content -->
313
+ </foundation-layout-item>
314
+
315
+ <foundation-layout-region type="horizontal">
316
+ <foundation-layout-item title="Component 2">
317
+ <!-- Content -->
318
+ </foundation-layout-item>
319
+ <foundation-layout-item title="Component 3">
320
+ <!-- Content -->
321
+ </foundation-layout-item>
322
+ </foundation-layout-region>
323
+ </foundation-layout-region>
324
+
325
+ </foundation-layout>
326
+ ```
327
+
328
+ Would render the following:
329
+
330
+ ```
331
+ +-------------+---------------------------------------+
332
+ | | |
333
+ | | Component 2 Contents |
334
+ | Component | |
335
+ | 1 +---------------------------------------+
336
+ | Contents | |
337
+ | | Component 3 Contents |
338
+ | | |
339
+ +-------------+---------------------------------------+
340
+ ```
341
+
342
+ Component 1 has a Close button. By default, Component 1 would be 50% width and 2 and 3 would take up the other 50% width, but here we set `25%`
343
+ as the width of Component 1 layout item (width because it is the size in the context of a vertical split).
344
+
345
+ ### Multi-nested example
346
+
347
+ If instead we had:
348
+
349
+ ```html
350
+ <foundation-layout>
351
+ <foundation-layout-region type="vertical">
352
+ <foundation-layout-item title="Component 1" size="25%" closable>
353
+ <!-- Content -->
354
+ </foundation-layout-item>
355
+
356
+ <foundation-layout-region type="horizontal">
357
+ <foundation-layout-region type="vertical">
358
+ <foundation-layout-item title="Component 2">
359
+ <!-- Content -->
360
+ </foundation-layout-item>
361
+ <foundation-layout-item title="Component 3">
362
+ <!-- Content -->
363
+ </foundation-layout-item>
364
+ <foundation-layout-item title="Component 4">
365
+ <!-- Content -->
366
+ </foundation-layout-item>
367
+ </foundation-layout-region>
368
+
369
+ <foundation-layout-region type="tabs">
370
+ <foundation-layout-item title="Component 5">
371
+ <!-- Content -->
372
+ </foundation-layout-item>
373
+ <foundation-layout-item title="Component 6">
374
+ <!-- Content -->
375
+ </foundation-layout-item>
376
+ </foundation-layout-region>
377
+ </foundation-layout-region>
378
+ </foundation-layout-region>
379
+
380
+ </foundation-layout>
381
+ ```
382
+
383
+ This would render the following:
384
+
385
+ ```
386
+ +-------------+------------+-------------+------------+
387
+ | | | | |
388
+ | | Comp 2 | Comp 3 | Comp 4 |
389
+ | Component | | | |
390
+ | 1 +------------+-------------+------------+
391
+ | Contents |_5_|_6_| |
392
+ | | Component 5 Contents |
393
+ | | |
394
+ +-------------+---------------------------------------+
395
+ ```
396
+ Component 1 has a Close button. Component 1 takes up 25% of the initial width. Components 2,3,4 take up a third of the _remaining_ width between them
397
+ (default behaviour) and 5 and 6 are tabbed.
398
+
399
+ ### `repeat` directive
400
+
401
+ You can use [FAST template directives](https://www.fast.design/docs/fast-element/using-directives) such as `repeat`
402
+
403
+ ```javascript
404
+ interface Position {
405
+ symbol: string;
406
+ }
407
+
408
+ class Commodities extends FASTElement {
409
+ positions: Position[] // Not @observable - see following section
410
+
411
+ ...
412
+ }
413
+
414
+ const template = html<Commodities>`
415
+ <foundation-layout>
416
+ <foundation-layout-region type="horizontal">
417
+ ${when(x => x.positions, html<Position>`
418
+ <foundation-layout-item title="${x => x.symbol}">
419
+ <chart symbol="${x => x.symbol}"></chart>
420
+ </foundation-layout-item>`)}
421
+ </foundation-layout-region>
422
+ </foundation-layout>`;
423
+ ```
424
+
425
+ For an example where the `Commodities` object has three positions, you will see the following output:
426
+ ```
427
+ +-----------------------------------------------------+
428
+ | Component 1 Contents |
429
+ +-----------------------------------------------------+
430
+ | Component 2 Contents |
431
+ +-----------------------------------------------------+
432
+ | Component 3 Contents |
433
+ +-----------------------------------------------------+
434
+ ```
435
+
436
+
437
+ :::note
438
+ `<chart>` is just an example component; it doesn't exist within `foundation-ui`.
439
+ :::
440
+
441
+ ### `when` directive
442
+
443
+ Using the `when` directive:
444
+
445
+ ```javascript
446
+ @customElement({
447
+ name: 'my-element',
448
+ template,
449
+ })
450
+ class Analytics extends FASTElement {
451
+ showIndexFunds = true; // not @observable
452
+ }
453
+
454
+ var template = html<Analytics>`
455
+ <button class="toggle">Toggle Index</button>
456
+ <foundation-layout>
457
+ <foundation-layout-region>
458
+ <foundation-layout-item>
459
+ <chart type="stocks"></chart>
460
+ </foundation-layout-item>
461
+
462
+ ${when(x => x.showIndexFunds, html`
463
+ <foundation-layout-item>
464
+ <chart type="index-funds"></chart>
465
+ </foundation-layout-item>
466
+ `)}
467
+
468
+ </foundation-layout-region>
469
+ </foundation-layout>
470
+ `;
471
+ ```
472
+
473
+ You would see both items rendered like this:
474
+ ```
475
+ +---------------------------------------------+
476
+ | Stocks Chart |
477
+ +---------------------------------------------+
478
+ | Index Chart |
479
+ +---------------------------------------------+
480
+ ```
481
+
482
+ If you had `showIndexFunds = false;` then only the `Stocks Chart` would be rendered.
483
+
484
+ :::danger
485
+ Directives are for initialising the layout only and should *not* be used with changing `@observable` attributes which would cause the
486
+ layout to reinitialise incorrectly - this will duplicate the panels. For example, you can use the
487
+ `when` directive to conditionally render a pane during initialisation, but not to toggle whether to show/hide the pane afterwards.
488
+ See [this example](#observables-with-directives).
489
+ :::
490
+
491
+ ### Multiple instances
492
+
493
+ Consider the following example:
494
+ ```html
495
+ <div class="container" style="display: grid; grid-template-columns: 1fr; grid-auto-rows: minmax(46vh, auto)">
496
+ <div style="display: block; position: relative;">
497
+ <foundation-layout>
498
+ <foundation-layout-region>
499
+ <foundation-layout-item><h1>Item 1</h1></foundation-layout-item>
500
+ <foundation-layout-item><h1>Item 2</h1></foundation-layout-item>
501
+ </foundation-layout-region>
502
+ </foundation-layout>
503
+ </div>
504
+ <div style="display: block; position: relative;">
505
+ <foundation-layout>
506
+ <foundation-layout-region type="vertical">
507
+ <foundation-layout-item><h1>Item 3</h1></foundation-layout-item>
508
+ <foundation-layout-item><h1>Item 4</h1></foundation-layout-item>
509
+ </foundation-layout-region>
510
+ </foundation-layout>
511
+ </div>
512
+ </div>
513
+ ```
514
+
515
+ This describes the following layout:
516
+ ```
517
+ +---------------------------------------------+
518
+ | Item 1 |
519
+ +---------------------------------------------+
520
+ | Item 2 |
521
+ +---------------------------------------------+
522
+
523
+ +----------------------+----------------------+
524
+ | | |
525
+ | Item 3 | Item 4 |
526
+ | | |
527
+ +----------------------+----------------------+
528
+ ```
529
+ Here a grid region has been used to style two completely separate instances of the dynamic layout. Even though we have named each
530
+ `<h1>` sequentially, the two layouts are completely separate and the default titles of each tab (Item 1 and Item 2 for both layouts),
531
+ will reflect this. You can configure each layout separately, and you cannot drag layout items from one layout into the other one.
532
+
533
+ :::info
534
+ This is just an example; you could have more than two layouts on a page or style them with a different method to the grid.
535
+ :::
536
+
537
+ ### Adding items dynamically
538
+
539
+ This is an example of using the JavaScript API to add items onto the layout at runtime. Before reading this example you should familiarise yourself with the [API Section](#javascript-api).
540
+
541
+ Say you want the user to be able to choose between three different types of item tht can be put onto the layout - a profile-management table, and a pie & column chart.
542
+
543
+ ```typescript
544
+ // Can either create an element and initialise it completely using JavaScript
545
+ const profileManagement = document.createElement('profile-management');
546
+ // Or could grab a reference to one you create via FAST markup
547
+ const pieChart = document.getElementById('pie-chart');
548
+ // In idiomatic FAST we can have a reference using `ref` directive
549
+ // const colChart = this.columnChart;
550
+ ```
551
+
552
+ We can then register these elements with the layout system. Registering it with the layout system removes it from its original location.
553
+ ```typescript
554
+ // Using a duplicate registration name is a runtime error
555
+ this.layout.registerItem('profile', [profileManagement]);
556
+ this.layout.registerItem('pie', [pieChart]);
557
+ this.layout.registerItem('colChart', [this.columnChart]);
558
+ ```
559
+
560
+ Finally, use the `addItem` API to add a pane onto the layout using a previously registered item.
561
+ ```typescript
562
+ this.layout.addItem({
563
+ registration: 'profile',
564
+ name: 'Profile Management',
565
+ closable: true,
566
+ })
567
+ ```
568
+ Using `addItem` with a `registration` that has not been set is a runtime error. Remember `addItem` has an optional second parameter for setting the placement of the new pane.
569
+
570
+ :::tip
571
+ Items registered using the declarative API use the same pool of registration names, so you can also use `addItem` to add them to the layout too.
572
+ :::
573
+
574
+ #### Contained example
575
+
576
+ This is a complete example of the above, omitting imports.
577
+
578
+ ```typescript
579
+ // template
580
+ export const template = html<ContainedExample>`
581
+ <div style="display: grid; grid-template-columns: 1fr; grid-auto-rows: minmax(7vh, auto)">
582
+ <div style="display: block; position: relative;">
583
+ <foundation-button @click=${(x) => x.addItem('1')}>Test 1</foundation-button>
584
+ <foundation-button @click=${(x) => x.addItem('2')}>Test 2</foundation-button>
585
+ <foundation-button @click=${(x) => x.addItem('3')}>Test 3</foundation-button>
586
+ </div>
587
+ <div style="display: block; position: relative; grid-row-start: 2; grid-row-end: 12;">
588
+ <foundation-layout ${ref('containedExampleLayout')}></foundation-layout>
589
+ </div>
590
+ </div>
591
+ `;
592
+
593
+ // class
594
+ @customElement({
595
+ name: 'contained-example',
596
+ template,
597
+ })
598
+ export class ContainedExample extends FASTElement {
599
+ containedExampleLayout: FoundationLayout;
600
+ private _addedPaneCount = 0;
601
+
602
+ connectedCallback(): void {
603
+ super.connectedCallback();
604
+
605
+ const h1 = document.createElement('h1');
606
+ h1.innerHTML = 'Example 1';
607
+ const p1 = document.createElement('p');
608
+ p1.innerHTML = 'Ex 1';
609
+
610
+ const h2 = document.createElement('h2');
611
+ h2.innerHTML = 'Example 2';
612
+ const p2 = document.createElement('p');
613
+ p2.innerHTML = 'Ex 2';
614
+
615
+ const h3 = document.createElement('h3');
616
+ h3.innerHTML = 'Example 3';
617
+ const p3 = document.createElement('p');
618
+ p3.innerHTML = 'Ex 3';
619
+
620
+ this.containedExampleLayout.registerItem('1', [h1, p1]);
621
+ this.containedExampleLayout.registerItem('2', [h2, p2]);
622
+ this.containedExampleLayout.registerItem('3', [h3, p3]);
623
+ }
624
+
625
+ addItem(registration: string) {
626
+ this.containedExampleLayout.addItem({
627
+ registration,
628
+ title: `${registration} (${(this._addedPaneCount += 1)})`,
629
+ closable: true,
630
+ });
631
+ }
632
+ }
633
+ ```
634
+
635
+ ### Loading serialised layouts
636
+
637
+ This is an elaborate example of using the JavaScript API with consideration of the registered names. Before reading this example, you should familiarise yourself with the [API Section](#javascript-api):
638
+
639
+ ```html
640
+ <foundation-layout>
641
+ <foundation-layout-region type="horizontal">
642
+ <foundation-layout-item title="Trades" registration="trades">
643
+ <!-- Content -->
644
+ </foundation-layout-item>
645
+ <foundation-layout-item title="Users" registration="users">
646
+ <!-- Content -->
647
+ </foundation-layout-item>
648
+ </foundation-layout-region>
649
+ </foundation-layout>
650
+ ```
651
+
652
+ We can use `layoutRequiredRegistrations()` on the config returned from `getLayout()` to see the registered names that are required to load the layout.
653
+
654
+ ```javascript
655
+ const layout = document.querySelector('foundation-layout'); // as FoundatonLayout in TypeScript;
656
+ const layoutConfig = layout.getLayout();
657
+ console.log(FoundatonLayout.layoutRequiredRegistrations(layoutConfig))
658
+ ```
659
+ This will log `['trades','users']` because these are the two registered panes. You can then load any layout that only contains either/both of these items.
660
+
661
+ Consider the situation where we dynamically add an item to the right-hand side of the layout.
662
+ ```javascript
663
+ const newItem = document.createElement('p'); //simple example
664
+ newItem.innerText = 'Test';
665
+
666
+ layout.registerItem(test, [newItem]);
667
+ const layoutConfigTwo = layout.getLayout()
668
+ console.log(FoundationLayout.layoutRequiredRegistrations(layoutConfigTwo));
669
+ ```
670
+ Now we get `[ "test", "trades", "users"]` as the output, because to load `layoutConfigTwo` we now need all three of those registered panes.
671
+
672
+ Consider now where the user refreshes the page to go back to the original state of the layout with just the two elements added, but then tries to load:
673
+
674
+ `layoutConfigTwo`:
675
+ ```javascript
676
+ // User has refreshed page
677
+
678
+ console.log(layout.registeredItems());
679
+ // Ouputs ['trades','users']
680
+
681
+ layout.loadLayout(layoutConfigTwo);
682
+ // Uncaught Error: Trying to load layout with extra components. The component(s) not currently loaded are "test"
683
+ ```
684
+ Notice the error message says that the `test` component is missing. This is because it was required as part of the layout when we used `getLayout()`, but it hasn't been added as part of the layout now. If we added the item using `registerItem()` we could subsequently run `layout.loadLayout(layoutConfigTwo);` to load the layout successfully.
685
+
686
+ :::warning
687
+ Just because an item is not displayed on the layout does not mean it is not registered. `.getLayout()` gets only the current layout config, so you cannot use it to see every single item that is currently registered (unless every item is added). This is why you should use `.registeredItems()` to get the currently registered items.
688
+ :::
689
+
690
+ #### Proactively registering items
691
+
692
+ Here is a simple approach to ensure that all items are registered when you load a layout; loop through all the items that you could possibly load and register them.
693
+
694
+ ```javascript
695
+ const allItems = [
696
+ {registration: 'trades', elements: [...], },
697
+ {registration: 'users', elements: [...], },
698
+ {registration: 'profiles', elements: [...], },
699
+ {registration: 'notifications', elements: [...], },
700
+ ];
701
+
702
+ allItems.forEach(({registration, elements}) => {
703
+ layout.registerItem(registration, elements);
704
+ })
705
+ ```
706
+ Now all those items will be registered with the layout for potential use when calling `loadLayout()`, or added using `addItem()`.
707
+
708
+ #### Reactively registering items
709
+
710
+ Alternatively, you could query the current layout and the layout you want to load to see if there are any missing registered items; you can then register the missing ones. Using our previous examples:
711
+
712
+ ```javascript
713
+ const currentRegistrations = FoundatonLayout.registeredItems();
714
+ // ['trades','users']
715
+ const requiredRegistrations = FoundatonLayout.layoutRequiredRegistrations(layoutConfigTwo);
716
+ // ['test','trades','users']
717
+
718
+ // We can see 'test' is missing and therefore we should register it
719
+ layout.registerItem(test, [element]);
720
+ ```
721
+
722
+ :::info
723
+ Only items _missing_ from the `requiredRegistrations` is an issue. If there are items in the `currentRegistrations` that are not in `requiredRegistrations`, this is *not* an issue - because these will simply be unused registrations.
724
+ :::
725
+
726
+ ## Incorrect examples
727
+
728
+ The following section contains examples of incorrect usage, which are useful for troubleshooting.
729
+
730
+ ### Non-layout child
731
+
732
+ The following example is invalid:
733
+
734
+ ```html
735
+ <foundation-layout>
736
+ <foundation-layout-region type="horizontal">
737
+ <h1>My splits</h1>
738
+ <foundation-layout-item title="Component 1">
739
+ <!-- Content -->
740
+ </foundation-layout-item>
741
+ <foundation-layout-item title="Component 2">
742
+ <!-- Content -->
743
+ </foundation-layout-item>
744
+ </foundation-layout-region>
745
+ </foundation-layout>
746
+ ```
747
+ This is because there is a child of one of the layout regions which isn't another layout region or layout item (the `<h1>`). This will throw a runtime error.
748
+
749
+ ### Layout region in tabs
750
+
751
+ The following example is invalid:
752
+
753
+ ```html
754
+ <foundation-layout>
755
+ <foundation-layout-region type="tabs">
756
+
757
+ <foundation-layout-region type="vertical">
758
+ <foundation-layout-item title="Component 1">
759
+ <!-- Content -->
760
+ </foundation-layout-item>
761
+ <foundation-layout-item title="Component 2">
762
+ <!-- Content -->
763
+ </foundation-layout-item>
764
+ </foundation-layout-region>
765
+
766
+ <foundation-layout-item title="Component 3">
767
+ <!-- Content -->
768
+ </foundation-layout-item>
769
+
770
+ </foundation-layout-region>
771
+ </foundation-layout>
772
+ ```
773
+ This is because you cannot have more layout regions nested inside a tab region. You will get undefined behaviour.
774
+
775
+
776
+ ### Multiple items in root
777
+
778
+ The following example is invalid:
779
+
780
+ ```html
781
+ <foundation-layout>
782
+ <foundation-layout-item title="Component 1">
783
+ <!-- Content -->
784
+ </foundation-layout-item>
785
+ <foundation-layout-item title="Component 2">
786
+ <!-- Content -->
787
+ </foundation-layout-item>
788
+ <foundation-layout-item title="Component 3">
789
+ <!-- Content -->
790
+ </foundation-layout-item>
791
+ </foundation-layout>
792
+ ```
793
+ This is because you cannot have multiple layout elements as the immediate child of the layout root. You will get a runtime error.
794
+
795
+ ### Nested item
796
+
797
+ The following example is invalid:
798
+
799
+ ```html
800
+ <foundation-layout>
801
+ <foundation-layout-item title="Component 1">
802
+ <foundation-layout-item title="Component 2">
803
+ <!-- Content -->
804
+ </foundation-layout-item>
805
+ <foundation-layout-item title="Component 3">
806
+ <!-- Content -->
807
+ </foundation-layout-item>
808
+ </foundation-layout-item>
809
+ </foundation-layout>
810
+ ```
811
+ This is because you cannot have `<foundation-layout-item>` inside other `<foundation-layout-item>`. You will get a runtime error.
812
+
813
+ ### Observables with directives
814
+
815
+ The following is invalid:
816
+
817
+ ```javascript
818
+ @customElement({
819
+ name: 'my-element',
820
+ template,
821
+ })
822
+ class Analytics extends FASTElement {
823
+ @observable showIndexFunds = true;
824
+
825
+ toggleShowIndexFunds() {
826
+ this.showIndexFunds = !this.showIndexFunds;
827
+ }
828
+ }
829
+
830
+ var template = html<Analytics>`
831
+ <button
832
+ class="toggle"
833
+ @click=${x => x.toggleShowIndexFunds()}
834
+ >Toggle Index</button>
835
+ <foundation-layout>
836
+ <foundation-layout-region>
837
+ <foundation-layout-item>
838
+ <chart type="stocks"></chart>
839
+ </foundation-layout-item>
840
+
841
+ ${when(x => x.showIndexFunds, html`
842
+ <foundation-layout-item>
843
+ <chart type="index-funds"></chart>
844
+ </foundation-layout-item>
845
+ `)}
846
+
847
+ </foundation-layout-region>
848
+ </foundation-layout>
849
+ `;
850
+ ```
851
+
852
+ Initially you will see both items correctly rendered like this:
853
+ ```
854
+ +---------------------------------------------+
855
+ | Stocks Chart |
856
+ +---------------------------------------------+
857
+ | Index Chart |
858
+ +---------------------------------------------+
859
+ ```
860
+ But as the user clicks the toggle button, the `Index Chart` will not be taken away and added back in.
861
+ Instead, it will be added as a duplicate every time the observable is set true. Additionally, the contents
862
+ of the panel will be wiped as duplicates are added.
863
+
864
+ To work around this, you would use FAST directives inside custom web components inside the layout.
865
+
866
+ ### Binding events inline in the declarative API
867
+ The following example is invalid:
868
+
869
+ ```html
870
+ <foundation-layout>
871
+ <foundation-layout-item>
872
+ <input type="checkbox" @change=${(x,c) => x.doSomething()} />
873
+ </foundation-layout-item>
874
+ </foundation-layout>
875
+ ```
876
+
877
+ Because of a limitation in the [cloneNode() API](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode), event listeners are *not* copied.
878
+ This process is part of the process of adding an item to the layout, using both the declarative HTML and JavaScript APIs. So while you will see
879
+ a checkbox on the screen as part of the layout, the event listener will *not* fire when you `change` the checkbox. This applies to all items and events.
880
+
881
+ The idiomatic FAST way of implementing this event binding is to create a custom element and attach the event internally.
882
+
883
+ ```typescript
884
+ // template
885
+ export const exampleComponentTemplate = html<ExampleComponent>`
886
+ <template>
887
+ <input type="checkbox" ${ref('checkbox')} @change=${(x, c) => x.doSomething()} />
888
+ </template>
889
+ `;
890
+
891
+ // model
892
+ @customElement({
893
+ name: 'example-component',
894
+ template: exampleComponentTemplate,
895
+ })
896
+ export class ExampleComponent extends FASTElement {
897
+ checkbox: Checkbox;
898
+ doSomething() { } // do something important
899
+ }
900
+ ```
901
+
902
+ You can then use the custom component in the layout:
903
+
904
+ ```html
905
+ <foundation-layout>
906
+ <foundation-layout-item>
907
+ <example-component><example-component/>
908
+ </foundation-layout-item>
909
+ </foundation-layout>
910
+ ```
911
+
912
+
913
+
914
+ ## License
915
+
916
+ Note: this project provides front end dependencies and uses licensed components listed in the next section, thus licenses for those components are required during development. Contact [Genesis Global](https://genesis.global/contact-us/) for more details.