Skip to content

Commit a3c3f28

Browse files
authored
Merge pull request #1 from NuiCpp/feat/standalone-elements
Feat/standalone elements
2 parents f3523f3 + a618d68 commit a3c3f28

File tree

6 files changed

+109
-6
lines changed

6 files changed

+109
-6
lines changed

docs/bundling/general.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,15 +206,19 @@ int main(int, char** argv)
206206
}
207207
```
208208
209+
:::tip
210+
On windows, use `app.example` as host name for custom scheme urls, because its excluded from the DNS resolver, avoiding a 2 second delay.
211+
:::
212+
209213
In the frontend you can then use the custom scheme:
210214
```css
211215
.foo {
212-
background: url(nui://any_virtual_host_here/background.png);
216+
background: url(nui://app.example/background.png);
213217
}
214218
```
215219

216220
```javascript
217-
import EditorWorker from 'url:nui://host/monaco-editor/esm/vs/editor/editor.worker.js';
221+
import EditorWorker from 'url:nui://app.example/monaco-editor/esm/vs/editor/editor.worker.js';
218222
```
219223

220224
### Virtual Host Name to Folder Mapping

docs/reference/standalone_element.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Standalone Element
2+
3+
A standalone element is an element that is not part of the Nui::Dom.
4+
These elements can be used to pass them to javascript libraries expecting HTML elements.
5+
6+
```cpp
7+
#include <nui/frontend/elements.hpp>
8+
#include <nui/frontend/attributes.hpp>
9+
#include <nui/frontend/dom/element.hpp>
10+
11+
struct MyComponent::Implementation
12+
{
13+
std::shared_ptr<Nui::Dom::Element> element{};
14+
};
15+
16+
Nui::ElementRenderer MyComponent::render()
17+
{
18+
using namespace Nui::Elements;
19+
using namespace Nui::Attributes;
20+
21+
return div{
22+
id = "my-component",
23+
!reference.onMaterialize([this](Nui::val const& element){
24+
// Create a standalone element
25+
impl_->element = Nui::Dom::makeStandaloneElement(div{}("Hello World!"));
26+
27+
Nui::val::global("assignElementToJavascriptFramework")(element->val());
28+
})
29+
}();
30+
}
31+
```

docs/tutorials/attributes.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,4 +248,20 @@ const auto ui = input{
248248
// will not be set at all if maybeAString is nullopt:
249249
value = maybeAString
250250
};
251-
```
251+
```
252+
253+
## Delayed Attributes
254+
Sometimes you want to set an attribute after the element is inserted into the DOM.
255+
This can be done with the exclamation mark:
256+
```cpp
257+
using namespace Nui::Elements;
258+
using namespace Nui::Attributes;
259+
using Nui::Elements::div;
260+
261+
const auto d = div{
262+
!reference = [](Nui::val elem){
263+
// elem satisfies isConnected here https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected
264+
}
265+
}();
266+
```
267+

docs/tutorials/observed_rendering.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,36 @@ Nui::Observed<int> number{0};
1212

1313
const auto ui = div{}(
1414
observe(str, number),
15-
// This function is recalled and regenerates its respective elements,
15+
// This function is recalled and regenerates its respective elements,
1616
// when 'str' or 'number' changes.
17-
[&str, &number](){
17+
[&str, &number]() -> Nui::ElementRenderer {
1818
const auto result = *str + std::to_string(*number);
1919
return span{}(result);
2020
}
2121
)
22+
```
23+
24+
## shared_ptr of Observed
25+
26+
Sometimes Observed may expire while the element affected by it is still part of the DOM.
27+
Nui can use weak_ptrs to avoid dangling pointers to expired Observed.
28+
```cpp
29+
#include <nui/frontend.hpp>
30+
31+
/*...*/
32+
33+
std::shared_ptr<Nui::Observed<std::string>> str = std::make_shared<Nui::Observed<std::string>>("test");
34+
35+
const auto ui = div{}(
36+
observe(str),
37+
// This function is recalled and regenerates its respective elements,
38+
// when 'str' changes. Unless str is expired.
39+
[weak = std::weak_ptr{str}]() -> Nui::ElementRenderer {
40+
if (auto str = weak.lock(); str)
41+
{
42+
return span{}(str->value());
43+
}
44+
return Nui::nil();
45+
}
46+
)
2247
```

docs/tutorials/range_rendering.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ auto foo() {
6363
std::transform(proxy->begin(), proxy->end(), proxy->begin(), [](int elem){
6464
return elem * 2;
6565
});
66+
67+
// You can also work directly on the value and call modify later:
68+
auto& value = numbers.value();
69+
std::transform(value.begin(), value.end(), value.begin(), [](int elem){
70+
return elem * 2;
71+
});
72+
73+
// modifyNow also calls the eventContext executeActiveEventsImmendiately.
74+
// This is not necessary from event attributes, because its called at the end anyway.
75+
numbers.modifyNow();
6676
}
6777
}()
6878
);
@@ -122,4 +132,16 @@ auto foo() {
122132
}
123133
)
124134
}
125-
```
135+
```
136+
137+
## Notes about the Optimization
138+
The ranges optimization that is applied to Observed<std::vector> and Observed<std::deque> makes it so that only the changed/inserted elements are rerendered and only erased elements are removed and nothing else is rerendered.
139+
This is done by tracking the changes using some algorithms on an interval tree.
140+
141+
Insertions, modifications and erasures are only ever tracked alone, so if you switch from inserting elements to modifying elements a rerender is forced.
142+
If you erase something after modifying, all erased elements that were previously modified will not be rerendered only if the erasure happens at the end.
143+
If you erase something after inserting, all erased elements that were previously inserted will not be rerendered only if the erasure happens at the end.
144+
145+
All wisdoms about modifying a vector apply to these optimizations. It is optimal to only ever add or erase from the end of the vector.
146+
The most detrimental thing you can do is inserting at every odd position or erasing at every odd position, this will defeat the optimization and it will
147+
be much better to just rerender the entire range.

sidebars.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ const sidebars = {
210210
type: 'doc',
211211
id: 'reference/text',
212212
label: 'Plain Text Nodes',
213+
},
214+
{
215+
type: 'doc',
216+
id: 'reference/standalone_element',
217+
label: 'Standalone Element',
213218
}
214219
]
215220
},

0 commit comments

Comments
 (0)