@lampdotdev/lamp 0.0.0-stage → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (464) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -2
  3. package/Resources/Devices/roku.json +410 -0
  4. package/Resources/Devices/xbox-one.json +367 -0
  5. package/Resources/GameKit/NOTICE.md +63 -0
  6. package/Resources/GameKit/apple/LampPage.swift +1646 -0
  7. package/Resources/GameKit/apple/LampPlayer.swift +46 -0
  8. package/Resources/GameKit/apple/LampWebApp.swift +63 -0
  9. package/Resources/GameKit/apple/LampWebGame.swift +87 -0
  10. package/Resources/GameKit/apple/Native.swift +12 -0
  11. package/Resources/GameKit/build.sh +55 -0
  12. package/Resources/GameKit/lamp_game.h +116 -0
  13. package/Resources/GameKit/lamp_host.h +19 -0
  14. package/Resources/GameKit/lamp_kit.cpp +61 -0
  15. package/Resources/GameKit/lamp_sound.cpp +455 -0
  16. package/Resources/GameKit/lamp_xbox.cpp +374 -0
  17. package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
  18. package/Resources/GameKit/libraries/cgltf.h +7240 -0
  19. package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
  20. package/Resources/GameKit/libraries/dr_wav.h +9209 -0
  21. package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
  22. package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
  23. package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
  24. package/Resources/GameKit/libraries/sokol_log.h +335 -0
  25. package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
  26. package/Resources/GameKit/libraries/stb_image.h +7988 -0
  27. package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
  28. package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
  29. package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
  30. package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
  31. package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
  32. package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
  33. package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
  34. package/Resources/GameKit/web/lamp-game.js +3036 -0
  35. package/Resources/GameKit/web/lamp-phaser.js +128 -0
  36. package/Resources/WebHost/App.exe +0 -0
  37. package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
  38. package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
  39. package/Resources/WebHost/lamp_controllers.h +1506 -0
  40. package/Resources/WebHost/lamp_web_host.cpp +1173 -0
  41. package/Resources/WebLibraries/earlier.txt +318 -0
  42. package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
  43. package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
  44. package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
  45. package/Resources/WebLibraries/qrcode/LICENSE +21 -0
  46. package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
  47. package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
  48. package/Resources/WebLibraries/rapier/LICENSE +201 -0
  49. package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
  50. package/Resources/WebLibraries/rapier/rapier.js +2 -0
  51. package/Resources/WebLibraries/three/LICENSE +21 -0
  52. package/Resources/WebLibraries/three/NOTICE.md +4 -0
  53. package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
  54. package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
  55. package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
  56. package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
  57. package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
  58. package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
  59. package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
  60. package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
  61. package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
  62. package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
  63. package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
  64. package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
  65. package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
  66. package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
  67. package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
  68. package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
  69. package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
  70. package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
  71. package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
  72. package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
  73. package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
  74. package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
  75. package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
  76. package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
  77. package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
  78. package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
  79. package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
  80. package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
  81. package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
  82. package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
  83. package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
  84. package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
  85. package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
  86. package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
  87. package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
  88. package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
  89. package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
  90. package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
  91. package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
  92. package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
  93. package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
  94. package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
  95. package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
  96. package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
  97. package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
  98. package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
  99. package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
  100. package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
  101. package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
  102. package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
  103. package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
  104. package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
  105. package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
  106. package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
  107. package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
  108. package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
  109. package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
  110. package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
  111. package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
  112. package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
  113. package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
  114. package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
  115. package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
  116. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
  117. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
  118. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
  119. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
  120. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
  121. package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
  122. package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
  123. package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
  124. package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
  125. package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
  126. package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
  127. package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
  128. package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
  129. package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
  130. package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
  131. package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
  132. package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
  133. package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
  134. package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
  135. package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
  136. package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
  137. package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
  138. package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
  139. package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
  140. package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
  141. package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
  142. package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
  143. package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
  144. package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
  145. package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
  146. package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
  147. package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
  148. package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
  149. package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
  150. package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
  151. package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
  152. package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
  153. package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
  154. package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
  155. package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
  156. package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
  157. package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
  158. package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
  159. package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
  160. package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
  161. package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
  162. package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
  163. package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
  164. package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
  165. package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
  166. package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
  167. package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
  168. package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
  169. package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
  170. package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
  171. package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
  172. package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
  173. package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
  174. package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
  175. package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
  176. package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
  177. package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
  178. package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
  179. package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
  180. package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
  181. package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
  182. package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
  183. package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
  184. package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
  185. package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
  186. package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
  187. package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
  188. package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
  189. package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
  190. package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
  191. package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
  192. package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
  193. package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
  194. package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
  195. package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
  196. package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
  197. package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
  198. package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
  199. package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
  200. package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
  201. package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
  202. package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
  203. package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
  204. package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
  205. package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
  206. package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
  207. package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
  208. package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
  209. package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
  210. package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
  211. package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
  212. package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
  213. package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
  214. package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
  215. package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
  216. package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
  217. package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
  218. package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
  219. package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
  220. package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
  221. package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
  222. package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
  223. package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
  224. package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
  225. package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
  226. package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
  227. package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
  228. package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
  229. package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
  230. package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
  231. package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
  232. package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
  233. package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
  234. package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
  235. package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
  236. package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
  237. package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
  238. package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
  239. package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
  240. package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
  241. package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
  242. package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
  243. package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
  244. package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
  245. package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
  246. package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
  247. package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
  248. package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
  249. package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
  250. package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
  251. package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
  252. package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
  253. package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
  254. package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
  255. package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
  256. package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
  257. package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
  258. package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
  259. package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
  260. package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
  261. package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
  262. package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
  263. package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
  264. package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
  265. package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
  266. package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
  267. package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
  268. package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
  269. package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
  270. package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
  271. package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
  272. package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
  273. package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
  274. package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
  275. package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
  276. package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
  277. package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
  278. package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
  279. package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
  280. package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
  281. package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
  282. package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
  283. package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
  284. package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
  285. package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
  286. package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
  287. package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
  288. package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
  289. package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
  290. package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
  291. package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
  292. package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
  293. package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
  294. package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
  295. package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
  296. package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
  297. package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
  298. package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
  299. package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
  300. package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
  301. package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
  302. package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
  303. package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
  304. package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
  305. package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
  306. package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
  307. package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
  308. package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
  309. package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
  310. package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
  311. package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
  312. package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
  313. package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
  314. package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
  315. package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
  316. package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
  317. package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
  318. package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
  319. package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
  320. package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
  321. package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
  322. package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
  323. package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
  324. package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
  325. package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
  326. package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
  327. package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
  328. package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
  329. package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
  330. package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
  331. package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
  332. package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
  333. package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
  334. package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
  335. package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
  336. package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
  337. package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
  338. package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
  339. package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
  340. package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
  341. package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
  342. package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
  343. package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
  344. package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
  345. package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
  346. package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
  347. package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
  348. package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
  349. package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
  350. package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
  351. package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
  352. package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
  353. package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
  354. package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
  355. package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
  356. package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
  357. package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
  358. package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
  359. package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
  360. package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
  361. package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
  362. package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
  363. package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
  364. package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
  365. package/Resources/WebLibraries/three/three.core.js +61162 -0
  366. package/Resources/WebLibraries/three/three.module.js +19537 -0
  367. package/Resources/WebLibraries/three/three.tsl.js +41903 -0
  368. package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
  369. package/Resources/skills/2d-game/SKILL.md +305 -0
  370. package/Resources/skills/3d-game/SKILL.md +274 -0
  371. package/Resources/skills/accounts/SKILL.md +41 -0
  372. package/Resources/skills/android-design/SKILL.md +159 -0
  373. package/Resources/skills/app-ai/SKILL.md +154 -0
  374. package/Resources/skills/app-intents/SKILL.md +31 -0
  375. package/Resources/skills/app-kinds/SKILL.md +122 -0
  376. package/Resources/skills/apple-watch/SKILL.md +43 -0
  377. package/Resources/skills/assets/SKILL.md +183 -0
  378. package/Resources/skills/building-blocks/SKILL.md +97 -0
  379. package/Resources/skills/device-control/SKILL.md +56 -0
  380. package/Resources/skills/device-integrations/SKILL.md +278 -0
  381. package/Resources/skills/finder-files/SKILL.md +19 -0
  382. package/Resources/skills/game/SKILL.md +414 -0
  383. package/Resources/skills/game-3d/SKILL.md +12 -0
  384. package/Resources/skills/game-art/SKILL.md +11 -0
  385. package/Resources/skills/game-feel/SKILL.md +13 -0
  386. package/Resources/skills/game-levels/SKILL.md +12 -0
  387. package/Resources/skills/game-live/SKILL.md +12 -0
  388. package/Resources/skills/game-physics/SKILL.md +13 -0
  389. package/Resources/skills/game-playtest/SKILL.md +26 -0
  390. package/Resources/skills/game-ui/SKILL.md +278 -0
  391. package/Resources/skills/github-projects/SKILL.md +59 -0
  392. package/Resources/skills/icloud-sync/SKILL.md +30 -0
  393. package/Resources/skills/iphone-hardware/SKILL.md +57 -0
  394. package/Resources/skills/iphone-widgets/SKILL.md +53 -0
  395. package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
  396. package/Resources/skills/mac-widgets/SKILL.md +60 -0
  397. package/Resources/skills/maps/SKILL.md +8 -0
  398. package/Resources/skills/menu-bar/SKILL.md +36 -0
  399. package/Resources/skills/more-apps/SKILL.md +53 -0
  400. package/Resources/skills/phone-controllers/SKILL.md +79 -0
  401. package/Resources/skills/phone-pages/SKILL.md +173 -0
  402. package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
  403. package/Resources/skills/scene-3d/SKILL.md +27 -0
  404. package/Resources/skills/scripting/SKILL.md +17 -0
  405. package/Resources/skills/share-extension/SKILL.md +22 -0
  406. package/Resources/skills/tv-design/SKILL.md +72 -0
  407. package/Resources/skills/web-app/SKILL.md +136 -0
  408. package/Resources/skills/web-game/SKILL.md +95 -0
  409. package/Resources/skills/web-or-native/SKILL.md +103 -0
  410. package/Resources/skills/wish-links/SKILL.md +156 -0
  411. package/THIRD_PARTY_NOTICES.md +170 -0
  412. package/cli/android.mjs +941 -0
  413. package/cli/browser.mjs +268 -0
  414. package/cli/calls.mjs +390 -0
  415. package/cli/dev.mjs +773 -0
  416. package/cli/devices.mjs +984 -0
  417. package/cli/lamp.mjs +1016 -0
  418. package/cli/lampapp.mjs +332 -0
  419. package/cli/lamps/android-host/LampPageGateway.kt +345 -0
  420. package/cli/lamps/android-host/app/build.gradle.kts +40 -0
  421. package/cli/lamps/android-host/build.gradle.kts +4 -0
  422. package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
  423. package/cli/lamps/android-host/game/MainActivity.kt +173 -0
  424. package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
  425. package/cli/lamps/android-host/gradle.properties +8 -0
  426. package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
  427. package/cli/lamps/android-host/page/MainActivity.kt +193 -0
  428. package/cli/lamps/android-host/settings.gradle.kts +30 -0
  429. package/cli/lamps/android-host/tools.json +43 -0
  430. package/cli/lamps/lamp-controllers.js +2 -0
  431. package/cli/lamps/lamp-for-games.js +6863 -0
  432. package/cli/lamps/lamp.js +7023 -0
  433. package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
  434. package/cli/lamps/mac-starter/APP.md +12 -0
  435. package/cli/lamps/mac-starter/Package.swift +8 -0
  436. package/cli/lamps/mac-starter/Sources/App.swift +11 -0
  437. package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
  438. package/cli/lamps/mac-starter/Sources/LampSupport.swift +18097 -0
  439. package/cli/lamps/mac-starter/build.sh +336 -0
  440. package/cli/lamps/mac-starter/gitignore +3 -0
  441. package/cli/lamps/mac-starter/lamp-starter.json +6 -0
  442. package/cli/lamps/web-starter/APP.md +8 -0
  443. package/cli/lamps/web-starter/app.js +1 -0
  444. package/cli/lamps/web-starter/index.html +17 -0
  445. package/cli/lamps/web-starter/lamp-starter.json +5 -0
  446. package/cli/lamps/web-starter/lamp.js +7023 -0
  447. package/cli/lamps/web-starter/style.css +25 -0
  448. package/cli/link.mjs +138 -0
  449. package/cli/mac.mjs +621 -0
  450. package/cli/mdns.mjs +205 -0
  451. package/cli/msix.mjs +413 -0
  452. package/cli/network.mjs +209 -0
  453. package/cli/outside.mjs +140 -0
  454. package/cli/page.js +165 -0
  455. package/cli/place.mjs +298 -0
  456. package/cli/png.mjs +184 -0
  457. package/cli/share.mjs +202 -0
  458. package/cli/skill/SKILL.md +255 -0
  459. package/cli/skills.mjs +71 -0
  460. package/cli/state.mjs +173 -0
  461. package/cli/update.mjs +57 -0
  462. package/package.json +20 -4
  463. package/site/lib/quota.js +59 -0
  464. package/site/lib/shared-wishes.js +996 -0
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: android-design
3
+ description: How a good Android app looks and behaves - Material 3 theme and color roles, layouts for phones, foldables and tablets, navigation and predictive back, which component for which job, empty, loading and error states, motion and accessibility. Read before designing or restyling an Android app's screens.
4
+ ---
5
+
6
+ # Designing an Android app
7
+
8
+ The person should feel they're holding an app Google might have made: calm surfaces, one accent, rounded shapes, big
9
+ readable type, and everything where Android people expect it. It's Jetpack Compose with Material 3 (version 1.4 in
10
+ these apps). Everything below compiles with the libraries already in app/build.gradle.kts.
11
+
12
+ ## Theme
13
+
14
+ - Keep the scaffold's `AppTheme`: dynamic color from the wallpaper on Android 12 and later, and a scheme of your own
15
+ before that. Make that scheme from the app's one accent: `lightColorScheme(primary = …, primaryContainer = …,
16
+ secondary = …, tertiary = …)` and its dark twin, each container a lighter (light theme) or deeper (dark theme) tone
17
+ of its color, with its `on…` color legible on it.
18
+ - Color by role, never by hex in a screen: `primary` for the one most important action, `primaryContainer` and
19
+ `secondaryContainer` for things to stand out softly (a selected card, a highlighted number), `tertiaryContainer` for
20
+ a contrasting accent, `surface` with `surfaceContainerLow` … `surfaceContainerHighest` for layers (a card on a page
21
+ is one step higher than the page), `onSurfaceVariant` for secondary text, `outlineVariant` for dividers, `error` and
22
+ `errorContainer` for problems. A color that isn't a role (a category's own color, a chart's series) still gets a
23
+ light and a dark value.
24
+ - Type from `MaterialTheme.typography` only: `displayLarge`/`displayMedium` for a hero number or a timer,
25
+ `headlineSmall`…`headlineLarge` for a screen's big title, `titleMedium`/`titleLarge` for a card's or a list item's
26
+ title, `bodyLarge` for reading, `bodyMedium` for supporting text, `labelLarge` for buttons and `labelMedium`/
27
+ `labelSmall` for chips and captions. A number that changes uses `fontFeatureSettings = "tnum"` so it doesn't jiggle.
28
+ Sizes are in sp, so the person's font size applies.
29
+ - Shapes from `MaterialTheme.shapes`: `extraLarge` (28 dp) for a hero card or a sheet, `large` for cards, `medium`
30
+ for smaller containers, `small` for chips and fields, `CircleShape` for avatars and icon buttons. Current Android is
31
+ generous with roundness and size: a big rounded card with a large number in it reads better than a dense table.
32
+
33
+ ## Edge to edge and insets
34
+
35
+ - The app draws behind the status and navigation bars (`enableEdgeToEdge()` in MainActivity). `Scaffold` hands its
36
+ content the padding that keeps it clear of them and of its own bars: pass it on, and for a list give it as
37
+ `contentPadding` (`LazyColumn(contentPadding = innerPadding)`), so the list scrolls under the bars and its last item
38
+ ends above the gesture bar rather than being cut off.
39
+ - A text field near the bottom needs `Modifier.imePadding()` (or the Scaffold's `contentWindowInsets`) so the keyboard
40
+ doesn't cover it. A screen without a Scaffold uses `Modifier.safeDrawingPadding()`.
41
+ - A game or a full-screen viewer can hide the system bars with `WindowCompat.getInsetsController(window,
42
+ window.decorView).hide(WindowInsetsCompat.Type.systemBars())`, with `systemBarsBehavior =
43
+ BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE`; nothing else should.
44
+
45
+ ## Every screen size
46
+
47
+ Phones, foldables and tablets run the same app, and the window can be resized. Choose the layout by the width the app
48
+ has, read at the top of the screen with `BoxWithConstraints` (no extra library): under 600 dp is compact (a phone held
49
+ upright), 600 to 840 medium (a foldable open, a small tablet, a phone on its side), 840 and over expanded.
50
+
51
+ - Compact: one pane, a bottom `NavigationBar` for three to five top-level destinations.
52
+ - Medium and expanded: a `NavigationRail` at the start edge in place of the bottom bar, and a list beside its detail
53
+ (the list about 360 dp wide, the detail filling the rest) where a phone would go from one to the other. Selecting
54
+ in the list changes the pane beside it, not the screen.
55
+ - Content never stretches across a wide window: reading text and forms stay within about 640 dp, centered or beside
56
+ something else. Grids use `LazyVerticalGrid(GridCells.Adaptive(minSize = 160.dp))` so columns follow the width.
57
+ - Never lock the orientation, and don't assume the window is the screen.
58
+
59
+ ## Navigation and back
60
+
61
+ - Screens are destinations in Navigation 3: each a `@Serializable` class or object implementing `NavKey`, the stack
62
+ `rememberNavBackStack(Home)` (it survives Lamp's reopen and Android's), and `NavDisplay` showing its top with an
63
+ `entryProvider`. Going to a screen adds to the stack; back removes from it.
64
+ - Back is the system's gesture, with its predictive preview of where it leads (on by default for these apps): let
65
+ `NavDisplay` handle it. Use `BackHandler` only to close something on the screen itself (a search, a selection, a
66
+ sheet's own state), never to ask "are you sure you want to leave?".
67
+ - Top-level destinations (the bottom bar's) don't stack on each other: switching to one replaces the stack's root, and
68
+ each keeps its own scroll position.
69
+ - The top app bar: `CenterAlignedTopAppBar` or `TopAppBar` for an ordinary screen; `LargeTopAppBar` with
70
+ `TopAppBarDefaults.exitUntilCollapsedScrollBehavior()` for a collection's home, whose big title shrinks into the bar
71
+ as the list scrolls (connect it with `Modifier.nestedScroll(scrollBehavior.nestedScrollConnection)`). An up arrow
72
+ (`Icons.AutoMirrored.Rounded.ArrowBack`) only on screens below the top level. At most two or three action icons;
73
+ the rest in an overflow menu (`DropdownMenu` from `Icons.Rounded.MoreVert`).
74
+
75
+ ## The right component for the job
76
+
77
+ - The one main thing to create: a `FloatingActionButton`, or `ExtendedFloatingActionButton` with a word when the icon
78
+ alone isn't obvious, shrinking to its icon as the list scrolls (`expanded = !listState.canScrollBackward`). One per
79
+ screen, and none on a screen whose job is reading.
80
+ - Rows of things: `ListItem` (headline, supporting text, a leading icon, avatar or picture, a trailing value, switch or
81
+ chevron) in a `LazyColumn`, with `HorizontalDivider` only where items run together. Cards (`Card`, `ElevatedCard`,
82
+ `OutlinedCard`) for things that are each a little page (a recipe, a place), not for every row.
83
+ - Choosing: `FilterChip`s in a scrolling row for filters, `SingleChoiceSegmentedButtonRow` for two to five views of the
84
+ same thing, `Switch` for on and off (in a `ListItem`'s trailing slot for settings), `RadioButton`s or a menu
85
+ (`ExposedDropdownMenuBox`) for one of many, `Slider` for an amount, `DatePickerDialog` and `TimePicker` for when.
86
+ - Searching: a `SearchBar` at the top of a collection, or a search action that opens one.
87
+ - More about one thing, or a few actions on it: a `ModalBottomSheet`. A dialog (`AlertDialog`) only for a choice that
88
+ can't wait or can't be undone.
89
+ - After deleting or archiving: do it at once and offer Undo in a `Snackbar` (`SnackbarHost` in the Scaffold), rather
90
+ than asking first. Lists can delete or archive with a swipe (`SwipeToDismissBox`), with the same Undo.
91
+ - Content fetched from the network or the AI: `PullToRefreshBox` around the list.
92
+ - Icons from `Icons.Rounded` throughout (one style per app), `Icons.AutoMirrored.Rounded` for ones with a direction.
93
+ - `TopAppBar`, the search bar, bottom sheets, date and time pickers, `SwipeToDismissBox`, `PullToRefreshBox` and
94
+ `ExposedDropdownMenuBox` need `@OptIn(ExperimentalMaterial3Api::class)`: put `@file:OptIn(ExperimentalMaterial3Api::class)`
95
+ at the top of a file that uses them.
96
+ - Not in this version of Material, so don't reach for them: `MaterialExpressiveTheme`, `LoadingIndicator`,
97
+ `ButtonGroup`, `FloatingToolbar`, `SplitButton`, `FloatingActionButtonMenu`, `NavigationSuiteScaffold` and the
98
+ adaptive list-detail scaffolds. The layouts above do their jobs with what's here.
99
+
100
+ ## Every state
101
+
102
+ Design each screen in every state it can be in, since the person will see all of them:
103
+
104
+ - Empty: an icon (48 to 64 dp, `onSurfaceVariant`), a short headline, one sentence and the one action that fills it,
105
+ centered in the space. Not a blank list.
106
+ - Loading: a `CircularProgressIndicator` in the space the content will take, or a `LinearProgressIndicator` under the
107
+ top bar while what's on screen is refreshed; for a list, a few placeholder rows in `surfaceContainerHigh` shapes
108
+ reads calmer than a spinner. An AI call shows what it's doing ("Writing a summary…"), and its result arrives with
109
+ a fade.
110
+ - Failed: say what went wrong in plain words and offer Try Again, in place of the content; a failure of something in
111
+ the background is a Snackbar.
112
+ - Lots: long names wrap or end in an ellipsis (`maxLines`, `overflow = TextOverflow.Ellipsis`), and a list of
113
+ thousands is still a `LazyColumn` with `key = { it.id }`.
114
+ - Big text: at the largest font size (twice the default) nothing overlaps or is cut off; rows grow taller, and a row of
115
+ buttons wraps (`FlowRow`).
116
+ - Dark: everything by role, so it follows the system; check that a picture or a custom color still reads.
117
+
118
+ ## Motion
119
+
120
+ Motion says where something came from and where it went, quickly and with a little spring.
121
+
122
+ - Appearing and disappearing: `AnimatedVisibility` (fade with expand or slide), `AnimatedContent` or `Crossfade`
123
+ when one thing becomes another, `Modifier.animateContentSize()` when something grows.
124
+ - Lists: `Modifier.animateItem()` on each item, so adding, removing and reordering move rather than jump.
125
+ - Values: `animateFloatAsState`, `animateColorAsState` and friends with `spring(dampingRatio =
126
+ Spring.DampingRatioMediumBouncy, stiffness = Spring.StiffnessMediumLow)` for things the person touched,
127
+ `tween(200 to 300 ms)` for fades.
128
+ - Feel: `LocalHapticFeedback.current.performHapticFeedback(HapticFeedbackType.LongPress)` on a long press, a toggle
129
+ or a completed drag; not on every tap.
130
+
131
+ ## Touch and accessibility
132
+
133
+ - Every touch target at least 48 by 48 dp (an `IconButton` already is), with 8 dp between neighbors.
134
+ - Icon-only buttons have a `contentDescription` saying what they do ("Delete note"), decorative images `null`.
135
+ Headings are marked `Modifier.semantics { heading() }`; a row that's one thing to tap is one element
136
+ (`Modifier.clickable` on the row, `mergeDescendants`).
137
+ - Text contrast at least 4.5 to 1 on its background (the `on…` roles are), and never color alone to say something:
138
+ pair it with an icon or a word.
139
+
140
+ ## Games
141
+
142
+ A game draws itself: a `Canvas` filling the screen, its loop in `LaunchedEffect` with `withFrameNanos`, input from
143
+ `pointerInput` (`detectTapGestures`, `detectDragGestures`). Material's controls are for its menus and score screen
144
+ only. Hide the system bars while playing, keep the game's state in a class the Canvas reads, and save the score and
145
+ progress with LampStore.
146
+
147
+ A game has sound: a short effect (under a second) for each thing the player does or meets, from `SoundPool` with each
148
+ sound loaded once (files in `app/src/main/res/raw`, .ogg or .wav, or what the `assets` tool brought into
149
+ `app/src/main/assets`, opened with `context.assets.openFd("<pack>/<file>")`), and music only when it suits, quiet (0.3
150
+ to 0.4) under effects at 0.6 to 0.8, from a `MediaPlayer` with `isLooping`. Look in the `assets` tool first; only for what nothing there fits, make the effects in code: a
151
+ few hundredths of a second of a wave written into an `AudioTrack` (`MODE_STATIC`), with soft ends so it doesn't click.
152
+ Pause the music when the activity stops and release both when it's destroyed. Its settings turn sound and music on and
153
+ off, kept with LampStore. The emulator plays it on the Mac's speakers.
154
+
155
+ ## Checking it
156
+
157
+ Look at each screen with `look_at_app` as you build it, with real-looking content in it (several items, long and short
158
+ names) and empty. Compare against the list above: the bars clear of the system's, one accent, roles not hex, the
159
+ type scale, nothing smaller than 48 dp to tap, and every state designed.
@@ -0,0 +1,154 @@
1
+ ---
2
+ name: app-ai
3
+ description: AI inside the app - whether it belongs at all (asked for, worth offering with one question first, or left out), Apple's on-device frameworks first, LampAI for open-ended text and pictures, decisions for judging things by what they mean, checked actions for doing what the person asks, setup and where data goes, untrusted text, and dates. Read before writing any of it.
4
+ ---
5
+
6
+ # AI inside the app
7
+
8
+ ## Whether AI belongs, and asking first
9
+
10
+ Lamp never adds AI the person didn't ask for. Keep it in mind as one way to make an app better, not the point of every
11
+ app: most need none. Decide from what they want to get done, the kind of app, the data it has and what a wrong answer
12
+ would cost.
13
+
14
+ - **Asked for**: the request itself is for what AI does ("summarize my emails", "understand what I say", "suggest a
15
+ name"). Build it with the smallest block that does it, and say in a sentence what it does and where it's worked out.
16
+ - **Worth offering**: AI would add something definite (understanding what they type, reading what they hand the app,
17
+ drafting) but they didn't ask for it. Before writing any of the app, ask with one `ask` that says what they're
18
+ making and what AI would do in it, in their words: "I see you're making a recipe box. Want AI to turn a pasted recipe
19
+ into a card and find recipes by what's in your fridge?", answered No thanks or Yes, in that order, so leaving it to
20
+ you means none. Then build: with that AI after a yes, without it otherwise.
21
+ - **Leave it out**: exact rules already do it, the gain is vague, or facts, timing or anything in real time would get
22
+ less reliable. Ordinary code, and no question about AI.
23
+
24
+ Don't pester. Offer AI at most once for an app, where it would change what the app can do, never for small changes or
25
+ in every reply. A no is for that app alone: write "AI: offered, declined" in its APP.md (not in Lamp's notes about the
26
+ person), don't offer AI in that app again unless they bring it up, and still offer it in other apps where it fits.
27
+
28
+ A kitchen timer with three presets and a loud alarm has no AI and no question about it: durations, scheduling and the
29
+ alarm are code. A remote "with buttons for my TV" is buttons, and "Want AI to turn 'movie night' into a routine for
30
+ your TV and speaker?" is worth one question before building it. "Let me say 'movie night' and have it use my TV and
31
+ speaker" asks for it, so it's built: a routine the person reviews and saves, which then runs from its button with no AI.
32
+
33
+ Which block: Apple's frameworks where one fits; `ask(..., as:)` for a structured draft; a decision for a judgment by
34
+ meaning; a checked action (below) for a request that changes something. Arithmetic, ids, permissions, what's saved and
35
+ what's true stay in code. A model's confidence is never permission to change something.
36
+
37
+ When AI goes in (asked for, or after a yes), write its contract in APP.md under the feature, a few lines: what it
38
+ gives the person, which block, what's sent and where it's worked out (from `LampAI.status`, below), what it may
39
+ change, what the app checks, what happens without it, and the case that proves it works. Keep it current as the feature changes.
40
+
41
+ ## On-device frameworks first
42
+
43
+ Prefer Apple's on-device frameworks whenever one fits the job: they're instant, free, private and work offline.
44
+
45
+ - Text in images or PDFs, barcodes and QR codes, faces, body or hand poses, cutting a subject out of its background,
46
+ image tags or similarity → Vision (VisionKit's ImageAnalysisOverlayView for Live Text in an image view).
47
+ - Speech to text → Speech (SFSpeechRecognizer, with requiresOnDeviceRecognition when supported).
48
+ - Reading text aloud → AVSpeechSynthesizer.
49
+ - Language detection, names and places, sentiment, semantic search → NaturalLanguage (NLTagger, NLEmbedding).
50
+ - Recognizing sounds → SoundAnalysis.
51
+ - Photo filters and effects → Core Image.
52
+ - Translation → Translation, inside `if #available(macOS 15, *)` on the Mac and `if #available(iOS 18, *)` on iPhone.
53
+
54
+ The app already declares microphone, speech recognition and camera permissions (and calendars, reminders, contacts
55
+ and photos; on the Mac also Bluetooth and Mail); request authorization before use and handle denial in the UI.
56
+
57
+ ## LampAI for the rest
58
+
59
+ For open-ended AI work those frameworks can't do (summarizing, extracting, rewriting, answering questions,
60
+ generating text, understanding what a picture means), use `LampAI.ask(...)` from LampSupport.swift. Read its doc
61
+ comment for usage. Never call AI APIs directly, never ask the user for API keys. It accepts `images:` (`NSImage` on
62
+ the Mac, `UIImage` on iPhone, `LampImage` in an app for both) when the AI needs to look at photos or screenshots. To
63
+ create or edit pictures, use `LampAI.makeImage(...)`, `LampAI.editImage(...)` or `LampAI.editImages(...)`; these take
64
+ 10–60 seconds. Show a ProgressView while waiting and show errors in the UI.
65
+
66
+ ## Doing what the person asks: checked actions
67
+
68
+ `LampAI.act` in Swift is a `LampActSession` (its comment has the whole API) holding the app's own tools: reads that look
69
+ things up and writes that change them, each a few lines over the app's data and its ordinary commands. The AI proposes
70
+ calls, Lamp checks their shapes, the app's `check` says whether that exact change is allowed now, and its `run` makes it
71
+ and returns a receipt. Lamp keeps the loop, its limits (4 AI steps between questions, 6 changes a request, 3 questions
72
+ back, the route's time), cancellation, questions back and the receipts.
73
+
74
+ ```swift
75
+ struct Rename: Decodable { let id: String; let name: String }
76
+
77
+ let session = LampActSession(about: "A list of rooms. Ask which room when two could fit.", tools: [
78
+ .read("rooms", "Every room: id and name.") { store.rooms.map { ["id": $0.id, "name": $0.name] } },
79
+ .write("rename", "Renames one room.", args: ["id": .text("A room's id from rooms"), "name": .text("The new name")], as: Rename.self,
80
+ check: { r, _ in store.room(r.id) == nil ? "There's no room with that id." : r.name.isEmpty ? "Say the new name." : nil },
81
+ run: { r, _ in try store.rename(r.id, to: r.name); return LampActReceipt("Renamed to \(r.name)") }),
82
+ ])
83
+ let result = await session.ask(typed).result
84
+ if let question = result.question { askBack(question, offering: result.choices) } // then session.answer(reply)
85
+ else { status = result.summary }
86
+ ```
87
+
88
+ - Show the feature where `await LampAI.status(.act)` says it's available, with what answers and where its `processing`
89
+ is (`remote` for a service, Claude Code and Codex included; `onDevice` for a model on this Mac). When it isn't, keep
90
+ the feature visible with its `reason` and a "Set up in Lamp" button (`LampAI.openSetup(for: .act)`), or "Open Lamp" /
91
+ "Update Lamp" when `setup` says so; keep the typed draft, and every manual control working. Check again when the app
92
+ comes back to the front, and never send the draft by itself after setup. Available is no guarantee: show the actual
93
+ failure (`result.error`) with the request kept and an explicit Try Again.
94
+ - A tool is a named read or write over the app's own data, ids in and ids out: never "run this", never an address the
95
+ AI gives, never another app. Device names, messages and pages are data, not instructions.
96
+ - Every write's `check` looks its items up again by id and says in a sentence why it can't be done now (gone, not
97
+ connected, can't do that, out of range); make the final check and the change one step for local data, or have `run`
98
+ check the revision again. Make the ids of what a write adds from `call.key`, so the same change delivered twice finds
99
+ it instead of adding a second.
100
+ - Say what happened from `result.done` (the receipts), `failed`, `skipped` and `stopped`, which is what `summary` does:
101
+ never from the AI's `reply`, which is shown only for a question or when nothing changed. A receipt says what the code
102
+ knows: "Sent" when a device took a command, never "The TV is on".
103
+ - Offer `result.choices` as buttons for a question; only the first answer counts (`session.answer` returns nil after).
104
+ - Cancel (`turn.cancel()`) when the person stops or closes it. A change already sent stays in the receipts as sent:
105
+ never say nothing happened. Don't retry a change whose outcome is uncertain by yourself; show what's left for the
106
+ person to run again.
107
+ - For a change with real consequences (a device, a message, money), let the AI build a draft the person reviews and
108
+ confirms with the app's own button, rather than act at once. Confirming is the app's policy for that change; it isn't
109
+ what makes the arguments safe, `check` is.
110
+ - Not on a phone away from the Mac: actions need Lamp, and `status(.act)` says so there.
111
+
112
+ A web page's `LampAI.act` is the same contract in lamp.js: the web-app skill's "Doing things for the person".
113
+
114
+ ## Decisions
115
+
116
+ When the app has to judge things by what they mean, decisions are the tool. `LampAI.isTrue`, `LampAI.choose`,
117
+ `LampAI.rate` and `LampAI.decide` call a decision model (Jev) that is smart, very fast (well under a second) and
118
+ extremely cheap (about $0.04 per million input tokens: judging hundreds of items costs a fraction of a cent). In an app
119
+ whose AI was asked for or accepted, where it sorts, filters, labels, prioritizes, groups, matches, routes, moderates or
120
+ flags things by what they are or mean (file names, messages, notes, titles, descriptions, what the person meant), use
121
+ one rather than keyword lists, regexes, extension rules or other hand-written heuristics that guess at meaning. In an
122
+ app without AI, judging by meaning is a reason to offer it (above), not to add it. Where an exact rule
123
+ decides it (a size, a date, a type the system reports), that's code, not a decision. It's fine to judge every item
124
+ individually.
125
+
126
+ To judge a list, hand the whole list to `LampAI.isTrue(_:each:)`, `LampAI.choose(_:from:each:)`,
127
+ `LampAI.rate(_:levels:each:)` or, for several questions per item, `LampAI.decideEach(items, questions)`: they run
128
+ about 12 at a time, keep the order, report `progress: { done, total in }` on the main thread and return one
129
+ `LampVerdict` per item (`item`, `probability` / `choice` / `score` / `confidence`, and `error` for an item that
130
+ couldn't be judged). Pass `remember: seconds` to save verdicts so unchanged items aren't judged again until they
131
+ expire (e.g. a week for files, a day for messages). Never write your own TaskGroup, loop, progress counter or verdict
132
+ cache for this. Ask several questions about one thing in one `decide` call. Use code for exact facts (sizes, dates,
133
+ duplicates, arithmetic) and combine them with decisions: pass the facts in as part of the state. Use the returned
134
+ probabilities and confidence to choose between acting automatically, suggesting, and asking the user. Decisions take
135
+ text or JSON-friendly data, not images.
136
+
137
+ ## Untrusted text
138
+
139
+ Text the person didn't type into the app themselves is untrusted: emails, messages, notifications, web pages, file
140
+ contents, the clipboard, anything read from another app. It can contain instructions aimed at the AI ("ignore the
141
+ above and…"). Never interpolate it into a prompt: pass it as `data:` (`LampAI.ask("Summarize this email in one
142
+ line.", data: email.body)`), and Lamp fences it off so the AI works on it without obeying it. In decisions it goes in
143
+ `about:`, with the question in your own words. Don't write regexes, keyword filters or "sanitizing" code against it.
144
+ Fencing helps the AI read it as material rather than orders, but it is no guarantee: what the app does with an answer
145
+ is held by the app's own code, a write's `check`, ids looked up again, the person's review of anything consequential.
146
+
147
+ ## Dates and times
148
+
149
+ `LampAI.ask` already tells the AI the current date, time and time zone, so don't add them yourself. Give the AI a
150
+ date with `LampAI.when(date)` (it writes "Mon 5 Oct 2026 at 15:00 (in 44 minutes)", with the distance worked out in
151
+ code); Dates inside `about:` are written that way automatically. Get a date back by asking for ISO 8601 and decoding
152
+ into a `Date` property with `ask(..., as:)`, or with `LampAI.date(from:)`. Always keep the `Date` itself and work out
153
+ "in 44 minutes", "overdue" or "ended" in code when it's shown (`Text(date, style: .relative)` or a TimelineView keeps
154
+ it current); never store or display a relative time the AI wrote, because it's wrong minutes later.
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: app-intents
3
+ description: Giving the app's main actions to Siri, Shortcuts, Spotlight and the Action button with App Intents - the intent structs, AppShortcuts phrases, entities, what the build needs, and what to tell the person. Read before writing or changing Sources/Intents.swift.
4
+ ---
5
+
6
+ # App Intents
7
+
8
+ ## Writing them
9
+
10
+ In Sources/Intents.swift, `import AppIntents` and write a struct per action: `struct AddItemIntent: AppIntent` with
11
+ `static let title: LocalizedStringResource = "Add Item"`, its inputs as `@Parameter(title: "Item") var item:
12
+ String`, and `func perform() async throws -> some IntentResult & ProvidesDialog` that does the work with the app's own
13
+ code (LampStore and the rest: it runs in the app, started without a window when it isn't open) and ends
14
+ `return .result(dialog: "Added \(item)")`; `static let openAppWhenRun = true` only for one that has to show the app.
15
+
16
+ Then one `struct AppShortcuts: AppShortcutsProvider` whose `static var appShortcuts` lists them,
17
+ `AppShortcut(intent: AddItemIntent(), phrases: ["Add an item to \(.applicationName)"], shortTitle: "Add Item",
18
+ systemImageName: "cart")`: that is what Siri hears and Spotlight and Shortcuts show with no setup. Every phrase names
19
+ `\(.applicationName)`, and a phrase can name only a parameter that is an `AppEnum` or `AppEntity`, never a String. For
20
+ the app's own things (lists, notes, places), an `AppEntity` with an `EntityQuery` lets Shortcuts pick one.
21
+
22
+ Titles and phrases are plain literals: the build reads them from the code and fails on what it can't read.
23
+
24
+ ## Checking and telling the person
25
+
26
+ When the build warns that Xcode isn't installed, the app works but the system doesn't see its intents: say so.
27
+ Nothing here can run an intent, so check that the build succeeds and that what perform calls works in the app, then
28
+ tell the user in a sentence what to say to Siri or search for.
29
+
30
+ A Mac app's App Intents work when Lamp signs it for the user's Apple developer team; when it can't, `look_at_app`
31
+ says so, and you tell the user how to turn them on as it says.
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: app-kinds
3
+ description: How each kind of app (tool, companion, collection, dashboard, canvas, utility, game or toy) is laid out, looks and talks on a Mac and on iPhone, made natively or as a web app, and on a Mac where the app works - a window, or a utility that works where the person already is. Read before writing a new app or changing an app's kind.
4
+ ---
5
+
6
+ # The kinds of app
7
+
8
+ Everything the person didn't say about the look follows the app's kind; their own direction always wins over it. A
9
+ style they gave wins over the kind's look but keeps its structure: a "cozy" water tracker is a companion app, made
10
+ cozy. Every kind feels like Apple made it, following the Human Interface Guidelines of the app's platform. Put the
11
+ kind in APP.md's first line (`Kind: companion`), and never name kinds to the person.
12
+
13
+ What follows names SwiftUI's pieces. A web app is laid out the same way in HTML and CSS: the system font
14
+ (`-apple-system, system-ui`), light and dark (`prefers-color-scheme`), a grid of cards for LazyVGrid, a side panel for
15
+ an inspector, a sheet as a dialog over the page, a chart drawn in SVG, symbols as small SVG icons kept in Web/, and a
16
+ spring as a CSS transition. A menu bar icon, a widget and a haptic are native code's (the web-or-native skill).
17
+
18
+ ## On a Mac: where the app works
19
+
20
+ Before the kind, decide where the app works. A utility that works where the person is or in the background, and a
21
+ menu bar app, are made natively (the web-or-native skill).
22
+
23
+ - When the wish acts on something the user already has in front of them in another app (the text they selected, the
24
+ post or message they're writing there, the file or page they're looking at), don't make a window to paste or drop
25
+ it into: make a utility that works where they are. A `LampHotKey` takes the selection: read it from the focused
26
+ element through Accessibility (kAXFocusedUIElementAttribute, then kAXSelectedTextAttribute; `LampPermissions` asks
27
+ for Accessibility), and when that gives nothing, send ⌘C and read the clipboard, putting back what was on it. Show
28
+ the result in a small floating panel that doesn't take focus from their app (an NSPanel with `.nonactivatingPanel`
29
+ at `.floating` level, near the mouse) with the one or two actions that make sense (put it back in place by pasting,
30
+ copy, save), or put it straight back in place when that's what they asked for; the menu bar icon holds the
31
+ settings, where the shortcut can be changed.
32
+ - When the wish waits or watches for something (a folder, a time, the calendar, a site, the clipboard), it's a
33
+ utility too: it works in the background and reaches the user with a notification, never a window they must open
34
+ to check. Such a utility declares `{"background": true}` in `capabilities.json` at the app's root: then it opens at
35
+ login and keeps running, and Lamp tells the user so (don't explain it yourself; put Open at Login in its Settings
36
+ so they can turn it off). What runs at a time or every so often uses `LampSchedule`.
37
+ - A window is for what the user brings things to and comes back to: writing, collecting, browsing, playing.
38
+ - Collecting from wherever the user finds things (recipes from any website, articles, quotes, products) is both: the
39
+ window to keep and find them in, and a way to save from where they are without coming to the window: a hotkey that
40
+ takes the page or selection in front of them (the current tab's address from Safari, Chrome or Arc through
41
+ AppleScript, or the selected text) and saves it with a brief floating confirmation, besides dropping or pasting a
42
+ link.
43
+
44
+ A menu bar app is written as the menu-bar skill says.
45
+
46
+ ## Tool
47
+
48
+ Notes, inventory, lists, logs, a CRM: keeping and finding things. The base design in your rules, exactly. Dense and
49
+ calm: system colors, the accent color, SF Symbols, no illustration. It's judged on how fast things are found, added
50
+ and changed.
51
+
52
+ ## Companion
53
+
54
+ Water, a timer, habits, mood, a plant, breathing: a small ritual come back to many times a day.
55
+
56
+ - One main screen built around one picture of where you are now (the glass, the timer, the plant), not a list or a
57
+ sidebar; history is one step away. That picture is art from `make_art`, never shapes drawn in code, and it always
58
+ shows the state: animate it (fill it with a mask, grow, move or scale it), never a static picture beside a progress
59
+ bar.
60
+ - A palette of two or three colors that suit the subject, as named colors with light and dark versions; text and
61
+ controls keep system colors. The one number that matters is large (.largeTitle or bigger, .rounded design).
62
+ - The main action is one big, obvious button or a tap on the picture, with a spring animation (on iPhone, and a
63
+ haptic: sensoryFeedback); something small and pleasant happens when a goal is met, and nothing nags.
64
+ - Short, warm words with a little personality ("Nice. Two to go."), never at the cost of clarity.
65
+ - Reminders come as notifications; on a Mac it also shows its state in the menu bar (LampMenuBar with
66
+ `dockIcon: true`, its label the time left or the count).
67
+ - One first screen is allowed when the app can't work without a choice (a daily goal), with a sensible default
68
+ filled in; never a tour.
69
+
70
+ ## Collection
71
+
72
+ Recipes, books, wines, trips, records: things nice to look at. Pictures lead, in an adaptive grid of cards
73
+ (LazyVGrid) with large images and titles under them; a list as an option, not the default. The detail is a full page
74
+ with a large picture at the top and the facts below, like an album in Music. Every item has a picture: the user's own
75
+ photo, or else art from `make_art` for the kind of item, so the grid is never gray placeholders; the empty state
76
+ shows some of that art too, so a new app doesn't open on a blank page. Search, sort and filter as Photos does
77
+ (toolbar menus, scopes), not as a form.
78
+
79
+ ## Dashboard
80
+
81
+ Spending, fitness totals, a server's status: look, understand, leave. The one or two numbers that matter come first
82
+ and large, details below. Swift Charts for anything over time, kept simple: no grid clutter, the latest point marked,
83
+ values labeled where they matter. Color means good, warning or bad and nothing else; a soft gradient from the state
84
+ behind the main number is the only decoration. No art. On a Mac, when it's checked often, a menu bar icon shows the
85
+ main number.
86
+
87
+ A dashboard on a TV, glanced at from across a room (a family calendar or chore board, a scoreboard, a photo frame), is
88
+ designed as the tv-design skill says.
89
+
90
+ ## Canvas
91
+
92
+ Drawing, diagrams, layout, long writing: making a thing. A minimal interface with the content front and center.
93
+
94
+ - On a Mac: a larger toolbar (labels under the icons where there's room) holds the tools, never a palette drawn on
95
+ the canvas; settings for the selection go in an `.inspector`, hidden when nothing is selected. Proper windows:
96
+ DocumentGroup with a window per document, tabs, full screen, and a focus mode that hides the toolbar and inspector.
97
+ - On iPhone: the canvas goes edge to edge; tools in a bottom toolbar, settings for the selection in a sheet with
98
+ detents (an inspector on iPad), and a tap on empty canvas hides the chrome. DocumentGroup for documents.
99
+
100
+ Undo for everything, autosave, export; every gesture (drag, resize, pinch) also has a command or button. No art: the
101
+ user's work is the only thing to look at.
102
+
103
+ ## Utility
104
+
105
+ A clipboard history, automations, a folder watcher: works while you do other things. Quiet: a notification only when
106
+ something needs the user.
107
+
108
+ - On a Mac it lives in the menu bar (LampMenuBar) with a Settings window, and has no main window unless it has
109
+ something to show. When it has one main thing to turn on and off (pause syncing, keep awake, watch the folder), a
110
+ click on the icon does it, the icon shows the state with two clearly different symbols, and a right-click shows the
111
+ menu (LampMenuBar's switch). Otherwise a click shows a menu (LampMenuBar(menu:)). Prefer a menu, with toggles as
112
+ checkmarks, to a panel; a panel only for what a menu can't do (a search field over a long history, a preview, a
113
+ slider you watch while dragging).
114
+ - On iPhone it does its work through App Intents (Shortcuts and Siri) and the share sheet wherever it can, and the
115
+ app itself is one screen: its settings and what it did recently.
116
+
117
+ ## Game or toy
118
+
119
+ Played rather than used: fully custom, with no standard chrome while playing; pause, settings and scores are standard
120
+ and large. SwiftUI animation for the simplest toy in a native app. Anything played in real time is a game, made web
121
+ by default wherever Lamp has a host for a page (the web-or-native skill): open the game skill, which says what it's
122
+ drawn with and has its controls, sound, saves and smoothness for each way it's made.
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: apple-watch
3
+ description: The app's Apple Watch app and its complications (Watch/) - the watch app, complications on a watch face, the data the phone shares with them, taps sent back to the phone, and workouts saved to Health. Read before writing or changing anything in Watch/.
4
+ ---
5
+
6
+ # An Apple Watch app with complications
7
+
8
+ ## The watch app
9
+
10
+ Write it in SwiftUI in a `Watch/` folder at the app's root, starting with Watch/WatchApp.swift: one `@main` App whose
11
+ WindowGroup ends in `.lampWatch()`, which keeps complications current while the watch app is closed, and a screen or
12
+ two of big controls. The watch app's icon is the app's.
13
+
14
+ ## Complications
15
+
16
+ They go in Watch/Complications/: one `@main` `WidgetBundle` of `StaticConfiguration`s with `.supportedFamilies` from
17
+ `.accessoryCircular`, `.accessoryRectangular`, `.accessoryInline` and `.accessoryCorner`, and
18
+ `.containerBackground(.fill.tertiary, for: .widget)`.
19
+
20
+ Neither the watch app nor its complications share code with Sources/ or have LampSupport.swift: declare the Codable
21
+ types they read in each folder. Watch/LampWatchSupport.swift and its copy in Complications/ are Lamp's: never edit
22
+ them.
23
+
24
+ ## The data
25
+
26
+ - In the app, `LampWatch.share(Today(…), as: "today")` at launch and whenever it changes.
27
+ - On the watch, `@LampWatched("today") var today: Today?` in a view, or `LampWatch.read(Today.self, from: "today")` in
28
+ a complication's timeline, nil until the phone has first shared.
29
+ - A tap on the watch: `LampWatch.send("addGlass", 1)`, done in the app by `LampWatch.onAction { name, payload in … }`
30
+ set at launch (`payload.decode(Int.self)`), which shares what changed.
31
+
32
+ ## Workouts
33
+
34
+ A workout on the watch, saved to Health with heart rate, calories and distance: `@StateObject private var workout =
35
+ LampWorkout()` from Watch/LampWatchSupport.swift, `try await workout.start(.running)`, `pause()`, `resume()`,
36
+ `await workout.end()`, with `{"healthkit": true}` in capabilities.json. The simulator's watch measures nothing, so
37
+ check it starts and ends.
38
+
39
+ ## Trying it and saying so
40
+
41
+ Lamp opens the watch app on an Apple Watch simulator beside the iPhone; `look_at_app` and `use_app` see only the
42
+ iPhone, so don't try them on the watch. Say in a sentence that it's on the watch, and that a complication is added by
43
+ editing a watch face.