kmcom-nuxt-layers 1.7.8 → 2.1.6

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 (520) hide show
  1. package/docs/layout-shift-causes.md +94 -0
  2. package/layers/animations/nuxt.config.ts +17 -0
  3. package/layers/animations/package.json +6 -0
  4. package/layers/animations/tsconfig.json +7 -0
  5. package/layers/canvas/app/components/ShaderCanvas.vue +125 -0
  6. package/layers/{shader → canvas}/app/composables/useRendererCapabilities.ts +10 -2
  7. package/layers/{shader → canvas}/app/composables/useShaderTime.ts +3 -3
  8. package/layers/canvas/app/types/renderer.ts +50 -0
  9. package/layers/canvas/nuxt.config.ts +189 -0
  10. package/layers/canvas/package.json +22 -0
  11. package/layers/canvas/tsconfig.json +7 -0
  12. package/layers/content/app/components/Blog/Article.vue +12 -6
  13. package/layers/content/app/components/Blog/Card.vue +24 -24
  14. package/layers/content/app/components/Blog/List.vue +8 -11
  15. package/layers/content/app/components/Gallery/AmbientImage.vue +15 -15
  16. package/layers/content/app/components/Gallery/Card.vue +19 -19
  17. package/layers/content/app/components/Gallery/Detail.vue +29 -20
  18. package/layers/content/app/components/Gallery/Grid.vue +8 -11
  19. package/layers/content/app/components/Gallery/ImageDetail.vue +18 -17
  20. package/layers/content/app/components/Gallery/ImagePage.vue +8 -9
  21. package/layers/content/app/components/Gallery/Lightbox.vue +38 -33
  22. package/layers/content/app/components/Gallery/Page.vue +8 -8
  23. package/layers/content/app/components/Gallery/SlugPage.vue +7 -8
  24. package/layers/content/app/components/NuxtContent/Detail.vue +29 -27
  25. package/layers/content/app/components/NuxtContent/List.vue +10 -9
  26. package/layers/content/app/components/NuxtContent/Renderer.vue +4 -4
  27. package/layers/content/app/components/NuxtContent/Surround.vue +3 -3
  28. package/layers/content/app/components/NuxtContent/Toc.vue +5 -5
  29. package/layers/content/app/components/Portfolio/Card.vue +17 -17
  30. package/layers/content/app/components/Portfolio/ColorPalette.vue +11 -11
  31. package/layers/content/app/components/Portfolio/Detail.vue +9 -13
  32. package/layers/content/app/components/Portfolio/ItemPage.vue +8 -9
  33. package/layers/content/app/components/Portfolio/List.vue +10 -13
  34. package/layers/content/app/components/Portfolio/Page.vue +8 -8
  35. package/layers/content/app/components/Portfolio/Typography.vue +4 -4
  36. package/layers/content/app/components/content/Figure.vue +14 -14
  37. package/layers/content/app/composables/createPortfolioComposables.ts +1 -0
  38. package/layers/content/app/composables/useCollectionItem.ts +4 -1
  39. package/layers/content/app/composables/useCollectionSurround.ts +1 -0
  40. package/layers/content/app/composables/useContentPage.ts +1 -0
  41. package/layers/content/app/composables/useGalleryItems.ts +1 -0
  42. package/layers/content/app/composables/usePortfolioItems.ts +1 -0
  43. package/layers/content/app/types/app-config.d.ts +1 -1
  44. package/layers/content/app/types/content.ts +27 -30
  45. package/layers/content/nuxt.config.ts +4 -3
  46. package/layers/content/package.json +4 -4
  47. package/layers/core/app/components/DiagnosticsPage.vue +203 -203
  48. package/layers/core/app/components/ErrorBoundary.vue +51 -49
  49. package/layers/core/app/components/LoadingScreen.vue +112 -111
  50. package/layers/core/app/composables/useBrowser.ts +2 -1
  51. package/layers/core/app/composables/useCache.ts +4 -2
  52. package/layers/core/app/composables/useErrorLog.ts +7 -10
  53. package/layers/core/app/composables/useFeatures.ts +4 -2
  54. package/layers/core/app/composables/useLoading.ts +1 -0
  55. package/layers/core/app/composables/useNetworkInfo.ts +1 -0
  56. package/layers/core/app/composables/usePWAInfo.ts +4 -3
  57. package/layers/core/app/composables/useRendering.ts +1 -0
  58. package/layers/core/app/composables/useScreen.ts +1 -0
  59. package/layers/core/app/composables/useScrollGuard.ts +2 -1
  60. package/layers/core/app/pages/[...slug].vue +99 -99
  61. package/layers/core/app/plugins/error-handler.ts +1 -1
  62. package/layers/core/app/plugins/feature-detection.client.ts +2 -1
  63. package/layers/core/app/plugins/init.ts +8 -19
  64. package/layers/core/app/plugins/loading.client.ts +4 -2
  65. package/layers/core/app/plugins/scroll-guard.client.ts +4 -4
  66. package/layers/core/app/types/app-config.d.ts +5 -1
  67. package/layers/core/app/types/detection.ts +8 -8
  68. package/layers/core/app/types/index.ts +5 -4
  69. package/layers/core/app/types/loading.ts +3 -3
  70. package/layers/core/app/types/runtime-config.ts +2 -2
  71. package/layers/core/app/types/scroll-guard.ts +2 -2
  72. package/layers/core/app/types/site.ts +43 -0
  73. package/layers/core/app/utils/helpers.ts +4 -0
  74. package/layers/core/nuxt.config.ts +1 -0
  75. package/layers/core/package.json +1 -1
  76. package/layers/feeds/app/app.config.ts +23 -0
  77. package/layers/feeds/app/assets/css/feeds.css +66 -0
  78. package/layers/feeds/app/plugins/feed-head.ts +73 -0
  79. package/layers/feeds/nuxt.config.ts +36 -0
  80. package/layers/feeds/package.json +23 -0
  81. package/layers/feeds/tsconfig.json +7 -0
  82. package/layers/forms/app/components/Form/Contact.vue +1 -0
  83. package/layers/forms/app/components/Form/Field.vue +70 -74
  84. package/layers/forms/app/composables/useFormSchema.ts +2 -0
  85. package/layers/forms/app/config/fields.ts +1 -0
  86. package/layers/forms/app/types/app-config.d.ts +1 -1
  87. package/layers/forms/app/types/fields.ts +1 -1
  88. package/layers/forms/nuxt.config.ts +4 -9
  89. package/layers/forms/package.json +4 -9
  90. package/layers/layout/app/assets/css/layout/grids.css +12 -12
  91. package/layers/layout/app/assets/css/layout/modes/fluid.css +10 -10
  92. package/layers/layout/app/components/Layout/Container.vue +34 -34
  93. package/layers/layout/app/components/Layout/Grid/Debug.vue +55 -55
  94. package/layers/layout/app/components/Layout/Grid/Item.vue +239 -231
  95. package/layers/layout/app/components/Layout/Main.vue +27 -23
  96. package/layers/layout/app/components/Layout/Page/Container.vue +71 -67
  97. package/layers/layout/app/components/Layout/Page/Header.vue +22 -21
  98. package/layers/layout/app/components/Layout/Page/index.vue +1 -0
  99. package/layers/layout/app/components/Layout/Section/Gallery.vue +49 -48
  100. package/layers/layout/app/components/Layout/Section/Grid.vue +29 -29
  101. package/layers/layout/app/components/Layout/Section/Hero.vue +31 -29
  102. package/layers/layout/app/components/Layout/Section/Sidebar.vue +48 -48
  103. package/layers/layout/app/components/Layout/Section/Split.vue +28 -28
  104. package/layers/layout/app/components/Layout/Section/Stack.vue +39 -37
  105. package/layers/layout/app/components/Layout/Section/Title.vue +21 -20
  106. package/layers/layout/app/composables/GridPlacement.ts +1 -1
  107. package/layers/layout/app/composables/useGridConfig.ts +2 -1
  108. package/layers/layout/app/types/app-config.d.ts +2 -1
  109. package/layers/layout/app/types/layouts.ts +4 -4
  110. package/layers/layout/nuxt.config.ts +4 -1
  111. package/layers/mailer/nuxt.config.ts +26 -0
  112. package/layers/mailer/package.json +15 -0
  113. package/layers/mailer/tsconfig.json +7 -0
  114. package/layers/motion/app/components/Motion/index.vue +5 -5
  115. package/layers/motion/nuxt.config.ts +6 -22
  116. package/layers/motion/package.json +0 -5
  117. package/layers/navigation/app/app.config.ts +38 -0
  118. package/layers/navigation/app/assets/css/navigation.css +3 -0
  119. package/layers/navigation/app/components/Links/Group.vue +49 -0
  120. package/layers/navigation/app/components/Links/Named.vue +33 -0
  121. package/layers/navigation/app/components/Mast/Footer.vue +13 -0
  122. package/layers/{ui → navigation}/app/components/Mast/Header.vue +2 -2
  123. package/layers/{ui → navigation}/app/components/Mast/Nav.vue +2 -2
  124. package/layers/navigation/app/components/Mast/NavModal.vue +76 -0
  125. package/layers/{ui → navigation}/app/composables/mastNav.ts +7 -4
  126. package/layers/{ui → navigation}/app/composables/toast.ts +1 -0
  127. package/layers/{ui → navigation}/app/composables/useSite.ts +1 -0
  128. package/layers/navigation/app/types/nav.ts +11 -0
  129. package/layers/{ui → navigation}/app/utils/createModal.ts +2 -1
  130. package/layers/navigation/nuxt.config.ts +19 -0
  131. package/layers/navigation/package.json +6 -0
  132. package/layers/navigation/tsconfig.json +7 -0
  133. package/layers/page-transitions/app/app.config.ts +15 -0
  134. package/layers/page-transitions/app/composables/usePageTransition.ts +32 -0
  135. package/layers/page-transitions/app/plugins/page-transitions.client.ts +14 -0
  136. package/layers/page-transitions/nuxt.config.ts +17 -0
  137. package/layers/page-transitions/package.json +6 -0
  138. package/layers/page-transitions/tsconfig.json +7 -0
  139. package/layers/routing/app/composables/{useFeatures.ts → useFeatureFlags.ts} +1 -1
  140. package/layers/routing/app/composables/useRoutingConfig.ts +5 -6
  141. package/layers/routing/app/middleware/01.maintenance.global.ts +1 -1
  142. package/layers/routing/app/middleware/02.governance.global.ts +2 -2
  143. package/layers/routing/app/plugins/feature-flags.client.ts +4 -4
  144. package/layers/routing/app/plugins/scroll-routing.client.ts +4 -3
  145. package/layers/routing/app/types/app-config.d.ts +2 -1
  146. package/layers/routing/app/types/route-meta.d.ts +1 -1
  147. package/layers/routing/app/types/routing.ts +5 -2
  148. package/layers/routing/app/utils/resolveRoute.ts +2 -2
  149. package/layers/routing/nuxt.config.ts +6 -2
  150. package/layers/scripts/app/app.config.ts +44 -0
  151. package/layers/scripts/app/composables/useAnalytics.ts +49 -0
  152. package/layers/scripts/app/composables/useGtm.ts +21 -0
  153. package/layers/scripts/app/composables/useScriptLoader.ts +31 -0
  154. package/layers/scripts/app/composables/useScriptsConsent.ts +23 -0
  155. package/layers/scripts/app/composables/useYoutubeEmbed.ts +14 -0
  156. package/layers/scripts/nuxt.config.ts +22 -0
  157. package/layers/scripts/package.json +14 -0
  158. package/layers/scripts/tsconfig.json +7 -0
  159. package/layers/{motion/app/types/app-config.d.ts → scroll/app/app.config.ts} +16 -1
  160. package/layers/scroll/app/components/Motion/HorizontalScroll.vue +61 -0
  161. package/layers/scroll/app/components/Motion/Parallax.vue +76 -0
  162. package/layers/scroll/app/components/Motion/PinnedSection.vue +77 -0
  163. package/layers/scroll/app/components/Motion/ScrollLink.vue +50 -0
  164. package/layers/scroll/app/components/Motion/ScrollProgress.vue +85 -0
  165. package/layers/scroll/app/components/Motion/ScrollScene.vue +121 -0
  166. package/layers/{motion → scroll}/app/components/Motion/ScrollStats.vue +51 -50
  167. package/layers/scroll/app/components/Motion/ScrollStep.vue +44 -0
  168. package/layers/{motion → scroll}/app/composables/useGsap.ts +0 -6
  169. package/layers/{motion → scroll}/app/composables/useScrollSteps.ts +2 -5
  170. package/layers/{motion → scroll}/app/composables/useSectionProgress.ts +14 -7
  171. package/layers/{motion → scroll}/app/composables/useSmoothScroll.ts +6 -37
  172. package/layers/{motion → scroll}/app/plugins/locomotive-scroll.client.ts +3 -2
  173. package/layers/scroll/nuxt.config.ts +33 -0
  174. package/layers/scroll/package.json +11 -0
  175. package/layers/scroll/tsconfig.json +7 -0
  176. package/layers/seo/app/app.config.ts +30 -0
  177. package/layers/seo/app/composables/useSeoConfig.ts +14 -0
  178. package/layers/seo/nuxt.config.ts +34 -0
  179. package/layers/seo/package.json +14 -0
  180. package/layers/seo/tsconfig.json +7 -0
  181. package/layers/shader/app/components/Effect/Bloom.vue +2 -2
  182. package/layers/shader/app/components/Effect/ChromaticAberration.vue +2 -2
  183. package/layers/shader/app/components/Effect/PostProcessing.vue +14 -10
  184. package/layers/shader/app/components/Material/AmbientAurora.client.vue +162 -158
  185. package/layers/shader/app/components/Material/AmbientFlow.client.vue +165 -161
  186. package/layers/shader/app/components/Material/AmbientGradientMesh.client.vue +179 -162
  187. package/layers/shader/app/components/Material/AmbientNebula.client.vue +167 -163
  188. package/layers/shader/app/components/Material/AmbientOcean.client.vue +154 -150
  189. package/layers/shader/app/components/Material/Fresnel.client.vue +78 -75
  190. package/layers/shader/app/components/Material/Gradient.client.vue +175 -173
  191. package/layers/shader/app/components/Material/Image.client.vue +228 -225
  192. package/layers/shader/app/components/Material/Node.client.vue +66 -63
  193. package/layers/shader/app/components/Material/Noise.client.vue +128 -124
  194. package/layers/shader/app/components/Mesh/Plane.vue +20 -18
  195. package/layers/shader/app/components/Node/Color.client.vue +47 -45
  196. package/layers/shader/app/components/Node/Fresnel.client.vue +47 -47
  197. package/layers/shader/app/components/Node/Gradient.client.vue +120 -70
  198. package/layers/shader/app/components/Node/Mix.client.vue +41 -39
  199. package/layers/shader/app/components/Node/Noise.client.vue +91 -83
  200. package/layers/shader/app/components/Pipeline/ACESTonemap.client.vue +7 -10
  201. package/layers/shader/app/components/Pipeline/AddBlend.client.vue +33 -19
  202. package/layers/shader/app/components/Pipeline/AgedFilm.client.vue +61 -40
  203. package/layers/shader/app/components/Pipeline/Aurora.client.vue +92 -56
  204. package/layers/shader/app/components/Pipeline/BilinearGradient.client.vue +65 -34
  205. package/layers/shader/app/components/Pipeline/BillowNoise.client.vue +56 -32
  206. package/layers/shader/app/components/Pipeline/BrightnessContrast.client.vue +36 -20
  207. package/layers/shader/app/components/Pipeline/CellularNoise.client.vue +55 -31
  208. package/layers/shader/app/components/Pipeline/ChannelMixer.client.vue +62 -34
  209. package/layers/shader/app/components/Pipeline/ChebyshevNoiseField.client.vue +77 -50
  210. package/layers/shader/app/components/Pipeline/Checkerboard.client.vue +50 -31
  211. package/layers/shader/app/components/Pipeline/ChromaticAberration.client.vue +49 -33
  212. package/layers/shader/app/components/Pipeline/ChromaticScreenWaves.client.vue +61 -36
  213. package/layers/shader/app/components/Pipeline/Circle.client.vue +53 -30
  214. package/layers/shader/app/components/Pipeline/Clouds.client.vue +86 -48
  215. package/layers/shader/app/components/Pipeline/ColorBurnBlend.client.vue +34 -19
  216. package/layers/shader/app/components/Pipeline/ColorDodgeBlend.client.vue +34 -19
  217. package/layers/shader/app/components/Pipeline/ColourRamp.client.vue +76 -46
  218. package/layers/shader/app/components/Pipeline/ComplexPlaneField.client.vue +80 -50
  219. package/layers/shader/app/components/Pipeline/ConicGradient.client.vue +46 -28
  220. package/layers/shader/app/components/Pipeline/CosinePalette.client.vue +80 -53
  221. package/layers/shader/app/components/Pipeline/CoverageAlpha.client.vue +12 -14
  222. package/layers/shader/app/components/Pipeline/Cross.client.vue +66 -37
  223. package/layers/shader/app/components/Pipeline/CurlNoise.client.vue +58 -35
  224. package/layers/shader/app/components/Pipeline/DarkenBlend.client.vue +34 -19
  225. package/layers/shader/app/components/Pipeline/DayNightCycle.client.vue +65 -39
  226. package/layers/shader/app/components/Pipeline/Desaturate.client.vue +23 -16
  227. package/layers/shader/app/components/Pipeline/DiagonalGradient.client.vue +50 -29
  228. package/layers/shader/app/components/Pipeline/DiamondGradient.client.vue +47 -29
  229. package/layers/shader/app/components/Pipeline/DifferenceBlend.client.vue +34 -19
  230. package/layers/shader/app/components/Pipeline/DivideBlend.client.vue +34 -19
  231. package/layers/shader/app/components/Pipeline/DomainWarpedNoise.client.vue +79 -37
  232. package/layers/shader/app/components/Pipeline/Dots.client.vue +70 -34
  233. package/layers/shader/app/components/Pipeline/DuoTone.client.vue +40 -26
  234. package/layers/shader/app/components/Pipeline/ExclusionBlend.client.vue +38 -19
  235. package/layers/shader/app/components/Pipeline/ExponentialFog.client.vue +52 -35
  236. package/layers/shader/app/components/Pipeline/Exposure.client.vue +22 -16
  237. package/layers/shader/app/components/Pipeline/FBMNoise.client.vue +62 -39
  238. package/layers/shader/app/components/Pipeline/FilmBurn.client.vue +60 -38
  239. package/layers/shader/app/components/Pipeline/FilmGrain.client.vue +53 -31
  240. package/layers/shader/app/components/Pipeline/FisheyeRay.client.vue +39 -28
  241. package/layers/shader/app/components/Pipeline/Flame.client.vue +59 -35
  242. package/layers/shader/app/components/Pipeline/FocalGradient.client.vue +56 -33
  243. package/layers/shader/app/components/Pipeline/Gamma.client.vue +21 -16
  244. package/layers/shader/app/components/Pipeline/GodRays.client.vue +76 -42
  245. package/layers/shader/app/components/Pipeline/GradientNoise.client.vue +57 -32
  246. package/layers/shader/app/components/Pipeline/Grain.client.vue +84 -47
  247. package/layers/shader/app/components/Pipeline/Grid.client.vue +56 -33
  248. package/layers/shader/app/components/Pipeline/Halation.client.vue +52 -34
  249. package/layers/shader/app/components/Pipeline/Halftone.client.vue +34 -23
  250. package/layers/shader/app/components/Pipeline/HardLightBlend.client.vue +33 -19
  251. package/layers/shader/app/components/Pipeline/Haze.client.vue +57 -36
  252. package/layers/shader/app/components/Pipeline/Hexagon.client.vue +54 -31
  253. package/layers/shader/app/components/Pipeline/Hue.client.vue +20 -16
  254. package/layers/shader/app/components/Pipeline/Invert.client.vue +6 -10
  255. package/layers/shader/app/components/Pipeline/LensFlare.client.vue +56 -37
  256. package/layers/shader/app/components/Pipeline/LightenBlend.client.vue +31 -19
  257. package/layers/shader/app/components/Pipeline/LinearGradient.client.vue +36 -28
  258. package/layers/shader/app/components/Pipeline/LinearGradient4.client.vue +65 -43
  259. package/layers/shader/app/components/Pipeline/LinearToSRGB.client.vue +26 -20
  260. package/layers/shader/app/components/Pipeline/Marble.client.vue +97 -57
  261. package/layers/shader/app/components/Pipeline/MixBlend.client.vue +45 -35
  262. package/layers/shader/app/components/Pipeline/MonochromeTint.client.vue +40 -25
  263. package/layers/shader/app/components/Pipeline/MultiplyBlend.client.vue +33 -19
  264. package/layers/shader/app/components/Pipeline/NoisyGradient.client.vue +83 -42
  265. package/layers/shader/app/components/Pipeline/NoisyGradientBlend.client.vue +141 -81
  266. package/layers/shader/app/components/Pipeline/OverlayBlend.client.vue +33 -19
  267. package/layers/shader/app/components/Pipeline/PaperTexture.client.vue +47 -30
  268. package/layers/shader/app/components/Pipeline/Polygon.client.vue +74 -37
  269. package/layers/shader/app/components/Pipeline/Posterise.client.vue +21 -16
  270. package/layers/shader/app/components/Pipeline/RadialGradient.client.vue +45 -30
  271. package/layers/shader/app/components/Pipeline/RayAutoOrbit.client.vue +43 -30
  272. package/layers/shader/app/components/Pipeline/RayMouseOrbit.client.vue +60 -47
  273. package/layers/shader/app/components/Pipeline/RayRotateX.client.vue +28 -20
  274. package/layers/shader/app/components/Pipeline/RayRotateY.client.vue +28 -20
  275. package/layers/shader/app/components/Pipeline/RayRotateZ.client.vue +28 -20
  276. package/layers/shader/app/components/Pipeline/RayTiltBasis.client.vue +55 -34
  277. package/layers/shader/app/components/Pipeline/RaymarchTunnel.client.vue +132 -88
  278. package/layers/shader/app/components/Pipeline/Rectangle.client.vue +78 -37
  279. package/layers/shader/app/components/Pipeline/ReinhardTonemap.client.vue +12 -14
  280. package/layers/shader/app/components/Pipeline/RidgedNoise.client.vue +54 -31
  281. package/layers/shader/app/components/Pipeline/Ring.client.vue +69 -34
  282. package/layers/shader/app/components/Pipeline/RingField.client.vue +63 -43
  283. package/layers/shader/app/components/Pipeline/RisographGrain.client.vue +66 -32
  284. package/layers/shader/app/components/Pipeline/RotatedGradientBlend.client.vue +73 -48
  285. package/layers/shader/app/components/Pipeline/SDFColourMask.client.vue +31 -25
  286. package/layers/shader/app/components/Pipeline/SDFRadialMask.client.vue +31 -21
  287. package/layers/shader/app/components/Pipeline/SRGBToLinear.client.vue +25 -20
  288. package/layers/shader/app/components/Pipeline/Saturation.client.vue +22 -16
  289. package/layers/shader/app/components/Pipeline/Scanlines.client.vue +42 -26
  290. package/layers/shader/app/components/Pipeline/ScreenBlend.client.vue +33 -19
  291. package/layers/shader/app/components/Pipeline/ShaderDebugger.client.vue +58 -45
  292. package/layers/shader/app/components/Pipeline/SimplexNoise.client.vue +59 -37
  293. package/layers/shader/app/components/Pipeline/SkyAtmosphere.client.vue +87 -54
  294. package/layers/shader/app/components/Pipeline/SoftLightBlend.client.vue +33 -19
  295. package/layers/shader/app/components/Pipeline/SolidColour.client.vue +24 -16
  296. package/layers/shader/app/components/Pipeline/SplitTone.client.vue +58 -34
  297. package/layers/shader/app/components/Pipeline/Star.client.vue +73 -37
  298. package/layers/shader/app/components/Pipeline/Starfield.client.vue +68 -34
  299. package/layers/shader/app/components/Pipeline/Stripes.client.vue +64 -36
  300. package/layers/shader/app/components/Pipeline/SubtractBlend.client.vue +33 -19
  301. package/layers/shader/app/components/Pipeline/TanhTonemap.client.vue +25 -19
  302. package/layers/shader/app/components/Pipeline/Threshold.client.vue +23 -17
  303. package/layers/shader/app/components/Pipeline/Tint.client.vue +36 -25
  304. package/layers/shader/app/components/Pipeline/Triangle.client.vue +54 -31
  305. package/layers/shader/app/components/Pipeline/UVAspectCorrect.client.vue +5 -10
  306. package/layers/shader/app/components/Pipeline/UVBreath.client.vue +44 -31
  307. package/layers/shader/app/components/Pipeline/UVBulge.client.vue +35 -21
  308. package/layers/shader/app/components/Pipeline/UVClamp.client.vue +14 -14
  309. package/layers/shader/app/components/Pipeline/UVColumnOffset.client.vue +36 -23
  310. package/layers/shader/app/components/Pipeline/UVFlipX.client.vue +6 -10
  311. package/layers/shader/app/components/Pipeline/UVFlipXY.client.vue +6 -10
  312. package/layers/shader/app/components/Pipeline/UVFlipY.client.vue +6 -10
  313. package/layers/shader/app/components/Pipeline/UVFractBand.client.vue +31 -21
  314. package/layers/shader/app/components/Pipeline/UVMousePull.client.vue +41 -33
  315. package/layers/shader/app/components/Pipeline/UVNoiseRotate.client.vue +65 -46
  316. package/layers/shader/app/components/Pipeline/UVNoiseWarp.client.vue +49 -30
  317. package/layers/shader/app/components/Pipeline/UVOrbit.client.vue +37 -29
  318. package/layers/shader/app/components/Pipeline/UVParallax.client.vue +41 -33
  319. package/layers/shader/app/components/Pipeline/UVPixelate.client.vue +21 -16
  320. package/layers/shader/app/components/Pipeline/UVPulse.client.vue +41 -28
  321. package/layers/shader/app/components/Pipeline/UVRipple.client.vue +53 -29
  322. package/layers/shader/app/components/Pipeline/UVRotate.client.vue +40 -32
  323. package/layers/shader/app/components/Pipeline/UVScale.client.vue +33 -25
  324. package/layers/shader/app/components/Pipeline/UVScroll.client.vue +26 -22
  325. package/layers/shader/app/components/Pipeline/UVScrollX.client.vue +20 -16
  326. package/layers/shader/app/components/Pipeline/UVScrollY.client.vue +20 -16
  327. package/layers/shader/app/components/Pipeline/UVShear.client.vue +33 -20
  328. package/layers/shader/app/components/Pipeline/UVSineWarpXY.client.vue +58 -40
  329. package/layers/shader/app/components/Pipeline/UVSwapAxes.client.vue +6 -10
  330. package/layers/shader/app/components/Pipeline/UVTile.client.vue +26 -22
  331. package/layers/shader/app/components/Pipeline/UVTwirl.client.vue +31 -21
  332. package/layers/shader/app/components/Pipeline/UVWarp.client.vue +44 -25
  333. package/layers/shader/app/components/Pipeline/VHSBleed.client.vue +63 -43
  334. package/layers/shader/app/components/Pipeline/ValueNoise.client.vue +57 -32
  335. package/layers/shader/app/components/Pipeline/Vibrance.client.vue +25 -19
  336. package/layers/shader/app/components/Pipeline/Vignette.client.vue +35 -24
  337. package/layers/shader/app/components/Pipeline/VoronoiEdges.client.vue +66 -38
  338. package/layers/shader/app/components/Pipeline/Water.client.vue +78 -39
  339. package/layers/shader/app/components/Pipeline/WaveBendLayer.client.vue +74 -46
  340. package/layers/shader/app/components/Pipeline/WaveColourLayer.client.vue +76 -43
  341. package/layers/shader/app/components/Pipeline/WhiteBalance.client.vue +38 -27
  342. package/layers/shader/app/components/Pipeline/Wood.client.vue +85 -50
  343. package/layers/shader/app/components/Preset/Aurora.client.vue +69 -52
  344. package/layers/shader/app/components/Preset/Flow.client.vue +63 -47
  345. package/layers/shader/app/components/Preset/GradientMesh.client.vue +63 -47
  346. package/layers/shader/app/components/Preset/Nebula.client.vue +65 -47
  347. package/layers/shader/app/components/Preset/Ocean.client.vue +64 -47
  348. package/layers/shader/app/components/Preset/ThemeAurora.client.vue +107 -70
  349. package/layers/shader/app/components/Preset/ThemeBubble.client.vue +108 -71
  350. package/layers/shader/app/components/Preset/ThemeFlow.client.vue +107 -70
  351. package/layers/shader/app/components/Preset/ThemeGradient.client.vue +108 -71
  352. package/layers/shader/app/components/Preset/ThemeLavaLamp.client.vue +107 -70
  353. package/layers/shader/app/components/Preset/ThemePlasma.client.vue +107 -70
  354. package/layers/shader/app/components/Preset/ThemeWave.client.vue +107 -70
  355. package/layers/shader/app/components/Shader/Background.client.vue +169 -163
  356. package/layers/shader/app/components/Shader/Debug.vue +45 -40
  357. package/layers/shader/app/components/Shader/Host.client.vue +120 -121
  358. package/layers/shader/app/components/Shader/Material.client.vue +42 -36
  359. package/layers/shader/app/components/Shader/Pipeline.client.vue +55 -46
  360. package/layers/shader/app/components/Shader/PipelineContext.vue +12 -12
  361. package/layers/shader/app/components/Shader/Runtime.client.vue +42 -37
  362. package/layers/shader/app/composables/useAmbientMaterials.ts +316 -105
  363. package/layers/shader/app/composables/useCSSColourUniform.ts +7 -6
  364. package/layers/shader/app/composables/useCSSFloatUniform.ts +4 -5
  365. package/layers/shader/app/composables/useMousePosition.ts +1 -1
  366. package/layers/shader/app/composables/useShader.ts +5 -3
  367. package/layers/shader/app/composables/useShaderColor.ts +8 -1
  368. package/layers/shader/app/composables/useShaderFloat.ts +3 -1
  369. package/layers/shader/app/composables/useShaderGraph.ts +6 -3
  370. package/layers/shader/app/composables/useShaderPerf.ts +2 -3
  371. package/layers/shader/app/composables/useShaderPipeline.ts +14 -6
  372. package/layers/shader/app/composables/useShaderRuntime.ts +7 -4
  373. package/layers/shader/app/composables/useShaderVec2.ts +4 -0
  374. package/layers/shader/app/composables/useSunDirectionUniform.ts +7 -6
  375. package/layers/shader/app/composables/useTSLNodes.ts +1 -0
  376. package/layers/shader/app/composables/useThemeColors.ts +14 -10
  377. package/layers/shader/app/composables/useUniforms.ts +5 -2
  378. package/layers/shader/app/plugins/shader.client.ts +3 -2
  379. package/layers/shader/app/shaders/common/blend.ts +3 -0
  380. package/layers/shader/app/shaders/common/complex.ts +4 -5
  381. package/layers/shader/app/shaders/common/effects.ts +10 -6
  382. package/layers/shader/app/shaders/common/grain.ts +4 -0
  383. package/layers/shader/app/shaders/common/lighting.ts +4 -1
  384. package/layers/shader/app/shaders/common/math.ts +3 -0
  385. package/layers/shader/app/shaders/common/noise.ts +7 -4
  386. package/layers/shader/app/shaders/common/noiseHelpers.ts +2 -0
  387. package/layers/shader/app/shaders/common/palette.ts +6 -1
  388. package/layers/shader/app/shaders/common/patterns.ts +7 -4
  389. package/layers/shader/app/shaders/common/sdf.ts +3 -1
  390. package/layers/shader/app/shaders/common/shapes.ts +3 -0
  391. package/layers/shader/app/shaders/common/tonemapping.ts +2 -0
  392. package/layers/shader/app/shaders/common/uv.ts +8 -1
  393. package/layers/shader/app/shaders/createMaterial.ts +6 -2
  394. package/layers/shader/app/shaders/layers/aurora.ts +6 -3
  395. package/layers/shader/app/shaders/layers/meshGradient.ts +6 -3
  396. package/layers/shader/app/shaders/layers/paperShading.ts +6 -2
  397. package/layers/shader/app/shaders/layers/shaderGradient.ts +5 -0
  398. package/layers/shader/app/shaders/layers/stripe.ts +6 -3
  399. package/layers/shader/app/shaders/types.ts +1 -0
  400. package/layers/shader/app/types/app-config.d.ts +1 -1
  401. package/layers/shader/app/types/index.ts +4 -4
  402. package/layers/shader/app/types/materials.ts +5 -4
  403. package/layers/shader/app/types/renderer.ts +1 -50
  404. package/layers/shader/app/types/tsl.ts +4 -3
  405. package/layers/shader/app/types/uniforms.ts +3 -2
  406. package/layers/shader/app/utils/tsl/animation.ts +2 -0
  407. package/layers/shader/app/utils/tsl/color.ts +5 -2
  408. package/layers/shader/app/utils/tsl/math.ts +1 -0
  409. package/layers/shader/app/utils/tsl/noise.ts +2 -0
  410. package/layers/shader/app/utils/tsl/oklch.ts +2 -0
  411. package/layers/shader/app/utils/tsl/patterns.ts +2 -0
  412. package/layers/shader/app/utils/tsl/tween.ts +4 -2
  413. package/layers/shader/app/utils/tsl/uv.ts +2 -0
  414. package/layers/shader/nuxt.config.ts +8 -115
  415. package/layers/shader/package.json +3 -9
  416. package/layers/theme/app/assets/css/theme.css +2 -2
  417. package/layers/theme/app/components/ThemePicker/AccentButton.vue +32 -30
  418. package/layers/theme/app/components/ThemePicker/Colors.vue +6 -5
  419. package/layers/theme/app/components/ThemePicker/Menu.vue +23 -23
  420. package/layers/theme/app/composables/useAccentColor.ts +2 -1
  421. package/layers/theme/app/composables/useThemeContrast.ts +1 -1
  422. package/layers/theme/app/composables/useThemeMotion.ts +1 -1
  423. package/layers/theme/app/composables/useThemeTransparency.ts +1 -4
  424. package/layers/theme/app/plugins/theme.client.ts +33 -15
  425. package/layers/theme/app/types/app-config.d.ts +3 -2
  426. package/layers/theme/app/types/theme.ts +1 -1
  427. package/layers/theme/nuxt.config.ts +4 -1
  428. package/layers/transitions/app/components/Motion/Transition.vue +76 -0
  429. package/layers/transitions/nuxt.config.ts +19 -0
  430. package/layers/transitions/package.json +6 -0
  431. package/layers/transitions/tsconfig.json +7 -0
  432. package/layers/typography/app/components/Typography/CodeBlock.vue +44 -0
  433. package/layers/typography/app/components/Typography/Headline.vue +90 -0
  434. package/layers/typography/app/components/Typography/HeadlineScreen.vue +75 -0
  435. package/layers/typography/app/components/Typography/QuoteBlock.vue +21 -0
  436. package/layers/{ui → typography}/app/components/Typography/TextStroke.vue +33 -32
  437. package/layers/typography/app/components/Typography/index.vue +54 -0
  438. package/layers/{ui → typography}/app/composables/typography.ts +1 -0
  439. package/layers/{ui → typography}/app/types/typography.ts +1 -1
  440. package/layers/typography/nuxt.config.ts +17 -0
  441. package/layers/typography/package.json +6 -0
  442. package/layers/typography/tsconfig.json +7 -0
  443. package/layers/ui/app/assets/css/ui.css +0 -20
  444. package/layers/ui/app/layouts/default.vue +2 -12
  445. package/layers/ui/nuxt.config.ts +5 -21
  446. package/layers/visual/app/app.config.ts +115 -0
  447. package/layers/visual/app/assets/css/visual.css +15 -0
  448. package/layers/visual/app/components/Accent/Blob.vue +32 -0
  449. package/layers/{ui → visual}/app/components/Accent/Scene.vue +26 -23
  450. package/layers/visual/app/components/Base/Modal.vue +123 -0
  451. package/layers/visual/app/components/Gradient/Background.vue +24 -0
  452. package/layers/visual/app/components/Gradient/Text.vue +24 -0
  453. package/layers/visual/app/components/Media/Picture.vue +51 -0
  454. package/layers/visual/app/components/Progress/Bar.vue +36 -0
  455. package/layers/{ui → visual}/app/components/Progress/Circular.vue +26 -25
  456. package/layers/visual/app/components/Tint/Overlay.vue +27 -0
  457. package/layers/{ui → visual}/app/composables/accent.ts +1 -0
  458. package/layers/{ui → visual}/app/composables/gradient.ts +3 -0
  459. package/layers/{ui → visual}/app/composables/picture.ts +2 -0
  460. package/layers/{ui → visual}/app/composables/tint.ts +3 -2
  461. package/layers/{ui → visual}/app/types/accent.ts +2 -2
  462. package/layers/{ui → visual}/app/types/gradient.ts +2 -2
  463. package/layers/{ui → visual}/app/types/media.ts +4 -3
  464. package/layers/{ui → visual}/app/types/tint.ts +1 -1
  465. package/layers/visual/nuxt.config.ts +19 -0
  466. package/layers/visual/package.json +6 -0
  467. package/layers/visual/tsconfig.json +7 -0
  468. package/package.json +29 -4
  469. package/layers/motion/app/app.config.ts +0 -27
  470. package/layers/motion/app/components/Motion/HorizontalScroll.vue +0 -61
  471. package/layers/motion/app/components/Motion/Parallax.vue +0 -75
  472. package/layers/motion/app/components/Motion/PinnedSection.vue +0 -77
  473. package/layers/motion/app/components/Motion/ScrollLink.vue +0 -49
  474. package/layers/motion/app/components/Motion/ScrollProgress.vue +0 -82
  475. package/layers/motion/app/components/Motion/ScrollScene.vue +0 -121
  476. package/layers/motion/app/components/Motion/ScrollStep.vue +0 -45
  477. package/layers/motion/app/components/Motion/Transition.vue +0 -76
  478. package/layers/shader/app/components/Shader/Canvas.vue +0 -121
  479. package/layers/ui/app/app.config.ts +0 -57
  480. package/layers/ui/app/components/Accent/Blob.vue +0 -29
  481. package/layers/ui/app/components/Base/Modal.vue +0 -111
  482. package/layers/ui/app/components/Gradient/Background.vue +0 -22
  483. package/layers/ui/app/components/Gradient/Text.vue +0 -22
  484. package/layers/ui/app/components/Links/Group.vue +0 -47
  485. package/layers/ui/app/components/Links/Named.vue +0 -31
  486. package/layers/ui/app/components/Mast/Footer.vue +0 -15
  487. package/layers/ui/app/components/Mast/NavModal.vue +0 -72
  488. package/layers/ui/app/components/Media/Picture.vue +0 -50
  489. package/layers/ui/app/components/Progress/Bar.vue +0 -35
  490. package/layers/ui/app/components/Tint/Overlay.vue +0 -25
  491. package/layers/ui/app/components/Typography/CodeBlock.vue +0 -42
  492. package/layers/ui/app/components/Typography/Headline.vue +0 -88
  493. package/layers/ui/app/components/Typography/HeadlineScreen.vue +0 -77
  494. package/layers/ui/app/components/Typography/QuoteBlock.vue +0 -20
  495. package/layers/ui/app/components/Typography/index.vue +0 -52
  496. package/layers/ui/app/types/app-config.d.ts +0 -22
  497. package/layers/ui/app/types/nav.ts +0 -5
  498. /package/layers/{motion → animations}/app/components/Motion/CountUp.vue +0 -0
  499. /package/layers/{motion → animations}/app/components/Motion/Cursor.vue +0 -0
  500. /package/layers/{motion → animations}/app/components/Motion/Magnetic.vue +0 -0
  501. /package/layers/{motion → animations}/app/components/Motion/Marquee.vue +0 -0
  502. /package/layers/{motion → animations}/app/components/Motion/MarqueeText.vue +0 -0
  503. /package/layers/{motion → animations}/app/components/Motion/Staggered.vue +0 -0
  504. /package/layers/{motion → animations}/app/components/Motion/TextReveal.vue +0 -0
  505. /package/layers/{motion → animations}/app/components/Motion/Tilt.vue +0 -0
  506. /package/layers/{motion → animations}/app/components/Motion/VelocityEffect.vue +0 -0
  507. /package/layers/{motion → animations}/app/composables/useCountUp.ts +0 -0
  508. /package/layers/{motion → animations}/app/composables/useCursorFollower.ts +0 -0
  509. /package/layers/{motion → animations}/app/composables/useMagneticElement.ts +0 -0
  510. /package/layers/{motion → animations}/app/composables/useMarqueeCopies.ts +0 -0
  511. /package/layers/{motion → animations}/app/composables/useMarqueeVelocity.ts +0 -0
  512. /package/layers/{motion → animations}/app/composables/useTiltEffect.ts +0 -0
  513. /package/layers/{ui → navigation}/app/components/Mast/Main.vue +0 -0
  514. /package/layers/{ui → navigation}/app/components/Site/Subtitle.vue +0 -0
  515. /package/layers/{ui → navigation}/app/components/Site/Title.vue +0 -0
  516. /package/layers/{ui → navigation}/app/utils/regex.ts +0 -0
  517. /package/layers/{motion/app/assets/css/motion.css → transitions/app/assets/css/transitions.css} +0 -0
  518. /package/layers/{ui → typography}/app/composables/color.ts +0 -0
  519. /package/layers/{ui → typography}/app/types/colors.ts +0 -0
  520. /package/layers/{ui → visual}/app/types/breakpoints.ts +0 -0
@@ -0,0 +1,94 @@
1
+ # Layout Shift Root Causes
2
+
3
+ Catalogue of layout shift (CLS) issues found and fixed in this monorepo, with root cause and resolution for each.
4
+
5
+ ---
6
+
7
+ ## 1. `Math.random()` SVG gradient ID — `Progress/Circular.vue`
8
+
9
+ **Cause:** `Math.random()` produces a different value on every call. Server and client generate different IDs for the `linearGradient`, so the `stroke="url(#...)"` reference breaks after hydration.
10
+
11
+ **Fix:** Replace with Nuxt's `useId()` which produces the same deterministic ID across server and client for a given component instance.
12
+
13
+ ---
14
+
15
+ ## 2. Locale-dependent date formatting — `Blog/Article.vue`
16
+
17
+ **Cause:** `new Date().toLocaleDateString()` with no locale argument uses the runtime's default locale. Node.js (server) and the browser may have different default locales, producing different date strings.
18
+
19
+ **Fix:** Pass an explicit locale string: `toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })`.
20
+
21
+ ---
22
+
23
+ ## 3. Year computed independently on server and client — `Mast/Footer.vue`
24
+
25
+ **Cause:** `new Date().getFullYear()` is evaluated independently on server and client. Around year boundaries (different timezones, late-night requests) the two values can differ.
26
+
27
+ **Fix:** Use `useState('footer-year', () => new Date().getFullYear())` so the year is serialised in the Nuxt payload and reused by the client without re-computing.
28
+
29
+ ---
30
+
31
+ ## 4. Feature flags all `false` on server — `DiagnosticsPage.vue`
32
+
33
+ **Cause:** `useFeatures()` detects browser capabilities which are unavailable on the server, so all flags default to `false`. The server renders `✗` for every feature; the client flips many to `true`, causing mismatches on every `v-if`.
34
+
35
+ **Fix:** Wrap the content in `<ClientOnly>` — browser capability detection is inherently client-only.
36
+
37
+ ---
38
+
39
+ ## 5. Theme composables using `useLocalStorage` — theme layer
40
+
41
+ **Cause:** `useLocalStorage` reads from localStorage which doesn't exist on the server. The server renders with the default value; the client reads the user's saved preference and produces different output.
42
+
43
+ **Fix:** Replace `useLocalStorage` with `useState` (SSR-safe, serialised to the Nuxt payload). A `.client.ts` plugin reads localStorage post-hydration and calls the setters to restore preferences — a deliberate two-phase update that avoids the mismatch.
44
+
45
+ ---
46
+
47
+ ## 6. Tailwind 4 `@config` restricting content scanning — `core.css`
48
+
49
+ **Cause:** The `tailwind.config.js` loaded via `@config` contained a `content:` array pointing only to the core layer's files. In Tailwind 4, this array restricts scanning to those paths, so utilities from `ui`, `layout`, `theme`, etc. layers were absent from the initial CSS bundle. In dev mode, Tailwind discovers them lazily via HMR, causing a visible shift.
50
+
51
+ **Fix:** Remove the `content:` array from `tailwind.config.js`. Tailwind 4's Vite plugin auto-discovers all Vite-processed files. Also added `@source` globs in `core.css` covering all layer and app directories for belt-and-suspenders eager scanning.
52
+
53
+ ---
54
+
55
+ ## 7. Vite CSS code splitting deferring stylesheets
56
+
57
+ **Cause:** Vite's default `cssCodeSplit: true` bundles CSS with the JS chunk that imports it. CSS for lazily-loaded components only arrives when that JS chunk is first requested, leaving the initial render unstyled.
58
+
59
+ **Fix:** Set `cssCodeSplit: false` in the playground app's `vite.build` config to merge all CSS into one bundle loaded at first paint.
60
+
61
+ ---
62
+
63
+ ## 8. `@layer` in a CSS file not processed by Tailwind — `ui.css`, `theme.css`
64
+
65
+ **Cause:** Using `@layer utilities { ... }` or `@layer base { ... }` inside a CSS file loaded via Nuxt's `css: []` array (not via `@import 'tailwindcss'`) creates a raw CSS cascade layer declaration outside Tailwind's pipeline. The browser processes this as a separate layer, triggering a style recalculation after initial paint.
66
+
67
+ **Fix:** Replace `@layer` blocks with plain selectors in any CSS file that isn't processed by Tailwind. Only CSS files that contain `@import 'tailwindcss'` should use `@layer`.
68
+
69
+ **Rule:** Never use `@layer` (or `@utility`) in a file loaded via `css: []` unless it also imports Tailwind.
70
+
71
+ ---
72
+
73
+ ## 9. `NuxtAnnouncer` / `NuxtRouteAnnouncer` inside a CSS grid — `app.vue`
74
+
75
+ **Cause:** `<NuxtAnnouncer>` and `<NuxtRouteAnnouncer>` were inside the `<NuxtLayout>` slot, making them direct children of the `mastmain` CSS grid. Before their `position: absolute` CSS loaded, they auto-placed as grid rows and pushed the `basesection` down by ~85px. When the CSS loaded and removed them from grid flow, the section jumped back up.
76
+
77
+ **Fix:** Remove `<NuxtAnnouncer>` and `<NuxtRouteAnnouncer>` entirely — they are boilerplate and not needed in this project.
78
+
79
+ ---
80
+
81
+ ## 10. Layout header hydration mismatch — `ui/layouts/default.vue`
82
+
83
+ **Cause:** The layout used `resolveComponent('MastHeader')` at runtime to detect whether a header component existed. In Nuxt 4, components are registered via compile-time auto-imports, not via `app.component()`, so `resolveComponent` always returns a string at runtime. Server-side Vue resolves it differently, so the header rendered on the server but not after client hydration — causing the section to shift up by the header height.
84
+
85
+ **Fix:** Remove the `resolveComponent` guard. The layout always renders `<MastHeader />` and `<MastFooter />` unconditionally; the components themselves handle empty states via `appConfig`.
86
+
87
+ ---
88
+
89
+ ## Key Rules Going Forward
90
+
91
+ - Never use `@layer` / `@utility` in CSS files loaded via `css: []` — use plain selectors instead.
92
+ - Never use runtime `resolveComponent` to conditionally render components in Nuxt 4 — components are compile-time, not runtime-registered.
93
+ - Use `useState` (not `useLocalStorage`) for any value rendered during SSR that might differ between server and client.
94
+ - Keep accessibility-only elements (`aria-live` regions, announcers) outside CSS grid containers to prevent them participating in grid flow.
@@ -0,0 +1,17 @@
1
+ export default defineNuxtConfig({
2
+ $meta: { name: 'animations' },
3
+
4
+ extends: ['../scroll'],
5
+
6
+ alias: {
7
+ '#layers/animations': import.meta.dirname,
8
+ '#layers/animations/types': `${import.meta.dirname}/app/types`,
9
+ },
10
+
11
+ compatibilityDate: '2026-06-06',
12
+
13
+ typescript: {
14
+ typeCheck: false,
15
+ strict: true,
16
+ },
17
+ })
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "kmcom-layer-animations",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./nuxt.config.ts"
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "../../apps/playground/tsconfig.json",
3
+ "compilerOptions": {
4
+ "strict": true
5
+ },
6
+ "exclude": ["node_modules"]
7
+ }
@@ -0,0 +1,125 @@
1
+ <!-- eslint-disable vue/no-boolean-default -->
2
+ <!-- eslint-disable @typescript-eslint/ban-ts-comment -->
3
+ <!-- eslint-disable vue/define-props-destructuring -->
4
+ <!-- eslint-disable @typescript-eslint/no-explicit-any -->
5
+ <script setup lang="ts">
6
+ // @ts-nocheck - Three.js WebGPU types + TresJS renderer factory
7
+ import { TresCanvas } from '@tresjs/core'
8
+ import {
9
+ ACESFilmicToneMapping,
10
+ CineonToneMapping,
11
+ Color,
12
+ LinearToneMapping,
13
+ ReinhardToneMapping,
14
+ SRGBColorSpace,
15
+ type ToneMapping,
16
+ } from 'three'
17
+ import { WebGPURenderer } from 'three/webgpu'
18
+
19
+ const props = withDefaults(
20
+ defineProps<{
21
+ clearColor?: string
22
+ toneMapping?: 'aces' | 'reinhard' | 'cineon' | 'linear'
23
+ outputColorSpace?: 'srgb' | 'linear'
24
+ shadows?: boolean
25
+ antialias?: boolean
26
+ alpha?: boolean
27
+ preserveDrawingBuffer?: boolean
28
+ powerPreference?: 'default' | 'high-performance' | 'low-power'
29
+ windowSize?: boolean
30
+ /** Use WebGPURenderer (required for node materials / TSL shaders) */
31
+ webgpu?: boolean
32
+ }>(),
33
+ {
34
+ clearColor: '#000000',
35
+ toneMapping: 'aces',
36
+ outputColorSpace: 'srgb',
37
+ shadows: false,
38
+ antialias: true,
39
+ alpha: false,
40
+ preserveDrawingBuffer: false,
41
+ powerPreference: 'high-performance',
42
+ windowSize: true,
43
+ webgpu: false,
44
+ }
45
+ )
46
+
47
+ const emit = defineEmits<{
48
+ ready: [context: any]
49
+ }>()
50
+
51
+ const config = useAppConfig()
52
+ const shaderConfig = (config.shader || {}) as {
53
+ toneMapping?: string
54
+ maxPixelRatio?: number
55
+ }
56
+
57
+ const toneMappingMap: Record<string, ToneMapping> = {
58
+ aces: ACESFilmicToneMapping,
59
+ reinhard: ReinhardToneMapping,
60
+ cineon: CineonToneMapping,
61
+ linear: LinearToneMapping,
62
+ }
63
+
64
+ const resolvedToneMapping = computed(() => {
65
+ const key = props.toneMapping || shaderConfig.toneMapping || 'aces'
66
+ return toneMappingMap[key] ?? ACESFilmicToneMapping
67
+ })
68
+
69
+ const resolvedColorSpace = computed(() => {
70
+ return props.outputColorSpace === 'srgb' ? SRGBColorSpace : 'srgb-linear'
71
+ })
72
+
73
+ const maxDpr = computed(() => {
74
+ const configDpr = shaderConfig.maxPixelRatio ?? 2
75
+ return Math.min(window.devicePixelRatio, configDpr)
76
+ })
77
+
78
+ // WebGPU renderer factory — TresJS v5 calls renderer.init() automatically
79
+ // when the returned object has isRenderer === true (three/webgpu Renderer base class)
80
+ const webgpuRendererFactory = props.webgpu
81
+ ? ({ canvas }: { canvas: any }) => {
82
+ const r = new WebGPURenderer({
83
+ canvas: unref(canvas),
84
+ antialias: props.antialias,
85
+ powerPreference: props.powerPreference,
86
+ })
87
+ r.setPixelRatio(Math.min(window.devicePixelRatio, maxDpr.value))
88
+ r.setClearColor(new Color(props.clearColor))
89
+ r.toneMapping = resolvedToneMapping.value
90
+ r.outputColorSpace = resolvedColorSpace.value
91
+ return r
92
+ }
93
+ : undefined
94
+
95
+ function onReady(context: any) {
96
+ emit('ready', context)
97
+ }
98
+ </script>
99
+
100
+ <template>
101
+ <TresCanvas
102
+ :clear-color
103
+ :tone-mapping="resolvedToneMapping"
104
+ :output-color-space="resolvedColorSpace"
105
+ :shadows
106
+ :antialias
107
+ :alpha
108
+ :preserve-drawing-buffer
109
+ :power-preference
110
+ :window-size
111
+ :dpr="maxDpr"
112
+ :renderer="webgpuRendererFactory"
113
+ class="shader-canvas"
114
+ @ready="onReady"
115
+ >
116
+ <slot />
117
+ </TresCanvas>
118
+ </template>
119
+
120
+ <style scoped>
121
+ .shader-canvas {
122
+ width: 100%;
123
+ height: 100%;
124
+ }
125
+ </style>
@@ -1,6 +1,14 @@
1
+ /* eslint-disable no-restricted-syntax */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ /* eslint-disable @typescript-eslint/consistent-type-assertions */
4
+ import {
5
+ QUALITY_PRESETS,
6
+ type QualityLevel,
7
+ type QualitySettings,
8
+ type RendererBackend,
9
+ type RendererCapabilities,
10
+ } from '#layers/canvas/types/renderer'
1
11
  import type { WebGLRenderer } from 'three'
2
- import type { QualityLevel, QualitySettings, RendererBackend, RendererCapabilities } from '../types'
3
- import { QUALITY_PRESETS } from '../types'
4
12
 
5
13
  /**
6
14
  * Detect and expose renderer capabilities
@@ -1,8 +1,8 @@
1
- /* eslint-disable no-restricted-imports */
2
- import { uniform } from 'three/tsl'
1
+ /* eslint-disable no-restricted-syntax */
3
2
  import { computed, onMounted, onUnmounted, ref } from 'vue'
3
+ import { uniform } from 'three/tsl'
4
4
 
5
- export interface ShaderTimeOptions {
5
+ export type ShaderTimeOptions = {
6
6
  autoStart?: boolean
7
7
  speed?: number
8
8
  }
@@ -0,0 +1,50 @@
1
+ export type RendererBackend = 'webgpu' | 'webgl'
2
+ export type QualityLevel = 'low' | 'medium' | 'high' | 'ultra'
3
+ export type ToneMappingPreset = 'aces' | 'reinhard' | 'cineon' | 'linear'
4
+
5
+ export type RendererCapabilities = {
6
+ backend: RendererBackend
7
+ maxTextureSize: number
8
+ maxTextures: number
9
+ maxVertexUniforms: number
10
+ maxFragmentUniforms: number
11
+ floatTextures: boolean
12
+ anisotropy: number
13
+ precision: 'lowp' | 'mediump' | 'highp'
14
+ devicePixelRatio: number
15
+ isWebGPU: boolean
16
+ }
17
+
18
+ export type QualitySettings = {
19
+ pixelRatio: number
20
+ antialias: boolean
21
+ shadows: boolean
22
+ postProcessing: boolean
23
+ }
24
+
25
+ export const QUALITY_PRESETS: Record<QualityLevel, QualitySettings> = {
26
+ low: {
27
+ pixelRatio: 1,
28
+ antialias: false,
29
+ shadows: false,
30
+ postProcessing: false,
31
+ },
32
+ medium: {
33
+ pixelRatio: 1.5,
34
+ antialias: true,
35
+ shadows: false,
36
+ postProcessing: true,
37
+ },
38
+ high: {
39
+ pixelRatio: 2,
40
+ antialias: true,
41
+ shadows: true,
42
+ postProcessing: true,
43
+ },
44
+ ultra: {
45
+ pixelRatio: 2,
46
+ antialias: true,
47
+ shadows: true,
48
+ postProcessing: true,
49
+ },
50
+ }
@@ -0,0 +1,189 @@
1
+ import type { Plugin } from 'vite'
2
+
3
+ /**
4
+ * Intercepts three.webgpu.js in SSR via the transform hook.
5
+ *
6
+ * Unlike resolveId (which isn't reliably called in vite-node dev mode after
7
+ * the module graph is built), transform IS called for every module evaluation.
8
+ * We know this because Vite's `define` substitution — which works via transform —
9
+ * successfully polyfilled `self` in earlier debugging.
10
+ *
11
+ * Both `three/webgpu` and `three/tsl` package.json exports resolve to the same
12
+ * file: three/build/three.webgpu.js. That file accesses `self` and `navigator`
13
+ * at module scope, crashing SSR startup. We return a lightweight stub instead.
14
+ */
15
+ function threeWebGPUSSRStub(): Plugin {
16
+ const tslNoop = `
17
+ const n = new Proxy(function noop() { return n }, {
18
+ get(_t, k) {
19
+ if (k === 'then' || k === Symbol.toPrimitive || k === Symbol.iterator || k === Symbol.toStringTag) return undefined
20
+ return n
21
+ },
22
+ apply() { return n },
23
+ construct() { return Object.create(n) },
24
+ })
25
+ `
26
+ const tslNames = [
27
+ // Constructors
28
+ 'float',
29
+ 'vec2',
30
+ 'vec3',
31
+ 'vec4',
32
+ 'color',
33
+ 'mat2',
34
+ 'mat3',
35
+ 'mat4',
36
+ // Uniforms / attributes
37
+ 'uniform',
38
+ 'attribute',
39
+ 'varying',
40
+ // Function definition
41
+ 'Fn',
42
+ // Arithmetic
43
+ 'add',
44
+ 'sub',
45
+ 'mul',
46
+ 'div',
47
+ 'mod',
48
+ 'abs',
49
+ 'sign',
50
+ 'floor',
51
+ 'ceil',
52
+ 'fract',
53
+ 'round',
54
+ 'min',
55
+ 'max',
56
+ 'clamp',
57
+ 'mix',
58
+ 'smoothstep',
59
+ 'pow',
60
+ 'sqrt',
61
+ 'exp',
62
+ 'log',
63
+ // Trigonometry
64
+ 'sin',
65
+ 'cos',
66
+ 'tan',
67
+ 'asin',
68
+ 'acos',
69
+ 'atan',
70
+ 'atan2',
71
+ // Vector operations
72
+ 'dot',
73
+ 'cross',
74
+ 'normalize',
75
+ 'length',
76
+ 'distance',
77
+ 'reflect',
78
+ 'refract',
79
+ // Matrix operations
80
+ 'transpose',
81
+ 'inverse',
82
+ // Texture
83
+ 'texture',
84
+ 'sampler',
85
+ // Comparison / selection
86
+ 'lessThan',
87
+ 'lessThanEqual',
88
+ 'greaterThan',
89
+ 'greaterThanEqual',
90
+ 'step',
91
+ 'select',
92
+ 'cond',
93
+ // Built-in inputs
94
+ 'uv',
95
+ 'time',
96
+ 'EPSILON',
97
+ 'Loop',
98
+ 'positionLocal',
99
+ 'positionWorld',
100
+ 'positionView',
101
+ 'normalLocal',
102
+ 'normalWorld',
103
+ 'normalView',
104
+ 'positionViewDirection',
105
+ 'cameraPosition',
106
+ // Timers
107
+ 'timerGlobal',
108
+ 'timerLocal',
109
+ 'timerDelta',
110
+ ]
111
+
112
+ const stub =
113
+ tslNoop +
114
+ tslNames.map((name) => `export const ${name} = n`).join('\n') +
115
+ `
116
+ // WebGPU class stubs (used by three/webgpu imports)
117
+ export class MeshBasicNodeMaterial {
118
+ constructor() { this.colorNode = null; this.side = null }
119
+ }
120
+ export class MeshStandardNodeMaterial {
121
+ constructor() { this.colorNode = null; this.side = null }
122
+ }
123
+ export class TextureLoader {
124
+ load() { return null }
125
+ }
126
+ export class UniformNode {}
127
+ export default {}
128
+ `
129
+
130
+ return {
131
+ name: 'three-webgpu-ssr-stub',
132
+ enforce: 'pre',
133
+ transform(_code, id, options) {
134
+ if (!options?.ssr) return null
135
+ if (!id.includes('three.webgpu.js') && !id.includes('three.tsl.js')) return null
136
+ return { code: stub, map: null }
137
+ },
138
+ }
139
+ }
140
+
141
+ export default defineNuxtConfig({
142
+ $meta: {
143
+ name: 'canvas',
144
+ },
145
+
146
+ compatibilityDate: '2026-06-06',
147
+
148
+ extends: ['../core'],
149
+
150
+ typescript: {
151
+ typeCheck: false,
152
+ strict: true,
153
+ },
154
+
155
+ modules: ['@tresjs/nuxt'],
156
+
157
+ tres: {
158
+ devtools: true,
159
+ },
160
+
161
+ alias: {
162
+ // More specific alias must be registered first — Vite/Rollup alias
163
+ // resolution is order-dependent (first prefix match wins), so
164
+ // '#layers/canvas' would otherwise shadow '#layers/canvas/types'
165
+ // and resolve it to '<root>/types/...' instead of '<root>/app/types/...'.
166
+ '#layers/canvas/types': `${import.meta.dirname}/app/types`,
167
+ '#layers/canvas': import.meta.dirname,
168
+ },
169
+
170
+ imports: {
171
+ dirs: [`${import.meta.dirname}/app/composables`],
172
+ },
173
+
174
+ vite: {
175
+ plugins: [threeWebGPUSSRStub()],
176
+ optimizeDeps: {
177
+ include: ['three', 'three/webgpu', 'three/tsl'],
178
+ esbuildOptions: {
179
+ target: 'esnext',
180
+ },
181
+ },
182
+ build: {
183
+ target: 'esnext',
184
+ },
185
+ ssr: {
186
+ noExternal: ['three'],
187
+ },
188
+ },
189
+ })
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "kmcom-layer-canvas",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./nuxt.config.ts",
6
+ "scripts": {
7
+ "dev": "nuxi dev",
8
+ "dev:playground": "PLAYGROUND_LAYERS=core,canvas pnpm -F playground dev",
9
+ "typecheck": "vue-tsc --noEmit -p ../../tsconfig.typecheck.json"
10
+ },
11
+ "dependencies": {
12
+ "@tresjs/cientos": "catalog:",
13
+ "@tresjs/core": "catalog:",
14
+ "@tresjs/nuxt": "catalog:",
15
+ "@tresjs/post-processing": "catalog:",
16
+ "@vueuse/core": "catalog:",
17
+ "three": "catalog:"
18
+ },
19
+ "devDependencies": {
20
+ "@types/three": "catalog:"
21
+ }
22
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "../../apps/playground/tsconfig.json",
3
+ "compilerOptions": {
4
+ "strict": true
5
+ },
6
+ "exclude": ["node_modules"]
7
+ }
@@ -1,18 +1,24 @@
1
1
  <script setup lang="ts">
2
- import type { BlogCollectionItem } from '@nuxt/content'
2
+ import type { BlogCollectionItem } from '@nuxt/content'
3
3
 
4
- const { slug } = defineProps<{
5
- slug: string
6
- }>()
4
+ const { slug } = defineProps<{
5
+ slug: string
6
+ }>()
7
7
 
8
- const asBlog = (item: unknown) => item as BlogCollectionItem
8
+ const asBlog = (item: unknown) => item as BlogCollectionItem
9
9
  </script>
10
10
 
11
11
  <template>
12
12
  <NuxtContentDetail collection="blog" :slug not-found-message="Blog post not found">
13
13
  <template #headline="{ item }">
14
14
  <div class="flex items-center gap-3 text-sm text-muted">
15
- <time v-if="asBlog(item).date">{{ new Date(asBlog(item).date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) }}</time>
15
+ <time v-if="asBlog(item).date">{{
16
+ new Date(asBlog(item).date).toLocaleDateString('en-US', {
17
+ year: 'numeric',
18
+ month: 'long',
19
+ day: 'numeric',
20
+ })
21
+ }}</time>
16
22
  <UBadge v-if="asBlog(item).badge" color="primary" variant="subtle">
17
23
  {{ asBlog(item).badge }}
18
24
  </UBadge>
@@ -1,30 +1,30 @@
1
1
  <!-- eslint-disable vue/require-default-prop -->
2
2
  <script setup lang="ts">
3
- const {
4
- title,
5
- description,
6
- date,
7
- image,
8
- badge,
9
- authors = [],
10
- to,
11
- } = defineProps<{
12
- title: string
13
- description?: string
14
- date?: string
15
- image?: string
16
- badge?: string
17
- authors?: { name: string; avatar?: string; url?: string }[]
18
- to?: string
19
- }>()
3
+ const {
4
+ title,
5
+ description,
6
+ date,
7
+ image,
8
+ badge,
9
+ authors = [],
10
+ to,
11
+ } = defineProps<{
12
+ title: string
13
+ description?: string
14
+ date?: string
15
+ image?: string
16
+ badge?: string
17
+ authors?: { name: string; avatar?: string; url?: string }[]
18
+ to?: string
19
+ }>()
20
20
 
21
- const postProps = computed(() => ({
22
- ...(description !== undefined && { description }),
23
- ...(date !== undefined && { date }),
24
- ...(image !== undefined && { image }),
25
- ...(badge !== undefined && { badge }),
26
- ...(to !== undefined && { to }),
27
- }))
21
+ const postProps = computed(() => ({
22
+ ...(description !== undefined && { description }),
23
+ ...(date !== undefined && { date }),
24
+ ...(image !== undefined && { image }),
25
+ ...(badge !== undefined && { badge }),
26
+ ...(to !== undefined && { to }),
27
+ }))
28
28
  </script>
29
29
 
30
30
  <template>
@@ -1,20 +1,17 @@
1
+ <!-- eslint-disable @typescript-eslint/ban-ts-comment -->
1
2
  <script setup lang="ts">
2
- // @ts-nocheck
3
- import type { BlogQueryOptions } from '../../types/content'
3
+ // @ts-nocheck
4
+ import type { BlogQueryOptions } from '../../types/content'
4
5
 
5
- const { options = {} } = defineProps<{
6
- options?: BlogQueryOptions
7
- }>()
6
+ const { options = {} } = defineProps<{
7
+ options?: BlogQueryOptions
8
+ }>()
8
9
 
9
- const { data: posts, status } = await useBlogPosts(options)
10
+ const { data: posts, status } = await useBlogPosts(options)
10
11
  </script>
11
12
 
12
13
  <template>
13
- <NuxtContentList
14
- :status="status"
15
- :has-items="!!posts?.length"
16
- empty-message="No blog posts found"
17
- >
14
+ <NuxtContentList :status :has-items="!!posts?.length" empty-message="No blog posts found">
18
15
  <UBlogPosts orientation="vertical">
19
16
  <UBlogPost
20
17
  v-for="post in posts"