@loomweaver/devkit 0.7.2

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 (100) hide show
  1. package/README.md +127 -0
  2. package/generators.json +41 -0
  3. package/package.json +38 -0
  4. package/src/generators/auth-source/generator.d.ts +4 -0
  5. package/src/generators/auth-source/generator.js +17 -0
  6. package/src/generators/auth-source/generator.js.map +1 -0
  7. package/src/generators/auth-source/schema.json +18 -0
  8. package/src/generators/distribution/generator.d.ts +4 -0
  9. package/src/generators/distribution/generator.js +61 -0
  10. package/src/generators/distribution/generator.js.map +1 -0
  11. package/src/generators/distribution/nx-files.d.ts +22 -0
  12. package/src/generators/distribution/nx-files.js +133 -0
  13. package/src/generators/distribution/nx-files.js.map +1 -0
  14. package/src/generators/distribution/schema.json +48 -0
  15. package/src/generators/frame-plugin/generator.d.ts +4 -0
  16. package/src/generators/frame-plugin/generator.js +20 -0
  17. package/src/generators/frame-plugin/generator.js.map +1 -0
  18. package/src/generators/frame-plugin/schema.json +22 -0
  19. package/src/generators/layout/generator.d.ts +4 -0
  20. package/src/generators/layout/generator.js +17 -0
  21. package/src/generators/layout/generator.js.map +1 -0
  22. package/src/generators/layout/schema.json +17 -0
  23. package/src/generators/nx-scaffold-shared.d.ts +32 -0
  24. package/src/generators/nx-scaffold-shared.js +87 -0
  25. package/src/generators/nx-scaffold-shared.js.map +1 -0
  26. package/src/generators/settings-store/generator.d.ts +4 -0
  27. package/src/generators/settings-store/generator.js +17 -0
  28. package/src/generators/settings-store/generator.js.map +1 -0
  29. package/src/generators/settings-store/schema.json +18 -0
  30. package/src/generators/shared.d.ts +47 -0
  31. package/src/generators/shared.js +152 -0
  32. package/src/generators/shared.js.map +1 -0
  33. package/src/generators/theme/generator.d.ts +4 -0
  34. package/src/generators/theme/generator.js +17 -0
  35. package/src/generators/theme/generator.js.map +1 -0
  36. package/src/generators/theme/schema.json +24 -0
  37. package/src/generators/weaver/generator.d.ts +4 -0
  38. package/src/generators/weaver/generator.js +75 -0
  39. package/src/generators/weaver/generator.js.map +1 -0
  40. package/src/generators/weaver/nx-files.d.ts +26 -0
  41. package/src/generators/weaver/nx-files.js +73 -0
  42. package/src/generators/weaver/nx-files.js.map +1 -0
  43. package/src/generators/weaver/schema.json +97 -0
  44. package/src/index.d.ts +15 -0
  45. package/src/index.js +47 -0
  46. package/src/index.js.map +1 -0
  47. package/src/lib/generate/casing.d.ts +4 -0
  48. package/src/lib/generate/casing.js +27 -0
  49. package/src/lib/generate/casing.js.map +1 -0
  50. package/src/lib/generate/generate.d.ts +2 -0
  51. package/src/lib/generate/generate.js +18 -0
  52. package/src/lib/generate/generate.js.map +1 -0
  53. package/src/lib/generate/types.d.ts +5 -0
  54. package/src/lib/generate/types.js +3 -0
  55. package/src/lib/generate/types.js.map +1 -0
  56. package/src/lib/scaffolds/scaffolds.d.ts +37 -0
  57. package/src/lib/scaffolds/scaffolds.js +357 -0
  58. package/src/lib/scaffolds/scaffolds.js.map +1 -0
  59. package/src/lib/validate/catalog.d.ts +15 -0
  60. package/src/lib/validate/catalog.js +247 -0
  61. package/src/lib/validate/catalog.js.map +1 -0
  62. package/src/lib/validate/i18n.d.ts +3 -0
  63. package/src/lib/validate/i18n.js +41 -0
  64. package/src/lib/validate/i18n.js.map +1 -0
  65. package/src/lib/validate/manifest.d.ts +8 -0
  66. package/src/lib/validate/manifest.js +74 -0
  67. package/src/lib/validate/manifest.js.map +1 -0
  68. package/src/lib/validate/types.d.ts +7 -0
  69. package/src/lib/validate/types.js +3 -0
  70. package/src/lib/validate/types.js.map +1 -0
  71. package/src/recipes/angular-distribution/logo.d.ts +1 -0
  72. package/src/recipes/angular-distribution/logo.js +9 -0
  73. package/src/recipes/angular-distribution/logo.js.map +1 -0
  74. package/src/recipes/angular-distribution/recipe.d.ts +25 -0
  75. package/src/recipes/angular-distribution/recipe.js +407 -0
  76. package/src/recipes/angular-distribution/recipe.js.map +1 -0
  77. package/src/recipes/angular-weaver/recipe.d.ts +48 -0
  78. package/src/recipes/angular-weaver/recipe.js +568 -0
  79. package/src/recipes/angular-weaver/recipe.js.map +1 -0
  80. package/src/recipes/angular-weaver/weaver-i18n.d.ts +3 -0
  81. package/src/recipes/angular-weaver/weaver-i18n.js +24 -0
  82. package/src/recipes/angular-weaver/weaver-i18n.js.map +1 -0
  83. package/src/recipes/auth-source/recipe.d.ts +11 -0
  84. package/src/recipes/auth-source/recipe.js +61 -0
  85. package/src/recipes/auth-source/recipe.js.map +1 -0
  86. package/src/recipes/frame-plugin/recipe.d.ts +11 -0
  87. package/src/recipes/frame-plugin/recipe.js +143 -0
  88. package/src/recipes/frame-plugin/recipe.js.map +1 -0
  89. package/src/recipes/layout/recipe.d.ts +10 -0
  90. package/src/recipes/layout/recipe.js +35 -0
  91. package/src/recipes/layout/recipe.js.map +1 -0
  92. package/src/recipes/settings-store/recipe.d.ts +10 -0
  93. package/src/recipes/settings-store/recipe.js +51 -0
  94. package/src/recipes/settings-store/recipe.js.map +1 -0
  95. package/src/recipes/shell-regions.d.ts +9 -0
  96. package/src/recipes/shell-regions.js +23 -0
  97. package/src/recipes/shell-regions.js.map +1 -0
  98. package/src/recipes/theme/recipe.d.ts +13 -0
  99. package/src/recipes/theme/recipe.js +142 -0
  100. package/src/recipes/theme/recipe.js.map +1 -0
@@ -0,0 +1,407 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.angularDistribution = void 0;
4
+ exports.resolveDistributionInput = resolveDistributionInput;
5
+ const casing_1 = require("../../lib/generate/casing");
6
+ const shell_regions_1 = require("../shell-regions");
7
+ const logo_1 = require("./logo");
8
+ const STYLES = ['tailwind', 'precompiled'];
9
+ function resolveDistributionInput(input) {
10
+ var _a, _b;
11
+ if (!(0, casing_1.isKebabId)(input.name)) {
12
+ throw new Error(`Distribution name must be kebab-case (e.g. "acme-studio"); got "${input.name}".`);
13
+ }
14
+ const styles = (_a = input.styles) !== null && _a !== void 0 ? _a : 'tailwind';
15
+ if (!STYLES.includes(styles)) {
16
+ throw new Error(`Unknown styles option "${styles}"; expected one of ${STYLES.join(', ')}.`);
17
+ }
18
+ const directory = input.directory === undefined
19
+ ? `apps/${input.name}`
20
+ : input.directory.trim();
21
+ const depth = directory.split('/').filter(Boolean).length;
22
+ return {
23
+ name: input.name,
24
+ title: ((_b = input.title) === null || _b === void 0 ? void 0 : _b.trim()) || (0, casing_1.toTitleCase)(input.name),
25
+ nodeModulesFromSrc: `${'../'.repeat(depth + 1)}node_modules`,
26
+ withTests: input.withTests !== false,
27
+ styles,
28
+ };
29
+ }
30
+ function mainTs() {
31
+ return `import { bootstrapApplication } from '@angular/platform-browser';
32
+ import { appConfig } from './app/app.config';
33
+ import { App } from './app/app';
34
+
35
+ bootstrapApplication(App, appConfig).catch((err) => console.error(err));
36
+ `;
37
+ }
38
+ function appConfigTs(d) {
39
+ return `import { ApplicationConfig } from '@angular/core';
40
+ import {
41
+ provideLayout,
42
+ provideShell,
43
+ provideShellRouter,
44
+ type ShellLayout,
45
+ } from '@loomweaver/shell';
46
+ import { provideProductIdentity } from '@loomweaver/plugin-sdk';
47
+
48
+ /* Which regions exist and where they dock. Contributions target these ids, so a region a
49
+ weaver names but this layout omits renders nothing — silently. 'primary' (rail) and
50
+ 'status-bar' (bar) are what the scaffolded weaver targets. */
51
+ export const layout: ShellLayout = {
52
+ regions: [
53
+ ${(0, shell_regions_1.renderRegions)(' ')}
54
+ ],
55
+ };
56
+
57
+ /* Everything this product is made of goes in this array: your weavers, their capability
58
+ grants and your branding. The shell arrives with every capability on; switch gestures
59
+ off with provideShellFeatures and drop contributions with provideShell({ omit }).
60
+ See LOOMWEAVER.md. */
61
+ export const appConfig: ApplicationConfig = {
62
+ providers: [
63
+ provideShellRouter(),
64
+ provideShell(),
65
+ provideLayout(layout),
66
+ provideProductIdentity({
67
+ name: '${d.title}',
68
+ tagline: 'Built on LoomWeaver',
69
+ logoUrl: 'logo.svg',
70
+ }),
71
+ ],
72
+ };
73
+ `;
74
+ }
75
+ function appTs() {
76
+ return `import { Component } from '@angular/core';
77
+ import { Shell } from '@loomweaver/shell';
78
+
79
+ @Component({
80
+ selector: 'app-root',
81
+ imports: [Shell],
82
+ templateUrl: './app.html',
83
+ })
84
+ export class App {}
85
+ `;
86
+ }
87
+ function appHtml() {
88
+ return `<lw-shell />\n`;
89
+ }
90
+ function appConfigSpec() {
91
+ return `import { layout } from './app.config';
92
+
93
+ /* A green starting point that pins the one trap the compiler cannot catch: a contribution aimed at
94
+ a region id this layout omits renders nothing, and says nothing. List the ids your weavers target
95
+ here, and this fails the day someone edits the layout instead of failing in the browser. */
96
+ describe('layout', () => {
97
+ it('declares the regions contributions target', () => {
98
+ const ids = layout.regions.map((region) => region.id);
99
+ for (const id of ['primary', 'status-bar', 'main']) {
100
+ expect(ids).toContain(id);
101
+ }
102
+ });
103
+ });
104
+ `;
105
+ }
106
+ function indexHtml(d) {
107
+ return `<!DOCTYPE html>
108
+ <html lang="en">
109
+ <head>
110
+ <meta charset="utf-8" />
111
+ <title>${d.title}</title>
112
+ <base href="/" />
113
+ <meta
114
+ http-equiv="Content-Security-Policy"
115
+ content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; frame-src 'self'; object-src 'none'; base-uri 'self'"
116
+ />
117
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
118
+ <meta name="theme-color" content="#2E96C9" />
119
+ <link rel="icon" type="image/svg+xml" href="logo.svg" />
120
+ <link rel="manifest" href="manifest.webmanifest" />
121
+ </head>
122
+ <body>
123
+ <app-root></app-root>
124
+ </body>
125
+ </html>
126
+ `;
127
+ }
128
+ function precompiledCss() {
129
+ return `/* The stylesheet we compiled: the design tokens, the .lw-* class contracts and every utility
130
+ the shell's own templates use. This application needs no Tailwind to build.
131
+
132
+ BRINGING YOUR OWN CSS FRAMEWORK? Import it INTO A CASCADE LAYER. Every rule we ship is layered,
133
+ and unlayered CSS outranks layered CSS whatever its specificity — so an unlayered Bootstrap
134
+ Reboot (button { border-radius: 0 }) strips the chrome's radii and borders without a fight.
135
+ A @layer statement is one of the few things allowed before @import:
136
+
137
+ @layer vendor;
138
+ @import 'bootstrap/dist/css/bootstrap.css' layer(vendor);
139
+
140
+ Then re-theme by pointing the --lw-* tokens at your framework's variables. For Bootstrap 5.3 the
141
+ whole 29-token mapping is a scaffold:
142
+
143
+ loomweaver theme --name acme --preset bootstrap
144
+ @import './themes/acme.css'; (after the import below) */
145
+
146
+ @import '@loomweaver/shell/styles/shell.css';
147
+ `;
148
+ }
149
+ function tailwindCss(d) {
150
+ return `@import 'tailwindcss';
151
+
152
+ /* LoomWeaver design tokens + theme (light/dark, brand colors). Every @import has to precede the
153
+ other at-rules below: that is what plain CSS requires, and it is what keeps editors from
154
+ flagging a misplaced @import in a file you did not write. */
155
+ @import '@loomweaver/shell/styles/theme.css';
156
+
157
+ @plugin '@tailwindcss/typography';
158
+
159
+ /* Generate the utility classes the shell (and your own components) use. The @source path must
160
+ reach your workspace's node_modules FROM THIS FILE — adjust the ../ hops if this project does
161
+ not sit at that depth, or Tailwind silently emits none of the shell's classes. */
162
+ @source '${d.nodeModulesFromSrc}/@loomweaver/shell';
163
+ @source './';
164
+ `;
165
+ }
166
+ function stylesCss(d) {
167
+ return d.styles === 'precompiled' ? precompiledCss() : tailwindCss(d);
168
+ }
169
+ function ngswConfig() {
170
+ return JSON.stringify({
171
+ $schema: './node_modules/@angular/service-worker/config/schema.json',
172
+ index: '/index.html',
173
+ assetGroups: [
174
+ {
175
+ name: 'app',
176
+ installMode: 'prefetch',
177
+ resources: {
178
+ files: ['/index.html', '/manifest.webmanifest', '/*.css', '/*.js'],
179
+ },
180
+ },
181
+ {
182
+ name: 'i18n',
183
+ installMode: 'prefetch',
184
+ updateMode: 'prefetch',
185
+ resources: {
186
+ files: ['/i18n/**/*.json'],
187
+ },
188
+ },
189
+ {
190
+ name: 'assets',
191
+ installMode: 'lazy',
192
+ updateMode: 'prefetch',
193
+ resources: {
194
+ files: [
195
+ '/**/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2|ico)',
196
+ ],
197
+ },
198
+ },
199
+ ],
200
+ }, null, 2);
201
+ }
202
+ function manifest(d) {
203
+ return JSON.stringify({
204
+ name: d.title,
205
+ short_name: d.title,
206
+ description: `${d.title} — a LoomWeaver distribution.`,
207
+ start_url: '/',
208
+ display: 'standalone',
209
+ background_color: '#ffffff',
210
+ theme_color: '#2E96C9',
211
+ icons: [{ src: 'logo.svg', type: 'image/svg+xml', sizes: 'any' }],
212
+ }, null, 2);
213
+ }
214
+ function stylesNotes(d) {
215
+ if (d.styles === 'precompiled') {
216
+ return [
217
+ '`src/styles.css` imports the stylesheet **we** compiled — tokens, the `.lw-*` class contracts',
218
+ "and every utility the shell's own templates use, 67 KB minified and 11 KB over the wire. There",
219
+ 'is nothing to install and nothing to configure: no `tailwindcss`, no `.postcssrc.json`, no',
220
+ '`@source` paths to miscount.',
221
+ '',
222
+ 'What you give up is writing Tailwind utilities in *your own* templates. The `--lw-*` tokens stay',
223
+ 'available to any CSS you write, so re-theming stays a token remap rather than a fight.',
224
+ '',
225
+ 'If you bring a CSS framework of your own, **import it into a cascade layer** — the file says how,',
226
+ 'and it is the one decision that determines whether the chrome survives the introduction. Prefer',
227
+ 'Tailwind after all? Re-run the scaffold with `--styles tailwind`.',
228
+ ];
229
+ }
230
+ return [
231
+ "`src/styles.css` compiles the shell's source theme with Tailwind 4, which is also what lets you",
232
+ 'write Tailwind utilities in your own templates. It needs two things the scaffold cannot add for',
233
+ 'you — the packages:',
234
+ '',
235
+ '```sh',
236
+ 'npm install -D tailwindcss @tailwindcss/postcss @tailwindcss/typography',
237
+ '```',
238
+ '',
239
+ 'and the PostCSS plugin, in a file next to your `package.json`:',
240
+ '',
241
+ '```jsonc',
242
+ '// .postcssrc.json',
243
+ '{ "plugins": { "@tailwindcss/postcss": {} } }',
244
+ '```',
245
+ '',
246
+ 'Use **semantic tokens only** in your own templates (`bg-surface`, `text-content`, `text-brand`,',
247
+ '`border-border`), never raw palette colours.',
248
+ '',
249
+ '**Count the `../` hops in the `@source` line.** It is resolved from the stylesheet, not from the',
250
+ 'workspace root, and the scaffold derived it from where this project sits. Move the project and',
251
+ "nothing errors — Tailwind simply emits none of the shell's classes and the app renders unstyled.",
252
+ '',
253
+ 'Want none of this? Re-run the scaffold with `--styles precompiled` and you get a one-line',
254
+ 'stylesheet that needs no Tailwind at all — the right choice if your product is themed with',
255
+ 'Bootstrap, Bulma or hand-written CSS.',
256
+ ];
257
+ }
258
+ function readme(d) {
259
+ return [
260
+ `# ${d.title} — a LoomWeaver distribution`,
261
+ '',
262
+ `The composition root that assembles the platform into a shippable product. It renders the bare`,
263
+ `shell out of the box; add your weavers and branding below. Your own README is untouched — the`,
264
+ `scaffold writes its notes here so it can never overwrite prose you wrote.`,
265
+ '',
266
+ '## Run it',
267
+ '',
268
+ 'In an Nx workspace (the generator wired the project):',
269
+ '',
270
+ '```sh',
271
+ `nx serve ${d.name}`,
272
+ '```',
273
+ '',
274
+ 'Scaffolded over the CLI or MCP, these files are sources without build wiring — drop them into',
275
+ "an application you already serve (`ng new`, or an Nx application). They keep Angular's own",
276
+ 'shape: `main.ts` bootstraps `App`, `App` renders `<lw-shell />`, and everything this product is',
277
+ 'made of lives in `app.config.ts`. Nothing of the generated app is deleted. Over an existing',
278
+ 'application `--force` replaces exactly the files above — all of them bootstrap wiring, none of',
279
+ 'them content you authored. Under Nx it additionally merges the build targets into that',
280
+ "project's `project.json`, keeping the targets, `implicitDependencies` and tags it already had.",
281
+ '',
282
+ 'Two leftovers from `ng new` are no longer referenced and can go: `src/app/app.routes.ts` (the',
283
+ 'shell owns content routing via `provideShellRouter()`) and `src/app/app.css`. The generated',
284
+ '`src/app/app.spec.ts` now fails — `App` pulls the whole shell into a bare `TestBed` — so delete',
285
+ 'it and test your own components instead of the composition root.',
286
+ '',
287
+ 'The project is generated **untagged**: Nx tags belong to your `depConstraints`, and inventing',
288
+ 'one would fail a lint policy you never opted this project into. If your workspace enforces',
289
+ 'module boundaries, give it tags your constraints allow — `--tags` at generation time, or',
290
+ '`tags` in `project.json` afterwards.',
291
+ '',
292
+ '## Compose weavers + branding (in `src/app/app.config.ts`)',
293
+ '',
294
+ 'The layout is already there. Adding a weaver is three providers plus its import — note the',
295
+ '**spread**, since `providePlugins` is variadic and returns an array:',
296
+ '',
297
+ '```ts',
298
+ "import { providePlugins, provideCapabilityGrants, provideTranslationNamespaces } from '@loomweaver/shell';",
299
+ "import { notesPlugin } from '@acme/notes-weaver'; // Nx: the workspace alias; otherwise a relative path",
300
+ '',
301
+ " provideTranslationNamespaces('notes'),",
302
+ " provideCapabilityGrants({ notes: ['contributions', 'ui', 'navigation'] }),",
303
+ ' ...providePlugins(notesPlugin),',
304
+ '```',
305
+ '',
306
+ "Grant exactly what the weaver's manifest declares — the broker is default-deny, so an ungranted",
307
+ 'plugin throws `CapabilityError` instead of quietly doing less. A weaver also needs its',
308
+ 'translations served: add an assets glob for its `src/lib/i18n` under `i18n/<id>` (the Nx',
309
+ 'generator does this for you).',
310
+ '',
311
+ '`public/logo.svg` is the LoomWeaver mark, dropped in as a placeholder so the top bar renders',
312
+ 'something from the first run instead of a broken image. Replace it with your own — any square',
313
+ 'image will do; `logoUrl` resolves against your served root. `tagline` is a',
314
+ 'translation key that falls back to rendering itself, so the literal above works but makes',
315
+ 'Transloco log a missing-translation warning in dev; point it at a key of your own to silence it.',
316
+ '',
317
+ 'That same file is also the **app icon**: the browser tab reads it, and the manifest names it so',
318
+ 'the app has an icon at all. One gap is left on purpose, because a scaffold writes text and',
319
+ 'cannot invent your artwork: **Chromium only offers installation once the manifest names a 192',
320
+ 'and a 512 raster icon**, and iOS ignores manifest icons entirely in favour of',
321
+ '`apple-touch-icon`. Drop `icon-192.png` and `icon-512.png` next to the logo, add them to the',
322
+ "manifest's `icons` and add an `apple-touch-icon` link to `index.html`, and the app becomes",
323
+ 'installable. Until then it runs and caches offline, it simply is not offered for installation.',
324
+ '',
325
+ '## Styles',
326
+ '',
327
+ ...stylesNotes(d),
328
+ '',
329
+ '## Build wiring',
330
+ '',
331
+ 'The Nx generator put all of this in `project.json`. Scaffolded over the CLI or MCP, add it to',
332
+ 'your build target yourself — `angular.json` under `projects.<name>.architect.build.options` with',
333
+ 'the Angular CLI, `project.json` under `targets.build.options` in Nx. Paths inside `assets` are',
334
+ 'resolved from the workspace root, so they read the same either way:',
335
+ '',
336
+ '```jsonc',
337
+ '"styles": ["src/styles.css"],',
338
+ '"assets": [',
339
+ ' { "glob": "**/*", "input": "public" },',
340
+ ' { "glob": "**/*", "input": "node_modules/@loomweaver/shell/i18n", "output": "i18n" },',
341
+ ' { "glob": "**/*", "input": "node_modules/@loomweaver/frame-kit/dist", "output": "frame-kit" }',
342
+ '],',
343
+ '"serviceWorker": "ngsw-config.json"',
344
+ '```',
345
+ '',
346
+ 'And in the **production** configuration of that same target:',
347
+ '',
348
+ '```jsonc',
349
+ '"optimization": { "styles": { "inlineCritical": false } }',
350
+ '```',
351
+ '',
352
+ 'Each of those earns its place. The **`@loomweaver/shell/i18n` glob** is the one whose absence is easy',
353
+ 'to misread: the shell fetches its own UI strings at runtime, so without it every label in the',
354
+ 'chrome renders as its raw translation key and nothing errors. The **frame-kit** glob only',
355
+ 'matters if you host sandboxed (iframe) plugins — install that package then; until you do, the',
356
+ 'glob simply matches nothing. **`serviceWorker`** emits the worker that `provideShell()` already',
357
+ 'registers for you (inert in dev) — never add `provideServiceWorker` yourself, and if you would',
358
+ 'rather ship no worker at all, drop `ngsw-config.json` and pass',
359
+ '`provideShell({ serviceWorker: false })`, because otherwise the registration 404s in production.',
360
+ '**`inlineCritical: false`** is not optional here: the `index.html` above ships a strict',
361
+ "`script-src 'self'`, and Angular's critical-CSS pass loads the stylesheet with an **inline**",
362
+ '`onload` handler that the policy blocks — the app then renders completely unstyled, and only in',
363
+ 'production builds.',
364
+ '',
365
+ '## Ship less than the whole workbench',
366
+ '',
367
+ 'The shell arrives with every capability on: splitting, dragging tabs between panes, pinning,',
368
+ 'stacking views, pop-out windows, keyboard shortcuts, the curation checklists. A product whose',
369
+ 'users would be overwhelmed by that switches parts off in the same providers array:',
370
+ '',
371
+ '```ts',
372
+ "import { provideShellFeatures } from '@loomweaver/shell';",
373
+ '',
374
+ ' provideShellFeatures({',
375
+ ' content: { splitRight: false, splitDown: false, moveTabs: false },',
376
+ ' sidebar: { stackViews: false },',
377
+ ' windows: { popout: false },',
378
+ ' }),',
379
+ '```',
380
+ '',
381
+ 'A switch takes the **affordance and the gesture**: turning `splitRight` off removes the toolbar',
382
+ 'button, the drop edges *and* `mod+\\`, so the capability cannot come back through a second door.',
383
+ 'Fields merge group by group, so name only what you turn off. The groups are `content`,',
384
+ '`sidebar`, `rail`, `workspaces`, `windows` and `commands`; everything is on by default except',
385
+ '`content.escalate`, the unlabelled double-click cycle on a tab.',
386
+ '',
387
+ 'That provider is for **gestures**. A command, a bar or rail item, a settings row or a menu entry',
388
+ 'is a *contribution* and goes instead — by id — into `provideShell({ omit: [...] })`. Where a',
389
+ 'capability is both, the feature switch wins and takes the menu entry with it.',
390
+ '',
391
+ 'A product backend is optional: implement the settings-store / auth-source ports',
392
+ '(`provideSettingsStore` / `provideAuthSource`, both against the `KeyValueStore` shape)',
393
+ 'with your own backend, or keep the local/anonymous defaults for a standalone UI.',
394
+ 'Working state stays on `WORKING_STATE_STORE` and never reaches your',
395
+ 'settings backend; back it separately with `provideWorkingStateStore` only if',
396
+ 'working state should travel across devices.',
397
+ '',
398
+ ].join('\n');
399
+ }
400
+ exports.angularDistribution = {
401
+ id: 'angular-distribution',
402
+ build(input) {
403
+ const d = resolveDistributionInput(input);
404
+ return Object.assign(Object.assign({ 'src/main.ts': mainTs(), 'src/app/app.config.ts': appConfigTs(d) }, (d.withTests ? { 'src/app/app.config.spec.ts': appConfigSpec() } : {})), { 'src/app/app.ts': appTs(), 'src/app/app.html': appHtml(), 'src/index.html': indexHtml(d), 'src/styles.css': stylesCss(d), 'public/logo.svg': logo_1.PLACEHOLDER_LOGO_SVG, 'public/manifest.webmanifest': manifest(d) + '\n', 'ngsw-config.json': ngswConfig() + '\n', 'LOOMWEAVER.md': readme(d) });
405
+ },
406
+ };
407
+ //# sourceMappingURL=recipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe.js","sourceRoot":"","sources":["../../../../../../../libs/tooling/devkit/src/recipes/angular-distribution/recipe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { Recipe } from '../../lib/generate/types';
2
+ export interface WeaverFeatures {
3
+ readonly command?: boolean;
4
+ readonly menu?: string | boolean;
5
+ readonly settings?: boolean;
6
+ readonly access?: string;
7
+ readonly shortcut?: string;
8
+ readonly barItem?: boolean;
9
+ readonly about?: boolean;
10
+ readonly instanceable?: boolean;
11
+ readonly container?: boolean;
12
+ readonly spec?: boolean;
13
+ }
14
+ export interface WeaverInput {
15
+ readonly id: string;
16
+ readonly name?: string;
17
+ readonly capabilities?: readonly string[];
18
+ readonly features?: WeaverFeatures;
19
+ /** Selector prefix for the generated components. Defaults to 'lw'. */
20
+ readonly prefix?: string;
21
+ /** The alias the consuming workspace imports the library under. Defaults to '@loomweaver/<id>-weaver'. */
22
+ readonly importPath?: string;
23
+ }
24
+ interface ResolvedFeatures {
25
+ readonly command: boolean;
26
+ readonly menuSlot?: string;
27
+ readonly settings: boolean;
28
+ readonly access?: string;
29
+ readonly shortcut: string;
30
+ readonly barItem: boolean;
31
+ readonly about: boolean;
32
+ readonly instanceable: boolean;
33
+ readonly container: boolean;
34
+ readonly spec: boolean;
35
+ }
36
+ export interface ResolvedWeaver {
37
+ readonly id: string;
38
+ readonly name: string;
39
+ readonly className: string;
40
+ readonly propertyName: string;
41
+ readonly capabilities: readonly string[];
42
+ readonly features: ResolvedFeatures;
43
+ readonly prefix: string;
44
+ readonly importPath: string;
45
+ }
46
+ export declare function resolveWeaverInput(input: WeaverInput): ResolvedWeaver;
47
+ export declare const angularWeaver: Recipe<WeaverInput>;
48
+ export {};