Current section

26 Versions

Jump to

Compare versions

21 files changed
+223 additions
-120 deletions
  @@ -2,11 +2,10 @@
2 2
3 3 Build rich, interactive UIs entirely in Elixir using Hologram's declarative component system. Your client-side code is intelligently transpiled to JavaScript, providing modern frontend capabilities without relying on any JavaScript frameworks.
4 4
5 - Website: https://hologram.page/
5 + Website: https://hologram.page
6 6
7 7 ## Sponsors
8 8
9 - ### Early Adopters (monthly tier)
10 9 * Calancea Daniel, [@D4no0](https://github.com/D4no0)
11 10 * Lucas Sifoni, [@Lucassifoni](https://github.com/Lucassifoni)
  @@ -0,0 +1,18 @@
1 + "use strict";
2 +
3 + import Type from "../type.mjs";
4 +
5 + export default class SelectEvent {
6 + static buildOperationParam(event) {
7 + const value = event.target.value.substring(
8 + event.target.selectionStart,
9 + event.target.selectionEnd,
10 + );
11 +
12 + return Type.map([[Type.atom("value"), Type.bitstring(value)]]);
13 + }
14 +
15 + static isEventIgnored(_event) {
16 + return false;
17 + }
18 + }
  @@ -1,17 +1,25 @@
1 1 "use strict";
2 2
3 3 export default class GlobalRegistry {
4 + // Made public to make tests easier
4 5 static rootKey = "hologram";
5 6
7 + static append(key, item) {
8 + const items = $.get(key) || [];
9 + $.set(key, [...items, item]);
10 + }
11 +
6 12 static get(key) {
7 - return globalThis?.[GlobalRegistry.rootKey]?.[key] || null;
13 + return globalThis?.[$.rootKey]?.[key] || null;
8 14 }
9 15
10 16 static set(key, value) {
11 - if (!globalThis[GlobalRegistry.rootKey]) {
12 - globalThis[GlobalRegistry.rootKey] = {};
17 + if (!globalThis[$.rootKey]) {
18 + globalThis[$.rootKey] = {};
13 19 }
14 20
15 - globalThis[GlobalRegistry.rootKey][key] = value;
21 + globalThis[$.rootKey][key] = value;
16 22 }
17 23 }
24 +
25 + const $ = GlobalRegistry;
  @@ -25,6 +25,7 @@ import ChangeEvent from "./events/change_event.mjs";
25 25 import FocusEvent from "./events/focus_event.mjs";
26 26 import MouseEvent from "./events/mouse_event.mjs";
27 27 import PointerEvent from "./events/pointer_event.mjs";
28 + import SelectEvent from "./events/select_event.mjs";
28 29 import SubmitEvent from "./events/submit_event.mjs";
29 30 import TransitionEvent from "./events/transition_event.mjs";
30 31
  @@ -37,15 +38,7 @@ import ManuallyPortedElixirIO from "./elixir/io.mjs";
37 38 import ManuallyPortedElixirKernel from "./elixir/kernel.mjs";
38 39 import ManuallyPortedElixirString from "./elixir/string.mjs";
39 40
40 - import {
41 - attributesModule,
42 - eventListenersModule,
43 - init,
44 - toVNode,
45 - vnode,
46 - } from "snabbdom";
47 -
48 - const patch = init([attributesModule, eventListenersModule]);
41 + import {toVNode} from "snabbdom";
49 42
50 43 // TODO: test
51 44 export default class Hologram {
  @@ -161,8 +154,7 @@ export default class Hologram {
161 154
162 155 Hologram.executeAction(nextAction);
163 156 } else {
164 - // TODO: consider: remove when there is a proper client-side bitstring implementation in place
165 - window.requestAnimationFrame(() => Hologram.render());
157 + Hologram.render();
166 158 }
167 159
168 160 if (!Type.isNil(nextPage)) {
  @@ -303,6 +295,7 @@ export default class Hologram {
303 295 window.requestAnimationFrame(() => {
304 296 Hologram.#patchPage(html);
305 297 window.scrollTo(0, 0);
298 +
306 299 history.pushState($.#historyId, null, pagePath);
307 300 });
308 301 }
  @@ -316,7 +309,7 @@ export default class Hologram {
316 309 Hologram.#pageParams,
317 310 );
318 311
319 - Hologram.virtualDocument = patch(
312 + Hologram.virtualDocument = Vdom.patchVirtualDocument(
320 313 Hologram.virtualDocument,
321 314 newVirtualDocument,
322 315 );
  @@ -495,6 +488,9 @@ export default class Hologram {
495 488 case "pointerup":
496 489 return PointerEvent;
497 490
491 + case "select":
492 + return SelectEvent;
493 +
498 494 case "submit":
499 495 return SubmitEvent;
500 496
  @@ -689,47 +685,9 @@ export default class Hologram {
689 685
690 686 const newVirtualDocument = Vdom.from(html);
691 687
692 - // First patch the root html element itself to handle its attributes
693 - Hologram.virtualDocument = patch(
688 + Hologram.virtualDocument = Vdom.patchVirtualDocument(
694 689 Hologram.virtualDocument,
695 - vnode(
696 - "html",
697 - {attrs: newVirtualDocument.data.attrs || {}},
698 - Hologram.virtualDocument.children,
699 - ),
700 - );
701 -
702 - // Then patch head and body separately to preserve JavaScript/CSS handling
703 -
704 - const oldHead = Hologram.virtualDocument.children.find(
705 - (child) => child.sel === "head",
706 - );
707 -
708 - const newHead = newVirtualDocument.children.find(
709 - (child) => child.sel === "head",
710 - );
711 -
712 - const oldBody = Hologram.virtualDocument.children.find(
713 - (child) => child.sel === "body",
714 - );
715 -
716 - const newBody = newVirtualDocument.children.find(
717 - (child) => child.sel === "body",
718 - );
719 -
720 - Hologram.virtualDocument.children = Hologram.virtualDocument.children.map(
721 - (child) => {
722 - switch (child.sel) {
723 - case "body":
724 - return patch(oldBody, newBody);
725 -
726 - case "head":
727 - return patch(oldHead, newHead);
728 -
729 - default:
730 - return child;
731 - }
732 - },
690 + newVirtualDocument,
733 691 );
734 692 }
  @@ -114,7 +114,7 @@ export default class Interpreter {
114 114 return `function ${moduleName}.${functionName}/${arity} is undefined or private`;
115 115 }
116 116
117 - return `function ${moduleName}.${functionName}/${arity} is undefined (module ${moduleName} is not available)`;
117 + return `function ${moduleName}.${functionName}/${arity} is undefined (module ${moduleName} is not available). Make sure the module name is correct and has been specified in full (or that an alias has been defined)`;
118 118 }
119 119
120 120 // callAnonymousFunction() has no unit tests in interpreter_test.mjs, only:
Loading more files…