metaowl 0.2.9 → 0.2.10

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.
@@ -397,6 +397,39 @@ router.beforeEach((to, from, next) => {
397
397
  - File: pages/blog/[slug]/Blog.js → URL: /blog/:slug
398
398
  - File: pages/[...path]/NotFound.js → URL: /:path(.*)
399
399
 
400
+ ### Layouts
401
+ Share page structures across routes with automatic layout resolution:
402
+
403
+ \`\`\`javascript
404
+ // pages/admin/Dashboard.js
405
+ export class DashboardPage extends Component {
406
+ static template = 'DashboardPage'
407
+ static layout = 'admin' // Use admin layout
408
+ }
409
+ \`\`\`
410
+
411
+ Layout Directory:
412
+ \`\`\`
413
+ src/
414
+ ├── layouts/
415
+ │ ├── default/
416
+ │ │ ├── DefaultLayout.js
417
+ │ │ └── DefaultLayout.xml
418
+ │ └── admin/
419
+ │ ├── AdminLayout.js
420
+ │ └── AdminLayout.xml
421
+ \`\`\`
422
+
423
+ Layout Template uses \`<t t-slot=\"default\"/>\` to render page content:
424
+ \`\`\`xml
425
+ <t t-name="AdminLayout">
426
+ <div class="layout-admin">
427
+ <aside>Sidebar</aside>
428
+ <main><t t-slot="default"/></main>
429
+ </div>
430
+ </t>
431
+ \`\`\`
432
+
400
433
  ### API Requests
401
434
  \`\`\`javascript
402
435
  import { Fetch } from 'metaowl'
@@ -521,6 +554,24 @@ router.push('/path')
521
554
  router.back()
522
555
  \`\`\`
523
556
 
557
+ ### Layouts
558
+ Shared page structures with automatic resolution.
559
+ \`\`\`javascript
560
+ // In page component
561
+ export class DashboardPage extends Component {
562
+ static template = 'DashboardPage'
563
+ static layout = 'admin' // Use admin layout
564
+ }
565
+ \`\`\`
566
+
567
+ // Layout component uses t-slot for page content:
568
+ // <t t-slot="default"/>
569
+
570
+ Layout functions:
571
+ - registerLayout(name, Component) - Register a layout
572
+ - resolveLayout(Component, path?) - Get layout for component
573
+ - setRouteLayout(path, name) - Assign layout to route
574
+
524
575
  ## Component Template
525
576
  \`\`\`javascript
526
577
  import { Component } from '@odoo/owl'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metaowl",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "Lightweight meta-framework for Odoo OWL — file-based routing, app mounting, Fetch helper, Cache, Meta tags, SSG generator, and a Vite plugin.",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/vite/plugin.js CHANGED
@@ -35,6 +35,7 @@ function collectXml(globPattern) {
35
35
  * @param {string} [options.publicDir='../public'] - Public assets directory.
36
36
  * @param {string} [options.componentsDir='src/components'] - OWL components directory.
37
37
  * @param {string} [options.pagesDir='src/pages'] - OWL pages directory.
38
+ * @param {string} [options.layoutsDir='src/layouts'] - OWL layouts directory.
38
39
  * @param {string[]} [options.restartGlobs] - Additional globs that trigger dev-server restart.
39
40
  * @param {string} [options.frameworkEntry] - Framework entry for manual chunk.
40
41
  * @param {string[]} [options.vendorPackages] - npm packages bundled into the vendor chunk.
@@ -51,6 +52,7 @@ export async function metaowlPlugin(options = {}) {
51
52
  publicDir = '../public',
52
53
  componentsDir = 'src/components',
53
54
  pagesDir = 'src/pages',
55
+ layoutsDir = 'src/layouts',
54
56
  restartGlobs = [],
55
57
  frameworkEntry = './node_modules/metaowl/index.js',
56
58
  vendorPackages = ['@odoo/owl'],
@@ -60,7 +62,8 @@ export async function metaowlPlugin(options = {}) {
60
62
 
61
63
  const componentXml = collectXml(`${componentsDir}/**/*.xml`)
62
64
  const pageXml = collectXml(`${pagesDir}/**/*.xml`)
63
- const allComponents = [...pageXml, ...componentXml]
65
+ const layoutXml = collectXml(`${layoutsDir}/**/*.xml`)
66
+ const allComponents = [...pageXml, ...componentXml, ...layoutXml]
64
67
 
65
68
  const defaultRestartGlobs = [
66
69
  `${root}/**/*.[jt]s`,
@@ -169,7 +172,8 @@ export async function metaowlPlugin(options = {}) {
169
172
  include: ['@odoo/owl'],
170
173
  entries: [
171
174
  `${componentsDir}/**/*.[jt]s`,
172
- `${pagesDir}/**/*.[jt]s`
175
+ `${pagesDir}/**/*.[jt]s`,
176
+ `${layoutsDir}/**/*.[jt]s`
173
177
  ],
174
178
  ...(cfg.optimizeDeps ?? {})
175
179
  }
@@ -198,10 +202,12 @@ export async function metaowlPlugin(options = {}) {
198
202
  if (!id.endsWith('/css.js')) return
199
203
  const compRel = componentsDir.replace(new RegExp(`^${root}[\\/]`), '')
200
204
  const pagesRel = pagesDir.replace(new RegExp(`^${root}[\\/]`), '')
205
+ const layoutsRel = layoutsDir.replace(new RegExp(`^${root}[\\/]`), '')
201
206
  return {
202
207
  code: code + '\n' +
203
208
  `import.meta.glob('/${compRel}/**/*.{css,scss}', { eager: true })\n` +
204
- `import.meta.glob('/${pagesRel}/**/*.{css,scss}', { eager: true })\n`,
209
+ `import.meta.glob('/${pagesRel}/**/*.{css,scss}', { eager: true })\n` +
210
+ `import.meta.glob('/${layoutsRel}/**/*.{css,scss}', { eager: true })\n`,
205
211
  map: null
206
212
  }
207
213
  }
@@ -213,7 +219,7 @@ export async function metaowlPlugin(options = {}) {
213
219
  const projectRoot = process.cwd()
214
220
 
215
221
  // Copy OWL XML templates (loaded at runtime via fetch — not processed by Vite)
216
- const xmlFiles = globSync([`${componentsDir}/**/*.xml`, `${pagesDir}/**/*.xml`])
222
+ const xmlFiles = globSync([`${componentsDir}/**/*.xml`, `${pagesDir}/**/*.xml`, `${layoutsDir}/**/*.xml`])
217
223
  for (const xmlFile of xmlFiles) {
218
224
  const relPath = xmlFile.replace(new RegExp(`^${root}[\\/]`), '')
219
225
  const dest = resolve(_outDirResolved, relPath)