slicejs-web-framework 3.2.2 → 3.3.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 (36) hide show
  1. package/.opencode/opencode.json +14 -0
  2. package/README.md +57 -134
  3. package/Slice/Components/Structural/ContextManager/ContextManagerDebugger.js +233 -110
  4. package/Slice/Components/Structural/Controller/Controller.js +9 -0
  5. package/Slice/Components/Structural/Controller/allowedValuesValidation.js +52 -0
  6. package/Slice/Components/Structural/Debugger/Debugger.js +392 -442
  7. package/Slice/Components/Structural/EventManager/EventManagerDebugger.js +264 -149
  8. package/Slice/Components/Structural/Router/Router.js +45 -14
  9. package/Slice/tests/props-allowed-values-validation.test.js +119 -0
  10. package/package.json +11 -9
  11. package/src/App/index.html +2 -8
  12. package/src/App/index.js +18 -21
  13. package/src/App/style.css +8 -37
  14. package/src/Components/AppComponents/AboutSection/AboutSection.css +9 -0
  15. package/src/Components/AppComponents/AboutSection/AboutSection.html +8 -0
  16. package/src/Components/AppComponents/AboutSection/AboutSection.js +12 -0
  17. package/src/Components/AppComponents/AppShell/AppShell.css +10 -0
  18. package/src/Components/AppComponents/AppShell/AppShell.html +4 -0
  19. package/src/Components/AppComponents/AppShell/AppShell.js +36 -0
  20. package/src/Components/AppComponents/HomeSection/HomeSection.css +20 -0
  21. package/src/Components/AppComponents/HomeSection/HomeSection.html +10 -0
  22. package/src/Components/AppComponents/HomeSection/HomeSection.js +19 -0
  23. package/src/Components/Visual/MultiRoute/MultiRoute.js +13 -6
  24. package/src/Components/components.js +4 -16
  25. package/src/routes.js +6 -12
  26. package/src/sliceConfig.json +2 -1
  27. package/Slice/Components/Structural/Debugger/Debugger.css +0 -620
  28. package/src/Components/AppComponents/HomePage/HomePage.css +0 -201
  29. package/src/Components/AppComponents/HomePage/HomePage.html +0 -37
  30. package/src/Components/AppComponents/HomePage/HomePage.js +0 -210
  31. package/src/Components/AppComponents/Playground/Playground.css +0 -12
  32. package/src/Components/AppComponents/Playground/Playground.html +0 -0
  33. package/src/Components/AppComponents/Playground/Playground.js +0 -111
  34. package/src/images/Slice.js-logo.png +0 -0
  35. package/src/images/im2/Slice.js-logo.png +0 -0
  36. package/src/testing.js +0 -888
@@ -0,0 +1,14 @@
1
+ {
2
+ "mcp": {
3
+ "thinking": {
4
+ "type": "local",
5
+ "command": ["npx", "-y", "@modelcontextprotocol/server-sequential-thinking"],
6
+ "enabled": true
7
+ },
8
+ "slicemcp": {
9
+ "type": "local",
10
+ "command": ["npx", "-y", "slicejs-mcp"],
11
+ "enabled": true
12
+ }
13
+ }
14
+ }
package/README.md CHANGED
@@ -1,46 +1,10 @@
1
- <!-- Improved compatibility of back to top link: See: https://github.com/VKneider/slice.js/pull/73 -->
2
- <a name="readme-top"></a>
3
- <!--
4
- *** Thanks for checking out the slice.js. If you have a suggestion
5
- *** that would make this better, please fork the repo and create a pull request
6
- *** or simply open an issue with the tag "enhancement".
7
- *** Don't forget to give the project a star!
8
- *** Thanks again! Now go create something AMAZING! :D
9
- -->
10
-
11
-
12
-
13
- <!-- PROJECT SHIELDS -->
14
- <!--
15
- *** I'm using markdown "reference style" links for readability.
16
- *** Reference links are enclosed in brackets [ ] instead of parentheses ( ).
17
- *** See the bottom of this document for the declaration of the reference variables
18
- *** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.
19
- *** https://www.markdownguide.org/basic-syntax/#reference-style-links
20
- -->
21
- [![Contributors][contributors-shield]][contributors-url]
22
- [![Forks][forks-shield]][forks-url]
23
- [![Stargazers][stars-shield]][stars-url]
24
- [![Issues][issues-shield]][issues-url]
25
- [![MIT License][license-shield]][license-url]
26
-
27
-
28
-
29
- <!-- PROJECT LOGO -->
30
- <br />
31
1
  <div align="center">
32
- <a href="https://github.com/VKneider/slice.js">
33
- <img src="readme_images/Slice.js-logo.svg" alt="Logo" width="150" height="150">
34
- </a>
35
-
36
- <h3 align="center">Slice.js</h3>
37
-
38
- <p align="center">
39
- Component-Based Web Development Framework
40
- <br />
2
+ <img src="readme_images/Slice.js-logo.svg" alt="Slice.js logo" width="150" />
3
+ <h1>Slice.js</h1>
4
+ <p>Component-Based Web Development Framework</p>
5
+ <p>
41
6
  <a href="https://slice-js-docs.vercel.app/Documentation"><strong>Explore the docs »</strong></a>
42
7
  <br />
43
- <br />
44
8
  <a href="https://slice-js-docs.vercel.app/">View Demo</a>
45
9
  ·
46
10
  <a href="https://github.com/VKneider/slice.js/issues/new?labels=bug&template=bug-report---.md">Report Bug</a>
@@ -49,126 +13,85 @@
49
13
  </p>
50
14
  </div>
51
15
 
16
+ ## About this repository
52
17
 
18
+ This repository contains the core of the Slice.js framework: the component runtime, routing system, bundle engine, and framework API. It is the package published as `slicejs-web-framework` on npm.
53
19
 
54
- <!-- TABLE OF CONTENTS -->
55
- <details>
56
- <summary>Table of Contents</summary>
57
- <ol>
58
- <li>
59
- <a href="#about-the-project">About The Project</a>
60
- </li>
61
- <li>
62
- <a href="#getting-started">Getting Started</a>
63
- <ul>
64
- <li><a href="#prerequisites">Prerequisites</a></li>
65
- <li><a href="#installation">Installation</a></li>
66
- </ul>
67
- </li>
68
- <li><a href="#roadmap">Roadmap</a></li>
69
- <li><a href="#contributing">Contributing</a></li>
70
- <li><a href="#license">License</a></li>
71
- <li><a href="#contact">Contact</a></li>
72
- </ol>
73
- </details>
20
+ ## Prerequisites
74
21
 
22
+ - Node.js >= 20
23
+ - npm or pnpm
75
24
 
25
+ ## Local development
76
26
 
77
- <!-- ABOUT THE PROJECT -->
78
- ## About The Project
79
-
80
- [![Product Name Screen Shot][product-screenshot]](https://slice-js-docs.vercel.app/)
81
-
82
- <p align="right">(<a href="#readme-top">back to top</a>)</p>
27
+ 1. **Clone the repository**
28
+ ```bash
29
+ git clone https://github.com/VKneider/slice.js.git
30
+ cd slice.js
31
+ ```
83
32
 
84
- <!-- GETTING STARTED -->
85
- ## Getting Started
33
+ 2. **Install dependencies**
34
+ ```bash
35
+ npm install
36
+ ```
86
37
 
87
- This is an example of how you may give instructions on setting up your project locally.
88
- To get a local copy up and running follow these simple example steps.
38
+ 3. **Initialize a test project** (optional, for CLI-based development)
39
+ ```bash
40
+ npx slicejs-cli init
41
+ ```
89
42
 
90
- ### Installation
43
+ 4. **Test changes locally**
44
+ ```bash
45
+ npx slicejs-cli dev
46
+ ```
91
47
 
92
- _Below is an example of how you can instruct your audience on installing and setting up your app. This template doesn't rely on any external dependencies or services._
48
+ ## Available commands
93
49
 
94
- 1. Install slicejs cli dependencies
95
- ```sh
96
- npm i slicejs-cli
97
- ```
98
- 2. Initialize slice project
99
- ```sh
100
- npm run slice:init
101
- ```
102
- 3. Build production output
103
- ```sh
104
- npm run slice:build
105
- ```
106
- 4. Start production server
107
- ```sh
108
- npm run slice:start
109
- ```
50
+ The framework does not expose commands directly. Use it through the CLI (`slicejs-cli`):
110
51
 
111
- Production uses `publicFolders` from `sliceConfig.json` to expose public asset folders like
112
- `/Themes`, `/Styles`, and `/assets`.
52
+ | Command | Description |
53
+ |---------|-------------|
54
+ | `npx slicejs-cli init` | Initialize a Slice.js project |
55
+ | `npx slicejs-cli dev` | Start development server |
56
+ | `npx slicejs-cli build` | Build for production |
57
+ | `npx slicejs-cli start` | Serve production build |
113
58
 
114
- Structural framework components are bundled into a dedicated framework bundle during `slice build`
115
- and served from `/dist/bundles/slice-bundle.framework.js`.
59
+ ## Documentation
116
60
 
117
- ### Documentation Access
61
+ Full documentation is available at [slice-js-docs.vercel.app](https://slice-js-docs.vercel.app/Documentation).
118
62
 
119
- Slice.js provides an MCP (Model Context Protocol) server for programmatic access to documentation:
63
+ Slice.js also provides an MCP server for programmatic documentation access:
120
64
 
121
65
  ```bash
122
66
  npx slicejs-mcp
123
67
  ```
124
68
 
125
- This allows AI assistants and tools to query, search, and retrieve Slice.js documentation seamlessly.
126
-
127
- <p align="right">(<a href="#readme-top">back to top</a>)</p>
128
-
129
-
130
-
131
- <!-- ROADMAP -->
132
- ## Roadmap
133
-
134
- - [x] Add Changelog
135
- - [ ] Add Image visual component
136
- - [ ] Modify Slice Card Visual Component
137
-
138
- See the [open issues](https://github.com/VKneider/slice.js/issues) for a full list of proposed features (and known issues).
139
-
140
- <p align="right">(<a href="#readme-top">back to top</a>)</p>
69
+ This allows AI assistants and tools to query, search, and retrieve Slice.js documentation.
141
70
 
71
+ ## Project structure
142
72
 
73
+ ```
74
+ slice.js/
75
+ ├── api/ # Framework API server
76
+ ├── src/ # Runtime source code
77
+ │ ├── App/ # Application engine
78
+ │ ├── Components/# Component system
79
+ │ └── ... # Routing, bundles, utilities
80
+ ├── Slice/ # Visual component framework
81
+ ├── types/ # TypeScript declarations
82
+ └── docs/ # Contribution guides
83
+ ```
143
84
 
144
- <!-- CONTRIBUTING -->
145
85
  ## Contributing
146
86
 
147
- We welcome contributions to the project! Please make sure to review the guidelines in the [CONTRIBUTING.md](docs/CONTRIBUTING.md) file before submitting any changes.
148
-
149
- <p align="right">(<a href="#readme-top">back to top</a>)</p>
150
-
87
+ We welcome contributions. Please review the guidelines in [CONTRIBUTING.md](docs/CONTRIBUTING.md) before submitting changes.
151
88
 
152
-
153
- <!-- LICENSE -->
154
89
  ## License
155
90
 
156
91
  Distributed under the MIT License. See `LICENSE` for more information.
157
92
 
158
- <p align="right">(<a href="#readme-top">back to top</a>)</p>
159
-
160
- <!-- MARKDOWN LINKS & IMAGES -->
161
- <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
162
- [contributors-shield]: https://img.shields.io/github/contributors/VKneider/slice.js.svg?style=for-the-badge
163
- [contributors-url]: https://github.com/VKneider/slice.js/graphs/contributors
164
- [forks-shield]: https://img.shields.io/github/forks/VKneider/slice.js.svg?style=for-the-badge
165
- [forks-url]: https://github.com/VKneider/slice.js/network/members
166
- [stars-shield]: https://img.shields.io/github/stars/VKneider/slice.js.svg?style=for-the-badge
167
- [stars-url]: https://github.com/VKneider/slice.js/stargazers
168
- [issues-shield]: https://img.shields.io/github/issues/VKneider/slice.js.svg?style=for-the-badge
169
- [issues-url]: https://github.com/VKneider/slice.js/issues
170
- [license-shield]: https://img.shields.io/github/license/VKneider/slice.js.svg?style=for-the-badge
171
- [license-url]: https://github.com/VKneider/slice.js/blob/master/LICENSE.txt
172
- [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
173
- [linkedin-url]: https://linkedin.com/in/VKneider
174
- [product-screenshot]: readme_images/screenshot.JPG
93
+ ## Contact
94
+
95
+ Slice.js - [@VKneider](https://github.com/VKneider)
96
+
97
+ Project Link: [https://github.com/VKneider/slice.js](https://github.com/VKneider/slice.js)
@@ -131,7 +131,7 @@ export default class ContextManagerDebugger extends HTMLElement {
131
131
  const preview = JSON.stringify(item.state, null, 2);
132
132
  return `
133
133
  <div class="context-row">
134
- <div class="context-header">
134
+ <div class="context-row-head">
135
135
  <div class="context-name">${item.name}</div>
136
136
  <div class="context-keys">${item.keys} keys</div>
137
137
  </div>
@@ -155,15 +155,19 @@ export default class ContextManagerDebugger extends HTMLElement {
155
155
  return `
156
156
  <div id="context-debugger">
157
157
  <div class="context-header">
158
- <div class="title">Contexts</div>
158
+ <div class="brand">
159
+ <span class="status-dot"></span>
160
+ <span class="glyph">◈</span>
161
+ <span class="title">CONTEXT</span>
162
+ </div>
159
163
  <div class="actions">
160
- <button id="context-refresh" class="btn">Refresh</button>
161
- <button id="context-close" class="btn">Close</button>
164
+ <button id="context-refresh" class="btn" title="Refresh" aria-label="Refresh">⟳</button>
165
+ <button id="context-close" class="btn" title="Close" aria-label="Close">✕</button>
162
166
  </div>
163
167
  </div>
164
168
  <div class="context-toolbar">
165
- <input id="context-filter" type="text" placeholder="Filter contexts" />
166
- <div class="count">Total: <span id="context-count">0</span></div>
169
+ <input id="context-filter" type="text" placeholder="filter contexts" autocomplete="off" spellcheck="false" />
170
+ <div class="count"><span id="context-count">0</span></div>
167
171
  </div>
168
172
  <div class="context-list" id="context-list"></div>
169
173
  </div>
@@ -172,124 +176,243 @@ export default class ContextManagerDebugger extends HTMLElement {
172
176
 
173
177
  renderStyles() {
174
178
  return `
175
- #context-debugger {
176
- position: fixed;
177
- bottom: 20px;
178
- left: 20px;
179
- width: min(380px, calc(100vw - 40px));
180
- max-height: 60vh;
181
- background: var(--primary-background-color);
182
- border: 1px solid var(--medium-color);
183
- border-radius: 12px;
184
- box-shadow: 0 16px 32px rgba(0, 0, 0, 0.15);
185
- display: none;
186
- flex-direction: column;
187
- z-index: 10001;
188
- overflow: hidden;
189
- }
179
+ /* Slice Instruments — context store. All selectors scoped to the
180
+ <slice-contextmanager-debugger> tag so nothing clashes with app styles. */
181
+ slice-contextmanager-debugger {
182
+ --si-accent: var(--primary-color, #6ee7ff);
183
+ --si-accent-rgb: var(--primary-color-rgb, 110, 231, 255);
184
+ --si-surface: rgba(17, 19, 28, 0.86);
185
+ --si-raised: rgba(255, 255, 255, 0.035);
186
+ --si-raised-2: rgba(255, 255, 255, 0.06);
187
+ --si-border: rgba(255, 255, 255, 0.09);
188
+ --si-text: #e8eaf2;
189
+ --si-dim: #888fa6;
190
+ --si-mono: ui-monospace, 'SF Mono', 'JetBrains Mono', 'Cascadia Code', Menlo, Consolas, monospace;
191
+ }
190
192
 
191
- #context-debugger.active {
192
- display: flex;
193
- }
193
+ slice-contextmanager-debugger #context-debugger {
194
+ position: fixed;
195
+ bottom: 20px;
196
+ left: 20px;
197
+ width: min(400px, calc(100vw - 40px));
198
+ max-height: 64vh;
199
+ background: var(--si-surface);
200
+ border: 1px solid var(--si-border);
201
+ border-radius: 14px;
202
+ box-shadow:
203
+ 0 24px 60px -12px rgba(0, 0, 0, 0.55),
204
+ 0 0 0 1px rgba(0, 0, 0, 0.2),
205
+ 0 0 38px -18px rgba(var(--si-accent-rgb), 0.55);
206
+ -webkit-backdrop-filter: blur(22px) saturate(1.3);
207
+ backdrop-filter: blur(22px) saturate(1.3);
208
+ display: none;
209
+ flex-direction: column;
210
+ z-index: 10001;
211
+ overflow: hidden;
212
+ color: var(--si-text);
213
+ font-family: var(--si-mono);
214
+ }
194
215
 
195
- #context-debugger * {
196
- box-sizing: border-box;
197
- }
216
+ slice-contextmanager-debugger #context-debugger.active {
217
+ display: flex;
218
+ animation: si-context-in 0.26s cubic-bezier(0.16, 1, 0.3, 1);
219
+ }
198
220
 
199
- .context-header {
200
- display: flex;
201
- justify-content: space-between;
202
- align-items: center;
203
- padding: 12px 14px;
204
- background: var(--tertiary-background-color);
205
- border-bottom: 1px solid var(--medium-color);
206
- user-select: none;
207
- }
221
+ @keyframes si-context-in {
222
+ from { opacity: 0; transform: translateY(10px) scale(0.985); }
223
+ to { opacity: 1; transform: translateY(0) scale(1); }
224
+ }
208
225
 
209
- .context-header .title {
210
- font-weight: 600;
211
- color: var(--font-primary-color);
212
- }
226
+ slice-contextmanager-debugger #context-debugger * { box-sizing: border-box; }
213
227
 
214
- .context-header .actions {
215
- display: flex;
216
- gap: 8px;
217
- }
228
+ slice-contextmanager-debugger #context-debugger::before {
229
+ content: '';
230
+ position: absolute;
231
+ left: 0; top: 0; bottom: 0;
232
+ width: 2px;
233
+ background: linear-gradient(180deg, var(--si-accent), transparent 70%);
234
+ opacity: 0.85;
235
+ pointer-events: none;
236
+ }
218
237
 
219
- .context-header .btn {
220
- padding: 6px 10px;
221
- border-radius: 6px;
222
- border: 1px solid var(--medium-color);
223
- background: var(--primary-background-color);
224
- color: var(--font-primary-color);
225
- cursor: pointer;
226
- font-size: 12px;
227
- }
238
+ slice-contextmanager-debugger #context-debugger > .context-header {
239
+ display: flex;
240
+ justify-content: space-between;
241
+ align-items: center;
242
+ padding: 12px 14px;
243
+ background:
244
+ radial-gradient(120% 140% at 0% 0%, rgba(var(--si-accent-rgb), 0.10), transparent 60%),
245
+ var(--si-raised);
246
+ border-bottom: 1px solid var(--si-border);
247
+ user-select: none;
248
+ }
228
249
 
229
- .context-toolbar {
230
- display: flex;
231
- gap: 10px;
232
- align-items: center;
233
- padding: 10px 12px;
234
- border-bottom: 1px solid var(--medium-color);
235
- }
250
+ slice-contextmanager-debugger .brand { display: flex; align-items: center; gap: 9px; }
236
251
 
237
- .context-toolbar input {
238
- flex: 1;
239
- min-width: 0;
240
- padding: 6px 8px;
241
- border-radius: 6px;
242
- border: 1px solid var(--medium-color);
243
- background: var(--primary-background-color);
244
- color: var(--font-primary-color);
245
- }
252
+ slice-contextmanager-debugger .status-dot {
253
+ width: 7px; height: 7px;
254
+ border-radius: 50%;
255
+ background: var(--si-accent);
256
+ animation: si-pulse-ctx 2.4s ease-out infinite;
257
+ }
246
258
 
247
- .context-list {
248
- padding: 10px 12px;
249
- overflow: auto;
250
- display: flex;
251
- flex-direction: column;
252
- gap: 10px;
253
- }
259
+ @keyframes si-pulse-ctx {
260
+ 0% { box-shadow: 0 0 0 0 rgba(var(--si-accent-rgb), 0.55); }
261
+ 70% { box-shadow: 0 0 0 7px rgba(var(--si-accent-rgb), 0); }
262
+ 100% { box-shadow: 0 0 0 0 rgba(var(--si-accent-rgb), 0); }
263
+ }
254
264
 
255
- .context-row {
256
- border: 1px solid var(--medium-color);
257
- border-radius: 8px;
258
- background: var(--tertiary-background-color);
259
- padding: 10px;
260
- display: flex;
261
- flex-direction: column;
262
- gap: 6px;
263
- }
265
+ slice-contextmanager-debugger .glyph { color: var(--si-accent); font-size: 12px; opacity: 0.9; }
264
266
 
265
- .context-name {
266
- font-weight: 600;
267
- color: var(--font-primary-color);
268
- }
267
+ slice-contextmanager-debugger .title {
268
+ font-weight: 600;
269
+ font-size: 11px;
270
+ letter-spacing: 0.18em;
271
+ color: var(--si-text);
272
+ }
269
273
 
270
- .context-keys {
271
- font-size: 12px;
272
- color: var(--font-secondary-color);
273
- }
274
+ slice-contextmanager-debugger .actions { display: flex; gap: 6px; }
275
+
276
+ slice-contextmanager-debugger .btn {
277
+ width: 26px; height: 26px;
278
+ display: flex; align-items: center; justify-content: center;
279
+ border-radius: 7px;
280
+ border: 1px solid var(--si-border);
281
+ background: var(--si-raised);
282
+ color: var(--si-dim);
283
+ cursor: pointer;
284
+ font-size: 13px;
285
+ line-height: 1;
286
+ transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
287
+ }
288
+ slice-contextmanager-debugger .btn:hover {
289
+ color: var(--si-text);
290
+ background: var(--si-raised-2);
291
+ border-color: rgba(var(--si-accent-rgb), 0.5);
292
+ }
293
+ slice-contextmanager-debugger .btn:active { transform: scale(0.92); }
294
+ slice-contextmanager-debugger #context-refresh:hover { color: var(--si-accent); }
295
+
296
+ slice-contextmanager-debugger .context-toolbar {
297
+ display: flex;
298
+ gap: 10px;
299
+ align-items: center;
300
+ padding: 10px 12px;
301
+ border-bottom: 1px solid var(--si-border);
302
+ }
274
303
 
275
- .context-preview {
276
- background: var(--primary-background-color);
277
- border-radius: 6px;
278
- padding: 8px;
279
- border: 1px solid var(--medium-color);
280
- max-height: 180px;
281
- overflow: auto;
282
- font-size: 11px;
283
- font-family: monospace;
284
- color: var(--font-primary-color);
285
- }
304
+ slice-contextmanager-debugger .context-toolbar input {
305
+ flex: 1;
306
+ min-width: 0;
307
+ padding: 7px 10px 7px 30px;
308
+ border-radius: 8px;
309
+ border: 1px solid var(--si-border);
310
+ background:
311
+ var(--si-raised) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%23888fa6' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E") no-repeat 10px center;
312
+ color: var(--si-text);
313
+ font-family: var(--si-mono);
314
+ font-size: 12px;
315
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
316
+ }
317
+ slice-contextmanager-debugger .context-toolbar input::placeholder { color: var(--si-dim); }
318
+ slice-contextmanager-debugger .context-toolbar input:focus {
319
+ outline: none;
320
+ border-color: rgba(var(--si-accent-rgb), 0.6);
321
+ box-shadow: 0 0 0 3px rgba(var(--si-accent-rgb), 0.12);
322
+ }
286
323
 
287
- .empty {
288
- color: var(--font-secondary-color);
289
- font-size: 12px;
290
- text-align: center;
291
- padding: 12px 0;
292
- }
324
+ slice-contextmanager-debugger .context-toolbar .count { font-size: 11px; color: var(--si-dim); min-width: 22px; text-align: center; }
325
+ slice-contextmanager-debugger .context-toolbar .count span { color: var(--si-accent); font-weight: 600; }
326
+
327
+ slice-contextmanager-debugger .context-list {
328
+ padding: 10px 12px 12px;
329
+ overflow: auto;
330
+ display: flex;
331
+ flex-direction: column;
332
+ gap: 9px;
333
+ }
334
+ slice-contextmanager-debugger .context-list::-webkit-scrollbar { width: 8px; }
335
+ slice-contextmanager-debugger .context-list::-webkit-scrollbar-thumb {
336
+ background: var(--si-raised-2);
337
+ border-radius: 8px;
338
+ border: 2px solid transparent;
339
+ background-clip: padding-box;
340
+ }
341
+ slice-contextmanager-debugger .context-list::-webkit-scrollbar-thumb:hover { background: rgba(var(--si-accent-rgb), 0.4); background-clip: padding-box; }
342
+
343
+ slice-contextmanager-debugger .context-row {
344
+ border: 1px solid var(--si-border);
345
+ border-left: 2px solid transparent;
346
+ border-radius: 10px;
347
+ background: var(--si-raised);
348
+ padding: 10px 11px;
349
+ display: flex;
350
+ flex-direction: column;
351
+ gap: 8px;
352
+ transition: border-color 0.18s ease, background 0.18s ease;
353
+ }
354
+ slice-contextmanager-debugger .context-row:hover { background: var(--si-raised-2); border-left-color: var(--si-accent); }
355
+
356
+ slice-contextmanager-debugger .context-row-head {
357
+ display: flex;
358
+ align-items: center;
359
+ justify-content: space-between;
360
+ gap: 10px;
361
+ }
362
+
363
+ slice-contextmanager-debugger .context-name {
364
+ font-weight: 600;
365
+ font-size: 12.5px;
366
+ color: var(--si-text);
367
+ font-family: var(--si-mono);
368
+ }
369
+
370
+ slice-contextmanager-debugger .context-keys {
371
+ font-size: 10px;
372
+ letter-spacing: 0.04em;
373
+ text-transform: uppercase;
374
+ color: var(--si-accent);
375
+ background: rgba(var(--si-accent-rgb), 0.12);
376
+ border: 1px solid rgba(var(--si-accent-rgb), 0.25);
377
+ padding: 1px 8px;
378
+ border-radius: 999px;
379
+ white-space: nowrap;
380
+ }
381
+
382
+ slice-contextmanager-debugger .context-preview {
383
+ background: rgba(0, 0, 0, 0.3);
384
+ border-radius: 8px;
385
+ padding: 10px;
386
+ border: 1px solid var(--si-border);
387
+ max-height: 200px;
388
+ overflow: auto;
389
+ font-size: 11px;
390
+ line-height: 1.55;
391
+ font-family: var(--si-mono);
392
+ color: #c5cad8;
393
+ white-space: pre;
394
+ margin: 0;
395
+ }
396
+ slice-contextmanager-debugger .context-preview::-webkit-scrollbar { width: 8px; height: 8px; }
397
+ slice-contextmanager-debugger .context-preview::-webkit-scrollbar-thumb {
398
+ background: var(--si-raised-2);
399
+ border-radius: 8px;
400
+ border: 2px solid transparent;
401
+ background-clip: padding-box;
402
+ }
403
+
404
+ slice-contextmanager-debugger .empty {
405
+ color: var(--si-dim);
406
+ font-size: 11px;
407
+ letter-spacing: 0.04em;
408
+ text-align: center;
409
+ padding: 22px 0;
410
+ }
411
+
412
+ @media (prefers-reduced-motion: reduce) {
413
+ slice-contextmanager-debugger #context-debugger.active { animation: none; }
414
+ slice-contextmanager-debugger .status-dot { animation: none; }
415
+ }
293
416
  `;
294
417
  }
295
418
  }
@@ -1,4 +1,5 @@
1
1
  import components from '/Components/components.js';
2
+ import { collectInvalidAllowedValueProps, formatAllowedValuesForLog } from './allowedValuesValidation.js';
2
3
 
3
4
  export default class Controller {
4
5
  constructor() {
@@ -904,6 +905,14 @@ export default class Controller {
904
905
  if (missingRequired.length > 0) {
905
906
  slice.logger.logError(componentName, `Missing required props: [${missingRequired.join(', ')}]`);
906
907
  }
908
+
909
+ const invalidAllowedValueProps = collectInvalidAllowedValueProps(staticProps, providedProps);
910
+ invalidAllowedValueProps.forEach(({ propName, value, allowedValues }) => {
911
+ slice.logger.logError(
912
+ componentName,
913
+ `Invalid value for prop "${propName}": ${JSON.stringify(value)}. Allowed values: ${formatAllowedValuesForLog(allowedValues)}`
914
+ );
915
+ });
907
916
  }
908
917
 
909
918
  extractUsedProps(component, staticProps = null) {