@adaas/are-html 0.0.12 → 0.0.14

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 (108) hide show
  1. package/dist/browser/index.d.mts +19 -4
  2. package/dist/browser/index.mjs +114 -7
  3. package/dist/browser/index.mjs.map +1 -1
  4. package/dist/node/{AreBinding.attribute-C6JasbJL.d.ts → AreBinding.attribute-Bm5LlOyE.d.ts} +7 -0
  5. package/dist/node/{AreBinding.attribute-C6qrxN8K.d.mts → AreBinding.attribute-doUvtOjc.d.mts} +7 -0
  6. package/dist/node/attributes/AreBinding.attribute.d.mts +1 -1
  7. package/dist/node/attributes/AreBinding.attribute.d.ts +1 -1
  8. package/dist/node/attributes/AreDirective.attribute.d.mts +1 -1
  9. package/dist/node/attributes/AreDirective.attribute.d.ts +1 -1
  10. package/dist/node/attributes/AreEvent.attribute.d.mts +1 -1
  11. package/dist/node/attributes/AreEvent.attribute.d.ts +1 -1
  12. package/dist/node/attributes/AreStatic.attribute.d.mts +1 -1
  13. package/dist/node/attributes/AreStatic.attribute.d.ts +1 -1
  14. package/dist/node/directives/AreDirectiveFor.directive.d.mts +1 -1
  15. package/dist/node/directives/AreDirectiveFor.directive.d.ts +1 -1
  16. package/dist/node/directives/AreDirectiveIf.directive.d.mts +1 -1
  17. package/dist/node/directives/AreDirectiveIf.directive.d.ts +1 -1
  18. package/dist/node/engine/AreHTML.compiler.d.mts +8 -1
  19. package/dist/node/engine/AreHTML.compiler.d.ts +8 -1
  20. package/dist/node/engine/AreHTML.compiler.js +17 -0
  21. package/dist/node/engine/AreHTML.compiler.js.map +1 -1
  22. package/dist/node/engine/AreHTML.compiler.mjs +17 -0
  23. package/dist/node/engine/AreHTML.compiler.mjs.map +1 -1
  24. package/dist/node/engine/AreHTML.context.js +2 -2
  25. package/dist/node/engine/AreHTML.context.js.map +1 -1
  26. package/dist/node/engine/AreHTML.context.mjs +3 -3
  27. package/dist/node/engine/AreHTML.context.mjs.map +1 -1
  28. package/dist/node/engine/AreHTML.interpreter.d.mts +3 -0
  29. package/dist/node/engine/AreHTML.interpreter.d.ts +3 -0
  30. package/dist/node/engine/AreHTML.interpreter.js +44 -0
  31. package/dist/node/engine/AreHTML.interpreter.js.map +1 -1
  32. package/dist/node/engine/AreHTML.interpreter.mjs +44 -0
  33. package/dist/node/engine/AreHTML.interpreter.mjs.map +1 -1
  34. package/dist/node/engine/AreHTML.lifecycle.d.mts +2 -1
  35. package/dist/node/engine/AreHTML.lifecycle.d.ts +2 -1
  36. package/dist/node/engine/AreHTML.lifecycle.js +13 -1
  37. package/dist/node/engine/AreHTML.lifecycle.js.map +1 -1
  38. package/dist/node/engine/AreHTML.lifecycle.mjs +13 -1
  39. package/dist/node/engine/AreHTML.lifecycle.mjs.map +1 -1
  40. package/dist/node/engine/AreHTML.tokenizer.d.mts +1 -1
  41. package/dist/node/engine/AreHTML.tokenizer.d.ts +1 -1
  42. package/dist/node/engine/AreHTML.transformer.d.mts +1 -1
  43. package/dist/node/engine/AreHTML.transformer.d.ts +1 -1
  44. package/dist/node/index.d.mts +1 -1
  45. package/dist/node/index.d.ts +1 -1
  46. package/dist/node/instructions/AreHTML.instructions.types.d.mts +2 -4
  47. package/dist/node/instructions/AreHTML.instructions.types.d.ts +2 -4
  48. package/dist/node/lib/AreDirective/AreDirective.component.d.mts +1 -1
  49. package/dist/node/lib/AreDirective/AreDirective.component.d.ts +1 -1
  50. package/dist/node/lib/AreDirective/AreDirective.types.d.mts +1 -1
  51. package/dist/node/lib/AreDirective/AreDirective.types.d.ts +1 -1
  52. package/dist/node/lib/AreHTML/AreHTML.tokenizer.d.mts +1 -1
  53. package/dist/node/lib/AreHTML/AreHTML.tokenizer.d.ts +1 -1
  54. package/dist/node/lib/AreHTMLAttribute/AreHTML.attribute.d.mts +1 -1
  55. package/dist/node/lib/AreHTMLAttribute/AreHTML.attribute.d.ts +1 -1
  56. package/dist/node/lib/AreHTMLNode/AreHTMLNode.d.mts +1 -1
  57. package/dist/node/lib/AreHTMLNode/AreHTMLNode.d.ts +1 -1
  58. package/dist/node/lib/AreHTMLNode/AreHTMLNode.js +14 -0
  59. package/dist/node/lib/AreHTMLNode/AreHTMLNode.js.map +1 -1
  60. package/dist/node/lib/AreHTMLNode/AreHTMLNode.mjs +14 -0
  61. package/dist/node/lib/AreHTMLNode/AreHTMLNode.mjs.map +1 -1
  62. package/dist/node/lib/AreRoot/AreRoot.component.js +26 -3
  63. package/dist/node/lib/AreRoot/AreRoot.component.js.map +1 -1
  64. package/dist/node/lib/AreRoot/AreRoot.component.mjs +26 -3
  65. package/dist/node/lib/AreRoot/AreRoot.component.mjs.map +1 -1
  66. package/dist/node/nodes/AreComment.d.mts +1 -1
  67. package/dist/node/nodes/AreComment.d.ts +1 -1
  68. package/dist/node/nodes/AreComponent.d.mts +1 -1
  69. package/dist/node/nodes/AreComponent.d.ts +1 -1
  70. package/dist/node/nodes/AreInterpolation.d.mts +1 -1
  71. package/dist/node/nodes/AreInterpolation.d.ts +1 -1
  72. package/dist/node/nodes/AreRoot.d.mts +1 -1
  73. package/dist/node/nodes/AreRoot.d.ts +1 -1
  74. package/dist/node/nodes/AreText.d.mts +1 -1
  75. package/dist/node/nodes/AreText.d.ts +1 -1
  76. package/examples/component-styles/concept.ts +41 -0
  77. package/examples/component-styles/containers/UI.container.ts +122 -0
  78. package/examples/component-styles/dist/index.html +25 -0
  79. package/examples/{jumpstart/dist/mor90p6y-0plg7g.js → component-styles/dist/mpq29j47-owas2v.js} +8326 -5942
  80. package/examples/component-styles/public/index.html +25 -0
  81. package/examples/component-styles/src/components/AppPage.component.ts +74 -0
  82. package/examples/component-styles/src/components/TheAlert.component.ts +81 -0
  83. package/examples/component-styles/src/components/TheButton.component.ts +71 -0
  84. package/examples/component-styles/src/components/TheCard.component.ts +64 -0
  85. package/examples/component-styles/src/concept.ts +70 -0
  86. package/examples/dashboard/dist/index.html +1 -1
  87. package/examples/dashboard/dist/{mpmt0gys-1r9rcu.js → mppzjw80-9gwa4h.js} +1223 -863
  88. package/examples/jumpstart/dist/index.html +1 -1
  89. package/examples/jumpstart/dist/{mor90p7p-1898bz.js → mppwx932-xbmb0x.js} +4215 -1984
  90. package/examples/signal-routing/concept.ts +41 -0
  91. package/examples/signal-routing/containers/UI.container.ts +126 -0
  92. package/examples/signal-routing/dist/index.html +18 -0
  93. package/examples/signal-routing/dist/mpq6u1wz-2pkqe2.js +14002 -0
  94. package/examples/signal-routing/public/index.html +18 -0
  95. package/examples/signal-routing/src/components/AboutPage.component.ts +74 -0
  96. package/examples/signal-routing/src/components/AppShell.component.ts +42 -0
  97. package/examples/signal-routing/src/components/HomePage.component.ts +76 -0
  98. package/examples/signal-routing/src/components/NavBar.component.ts +104 -0
  99. package/examples/signal-routing/src/components/SettingsPage.component.ts +98 -0
  100. package/examples/signal-routing/src/concept.ts +114 -0
  101. package/package.json +7 -5
  102. package/src/engine/AreHTML.compiler.ts +24 -7
  103. package/src/engine/AreHTML.context.ts +6 -4
  104. package/src/engine/AreHTML.interpreter.ts +54 -0
  105. package/src/engine/AreHTML.lifecycle.ts +16 -12
  106. package/src/instructions/AreHTML.instructions.types.ts +2 -4
  107. package/src/lib/AreHTMLNode/AreHTMLNode.ts +15 -0
  108. package/src/lib/AreRoot/AreRoot.component.ts +47 -7
@@ -14,6 +14,7 @@ import { AddCommentInstruction } from "@adaas/are-html/instructions/AddComment.i
14
14
  import { AddElementInstruction } from "@adaas/are-html/instructions/AddElement.instruction";
15
15
  import { AddListenerInstruction } from "@adaas/are-html/instructions/AddListener.instruction";
16
16
  import { AddTextInstruction } from "@adaas/are-html/instructions/AddText.instruction";
17
+ import { AddStyleInstruction } from "@adaas/are-html/instructions/AddStyle.instruction";
17
18
  import { AreDirectiveContext } from "@adaas/are-html/directive/AreDirective.context";
18
19
  import { AreHTMLNode } from "../lib/AreHTMLNode/AreHTMLNode";
19
20
  import { AreHTMLEngineContext } from "./AreHTML.context";
@@ -620,6 +621,59 @@ export class AreHTMLInterpreter extends AreInterpreter {
620
621
  context.removeInstructionElement(declaration);
621
622
  }
622
623
 
624
+ // ─────────────────────────────────────────────────────────────────────────────
625
+ // ── AddStyle — Apply / Update / Revert ───────────────────────────────────────
626
+ // ─────────────────────────────────────────────────────────────────────────────
627
+
628
+ @A_Frame.Define({
629
+ description: 'Inject a <style> element into the document <head> carrying the component CSS. Keyed by instruction ASEID so multiple components with styles do not collide. Subsequent Update calls refresh the textContent in-place.'
630
+ })
631
+ @AreInterpreter.Apply(AreHTMLInstructions.AddStyle)
632
+ @AreInterpreter.Update(AreHTMLInstructions.AddStyle)
633
+ addStyle(
634
+ @A_Inject(A_Caller) mutation: AddStyleInstruction,
635
+ @A_Inject(AreHTMLEngineContext) context: AreHTMLEngineContext,
636
+ @A_Inject(A_Logger) logger?: A_Logger,
637
+ ): void {
638
+ try {
639
+
640
+
641
+ const { styles } = mutation.payload;
642
+ const styleId = `are-style-${String(mutation.aseid)}`;
643
+
644
+ const existing = context.getElementByInstruction(mutation) as HTMLStyleElement | undefined;
645
+ if (existing) {
646
+ existing.textContent = styles;
647
+ } else {
648
+ const styleEl = context.container.createElement('style') as HTMLStyleElement;
649
+ styleEl.setAttribute('data-are-id', styleId);
650
+ styleEl.textContent = styles;
651
+ (context.container.head ?? context.container.body).appendChild(styleEl);
652
+
653
+ context.setInstructionElement(mutation, styleEl);
654
+ logger?.debug('green', `Style injected for ${String(mutation.aseid)}`);
655
+ }
656
+ } catch (error) {
657
+ logger?.error(error);
658
+ }
659
+
660
+ }
661
+
662
+ @A_Frame.Define({
663
+ description: 'Remove the <style> element that was injected by addStyle, cleaning up the document head.'
664
+ })
665
+ @AreInterpreter.Revert(AreHTMLInstructions.AddStyle)
666
+ removeStyle(
667
+ @A_Inject(A_Caller) mutation: AddStyleInstruction,
668
+ @A_Inject(AreHTMLEngineContext) context: AreHTMLEngineContext,
669
+ ): void {
670
+ const styleEl = context.getElementByInstruction(mutation);
671
+ if (styleEl?.parentNode) {
672
+ styleEl.parentNode.removeChild(styleEl);
673
+ }
674
+ context.removeInstructionElement(mutation);
675
+ }
676
+
623
677
  // ─────────────────────────────────────────────────────────────────────────────
624
678
  // ── SVG helpers ───────────────────────────────────────────────────────────────
625
679
  // ─────────────────────────────────────────────────────────────────────────────
@@ -19,7 +19,6 @@ import { A_Frame } from "@adaas/a-frame/core";
19
19
  export class AreHTMLLifecycle extends AreLifecycle {
20
20
 
21
21
  @AreLifecycle.Init(AreComponentNode)
22
- @AreLifecycle.Init(AreRootNode)
23
22
  initComponent(
24
23
  @A_Inject(A_Caller) node: AreHTMLNode,
25
24
  @A_Inject(A_Scope) scope: A_Scope,
@@ -28,21 +27,26 @@ export class AreHTMLLifecycle extends AreLifecycle {
28
27
  @A_Inject(A_Logger) logger?: A_Logger,
29
28
  ...args: any[]
30
29
  ): void {
31
- signalsContext?.subscribe(node);
30
+
31
+ if (node.component)
32
+ signalsContext?.subscribe(node);
33
+
32
34
  super.init(node, scope, context, logger, ...args);
33
35
  }
34
36
 
35
37
 
36
- // initRoot(
37
- // @A_Inject(A_Caller) node: AreHTMLNode,
38
- // @A_Inject(A_Scope) scope: A_Scope,
39
- // @A_Inject(AreHTMLEngineContext) context: AreHTMLEngineContext,
40
- // @A_Inject(AreSignalsContext) signalsContext?: AreSignalsContext,
41
- // @A_Inject(A_Logger) logger?: A_Logger,
42
- // ...args: any[]
43
- // ): void {
44
- // super.init(node, scope, context, logger, ...args);
45
- // }
38
+ @AreLifecycle.Init(AreRootNode)
39
+ initRoot(
40
+ @A_Inject(A_Caller) node: AreHTMLNode,
41
+ @A_Inject(A_Scope) scope: A_Scope,
42
+ @A_Inject(AreHTMLEngineContext) context: AreHTMLEngineContext,
43
+ @A_Inject(AreSignalsContext) signalsContext?: AreSignalsContext,
44
+ @A_Inject(A_Logger) logger?: A_Logger,
45
+ ...args: any[]
46
+ ): void {
47
+ signalsContext?.subscribe(node);
48
+ super.init(node, scope, context, logger, ...args);
49
+ }
46
50
 
47
51
 
48
52
  @AreLifecycle.Init(AreText)
@@ -30,10 +30,8 @@ export type AreHtmlAddCommentInstructionPayload = {
30
30
  }
31
31
 
32
32
  export type AreHtmlAddStyleInstructionPayload = {
33
- /** CSS property name in camelCase (e.g. "backgroundColor") or kebab-case (e.g. "background-color") */
34
- property: string;
35
- /** CSS property value */
36
- value: string;
33
+ /** Full CSS string to inject as a <style> block scoped to the component. Applied to the document head and reverted on unmount. */
34
+ styles: string;
37
35
  }
38
36
 
39
37
  export type AreHtmlAddListenerInstructionPayload = {
@@ -80,4 +80,19 @@ export class AreHTMLNode extends AreNode {
80
80
  return this.scope.resolveFlat<AreStyle>(AreStyle)!;
81
81
  }
82
82
 
83
+ /**
84
+ * Registers or updates the component-scoped CSS string for this node.
85
+ * Called by the @Are.Styles-decorated method on the associated component.
86
+ * A new AreStyle fragment is registered in scope on first call; subsequent
87
+ * calls update the existing fragment in-place.
88
+ */
89
+ setStyles(css: string): void {
90
+ const existing = this.scope.resolveFlat<AreStyle>(AreStyle);
91
+ if (existing) {
92
+ existing.styles = css;
93
+ } else {
94
+ this.scope.register(new AreStyle(css, this.aseid.toString()));
95
+ }
96
+ }
97
+
83
98
  }
@@ -2,7 +2,8 @@ import { A_Caller, A_Context, A_FormatterHelper, A_Inject, } from "@adaas/a-conc
2
2
  import { A_Frame } from "@adaas/a-frame/core";
3
3
  import { A_Logger } from "@adaas/a-utils/a-logger";
4
4
  import { A_SignalVector } from "@adaas/a-utils/a-signal";
5
- import { Are, ArePropDefinition, AreStore, AreNode, AreSignals, AreSignalsMeta, AreSignalsContext, AreRoute } from "@adaas/are";
5
+ import { Are, ArePropDefinition, AreStore, AreNode, AreSignals, AreSignalsMeta, AreSignalsContext } from "@adaas/are";
6
+ import { AreRoute } from "@adaas/are-html/signals/AreRoute.signal";
6
7
 
7
8
 
8
9
  @A_Frame.Define({
@@ -28,8 +29,18 @@ export class AreRoot extends Are {
28
29
 
29
30
  const rootId = root.id;
30
31
 
31
- // No routing config for this root — leave the existing template content intact
32
+ // No routing config for this root — but still honour body content or
33
+ // a 'default' attribute if one is present on the markup.
32
34
  if (signalsContext && !signalsContext.hasRoot(rootId)) {
35
+ if (!root.content?.trim()) {
36
+ // Fallback: legacy default= attribute
37
+ const defaultMatch = root.markup?.match(/\bdefault=["']([^"']*)["']/);
38
+ const defaultComponent = defaultMatch?.[1];
39
+ if (defaultComponent) {
40
+ root.setContent(`<${defaultComponent}></${defaultComponent}>`);
41
+ }
42
+ }
43
+ // Body content (or none) — tokenizer picks it up without intervention
33
44
  return;
34
45
  }
35
46
 
@@ -54,16 +65,29 @@ export class AreRoot extends Are {
54
65
  }
55
66
  }
56
67
 
57
- // 3. Fall back to the 'default' attribute on the node directly.
58
- // Note: root.attributes is NOT populated at this stage because tokenize()
59
- // runs after template() in the lifecycle. Read from raw markup instead.
68
+ // 3. Fall back to body content (the nodes already placed inside the
69
+ // <are-root> tag act as the default). No setContent() call needed —
70
+ // the tokenizer will process root.content as-is.
71
+ if (!componentName) {
72
+ if (root.content?.trim()) {
73
+ return;
74
+ }
75
+ }
76
+ // 3.5. Fall back to AreSignalsContext default component for this root.
77
+ if (!componentName) {
78
+ const defaultComp = signalsContext?.getDefault(rootId);
79
+ if (defaultComp?.name) {
80
+ componentName = A_FormatterHelper.toKebabCase(defaultComp.name);
81
+ }
82
+ }
83
+ // 4. Last resort: legacy default= attribute on the markup.
60
84
  if (!componentName) {
61
85
  const defaultMatch = root.markup?.match(/\bdefault=["']([^"']*)["']/);
62
86
  componentName = defaultMatch?.[1];
63
87
  }
64
88
 
65
89
  if (!componentName) {
66
- logger.warning('AreRoot: No component found for initial render. Please ensure a route condition or "default" attribute is set.');
90
+ logger.warning('AreRoot: No component found for initial render. Provide body content, a route condition, or a "default" attribute.');
67
91
  return;
68
92
  }
69
93
 
@@ -80,6 +104,7 @@ export class AreRoot extends Are {
80
104
  @A_Inject(AreSignalsContext) signalsContext?: AreSignalsContext,
81
105
  ) {
82
106
  const rootId = root.id;
107
+
83
108
  // No routing config for this root — signals do not affect its content
84
109
  if (signalsContext && !signalsContext.hasRoot(rootId)) {
85
110
  return;
@@ -98,15 +123,30 @@ export class AreRoot extends Are {
98
123
  ? A_FormatterHelper.toKebabCase(renderTarget.name)
99
124
  : store.get('default');
100
125
 
126
+ // No matching condition for this signal vector (e.g. AreInit before any route).
127
+ // Keep the current outlet content and do nothing.
101
128
  if (!componentName) {
102
- logger.warning('No component found for rendering in AreRoot. Please ensure that the signal vector matches at least one component or that a default component name is provided in the store.');
129
+ return;
130
+ }
131
+
132
+ // Guard: if the outlet already shows the same component, do nothing.
133
+ // Prevents infinite remount loops when a non-routing signal carries a
134
+ // stale routing signal in the accumulated A_SignalState vector.
135
+ // node.type is the kebab-case tag name — the most direct and reliable
136
+ // identifier (no constructor-name resolution, no proxy wrapping issues).
137
+ const currentChild = root.children[0] as AreNode | undefined;
138
+ if (currentChild?.type === componentName) {
103
139
  return;
104
140
  }
105
141
 
106
142
  root.setContent(`<${componentName}></${componentName}>`);
107
143
 
144
+ // Unsubscribe old children BEFORE destroying them.
145
+ // Without this, AreSignals.handleSignalVector keeps iterating stale
146
+ // (scope-less) nodes on every subsequent signal and throws an error.
108
147
  for (let i = 0; i < root.children.length; i++) {
109
148
  const child = root.children[i];
149
+ signalsContext?.unsubscribe(child);
110
150
  child.unmount();
111
151
  child.destroy();
112
152
  root.removeChild(child);