kmcom-nuxt-layers 2.2.11 → 2.2.13

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 (128) hide show
  1. package/docs/FALLOW-COMPLEXITY-DUPLICATION-AUDIT.md +65 -0
  2. package/docs/FEEDS.md +1 -2
  3. package/docs/IMPROVE-AUDIT-README.md +30 -0
  4. package/docs/IMPROVE-AUDIT-RESULTS.md +52 -0
  5. package/docs/IMPROVE-DEEP-AUDIT-RESULTS.md +81 -0
  6. package/docs/fallow-refactor/apps-debug.md +27 -0
  7. package/docs/fallow-refactor/apps-playground.md +46 -0
  8. package/docs/fallow-refactor/apps-visual-identity.md +41 -0
  9. package/docs/fallow-refactor/layers-animations.md +34 -0
  10. package/docs/fallow-refactor/layers-canvas.md +32 -0
  11. package/docs/fallow-refactor/layers-content.md +33 -0
  12. package/docs/fallow-refactor/layers-core.md +39 -0
  13. package/docs/fallow-refactor/layers-feeds.md +39 -0
  14. package/docs/fallow-refactor/layers-forms.md +30 -0
  15. package/docs/fallow-refactor/layers-layout.md +42 -0
  16. package/docs/fallow-refactor/layers-mailer.md +32 -0
  17. package/docs/fallow-refactor/layers-motion.md +27 -0
  18. package/docs/fallow-refactor/layers-navigation.md +31 -0
  19. package/docs/fallow-refactor/layers-page-transitions.md +30 -0
  20. package/docs/fallow-refactor/layers-routing.md +33 -0
  21. package/docs/fallow-refactor/layers-scripts.md +35 -0
  22. package/docs/fallow-refactor/layers-scroll.md +38 -0
  23. package/docs/fallow-refactor/layers-seo.md +32 -0
  24. package/docs/fallow-refactor/layers-shader.md +53 -0
  25. package/docs/fallow-refactor/layers-theme.md +33 -0
  26. package/docs/fallow-refactor/layers-transitions.md +27 -0
  27. package/docs/fallow-refactor/layers-typography.md +29 -0
  28. package/docs/fallow-refactor/layers-ui.md +27 -0
  29. package/docs/fallow-refactor/layers-visual.md +34 -0
  30. package/layers/animations/app/composables/useMagneticElement.ts +11 -9
  31. package/layers/animations/app/composables/useTiltEffect.ts +11 -9
  32. package/layers/animations/app/utils/pointerMotion.ts +31 -0
  33. package/layers/canvas/app/components/ShaderCanvas.vue +2 -2
  34. package/layers/content/app/composables/useCollectionItems.ts +28 -0
  35. package/layers/content/app/composables/useGalleryItems.ts +8 -14
  36. package/layers/content/app/composables/usePortfolioItems.ts +10 -18
  37. package/layers/core/app/composables/useBrowser.ts +9 -82
  38. package/layers/core/app/composables/useFeatures.ts +3 -27
  39. package/layers/core/app/plugins/init.ts +157 -135
  40. package/layers/core/app/utils/browserInfo.ts +115 -0
  41. package/layers/core/app/utils/featureClasses.ts +40 -0
  42. package/layers/core/app/utils/helpers.test.ts +51 -0
  43. package/layers/feeds/app/app.config.ts +4 -2
  44. package/layers/feeds/app/components/Feeds/Index.vue +229 -0
  45. package/layers/feeds/app/components/Feeds/RouteCard.vue +75 -0
  46. package/layers/feeds/app/plugins/feed-head.ts +27 -49
  47. package/layers/feeds/app/utils/feed-catalog.ts +184 -0
  48. package/layers/feeds/nuxt.config.ts +0 -1
  49. package/layers/feeds/package.json +1 -0
  50. package/layers/feeds/server/utils/content-adapter.test.ts +68 -0
  51. package/layers/feeds/server/utils/content-adapter.ts +2 -22
  52. package/layers/feeds/server/utils/feed-author.ts +32 -0
  53. package/layers/feeds/server/utils/feed-config.ts +88 -0
  54. package/layers/feeds/server/utils/feed-service.ts +11 -30
  55. package/layers/feeds/server/utils/feed-xml.ts +26 -0
  56. package/layers/feeds/server/utils/formats/rss.ts +10 -15
  57. package/layers/feeds/server/utils/formats.test.ts +71 -0
  58. package/layers/forms/app/components/Form/Field.vue +42 -30
  59. package/layers/forms/app/utils/fieldProps.ts +65 -0
  60. package/layers/layout/app/components/Layout/Grid/Item.vue +29 -146
  61. package/layers/layout/app/utils/gridPlacementStyle.ts +195 -0
  62. package/layers/mailer/app/types/mailer.ts +7 -25
  63. package/layers/mailer/server/utils/email.ts +28 -13
  64. package/layers/mailer/server/utils/hooks.ts +1 -20
  65. package/layers/navigation/app/composables/useSite.ts +2 -9
  66. package/layers/navigation/app/utils/site.ts +26 -0
  67. package/layers/routing/app/utils/resolveRoute.test.ts +47 -0
  68. package/layers/routing/app/utils/resolveRoute.ts +19 -10
  69. package/layers/scripts/app/composables/useAnalytics.ts +8 -41
  70. package/layers/scripts/app/composables/useGtm.ts +6 -13
  71. package/layers/scripts/app/utils/scriptClients.ts +70 -0
  72. package/layers/scroll/app/composables/useSmoothScroll.ts +9 -43
  73. package/layers/scroll/app/utils/scroll.ts +103 -0
  74. package/layers/seo/app/composables/useSeoConfig.ts +3 -9
  75. package/layers/seo/app/utils/seoConfig.ts +38 -0
  76. package/layers/shader/app/components/Material/AmbientAurora.client.vue +11 -33
  77. package/layers/shader/app/components/Material/AmbientFlow.client.vue +10 -37
  78. package/layers/shader/app/components/Material/AmbientGradientMesh.client.vue +10 -37
  79. package/layers/shader/app/components/Material/AmbientNebula.client.vue +12 -37
  80. package/layers/shader/app/components/Material/AmbientOcean.client.vue +9 -33
  81. package/layers/shader/app/components/Material/Gradient.client.vue +25 -46
  82. package/layers/shader/app/components/Material/Image.client.vue +10 -55
  83. package/layers/shader/app/components/Material/Node.client.vue +18 -5
  84. package/layers/shader/app/components/Material/Noise.client.vue +9 -43
  85. package/layers/shader/app/components/Preset/ThemeBubble.client.vue +2 -1
  86. package/layers/shader/app/components/Preset/ThemeFlow.client.vue +2 -1
  87. package/layers/shader/app/components/Preset/ThemeGradient.client.vue +2 -1
  88. package/layers/shader/app/components/Preset/ThemeLavaLamp.client.vue +2 -1
  89. package/layers/shader/app/components/Preset/ThemePlasma.client.vue +2 -1
  90. package/layers/shader/app/components/Preset/ThemeWave.client.vue +2 -1
  91. package/layers/shader/app/components/Shader/Background.client.vue +44 -24
  92. package/layers/shader/app/composables/useAmbientMaterials.ts +5 -1
  93. package/layers/shader/app/composables/useShader.ts +38 -23
  94. package/layers/shader/app/composables/useShaderGraph.ts +11 -6
  95. package/layers/shader/app/composables/useShaderMixBlend.ts +4 -4
  96. package/layers/shader/app/composables/useShaderRuntime.ts +0 -1
  97. package/layers/shader/app/composables/useShaderVec2.ts +2 -4
  98. package/layers/shader/app/composables/useThemePreset.ts +34 -8
  99. package/layers/shader/app/composables/useUniformWatchers.ts +15 -0
  100. package/layers/shader/app/composables/useUniforms.ts +0 -1
  101. package/layers/shader/app/shaders/common/blend.ts +4 -4
  102. package/layers/shader/app/shaders/common/effects.ts +38 -21
  103. package/layers/shader/app/shaders/common/grain.ts +46 -49
  104. package/layers/shader/app/shaders/common/lighting.ts +17 -15
  105. package/layers/shader/app/shaders/common/math.ts +2 -4
  106. package/layers/shader/app/shaders/common/nodes.ts +17 -0
  107. package/layers/shader/app/shaders/common/palette.ts +21 -11
  108. package/layers/shader/app/shaders/common/patterns.ts +25 -14
  109. package/layers/shader/app/shaders/common/shapes.ts +97 -88
  110. package/layers/shader/app/shaders/common/uv.ts +33 -34
  111. package/layers/shader/app/shaders/createMaterial.ts +92 -78
  112. package/layers/shader/app/shaders/layers/paperShading.ts +22 -10
  113. package/layers/shader/app/shaders/layers/shaderGradient.ts +46 -21
  114. package/layers/shader/app/utils/tsl/tween.ts +2 -4
  115. package/layers/shader/package.json +5 -1
  116. package/layers/theme/app/components/ThemePicker/Menu.vue +3 -25
  117. package/layers/theme/app/composables/useThemePreferenceModels.ts +39 -0
  118. package/layers/theme/server/plugins/theme-fouc.ts +1 -92
  119. package/layers/theme/server/utils/accent-css.ts +75 -0
  120. package/layers/typography/app/composables/typography.ts +3 -7
  121. package/layers/visual/app/composables/accent.ts +2 -9
  122. package/layers/visual/app/composables/gradient.ts +33 -46
  123. package/layers/visual/app/composables/picture.ts +2 -79
  124. package/layers/visual/app/utils/colorTokens.ts +23 -0
  125. package/layers/visual/app/utils/gradientStyle.ts +41 -0
  126. package/layers/visual/app/utils/responsiveSizes.ts +49 -0
  127. package/package.json +17 -5
  128. package/layers/feeds/server/routes/feed/discovery.get.ts +0 -29
@@ -0,0 +1,32 @@
1
+ # layers/mailer
2
+
3
+ `layers/mailer` has one high-complexity email helper and one type-like duplicate group.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `1` complexity finding.
8
+ - `layers/mailer/server/utils/email.ts:9` defines `sendContactEmail` with high complexity.
9
+
10
+ ## Duplication Findings
11
+
12
+ - `2` duplicate warnings.
13
+ - `app/types/mailer.ts:7-24` duplicates `server/utils/hooks.ts:3-20`.
14
+
15
+ ## Component Opportunities
16
+
17
+ - No component extraction is relevant.
18
+
19
+ ## Composable Opportunities
20
+
21
+ - No composable extraction is recommended.
22
+
23
+ ## Utility Opportunities
24
+
25
+ - Move shared hook/event types into one importable type module.
26
+ - Split `sendContactEmail()` into payload validation, recipient resolution, template data creation, and provider send call.
27
+
28
+ ## Acceptance Criteria
29
+
30
+ - The duplicated mailer type block has one source of truth.
31
+ - Server email sending behavior remains unchanged.
32
+ - `pnpm typecheck` passes.
@@ -0,0 +1,27 @@
1
+ # layers/motion
2
+
3
+ `layers/motion` has no complexity or duplication findings in the current Fallow snapshot used for this audit.
4
+
5
+ ## Complexity Findings
6
+
7
+ - No current findings.
8
+
9
+ ## Duplication Findings
10
+
11
+ - No current findings in the supplied Problems export.
12
+
13
+ ## Component Opportunities
14
+
15
+ - No extraction is recommended.
16
+
17
+ ## Composable Opportunities
18
+
19
+ - No extraction is recommended.
20
+
21
+ ## Utility Opportunities
22
+
23
+ - No extraction is recommended.
24
+
25
+ ## Agent Notes
26
+
27
+ Do not create refactor work for this layer unless a later Fallow run introduces findings.
@@ -0,0 +1,31 @@
1
+ # layers/navigation
2
+
3
+ `layers/navigation` has a small high-complexity composable finding. It also has a circular dependency warning outside this scope, but this document focuses on complexity and duplication only.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `1` complexity finding.
8
+ - `layers/navigation/app/composables/useSite.ts:3` defines `useSite` with high complexity.
9
+
10
+ ## Duplication Findings
11
+
12
+ - No duplication warnings for this layer in the supplied Problems export.
13
+
14
+ ## Component Opportunities
15
+
16
+ - No component extraction is recommended from the current findings.
17
+
18
+ ## Composable Opportunities
19
+
20
+ - Keep `useSite()` as the public composable.
21
+
22
+ ## Utility Opportunities
23
+
24
+ - Extract site config default resolution into a pure helper.
25
+ - Use small helpers for title, subtitle, nav groups, and footer defaults if those branches exist in the composable.
26
+
27
+ ## Acceptance Criteria
28
+
29
+ - `useSite()` keeps its public return shape.
30
+ - Config fallback behavior remains unchanged.
31
+ - `pnpm typecheck` passes.
@@ -0,0 +1,30 @@
1
+ # layers/page-transitions
2
+
3
+ `layers/page-transitions` has only low-risk moderate complexity findings.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `2` complexity findings.
8
+ - Both are moderate.
9
+ - Main findings include `usePageTransition.ts:12` and `page-transitions.client.ts:3`.
10
+
11
+ ## Duplication Findings
12
+
13
+ - No duplication warnings for this layer in the supplied Problems export.
14
+
15
+ ## Component Opportunities
16
+
17
+ - No component extraction is recommended.
18
+
19
+ ## Composable Opportunities
20
+
21
+ - Keep `usePageTransition()` as the public API.
22
+
23
+ ## Utility Opportunities
24
+
25
+ - Extract transition config defaulting if more transition modes are added.
26
+
27
+ ## Acceptance Criteria
28
+
29
+ - No behavior changes to page transition config.
30
+ - `pnpm typecheck` passes.
@@ -0,0 +1,33 @@
1
+ # layers/routing
2
+
3
+ `layers/routing` has modest complexity in route resolution and middleware checks. Keep the public utility API stable.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `3` complexity findings.
8
+ - `1` critical finding.
9
+ - `layers/routing/app/utils/resolveRoute.ts:8` defines `resolveRoute` with cyclomatic complexity `10`.
10
+ - `layers/routing/nuxt.config.ts:27` and `middleware/02.governance.global.ts:4` have moderate findings.
11
+
12
+ ## Duplication Findings
13
+
14
+ - No duplication warnings for this layer in the supplied Problems export.
15
+
16
+ ## Component Opportunities
17
+
18
+ - No component extraction is relevant.
19
+
20
+ ## Composable Opportunities
21
+
22
+ - No composable extraction is recommended.
23
+
24
+ ## Utility Opportunities
25
+
26
+ - Split `resolveRoute()` into maintenance, strict deny, layer deny, and feature result helpers.
27
+ - Keep the exported `resolveRoute()` as the orchestration function.
28
+
29
+ ## Acceptance Criteria
30
+
31
+ - `resolveRoute()` keeps the same input and output contract.
32
+ - Individual rule helpers can be tested independently.
33
+ - `pnpm typecheck` passes.
@@ -0,0 +1,35 @@
1
+ # layers/scripts
2
+
3
+ `layers/scripts` has high-complexity script and analytics composables. Split consent decisions from script loading.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `2` complexity findings.
8
+ - Both are high.
9
+ - Main findings include `useAnalytics.ts:10` and `useGtm.ts:1`.
10
+ - Fallow also identifies `useScriptsConsent.ts` as a high-impact split target because several files depend on it.
11
+
12
+ ## Duplication Findings
13
+
14
+ - No duplication warnings for this layer in the supplied Problems export.
15
+
16
+ ## Component Opportunities
17
+
18
+ - No component extraction is relevant.
19
+
20
+ ## Composable Opportunities
21
+
22
+ - Keep `useAnalytics()`, `useGtm()`, and `useScriptsConsent()` as public APIs.
23
+ - Extract consent evaluation from script loading side effects.
24
+
25
+ ## Utility Opportunities
26
+
27
+ - Create `resolveScriptConsentState()`.
28
+ - Create `shouldLoadScriptProvider()`.
29
+ - Create provider-specific script config builders.
30
+
31
+ ## Acceptance Criteria
32
+
33
+ - Consent logic can be tested without loading scripts.
34
+ - Public composable return shapes stay stable.
35
+ - `pnpm typecheck` passes.
@@ -0,0 +1,38 @@
1
+ # layers/scroll
2
+
3
+ `layers/scroll` has complexity in scroll option handling and motion components. The work is mostly local function splitting.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `10` complexity findings.
8
+ - `2` critical findings.
9
+ - `layers/scroll/app/composables/useSmoothScroll.ts:63` defines `scrollTo`.
10
+ - `layers/scroll/app/composables/useSmoothScroll.ts:116` defines `nativeScrollTo`.
11
+ - `layers/scroll/app/components/Motion/Parallax.vue:41` has a high-complexity computed arrow function.
12
+
13
+ ## Duplication Findings
14
+
15
+ - No duplication warnings for this layer in the supplied Problems export.
16
+
17
+ ## Component Opportunities
18
+
19
+ - No new component is recommended.
20
+ - Keep existing motion components as the public API.
21
+
22
+ ## Composable Opportunities
23
+
24
+ - Keep `useSmoothScroll()` as the public API.
25
+ - Extract option normalization into helper functions inside the composable or a utility module.
26
+
27
+ ## Utility Opportunities
28
+
29
+ - Create `normalizeScrollTarget()`.
30
+ - Create `normalizeScrollOptions()`.
31
+ - Create `runNativeScroll()`.
32
+ - Create `resolveParallaxTransform()` for the Parallax component.
33
+
34
+ ## Acceptance Criteria
35
+
36
+ - `scrollTo` and `nativeScrollTo` become small orchestration functions.
37
+ - Scroll behavior remains unchanged for string selectors, elements, numbers, and top scrolling.
38
+ - `pnpm typecheck` passes.
@@ -0,0 +1,32 @@
1
+ # layers/seo
2
+
3
+ `layers/seo` has a small complexity finding in config resolution. Treat this as a low-risk utility cleanup.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `1` complexity finding.
8
+ - `1` critical finding.
9
+ - `layers/seo/app/composables/useSeoConfig.ts:1` defines `useSeoConfig` with cyclomatic complexity `11`.
10
+
11
+ ## Duplication Findings
12
+
13
+ - No duplication warnings for this layer in the supplied Problems export.
14
+
15
+ ## Component Opportunities
16
+
17
+ - No component extraction is relevant.
18
+
19
+ ## Composable Opportunities
20
+
21
+ - Keep `useSeoConfig()` as the public composable.
22
+
23
+ ## Utility Opportunities
24
+
25
+ - Extract config defaults into a pure resolver.
26
+ - Use small helpers for site metadata, Open Graph defaults, and optional feature flags.
27
+
28
+ ## Acceptance Criteria
29
+
30
+ - `useSeoConfig()` becomes a thin wrapper around pure resolvers.
31
+ - Existing SEO config output remains unchanged.
32
+ - `pnpm typecheck` passes.
@@ -0,0 +1,53 @@
1
+ # layers/shader
2
+
3
+ `layers/shader` dominates the duplication report. It also has several critical complexity findings, but most work should preserve public component names and extract shared internals.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `41` complexity findings.
8
+ - `6` critical findings.
9
+ - `layers/shader/app/composables/useShader.ts:38` defines `applyConfig` with cyclomatic complexity `18` and cognitive complexity `20`.
10
+ - Other critical findings include `Material/Gradient.client.vue`, `Material/Node.client.vue`, `Shader/Background.client.vue`, and shader layer uniform update functions.
11
+
12
+ ## Duplication Findings
13
+
14
+ - `341` duplicate warnings.
15
+ - `useAmbientMaterials.ts:272-368` duplicates `useAmbientMaterials.ts:496-563` for `97` lines.
16
+ - `Material/AmbientFlow.client.vue:22-102` duplicates `Material/AmbientNebula.client.vue:23-103` for `81` lines.
17
+ - `Material/AmbientGradientMesh.client.vue:30-100` duplicates `Material/AmbientNebula.client.vue:30-100` for `71` lines.
18
+ - `Material/AmbientAurora.client.vue:28-92` duplicates `Material/AmbientOcean.client.vue:30-94` for `65` lines.
19
+ - Many `Pipeline/*` components duplicate uniform setup and stage registration.
20
+ - `Preset/Theme*.client.vue` files share a repeated theme preset wrapper pattern.
21
+
22
+ ## Component Opportunities
23
+
24
+ - Create an internal material host component for repeated canvas and plane markup.
25
+ - Create a shared preset shell for ambient preset components.
26
+ - Consider `Preset/Theme.client.vue` with a `preset` prop, while keeping existing `Preset/ThemeWave.client.vue`, `Preset/ThemeAurora.client.vue`, and similar wrappers.
27
+
28
+ ## Composable Opportunities
29
+
30
+ - Create `useReactiveShaderUniforms()` for repeated prop-to-uniform watchers.
31
+ - Create `useAmbientMaterial()` for shared speed, intensity, mouse, and color uniforms.
32
+ - Create `usePipelineStageUniforms()` for repeated `uniform()` plus `watch()` setup in pipeline components.
33
+ - Create `useShaderMaterialPlane()` for material creation, disposal, and render-plane lifecycle.
34
+
35
+ ## Utility Opportunities
36
+
37
+ - Create `layers/shader/app/utils/materialConfig.ts` for `applyNodeMaterialConfig()`.
38
+ - Create `layers/shader/app/utils/uniformSetters.ts` for repeated uniform updates.
39
+ - Create `layers/shader/app/utils/tsl/ambient.ts` for mouse offset, radial falloff, flow warp, aurora curtain, and palette mixing helpers.
40
+ - Extract shared noise pipeline builders that accept a noise strategy and color strategy.
41
+
42
+ ## Refactor Constraints
43
+
44
+ - Do not collapse all public pipeline components into one dynamic component unless there is a migration plan.
45
+ - Keep public auto-import component files as thin wrappers if needed.
46
+ - Consolidate internals before changing public component APIs.
47
+
48
+ ## Acceptance Criteria
49
+
50
+ - The largest shader duplicate groups shrink materially.
51
+ - Public shader component names continue to auto-import.
52
+ - `applyConfig` drops below critical complexity.
53
+ - `pnpm typecheck` passes.
@@ -0,0 +1,33 @@
1
+ # layers/theme
2
+
3
+ `layers/theme` has one duplicate with the playground and one server-side CSS generation complexity finding.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `2` complexity findings.
8
+ - `layers/theme/server/plugins/theme-fouc.ts:86` defines `buildAccentCSS` with high complexity.
9
+ - `layers/theme/app/plugins/theme.client.ts:5` has a moderate setup finding.
10
+
11
+ ## Duplication Findings
12
+
13
+ - `1` duplicate warning.
14
+ - `ThemePicker/Menu.vue:12-27` duplicates `apps/playground/app/pages/theme.vue:29-45`.
15
+
16
+ ## Component Opportunities
17
+
18
+ - Keep the canonical theme picker menu in `layers/theme`.
19
+ - Update the playground theme page to consume the layer component instead of duplicating menu behavior.
20
+
21
+ ## Composable Opportunities
22
+
23
+ - No new composable is required from the current findings.
24
+
25
+ ## Utility Opportunities
26
+
27
+ - Split `buildAccentCSS()` into token extraction, CSS variable formatting, and selector assembly helpers.
28
+
29
+ ## Acceptance Criteria
30
+
31
+ - The playground theme page no longer duplicates `ThemePicker/Menu.vue` logic.
32
+ - `buildAccentCSS()` delegates formatting to pure helpers.
33
+ - `pnpm typecheck` passes.
@@ -0,0 +1,27 @@
1
+ # layers/transitions
2
+
3
+ `layers/transitions` has no complexity or duplication findings in the current Fallow snapshot used for this audit.
4
+
5
+ ## Complexity Findings
6
+
7
+ - No current findings.
8
+
9
+ ## Duplication Findings
10
+
11
+ - No current findings in the supplied Problems export.
12
+
13
+ ## Component Opportunities
14
+
15
+ - No extraction is recommended.
16
+
17
+ ## Composable Opportunities
18
+
19
+ - No extraction is recommended.
20
+
21
+ ## Utility Opportunities
22
+
23
+ - No extraction is recommended.
24
+
25
+ ## Agent Notes
26
+
27
+ Do not create refactor work for this layer unless a later Fallow run introduces findings.
@@ -0,0 +1,29 @@
1
+ # layers/typography
2
+
3
+ `layers/typography` has one moderate normalization finding. Treat this as a low-priority utility cleanup.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `1` complexity finding.
8
+ - `layers/typography/app/composables/typography.ts:17` defines `normalizeAxis` with moderate complexity.
9
+
10
+ ## Duplication Findings
11
+
12
+ - No duplication warnings for this layer in the supplied Problems export.
13
+
14
+ ## Component Opportunities
15
+
16
+ - No component extraction is recommended.
17
+
18
+ ## Composable Opportunities
19
+
20
+ - Keep typography composables stable.
21
+
22
+ ## Utility Opportunities
23
+
24
+ - Replace branching in `normalizeAxis()` with a lookup table if the supported axes are fixed.
25
+
26
+ ## Acceptance Criteria
27
+
28
+ - Axis normalization output remains unchanged.
29
+ - `pnpm typecheck` passes.
@@ -0,0 +1,27 @@
1
+ # layers/ui
2
+
3
+ `layers/ui` has no complexity or duplication findings in the current Fallow snapshot used for this audit.
4
+
5
+ ## Complexity Findings
6
+
7
+ - No current findings.
8
+
9
+ ## Duplication Findings
10
+
11
+ - No current findings in the supplied Problems export.
12
+
13
+ ## Component Opportunities
14
+
15
+ - No extraction is recommended.
16
+
17
+ ## Composable Opportunities
18
+
19
+ - No extraction is recommended.
20
+
21
+ ## Utility Opportunities
22
+
23
+ - No extraction is recommended.
24
+
25
+ ## Agent Notes
26
+
27
+ Do not create refactor work for this layer unless a later Fallow run introduces findings.
@@ -0,0 +1,34 @@
1
+ # layers/visual
2
+
3
+ `layers/visual` has complexity in responsive image size formatting and gradient style helpers. Prefer pure utilities.
4
+
5
+ ## Complexity Findings
6
+
7
+ - `7` complexity findings.
8
+ - `1` critical finding.
9
+ - `layers/visual/app/composables/picture.ts:34` defines `responsiveSizesToString` with cyclomatic complexity `13` and cognitive complexity `17`.
10
+ - `layers/visual/app/composables/gradient.ts` has several high-complexity color and style helpers.
11
+
12
+ ## Duplication Findings
13
+
14
+ - No duplication warnings for this layer in the supplied Problems export.
15
+
16
+ ## Component Opportunities
17
+
18
+ - No component extraction is recommended.
19
+
20
+ ## Composable Opportunities
21
+
22
+ - Keep `picture.ts` and `gradient.ts` composable entry points stable.
23
+
24
+ ## Utility Opportunities
25
+
26
+ - Split `responsiveSizesToString()` into parser, normalizer, and serializer helpers.
27
+ - Extract shared color resolution used by accent and gradient helpers.
28
+ - Create a gradient style builder utility that has no Vue dependencies.
29
+
30
+ ## Acceptance Criteria
31
+
32
+ - `responsiveSizesToString` drops below critical complexity.
33
+ - Existing `Media/Picture.vue` behavior remains unchanged.
34
+ - `pnpm typecheck` passes.
@@ -1,3 +1,5 @@
1
+ import { resolvePointerSpring, usePointerMotionFrame } from '../utils/pointerMotion'
2
+
1
3
  export function useMagneticElement(
2
4
  elementRef: Ref<HTMLElement | null>,
3
5
  opts: {
@@ -7,7 +9,6 @@ export function useMagneticElement(
7
9
  stiffness?: number
8
10
  } = {}
9
11
  ) {
10
- const { gsap } = useGsap()
11
12
  const { elementX, elementY, elementWidth, elementHeight } = useMouseInElement(elementRef)
12
13
 
13
14
  const currentX = ref(0)
@@ -33,20 +34,21 @@ export function useMagneticElement(
33
34
  targetY = dy * strength
34
35
  }
35
36
 
36
- currentX.value += (targetX - currentX.value) * stiffness
37
- currentX.value *= 1 - damping
38
- currentY.value += (targetY - currentY.value) * stiffness
39
- currentY.value *= 1 - damping
37
+ currentX.value = resolvePointerSpring(currentX.value, targetX, {
38
+ damping,
39
+ stiffness,
40
+ })
41
+ currentY.value = resolvePointerSpring(currentY.value, targetY, {
42
+ damping,
43
+ stiffness,
44
+ })
40
45
 
41
46
  if (elementRef.value) {
42
47
  gsap.set(elementRef.value, { x: currentX.value, y: currentY.value })
43
48
  }
44
49
  }
45
50
 
46
- onMounted(() => gsap.ticker.add(tick))
47
-
48
- onUnmounted(() => {
49
- gsap.ticker.remove(tick)
51
+ const { gsap } = usePointerMotionFrame(tick, () => {
50
52
  if (elementRef.value) gsap.set(elementRef.value, { x: 0, y: 0 })
51
53
  })
52
54
 
@@ -1,3 +1,5 @@
1
+ import { resolvePointerSpring, usePointerMotionFrame } from '../utils/pointerMotion'
2
+
1
3
  export function useTiltEffect(
2
4
  elementRef: Ref<HTMLElement | null>,
3
5
  opts: {
@@ -7,7 +9,6 @@ export function useTiltEffect(
7
9
  stiffness?: number
8
10
  } = {}
9
11
  ) {
10
- const { gsap } = useGsap()
11
12
  const { elementX, elementY, elementWidth, elementHeight, isOutside } =
12
13
  useMouseInElement(elementRef)
13
14
 
@@ -33,10 +34,14 @@ export function useTiltEffect(
33
34
  targetRotateX = -ny * maxTilt
34
35
  }
35
36
 
36
- currentRotateX.value += (targetRotateX - currentRotateX.value) * stiffness
37
- currentRotateX.value *= 1 - damping
38
- currentRotateY.value += (targetRotateY - currentRotateY.value) * stiffness
39
- currentRotateY.value *= 1 - damping
37
+ currentRotateX.value = resolvePointerSpring(currentRotateX.value, targetRotateX, {
38
+ damping,
39
+ stiffness,
40
+ })
41
+ currentRotateY.value = resolvePointerSpring(currentRotateY.value, targetRotateY, {
42
+ damping,
43
+ stiffness,
44
+ })
40
45
 
41
46
  if (elementRef.value) {
42
47
  gsap.set(elementRef.value, {
@@ -47,10 +52,7 @@ export function useTiltEffect(
47
52
  }
48
53
  }
49
54
 
50
- onMounted(() => gsap.ticker.add(tick))
51
-
52
- onUnmounted(() => {
53
- gsap.ticker.remove(tick)
55
+ const { gsap } = usePointerMotionFrame(tick, () => {
54
56
  if (elementRef.value) gsap.set(elementRef.value, { rotateX: 0, rotateY: 0 })
55
57
  })
56
58
 
@@ -0,0 +1,31 @@
1
+ export function resolvePointerSpring(
2
+ current: number,
3
+ target: number,
4
+ options: {
5
+ damping?: number
6
+ stiffness?: number
7
+ } = {}
8
+ ) {
9
+ const damping = options.damping ?? 0
10
+ const stiffness = options.stiffness ?? 0
11
+ const next = current + (target - current) * stiffness
12
+ return next * (1 - damping)
13
+ }
14
+
15
+ export function usePointerMotionFrame(
16
+ update: () => void,
17
+ cleanup?: () => void
18
+ ) {
19
+ const { gsap } = useGsap()
20
+
21
+ onMounted(() => {
22
+ gsap.ticker.add(update)
23
+ })
24
+
25
+ onUnmounted(() => {
26
+ gsap.ticker.remove(update)
27
+ cleanup?.()
28
+ })
29
+
30
+ return { gsap }
31
+ }
@@ -9,7 +9,7 @@
9
9
  SRGBColorSpace,
10
10
  type ToneMapping,
11
11
  } from 'three'
12
- import { WebGPURenderer } from 'three/webgpu'
12
+ import * as ThreeWebGPU from 'three/webgpu'
13
13
 
14
14
  const {
15
15
  clearColor = '#000000',
@@ -70,7 +70,7 @@
70
70
  // WebGPU renderer factory — TresJS v5 calls renderer.init() automatically
71
71
  // when the returned object has isRenderer === true (three/webgpu Renderer base class)
72
72
  function webgpuRendererFactory({ canvas }: TresRendererSetupContext) {
73
- const r = new WebGPURenderer({
73
+ const r = new ThreeWebGPU.WebGPURenderer({
74
74
  canvas: unref(canvas),
75
75
  antialias,
76
76
  // WebGPU has no 'default' power preference — omit to let the browser decide
@@ -0,0 +1,28 @@
1
+ import type { Collections } from '@nuxt/content'
2
+
3
+ type CollectionItem<TCollection extends keyof Collections> = Collections[TCollection]
4
+
5
+ export function useCollectionItems<TCollection extends keyof Collections>(args: {
6
+ key: string
7
+ collection: TCollection
8
+ sort: (a: CollectionItem<TCollection>, b: CollectionItem<TCollection>) => number
9
+ options?: { limit?: number | undefined }
10
+ filter?: (item: CollectionItem<TCollection>) => boolean
11
+ }) {
12
+ const { key, collection, sort, options = {}, filter } = args
13
+
14
+ return useContentData(key, async () => {
15
+ let items = (await queryCollection(collection).all()) as CollectionItem<TCollection>[]
16
+ items = items.sort(sort)
17
+
18
+ if (filter) {
19
+ items = items.filter(filter)
20
+ }
21
+
22
+ if (options.limit !== undefined) {
23
+ items = items.slice(0, options.limit)
24
+ }
25
+
26
+ return items
27
+ })
28
+ }
@@ -1,21 +1,15 @@
1
1
  import type { GalleryQueryOptions } from '../types/content'
2
+ import { useCollectionItems } from './useCollectionItems'
2
3
 
3
4
  export function useGalleryItems(options: GalleryQueryOptions = {}) {
4
5
  const { tags, limit } = options
5
6
 
6
- return useContentData('gallery-items', async () => {
7
- let items = (await queryCollection('gallery').all()).sort((a, b) =>
8
- (b.date ?? '').localeCompare(a.date ?? '')
9
- )
10
-
11
- if (tags?.length) {
12
- items = items.filter((item) => item.tags?.some((tag: string) => tags.includes(tag)))
13
- }
14
-
15
- if (limit) {
16
- items = items.slice(0, limit)
17
- }
18
-
19
- return items
7
+ return useCollectionItems({
8
+ key: 'gallery-items',
9
+ collection: 'gallery',
10
+ sort: (a, b) => (b.date ?? '').localeCompare(a.date ?? ''),
11
+ options: { limit },
12
+ filter: (item) =>
13
+ !tags?.length || Boolean(item.tags?.some((tag: string) => tags.includes(tag))),
20
14
  })
21
15
  }