lego-dom 0.0.8 → 1.0.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 (175) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +49 -432
  3. package/cdn.html +124 -0
  4. package/docs/.vitepress/config.js +43 -5
  5. package/docs/api/directives.md +3 -3
  6. package/docs/api/globals.md +1 -1
  7. package/docs/api/index.md +3 -3
  8. package/docs/api/vite-plugin.md +1 -1
  9. package/docs/contributing/01-welcome.md +36 -0
  10. package/docs/contributing/02-registry.md +99 -0
  11. package/docs/contributing/03-batcher.md +110 -0
  12. package/docs/contributing/04-reactivity.md +87 -0
  13. package/docs/contributing/05-caching.md +59 -0
  14. package/docs/contributing/06-init.md +125 -0
  15. package/docs/contributing/07-observer.md +69 -0
  16. package/docs/contributing/08-snap.md +126 -0
  17. package/docs/contributing/09-diffing.md +69 -0
  18. package/docs/contributing/10-studs.md +76 -0
  19. package/docs/contributing/11-scanner.md +104 -0
  20. package/docs/contributing/12-render.md +116 -0
  21. package/docs/contributing/13-directives.md +225 -0
  22. package/docs/contributing/14-events.md +57 -0
  23. package/docs/contributing/15-router.md +9 -0
  24. package/docs/contributing/16-state.md +48 -0
  25. package/docs/contributing/17-legodom.md +55 -0
  26. package/docs/contributing/index.md +5 -0
  27. package/docs/examples/form.md +2 -2
  28. package/docs/examples/index.md +4 -4
  29. package/docs/examples/routing.md +8 -8
  30. package/docs/examples/sfc-showcase.md +4 -4
  31. package/docs/examples/todo-app.md +3 -3
  32. package/docs/guide/cdn-usage.md +16 -8
  33. package/docs/guide/components.md +34 -16
  34. package/docs/guide/contributing.md +2 -2
  35. package/docs/guide/directives.md +23 -23
  36. package/docs/guide/getting-started.md +41 -16
  37. package/docs/guide/index.md +12 -12
  38. package/docs/guide/lifecycle.md +1 -1
  39. package/docs/guide/quick-start.md +8 -5
  40. package/docs/guide/reactivity.md +30 -9
  41. package/docs/guide/routing.md +189 -289
  42. package/docs/guide/sfc.md +40 -40
  43. package/docs/guide/templating.md +4 -4
  44. package/docs/index.md +48 -14
  45. package/docs/public/logo.svg +17 -38
  46. package/docs/router/basic-routing.md +103 -0
  47. package/docs/router/cold-entry.md +91 -0
  48. package/docs/router/history.md +69 -0
  49. package/docs/router/index.md +73 -0
  50. package/docs/router/resolver.md +74 -0
  51. package/docs/router/surgical-swaps.md +134 -0
  52. package/examples/vite-app/README.md +2 -2
  53. package/examples/vite-app/index.html +9 -13
  54. package/examples/vite-app/package.json +4 -2
  55. package/examples/vite-app/src/app.css +3 -0
  56. package/examples/vite-app/src/app.js +29 -0
  57. package/examples/vite-app/src/components/app-navbar.lego +34 -0
  58. package/examples/vite-app/src/components/customers/customer-details.lego +24 -0
  59. package/examples/vite-app/src/components/customers/customer-orders.lego +21 -0
  60. package/examples/vite-app/src/components/customers/order-list.lego +55 -0
  61. package/examples/vite-app/src/components/greeting-card.lego +26 -26
  62. package/examples/vite-app/src/components/sample-component.lego +58 -58
  63. package/examples/vite-app/src/components/shells/customers-shell.lego +21 -0
  64. package/examples/vite-app/src/components/todo-list.lego +239 -0
  65. package/examples/vite-app/src/components/widgets/user-card.lego +27 -0
  66. package/examples/vite-app/vite.config.js +7 -2
  67. package/lego.js +2 -0
  68. package/main.js +280 -83
  69. package/package.json +8 -3
  70. package/parse-lego.js +17 -8
  71. package/parse-lego.test.js +1 -1
  72. package/{main.test.js → tests/main.test.js} +34 -17
  73. package/tests/parse-lego.test.js +65 -0
  74. package/vite-plugin.js +62 -24
  75. package/docs/.vitepress/dist/404.html +0 -22
  76. package/docs/.vitepress/dist/api/define.html +0 -35
  77. package/docs/.vitepress/dist/api/directives.html +0 -32
  78. package/docs/.vitepress/dist/api/globals.html +0 -27
  79. package/docs/.vitepress/dist/api/index.html +0 -25
  80. package/docs/.vitepress/dist/api/lifecycle.html +0 -38
  81. package/docs/.vitepress/dist/api/route.html +0 -34
  82. package/docs/.vitepress/dist/api/vite-plugin.html +0 -37
  83. package/docs/.vitepress/dist/assets/api_define.md.UA-ygUnQ.js +0 -11
  84. package/docs/.vitepress/dist/assets/api_define.md.UA-ygUnQ.lean.js +0 -1
  85. package/docs/.vitepress/dist/assets/api_directives.md.BV-D251p.js +0 -8
  86. package/docs/.vitepress/dist/assets/api_directives.md.BV-D251p.lean.js +0 -1
  87. package/docs/.vitepress/dist/assets/api_globals.md.DOjt7AV0.js +0 -3
  88. package/docs/.vitepress/dist/assets/api_globals.md.DOjt7AV0.lean.js +0 -1
  89. package/docs/.vitepress/dist/assets/api_index.md.OS6h01ct.js +0 -1
  90. package/docs/.vitepress/dist/assets/api_index.md.OS6h01ct.lean.js +0 -1
  91. package/docs/.vitepress/dist/assets/api_lifecycle.md.Ccm5xw6-.js +0 -14
  92. package/docs/.vitepress/dist/assets/api_lifecycle.md.Ccm5xw6-.lean.js +0 -1
  93. package/docs/.vitepress/dist/assets/api_route.md.CAHf_KNp.js +0 -10
  94. package/docs/.vitepress/dist/assets/api_route.md.CAHf_KNp.lean.js +0 -1
  95. package/docs/.vitepress/dist/assets/api_vite-plugin.md.DNn9VhL5.js +0 -13
  96. package/docs/.vitepress/dist/assets/api_vite-plugin.md.DNn9VhL5.lean.js +0 -1
  97. package/docs/.vitepress/dist/assets/app.BG5s3B0P.js +0 -1
  98. package/docs/.vitepress/dist/assets/chunks/@localSearchIndexroot.DQmuWC2Z.js +0 -1
  99. package/docs/.vitepress/dist/assets/chunks/VPLocalSearchBox.BO-PSxt1.js +0 -9
  100. package/docs/.vitepress/dist/assets/chunks/framework.B7OFBR9X.js +0 -19
  101. package/docs/.vitepress/dist/assets/chunks/theme.DA-iSa9B.js +0 -2
  102. package/docs/.vitepress/dist/assets/examples_form.md.B3stGKbu.js +0 -34
  103. package/docs/.vitepress/dist/assets/examples_form.md.B3stGKbu.lean.js +0 -1
  104. package/docs/.vitepress/dist/assets/examples_index.md.BDEG_D4J.js +0 -30
  105. package/docs/.vitepress/dist/assets/examples_index.md.BDEG_D4J.lean.js +0 -1
  106. package/docs/.vitepress/dist/assets/examples_routing.md.bqZ9DjDK.js +0 -338
  107. package/docs/.vitepress/dist/assets/examples_routing.md.bqZ9DjDK.lean.js +0 -1
  108. package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DLXaUiop.js +0 -13
  109. package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DLXaUiop.lean.js +0 -1
  110. package/docs/.vitepress/dist/assets/examples_todo-app.md.D5RhZoo5.js +0 -297
  111. package/docs/.vitepress/dist/assets/examples_todo-app.md.D5RhZoo5.lean.js +0 -1
  112. package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CAjf03Lr.js +0 -182
  113. package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CAjf03Lr.lean.js +0 -1
  114. package/docs/.vitepress/dist/assets/guide_components.md.BIFWF1Hc.js +0 -174
  115. package/docs/.vitepress/dist/assets/guide_components.md.BIFWF1Hc.lean.js +0 -1
  116. package/docs/.vitepress/dist/assets/guide_contributing.md.BgbUN-Mr.js +0 -1
  117. package/docs/.vitepress/dist/assets/guide_contributing.md.BgbUN-Mr.lean.js +0 -1
  118. package/docs/.vitepress/dist/assets/guide_directives.md.Bi3ynu1d.js +0 -140
  119. package/docs/.vitepress/dist/assets/guide_directives.md.Bi3ynu1d.lean.js +0 -1
  120. package/docs/.vitepress/dist/assets/guide_getting-started.md.2Nr1lp2z.js +0 -107
  121. package/docs/.vitepress/dist/assets/guide_getting-started.md.2Nr1lp2z.lean.js +0 -1
  122. package/docs/.vitepress/dist/assets/guide_index.md.GvZq_Yf2.js +0 -2
  123. package/docs/.vitepress/dist/assets/guide_index.md.GvZq_Yf2.lean.js +0 -1
  124. package/docs/.vitepress/dist/assets/guide_lifecycle.md.B28j1OzS.js +0 -304
  125. package/docs/.vitepress/dist/assets/guide_lifecycle.md.B28j1OzS.lean.js +0 -1
  126. package/docs/.vitepress/dist/assets/guide_quick-start.md.CNk3VGTF.js +0 -33
  127. package/docs/.vitepress/dist/assets/guide_quick-start.md.CNk3VGTF.lean.js +0 -1
  128. package/docs/.vitepress/dist/assets/guide_reactivity.md.CVsaMaPv.js +0 -135
  129. package/docs/.vitepress/dist/assets/guide_reactivity.md.CVsaMaPv.lean.js +0 -1
  130. package/docs/.vitepress/dist/assets/guide_routing.md.DSpDP25o.js +0 -193
  131. package/docs/.vitepress/dist/assets/guide_routing.md.DSpDP25o.lean.js +0 -1
  132. package/docs/.vitepress/dist/assets/guide_sfc.md.CVUP66tS.js +0 -187
  133. package/docs/.vitepress/dist/assets/guide_sfc.md.CVUP66tS.lean.js +0 -1
  134. package/docs/.vitepress/dist/assets/guide_templating.md.BgCGe4aa.js +0 -119
  135. package/docs/.vitepress/dist/assets/guide_templating.md.BgCGe4aa.lean.js +0 -1
  136. package/docs/.vitepress/dist/assets/index.md.xV1taCED.js +0 -23
  137. package/docs/.vitepress/dist/assets/index.md.xV1taCED.lean.js +0 -1
  138. package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  139. package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  140. package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  141. package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  142. package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  143. package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  144. package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  145. package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  146. package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  147. package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  148. package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  149. package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  150. package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  151. package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  152. package/docs/.vitepress/dist/assets/style.eycE2Jhw.css +0 -1
  153. package/docs/.vitepress/dist/examples/form.html +0 -58
  154. package/docs/.vitepress/dist/examples/index.html +0 -368
  155. package/docs/.vitepress/dist/examples/routing.html +0 -362
  156. package/docs/.vitepress/dist/examples/sfc-showcase.html +0 -37
  157. package/docs/.vitepress/dist/examples/todo-app.html +0 -321
  158. package/docs/.vitepress/dist/guide/cdn-usage.html +0 -206
  159. package/docs/.vitepress/dist/guide/components.html +0 -198
  160. package/docs/.vitepress/dist/guide/contributing.html +0 -25
  161. package/docs/.vitepress/dist/guide/directives.html +0 -164
  162. package/docs/.vitepress/dist/guide/getting-started.html +0 -131
  163. package/docs/.vitepress/dist/guide/index.html +0 -26
  164. package/docs/.vitepress/dist/guide/lifecycle.html +0 -328
  165. package/docs/.vitepress/dist/guide/quick-start.html +0 -57
  166. package/docs/.vitepress/dist/guide/reactivity.html +0 -159
  167. package/docs/.vitepress/dist/guide/routing.html +0 -217
  168. package/docs/.vitepress/dist/guide/sfc.html +0 -211
  169. package/docs/.vitepress/dist/guide/templating.html +0 -143
  170. package/docs/.vitepress/dist/hashmap.json +0 -1
  171. package/docs/.vitepress/dist/index.html +0 -47
  172. package/docs/.vitepress/dist/logo.svg +0 -38
  173. package/docs/.vitepress/dist/vp-icons.css +0 -1
  174. package/examples/vite-app/src/main.js +0 -11
  175. package/examples.js +0 -99
@@ -0,0 +1,134 @@
1
+ # Surgical Swaps: Mastering b-target
2
+
3
+ The true power of LegoJS lies in its ability to perform **Surgical Swaps**. In a traditional application, clicking a link often causes the entire page to re-render, destroying the state of your sidebar, header, or scroll position.
4
+
5
+ With `b-target` (and optionally `b-link`), we can choose to update only a specific "fragment" of the page.
6
+
7
+ ## The Problem with "Nuclear" Navigation
8
+
9
+ Imagine a messaging app (like LinkedIn or Slack). You have a sidebar full of conversations. When you click a message, you want the chat window to update, but you **don't** want the sidebar to reload.
10
+
11
+ If the sidebar reloads:
12
+
13
+ 1. The scroll position is lost.
14
+
15
+ 2. Any search text in the sidebar is cleared.
16
+
17
+ 3. The UI "flickers," making the app feel slow.
18
+
19
+
20
+ ## The Solution: `b-target`
21
+
22
+ The `b-target` directive allows a link to specify exactly where the new component should be rendered. It implies `b-link` (history update) by default.
23
+
24
+
25
+ ### Example: messaging-shell.html
26
+
27
+ In this SFC, we define a layout with a sidebar and a main content area. Clicking a contact updates _only_ the `<main>` area.
28
+
29
+ ```html
30
+ <!-- messaging-shell.html -->
31
+ <template>
32
+ <div class="messaging-layout">
33
+ <aside class="sidebar">
34
+ <h2>Contacts</h2>
35
+ <nav>
36
+ <a href="/chat/alice" b-target="#chat-window">Alice</a>
37
+ <a href="/chat/bob" b-target="#chat-window">Bob</a>
38
+ </nav>
39
+ </aside>
40
+
41
+ <main id="chat-window">
42
+ <p>Select a contact to start chatting.</p>
43
+ </main>
44
+ </div>
45
+ </template>
46
+
47
+ <script>
48
+ export default {
49
+ mounted() {
50
+ console.log("Messaging shell ready.");
51
+ }
52
+ }
53
+ </script>
54
+
55
+ <style>
56
+ .messaging-layout {
57
+ display: flex;
58
+ height: 100vh;
59
+ }
60
+ .sidebar {
61
+ width: 300px;
62
+ border-right: 1px solid #ccc;
63
+ }
64
+ #chat-window {
65
+ flex: 1;
66
+ padding: 20px;
67
+ }
68
+ </style>
69
+
70
+ ```
71
+
72
+ ### 1. Targeting by ID
73
+
74
+ You can tell Lego to find a specific element by its ID and replace its contents.
75
+
76
+ ```html
77
+ <!-- messaging-shell.html -->
78
+ <template>
79
+ <div class="layout">
80
+ <aside class="sidebar">
81
+ <div b-for="chat in threads">
82
+ <!-- Parent component (this shell) binds data to these links -->
83
+ <a href="/messaging/{{chat.id}}" b-target="#chat-window">
84
+ {{chat.userName}}
85
+ </a>
86
+ </div>
87
+ </aside>
88
+
89
+ <main id="chat-window">
90
+ <!-- Only this area will change when a link is clicked -->
91
+ <p>Select a conversation to begin.</p>
92
+ </main>
93
+ </div>
94
+ </template>
95
+
96
+ ```
97
+
98
+ ### 2. Targeting by Component Tag (The Web Component Way)
99
+
100
+ Because Lego is built on Custom Elements, you can target a component tag directly. The framework will find that tag and swap its internal content.
101
+
102
+ ```html
103
+ <a href="/profile/settings" b-target="settings-view">Edit Settings</a>
104
+
105
+ <settings-view>
106
+ <!-- Content gets swapped here -->
107
+ </settings-view>
108
+
109
+ ```
110
+
111
+ ## How the Target Resolver Works
112
+
113
+ When you click a link with a `b-target`, the LegoJS **Target Resolver** follows a specific hierarchy:
114
+
115
+ 1. **Local Scope**: It looks for the target inside the current component first. This prevents "ID collisions" if you have multiple instances of a layout.
116
+
117
+ 2. **Component Match**: If the target doesn't start with `#`, it treats it as a tag name (e.g., `thread-view`).
118
+
119
+ 3. **Global Fallback**: If it can't find a local match, it searches the entire document.
120
+
121
+ 4. **Router Fallback**: If no target is found, it defaults back to the `<lego-router>`.
122
+
123
+
124
+ ## Smart History
125
+
126
+ Even though we are only swapping a small part of the DOM, LegoJS is smart enough to update the browser's address bar.
127
+
128
+ When a surgical swap happens, Lego saves the "target" information into the browser's history state (`history.state.legoTargets`). This means that when a user hits the **Back Button**, Lego knows exactly which fragment needs to be swapped back to its previous state.
129
+
130
+ ## Summary
131
+
132
+ `b-target` turns your web app into a high-performance workspace. By keeping the "Shell" alive and only swapping "Fragments," you maintain state, eliminate flickers, and provide a desktop-like experience.
133
+
134
+ Next, we will tackle the most common question: **"What happens if I refresh the page while looking at a surgical fragment?"** We'll explore the **Cold Start: Self-Healing Layouts**.
@@ -1,6 +1,6 @@
1
- # LegoJS SFC and Vite Plugin Example
1
+ # Lego SFC and Vite Plugin Example
2
2
 
3
- This example demonstrates how to use LegoJS with Single File Components (.lego files) and the Vite plugin.
3
+ This example demonstrates how to use Lego with Single File Components (.lego files) and the Vite plugin.
4
4
 
5
5
  ## Setup
6
6
 
@@ -1,9 +1,10 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
+
3
4
  <head>
4
5
  <meta charset="UTF-8">
5
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>LegoJS Vite Example</title>
7
+ <title>Lego Vite Example</title>
7
8
  <style>
8
9
  body {
9
10
  font-family: system-ui, -apple-system, sans-serif;
@@ -28,18 +29,13 @@
28
29
  }
29
30
  </style>
30
31
  </head>
31
- <body>
32
- <h1>LegoJS + Vite Example</h1>
33
-
34
- <div class="info">
35
- <p><strong>✨ These components are auto-discovered from .lego files!</strong></p>
36
- <p>The Vite plugin automatically finds all .lego files in <code>src/components/</code> and registers them.</p>
37
- </div>
38
32
 
39
- <!-- These components are automatically discovered and hydrated -->
40
- <sample-component></sample-component>
41
- <greeting-card></greeting-card>
33
+ <body>
34
+ <app-navbar></app-navbar>
35
+ <lego-router id="app-outlet"></lego-router>
36
+ <aside id="outside-router"></aside>
42
37
 
43
- <script type="module" src="/src/main.js"></script>
38
+ <script type="module" src="/src/app.js"></script>
44
39
  </body>
45
- </html>
40
+
41
+ </html>
@@ -8,9 +8,11 @@
8
8
  "preview": "vite preview"
9
9
  },
10
10
  "dependencies": {
11
- "lego-dom": "file:../.."
11
+ "@tailwindcss/vite": "^4.1.18",
12
+ "lego-dom": "file:../..",
13
+ "tailwindcss": "^4.1.18"
12
14
  },
13
15
  "devDependencies": {
14
16
  "vite": "^5.0.0"
15
17
  }
16
- }
18
+ }
@@ -0,0 +1,3 @@
1
+ h1 {
2
+ color: red !important;
3
+ }
@@ -0,0 +1,29 @@
1
+ // Import Tailwind CSS
2
+ import './app.css';
3
+
4
+ // Import Lego core
5
+ import { Lego } from 'lego-dom/main.js';
6
+
7
+ // Import virtual module that auto-discovers and registers all .lego components
8
+ import registerComponents from 'virtual:lego-components';
9
+
10
+ // Register all auto-discovered components
11
+ registerComponents();
12
+
13
+ // 10. Define SPA Routes
14
+ Lego.route('/', 'sample-component');
15
+ Lego.route('/todo', 'todo-list');
16
+ Lego.route('/card', 'user-card');
17
+ Lego.route('/customers/:id/orders', 'customer-orders');
18
+ Lego.route('/customers/:id/details', 'customer-details');
19
+
20
+ // 11. Optional: Add a middleware example
21
+ Lego.route('/admin', 'admin-panel', async (params, globals) => {
22
+ console.log('Checking permissions for', params);
23
+ return globals.isLoggedIn;
24
+ });
25
+
26
+ // Initialize Lego
27
+ await Lego.init(document.body, {
28
+ tailwind: ['/src/app.css']
29
+ })
@@ -0,0 +1,34 @@
1
+ <style>
2
+ self {
3
+ display: block;
4
+ padding: 1rem;
5
+ background: #f9fafb;
6
+ border-bottom: 1px solid #e0e0e0;
7
+ }
8
+
9
+ nav {
10
+ display: flex;
11
+ justify-content: space-between;
12
+ align-items: center;
13
+ }
14
+ </style>
15
+
16
+ <template>
17
+ <nav>
18
+ <ul>
19
+ <li><a href="/" b-target="#outside-router" b-link="true">Home</a></li>
20
+ <li><a href="/todo" b-target>Todo</a></li>
21
+ <li><a href="/card" b-target>Card</a></li>
22
+ <li><a href="/customers/1/orders">Customers</a></li>
23
+ </ul>
24
+ </nav>
25
+ </template>
26
+
27
+ <script>
28
+ export default {
29
+ name: 'AppNavbar',
30
+ mounted() {
31
+ console.log('This is mounted');
32
+ }
33
+ }
34
+ </script>
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <customers-shell>
3
+ <div style="padding: 1rem; border: 1px dashed #4f46e5;">
4
+ <h3>👤 Customer Profile</h3>
5
+ <p>Details for Customer ID: <strong>{{ global.$route.params.id }}</strong></p>
6
+
7
+ <div style="display: grid; gap: 0.5rem; margin-top: 1rem;">
8
+ <div><strong>Status:</strong> Premium Member</div>
9
+ <div><strong>Joined:</strong> January 2024</div>
10
+ <div><strong>Region:</strong> Europe</div>
11
+ </div>
12
+
13
+ <div style="margin-top: 1rem;">
14
+ <a href="/customers/{{ global.$route.params.id }}/orders" b-target="#todo-container">View Orders</a>
15
+ </div>
16
+ </div>
17
+ </customers-shell>
18
+ </template>
19
+
20
+ <script>
21
+ export default {
22
+ name: 'CustomerDetails'
23
+ }
24
+ </script>
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <customers-shell>
3
+ <div style="padding: 1rem; border: 1px dashed #ccc;">
4
+ <h3>📦 Order History</h3>
5
+ <p>Viewing orders for Customer ID: <strong>{{ global.$route.params.id }}</strong></p>
6
+
7
+ <!-- Composition: Using another component inside -->
8
+ <order-list></order-list>
9
+
10
+ <div style="margin-top: 1rem;">
11
+ <a href="/customers/{{ global.$route.params.id }}/details" b-target="#todo-container">View Profile Info</a>
12
+ </div>
13
+ </div>
14
+ </customers-shell>
15
+ </template>
16
+
17
+ <script>
18
+ export default {
19
+ name: 'CustomerOrders'
20
+ }
21
+ </script>
@@ -0,0 +1,55 @@
1
+ <style>
2
+ ul {
3
+ list-style: none;
4
+ padding: 0;
5
+ }
6
+
7
+ li {
8
+ padding: 0.5rem;
9
+ border: 1px solid #eee;
10
+ margin-bottom: 0.5rem;
11
+ border-radius: 4px;
12
+ display: flex;
13
+ justify-content: space-between;
14
+ }
15
+
16
+ .status {
17
+ font-weight: bold;
18
+ color: #059669;
19
+ }
20
+ </style>
21
+
22
+ <template>
23
+ <div>
24
+ <h4>Recent Orders</h4>
25
+ <p b-show="loading">Loading orders for customer...</p>
26
+ <ul b-show="!loading">
27
+ <li b-for="order in orders">
28
+ <span>Order #{{ order.id }}</span>
29
+ <span class="status">{{ order.status }}</span>
30
+ </li>
31
+ </ul>
32
+ </div>
33
+ </template>
34
+
35
+ <script>
36
+ export default {
37
+ name: 'OrderList',
38
+ state: {
39
+ orders: [],
40
+ loading: true
41
+ },
42
+ async mounted() {
43
+ // Simulate API fetch using the customer ID from parent or global params
44
+ const customerId = Lego.globals.$route.params.id;
45
+ setTimeout(() => {
46
+ this.orders = [
47
+ { id: '101', status: 'Delivered' },
48
+ { id: '105', status: 'Shipped' },
49
+ { id: '110', status: 'Processing' }
50
+ ];
51
+ this.loading = false;
52
+ }, 800);
53
+ }
54
+ }
55
+ </script>
@@ -1,34 +1,34 @@
1
- <template>
2
- <style>
3
- self {
4
- display: block;
5
- padding: 1rem;
6
- background: #f3f4f6;
7
- border-radius: 0.5rem;
8
- margin: 0.5rem 0;
9
- }
1
+ <style>
2
+ self {
3
+ display: block;
4
+ padding: 1rem;
5
+ background: #f3f4f6;
6
+ border-radius: 0.5rem;
7
+ margin: 0.5rem 0;
8
+ }
10
9
 
11
- input {
12
- padding: 0.5rem;
13
- border: 1px solid #d1d5db;
14
- border-radius: 0.25rem;
15
- margin-right: 0.5rem;
16
- font-size: 1rem;
17
- }
10
+ input {
11
+ padding: 0.5rem;
12
+ border: 1px solid #d1d5db;
13
+ border-radius: 0.25rem;
14
+ margin-right: 0.5rem;
15
+ font-size: 1rem;
16
+ }
18
17
 
19
- .greeting {
20
- margin-top: 1rem;
21
- padding: 1rem;
22
- background: white;
23
- border-radius: 0.25rem;
24
- font-size: 1.25rem;
25
- color: #1f2937;
26
- }
27
- </style>
18
+ .greeting {
19
+ margin-top: 1rem;
20
+ padding: 1rem;
21
+ background: white;
22
+ border-radius: 0.25rem;
23
+ font-size: 1.25rem;
24
+ color: #1f2937;
25
+ }
26
+ </style>
28
27
 
28
+ <template>
29
29
  <div>
30
30
  <input b-sync="name" type="text" placeholder="Enter your name">
31
- <div class="greeting" b-if="name">
31
+ <div class="greeting" b-show="name">
32
32
  Hello, {{ name }}! 👋
33
33
  </div>
34
34
  </div>
@@ -1,75 +1,75 @@
1
- <template>
2
- <style>
3
- self {
4
- display: block;
5
- padding: 1.5rem;
6
- margin: 1rem 0;
7
- border: 2px solid #4f46e5;
8
- border-radius: 0.5rem;
9
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
10
- color: white;
11
- font-family: system-ui, -apple-system, sans-serif;
12
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
13
- }
1
+ <style>
2
+ self {
3
+ display: block;
4
+ padding: 1.5rem;
5
+ margin: 1rem 0;
6
+ border: 2px solid #4f46e5;
7
+ border-radius: 0.5rem;
8
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
9
+ color: white;
10
+ font-family: system-ui, -apple-system, sans-serif;
11
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
12
+ }
14
13
 
15
- .header {
16
- font-size: 1.5rem;
17
- font-weight: bold;
18
- margin-bottom: 0.5rem;
19
- }
14
+ .header {
15
+ font-size: 1.5rem;
16
+ font-weight: bold;
17
+ margin-bottom: 0.5rem;
18
+ }
20
19
 
21
- .content {
22
- margin: 1rem 0;
23
- line-height: 1.6;
24
- }
20
+ .content {
21
+ margin: 1rem 0;
22
+ line-height: 1.6;
23
+ }
25
24
 
26
- button {
27
- background: white;
28
- color: #4f46e5;
29
- border: none;
30
- padding: 0.5rem 1rem;
31
- border-radius: 0.25rem;
32
- font-weight: 600;
33
- cursor: pointer;
34
- transition: transform 0.2s;
35
- }
25
+ button {
26
+ background: white;
27
+ color: #4f46e5;
28
+ border: none;
29
+ padding: 0.5rem 1rem;
30
+ border-radius: 0.25rem;
31
+ font-weight: 600;
32
+ cursor: pointer;
33
+ transition: transform 0.2s;
34
+ }
36
35
 
37
- button:hover {
38
- transform: scale(1.05);
39
- }
36
+ button:hover {
37
+ transform: scale(1.05);
38
+ }
40
39
 
41
- .count {
42
- display: inline-block;
43
- background: rgba(255, 255, 255, 0.2);
44
- padding: 0.25rem 0.75rem;
45
- border-radius: 0.25rem;
46
- margin-left: 0.5rem;
47
- }
48
- </style>
40
+ .count {
41
+ display: inline-block;
42
+ background: rgba(255, 255, 255, 0.2);
43
+ padding: 0.25rem 0.75rem;
44
+ border-radius: 0.25rem;
45
+ margin-left: 0.5rem;
46
+ }
47
+ </style>
49
48
 
49
+ <template>
50
50
  <div class="header">{{ title }}</div>
51
51
  <div class="content">
52
- <p>This is a sample LegoJS component loaded from a .lego file!</p>
52
+ <p class="gobe">This is a sample Lego component loaded from a .lego file!</p>
53
53
  <p>Message: {{ message }}</p>
54
54
  </div>
55
55
  <button @click="incrementCount()">
56
- Click me!
56
+ Click me!
57
57
  <span class="count">{{ count }}</span>
58
58
  </button>
59
59
  </template>
60
60
 
61
61
  <script>
62
- export default {
63
- title: 'Sample Component',
64
- message: 'Hello from .lego file!',
65
- count: 0,
66
-
67
- incrementCount() {
68
- this.count++;
69
- },
70
-
71
- mounted() {
72
- console.log('Sample component mounted!');
62
+ export default {
63
+ title: 'Sample Component',
64
+ message: 'Hello from .lego file!',
65
+ count: 0,
66
+
67
+ incrementCount() {
68
+ this.count++;
69
+ },
70
+
71
+ mounted() {
72
+ console.log('Sample component mounted!');
73
+ }
73
74
  }
74
- }
75
- </script>
75
+ </script>
@@ -0,0 +1,21 @@
1
+ <style>
2
+ self {
3
+ display: block;
4
+ padding: 1rem;
5
+ background: #f9fafb;
6
+ border-bottom: 1px solid #e0e0e0;
7
+ }
8
+ </style>
9
+
10
+ <template>
11
+ <div>
12
+ <h2>Customers Shell</h2>
13
+ <slot></slot>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ export default {
19
+ name: 'CustomersShell'
20
+ }
21
+ </script>