@vibes.diy/prompts 14.3.202 → 14.3.204

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 (247) hide show
  1. package/llms/access.md +4 -4
  2. package/llms/backend.md +1 -1
  3. package/llms/blockly.md +2 -2
  4. package/llms/bluesky.md +1 -1
  5. package/llms/board-games.md +95 -1
  6. package/llms/calendar.md +1 -1
  7. package/llms/callai.md +4 -4
  8. package/llms/connections.md +1 -1
  9. package/llms/create-vibe.md +3 -3
  10. package/llms/fireproof.md +7 -7
  11. package/llms/github.md +6 -2
  12. package/llms/image-gen.md +2 -2
  13. package/llms/index.d.ts +28 -28
  14. package/llms/index.js +84 -84
  15. package/llms/index.js.map +1 -1
  16. package/llms/maps.js +14 -2
  17. package/llms/maps.js.map +1 -1
  18. package/llms/maps.md +212 -9
  19. package/llms/match-style.md +1 -1
  20. package/llms/motion.md +7 -7
  21. package/llms/p5.md +1 -1
  22. package/llms/physics.md +2 -2
  23. package/llms/reskin.js +8 -1
  24. package/llms/reskin.js.map +1 -1
  25. package/llms/reskin.md +99 -20
  26. package/llms/richtext.md +5 -5
  27. package/llms/spotify.md +1 -1
  28. package/llms/stripe-subscriptions.md +1 -1
  29. package/llms/stripe.md +3 -3
  30. package/llms/strudel.md +3 -3
  31. package/llms/three-js.md +4 -4
  32. package/llms/touch-games.js +1 -1
  33. package/llms/touch-games.js.map +1 -1
  34. package/llms/touch-games.md +3 -3
  35. package/llms/ui-blog.d.ts +2 -0
  36. package/llms/ui-blog.js +7 -0
  37. package/llms/ui-blog.js.map +1 -0
  38. package/llms/{pouf-blog.md → ui-blog.md} +10 -10
  39. package/llms/ui-booking.d.ts +2 -0
  40. package/llms/ui-booking.js +7 -0
  41. package/llms/ui-booking.js.map +1 -0
  42. package/llms/{pouf-booking.md → ui-booking.md} +8 -8
  43. package/llms/ui-calendar.d.ts +2 -0
  44. package/llms/ui-calendar.js +7 -0
  45. package/llms/ui-calendar.js.map +1 -0
  46. package/llms/{pouf-calendar.md → ui-calendar.md} +5 -5
  47. package/llms/ui-chat.d.ts +2 -0
  48. package/llms/ui-chat.js +7 -0
  49. package/llms/ui-chat.js.map +1 -0
  50. package/llms/{pouf-chat.md → ui-chat.md} +4 -4
  51. package/llms/ui-contact.d.ts +2 -0
  52. package/llms/ui-contact.js +7 -0
  53. package/llms/ui-contact.js.map +1 -0
  54. package/llms/{pouf-contact.md → ui-contact.md} +7 -7
  55. package/llms/ui-course.d.ts +2 -0
  56. package/llms/ui-course.js +7 -0
  57. package/llms/ui-course.js.map +1 -0
  58. package/llms/{pouf-course.md → ui-course.md} +9 -9
  59. package/llms/ui-crm.d.ts +2 -0
  60. package/llms/ui-crm.js +7 -0
  61. package/llms/ui-crm.js.map +1 -0
  62. package/llms/{pouf-crm.md → ui-crm.md} +5 -5
  63. package/llms/ui-dashboard.d.ts +2 -0
  64. package/llms/ui-dashboard.js +7 -0
  65. package/llms/ui-dashboard.js.map +1 -0
  66. package/llms/{pouf-dashboard.md → ui-dashboard.md} +7 -7
  67. package/llms/ui-editorial.d.ts +2 -0
  68. package/llms/ui-editorial.js +7 -0
  69. package/llms/ui-editorial.js.map +1 -0
  70. package/llms/{pouf-editorial.md → ui-editorial.md} +5 -5
  71. package/llms/ui-event.d.ts +2 -0
  72. package/llms/ui-event.js +7 -0
  73. package/llms/ui-event.js.map +1 -0
  74. package/llms/{pouf-event.md → ui-event.md} +5 -5
  75. package/llms/ui-feed.d.ts +2 -0
  76. package/llms/ui-feed.js +7 -0
  77. package/llms/ui-feed.js.map +1 -0
  78. package/llms/{pouf-feed.md → ui-feed.md} +5 -5
  79. package/llms/ui-game.d.ts +2 -0
  80. package/llms/ui-game.js +7 -0
  81. package/llms/ui-game.js.map +1 -0
  82. package/llms/{pouf-game.md → ui-game.md} +6 -6
  83. package/llms/ui-inbox.d.ts +2 -0
  84. package/llms/ui-inbox.js +7 -0
  85. package/llms/ui-inbox.js.map +1 -0
  86. package/llms/{pouf-inbox.md → ui-inbox.md} +5 -5
  87. package/llms/ui-inventory.d.ts +2 -0
  88. package/llms/ui-inventory.js +7 -0
  89. package/llms/ui-inventory.js.map +1 -0
  90. package/llms/{pouf-inventory.md → ui-inventory.md} +5 -5
  91. package/llms/ui-kanban.d.ts +2 -0
  92. package/llms/ui-kanban.js +7 -0
  93. package/llms/ui-kanban.js.map +1 -0
  94. package/llms/{pouf-kanban.md → ui-kanban.md} +5 -5
  95. package/llms/ui-landing.d.ts +2 -0
  96. package/llms/ui-landing.js +7 -0
  97. package/llms/ui-landing.js.map +1 -0
  98. package/llms/{pouf-landing.md → ui-landing.md} +6 -6
  99. package/llms/ui-login.d.ts +2 -0
  100. package/llms/ui-login.js +7 -0
  101. package/llms/ui-login.js.map +1 -0
  102. package/llms/{pouf-login.md → ui-login.md} +7 -7
  103. package/llms/ui-music.d.ts +2 -0
  104. package/llms/ui-music.js +7 -0
  105. package/llms/ui-music.js.map +1 -0
  106. package/llms/{pouf-music.md → ui-music.md} +6 -6
  107. package/llms/ui-onboarding.d.ts +2 -0
  108. package/llms/ui-onboarding.js +7 -0
  109. package/llms/ui-onboarding.js.map +1 -0
  110. package/llms/{pouf-onboarding.md → ui-onboarding.md} +5 -5
  111. package/llms/ui-pricing.d.ts +2 -0
  112. package/llms/ui-pricing.js +7 -0
  113. package/llms/ui-pricing.js.map +1 -0
  114. package/llms/{pouf-pricing.md → ui-pricing.md} +5 -5
  115. package/llms/ui-profile.d.ts +2 -0
  116. package/llms/ui-profile.js +7 -0
  117. package/llms/ui-profile.js.map +1 -0
  118. package/llms/{pouf-profile.md → ui-profile.md} +4 -4
  119. package/llms/ui-quiz.d.ts +2 -0
  120. package/llms/ui-quiz.js +7 -0
  121. package/llms/ui-quiz.js.map +1 -0
  122. package/llms/{pouf-quiz.md → ui-quiz.md} +6 -6
  123. package/llms/ui-settings.d.ts +2 -0
  124. package/llms/ui-settings.js +7 -0
  125. package/llms/ui-settings.js.map +1 -0
  126. package/llms/{pouf-settings.md → ui-settings.md} +5 -5
  127. package/llms/ui-storefront.d.ts +2 -0
  128. package/llms/ui-storefront.js +7 -0
  129. package/llms/ui-storefront.js.map +1 -0
  130. package/llms/{pouf-storefront.md → ui-storefront.md} +9 -9
  131. package/llms/ui-support.d.ts +2 -0
  132. package/llms/ui-support.js +7 -0
  133. package/llms/ui-support.js.map +1 -0
  134. package/llms/{pouf-support.md → ui-support.md} +5 -5
  135. package/llms/ui-testimonials.d.ts +2 -0
  136. package/llms/ui-testimonials.js +7 -0
  137. package/llms/ui-testimonials.js.map +1 -0
  138. package/llms/{pouf-testimonials.md → ui-testimonials.md} +6 -6
  139. package/llms/ui-todo.d.ts +2 -0
  140. package/llms/ui-todo.js +7 -0
  141. package/llms/ui-todo.js.map +1 -0
  142. package/llms/{pouf-todo.md → ui-todo.md} +5 -5
  143. package/llms/ui-weather.d.ts +2 -0
  144. package/llms/ui-weather.js +7 -0
  145. package/llms/ui-weather.js.map +1 -0
  146. package/llms/{pouf-weather.md → ui-weather.md} +5 -5
  147. package/llms/use-vibe.md +4 -4
  148. package/llms/use-viewer.md +5 -5
  149. package/llms/voxel.md +1 -1
  150. package/llms/web-audio.md +49 -26
  151. package/llms/worlds.md +3 -3
  152. package/llms/youtube.md +1 -1
  153. package/package.json +5 -5
  154. package/system-prompt-initial-instant.md +3 -3
  155. package/system-prompt.md +3 -3
  156. package/themes/colorsets.js +7 -7
  157. package/themes/colorsets.js.map +1 -1
  158. package/themes/looks/pouf/brief.md +87 -85
  159. package/themes/looks/pouf/catalog.generated.d.ts +1 -1
  160. package/themes/looks/pouf/catalog.generated.js +47 -17
  161. package/themes/looks/pouf/catalog.generated.js.map +1 -1
  162. package/themes/looks/pouf/variety.js +4 -4
  163. package/themes/looks/pouf/variety.js.map +1 -1
  164. package/llms/pouf-blog.d.ts +0 -2
  165. package/llms/pouf-blog.js +0 -6
  166. package/llms/pouf-blog.js.map +0 -1
  167. package/llms/pouf-booking.d.ts +0 -2
  168. package/llms/pouf-booking.js +0 -6
  169. package/llms/pouf-booking.js.map +0 -1
  170. package/llms/pouf-calendar.d.ts +0 -2
  171. package/llms/pouf-calendar.js +0 -6
  172. package/llms/pouf-calendar.js.map +0 -1
  173. package/llms/pouf-chat.d.ts +0 -2
  174. package/llms/pouf-chat.js +0 -6
  175. package/llms/pouf-chat.js.map +0 -1
  176. package/llms/pouf-contact.d.ts +0 -2
  177. package/llms/pouf-contact.js +0 -6
  178. package/llms/pouf-contact.js.map +0 -1
  179. package/llms/pouf-course.d.ts +0 -2
  180. package/llms/pouf-course.js +0 -6
  181. package/llms/pouf-course.js.map +0 -1
  182. package/llms/pouf-crm.d.ts +0 -2
  183. package/llms/pouf-crm.js +0 -6
  184. package/llms/pouf-crm.js.map +0 -1
  185. package/llms/pouf-dashboard.d.ts +0 -2
  186. package/llms/pouf-dashboard.js +0 -6
  187. package/llms/pouf-dashboard.js.map +0 -1
  188. package/llms/pouf-editorial.d.ts +0 -2
  189. package/llms/pouf-editorial.js +0 -6
  190. package/llms/pouf-editorial.js.map +0 -1
  191. package/llms/pouf-event.d.ts +0 -2
  192. package/llms/pouf-event.js +0 -6
  193. package/llms/pouf-event.js.map +0 -1
  194. package/llms/pouf-feed.d.ts +0 -2
  195. package/llms/pouf-feed.js +0 -6
  196. package/llms/pouf-feed.js.map +0 -1
  197. package/llms/pouf-game.d.ts +0 -2
  198. package/llms/pouf-game.js +0 -6
  199. package/llms/pouf-game.js.map +0 -1
  200. package/llms/pouf-inbox.d.ts +0 -2
  201. package/llms/pouf-inbox.js +0 -6
  202. package/llms/pouf-inbox.js.map +0 -1
  203. package/llms/pouf-inventory.d.ts +0 -2
  204. package/llms/pouf-inventory.js +0 -6
  205. package/llms/pouf-inventory.js.map +0 -1
  206. package/llms/pouf-kanban.d.ts +0 -2
  207. package/llms/pouf-kanban.js +0 -6
  208. package/llms/pouf-kanban.js.map +0 -1
  209. package/llms/pouf-landing.d.ts +0 -2
  210. package/llms/pouf-landing.js +0 -6
  211. package/llms/pouf-landing.js.map +0 -1
  212. package/llms/pouf-login.d.ts +0 -2
  213. package/llms/pouf-login.js +0 -6
  214. package/llms/pouf-login.js.map +0 -1
  215. package/llms/pouf-music.d.ts +0 -2
  216. package/llms/pouf-music.js +0 -6
  217. package/llms/pouf-music.js.map +0 -1
  218. package/llms/pouf-onboarding.d.ts +0 -2
  219. package/llms/pouf-onboarding.js +0 -6
  220. package/llms/pouf-onboarding.js.map +0 -1
  221. package/llms/pouf-pricing.d.ts +0 -2
  222. package/llms/pouf-pricing.js +0 -6
  223. package/llms/pouf-pricing.js.map +0 -1
  224. package/llms/pouf-profile.d.ts +0 -2
  225. package/llms/pouf-profile.js +0 -6
  226. package/llms/pouf-profile.js.map +0 -1
  227. package/llms/pouf-quiz.d.ts +0 -2
  228. package/llms/pouf-quiz.js +0 -6
  229. package/llms/pouf-quiz.js.map +0 -1
  230. package/llms/pouf-settings.d.ts +0 -2
  231. package/llms/pouf-settings.js +0 -6
  232. package/llms/pouf-settings.js.map +0 -1
  233. package/llms/pouf-storefront.d.ts +0 -2
  234. package/llms/pouf-storefront.js +0 -6
  235. package/llms/pouf-storefront.js.map +0 -1
  236. package/llms/pouf-support.d.ts +0 -2
  237. package/llms/pouf-support.js +0 -6
  238. package/llms/pouf-support.js.map +0 -1
  239. package/llms/pouf-testimonials.d.ts +0 -2
  240. package/llms/pouf-testimonials.js +0 -6
  241. package/llms/pouf-testimonials.js.map +0 -1
  242. package/llms/pouf-todo.d.ts +0 -2
  243. package/llms/pouf-todo.js +0 -6
  244. package/llms/pouf-todo.js.map +0 -1
  245. package/llms/pouf-weather.d.ts +0 -2
  246. package/llms/pouf-weather.js +0 -6
  247. package/llms/pouf-weather.js.map +0 -1
package/llms/richtext.md CHANGED
@@ -10,8 +10,8 @@ in Fireproof, saves after typing pauses, loads a document without echoing it
10
10
  back as a save, and styles the written text with Tailwind on the host.
11
11
 
12
12
  The sibling boundary: a short field (a title, a comment, a caption) is
13
- pouf's `Textarea` in a `Field`; a feed of posts is `pouf-feed`; a pipeline
14
- of stories with stages is `pouf-editorial`. Rich text is the right call when
13
+ the UI's `Textarea` in a `Field`; a feed of posts is `ui-feed`; a pipeline
14
+ of stories with stages is `ui-editorial`. Rich text is the right call when
15
15
  the person is writing a page.
16
16
 
17
17
  The worked examples below were built and measured for this doc (Chromium,
@@ -165,7 +165,7 @@ export function createEditor(host, { content = EMPTY_DOC, placeholder = "Start w
165
165
  import React, { useEffect, useMemo, useRef, useState } from "react";
166
166
  import { useFireproof } from "use-fireproof";
167
167
  import { useVibe, useViewer } from "use-vibes";
168
- import { Badge, Button, Card, Heading, IconButton, Row, Skeleton, Spacer, Stack, Text } from "@vibes.diy/pouf";
168
+ import { Badge, Button, Card, Heading, IconButton, Row, Skeleton, Spacer, Stack, Text } from "@vibes.diy/ui";
169
169
  import { EMPTY_DOC, createEditor, titleOf } from "./lib/editor.js";
170
170
 
171
171
  // The written page is styled from the host: Tailwind reaches into the editor with arbitrary
@@ -471,7 +471,7 @@ through Tailwind's arbitrary variants**: `[&_h1]:text-2xl`,
471
471
  `[&_.is-editor-empty:first-child::before]:content-[attr(data-placeholder)]`.
472
472
  The JSX stays class-only and the theme tokens (`text-primary`,
473
473
  `text-muted-foreground`, `bg-muted`) carry the owner's restyle into the
474
- written page. Measured: the pouf lint passes a host carrying these classes.
474
+ written page. Measured: the design lint passes a host carrying these classes.
475
475
 
476
476
  ## Commands and the toolbar
477
477
 
@@ -553,7 +553,7 @@ export function createEditor(host, { content = EMPTY_DOC, placeholder = "Start w
553
553
  import React, { useEffect, useRef, useState } from "react";
554
554
  import { useFireproof } from "use-fireproof";
555
555
  import { useVibe, useViewer } from "use-vibes";
556
- import { Badge, Button, Card, Heading, Row, Spacer, Stack, Text } from "@vibes.diy/pouf";
556
+ import { Badge, Button, Card, Heading, Row, Spacer, Stack, Text } from "@vibes.diy/ui";
557
557
  import { EMPTY_DOC, createEditor } from "./lib/editor.js";
558
558
 
559
559
  const PAGE_ID = "page:home";
package/llms/spotify.md CHANGED
@@ -325,7 +325,7 @@ function artistRow(a) {
325
325
  ```jsx app=spotify-browser
326
326
  import React, { useEffect, useRef, useState } from "react";
327
327
  import { apiFetch } from "use-vibes";
328
- import { Badge, Button, Field, Heading, Input, Row, Stack, Text } from "@vibes.diy/pouf";
328
+ import { Badge, Button, Field, Heading, Input, Row, Stack, Text } from "@vibes.diy/ui";
329
329
 
330
330
  // The setup verdict, read on mount and again whenever the app comes back into view: the owner
331
331
  // sets the pair in another tab and returns, and search unlocks without a reload.
@@ -683,7 +683,7 @@ export function club(doc, oldDoc, user, ctx) {
683
683
  import React, { useEffect, useRef, useState } from "react";
684
684
  import { useFireproof } from "use-fireproof";
685
685
  import { apiFetch, useViewer } from "use-vibes";
686
- import { Badge, Button, Heading, Row, Stack, Text } from "@vibes.diy/pouf";
686
+ import { Badge, Button, Heading, Row, Stack, Text } from "@vibes.diy/ui";
687
687
 
688
688
  // The setup verdict, read on mount and again whenever the app comes back into view: the owner
689
689
  // connects Stripe or saves the portal in another tab and returns, and the Join buttons unlock
package/llms/stripe.md CHANGED
@@ -570,7 +570,7 @@ export function orders(doc, oldDoc, user, ctx) {
570
570
  import React, { useEffect, useRef, useState } from "react";
571
571
  import { useFireproof } from "use-fireproof";
572
572
  import { apiFetch, useVibe } from "use-vibes";
573
- import { Badge, Button, Heading, Row, Stack, Text } from "@vibes.diy/pouf";
573
+ import { Badge, Button, Heading, Row, Stack, Text } from "@vibes.diy/ui";
574
574
 
575
575
  // The setup verdict, read on mount and again whenever the app comes back into view: the owner
576
576
  // connects Stripe in another tab and returns, and the Pay buttons unlock without a reload.
@@ -1184,8 +1184,8 @@ export function checks(doc, oldDoc, user, ctx) {
1184
1184
  import React, { useEffect, useRef, useState } from "react";
1185
1185
  import { useFireproof } from "use-fireproof";
1186
1186
  import { apiFetch } from "use-vibes";
1187
- import { Badge, Button, Field, Figure, Heading, Input, Metric, Row, Segmented, Stack, Text } from "@vibes.diy/pouf";
1188
- import { Checkbox } from "@vibes.diy/pouf/interactive";
1187
+ import { Badge, Button, Field, Figure, Heading, Input, Metric, Row, Segmented, Stack, Text } from "@vibes.diy/ui";
1188
+ import { Checkbox } from "@vibes.diy/ui/interactive";
1189
1189
 
1190
1190
  const money = (cents) => `$${(cents / 100).toFixed(2)}`;
1191
1191
  const post = (body) => ({ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) });
package/llms/strudel.md CHANGED
@@ -207,7 +207,7 @@ with every write gated on `can`.
207
207
  import React, { useEffect, useMemo, useState } from "react";
208
208
  import { useFireproof } from "use-fireproof";
209
209
  import { callAI, useVibe, useViewer } from "use-vibes";
210
- import { Badge, Button, Card, Field, Heading, Input, Row, Skeleton, Spacer, Stack, Text } from "@vibes.diy/pouf";
210
+ import { Badge, Button, Card, Field, Heading, Input, Row, Skeleton, Spacer, Stack, Text } from "@vibes.diy/ui";
211
211
  import { EXAMPLES, onPatternError, play, stop } from "./lib/strudel.js";
212
212
  import { rewritePrompt } from "./lib/pattern-prompt.js";
213
213
 
@@ -446,8 +446,8 @@ A groovebox whose lights follow the music, built on the same module:
446
446
  import React, { useEffect, useRef, useState } from "react";
447
447
  import { useFireproof } from "use-fireproof";
448
448
  import { useVibe, useViewer } from "use-vibes";
449
- import { Badge, Button, Card, Field, Heading, Icon, IconButton, Input, Row, Skeleton, Spacer, Stack, Text } from "@vibes.diy/pouf";
450
- import { Slider } from "@vibes.diy/pouf/interactive";
449
+ import { Badge, Button, Card, Field, Heading, Icon, IconButton, Input, Row, Skeleton, Spacer, Stack, Text } from "@vibes.diy/ui";
450
+ import { Slider } from "@vibes.diy/ui/interactive";
451
451
  import { gridToCode, play, stop } from "./lib/strudel.js";
452
452
 
453
453
  const ROWS = ["bd", "sd", "hh", "cp"];
package/llms/three-js.md CHANGED
@@ -1258,7 +1258,7 @@ import React, { useState, useEffect, useRef, useCallback } from "react";
1258
1258
  import { useFireproof } from "use-fireproof";
1259
1259
  import * as THREE from "three";
1260
1260
  import { useWorldControls } from "use-vibes";
1261
- import { Card, Heading, IconButton, Stack, Text } from "@vibes.diy/pouf";
1261
+ import { Card, Heading, IconButton, Stack, Text } from "@vibes.diy/ui";
1262
1262
 
1263
1263
  export default function SkyGlider() {
1264
1264
  const { database, useLiveQuery } = useFireproof("skyGliderScores");
@@ -1705,8 +1705,8 @@ import { OrbitControls } from "three/addons/controls/OrbitControls.js";
1705
1705
  import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
1706
1706
  import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
1707
1707
  import { HalftonePass } from "three/addons/postprocessing/HalftonePass.js";
1708
- import { Button, Card, Field, Heading, Input, RowCard, Stack, Text } from "@vibes.diy/pouf";
1709
- import { Checkbox, Select, Separator, Slider } from "@vibes.diy/pouf/interactive";
1708
+ import { Button, Card, Field, Heading, Input, RowCard, Stack, Text } from "@vibes.diy/ui";
1709
+ import { Checkbox, Select, Separator, Slider } from "@vibes.diy/ui/interactive";
1710
1710
 
1711
1711
  export default function HalftoneArtStudio() {
1712
1712
  const { database, useLiveQuery } = useFireproof("halftoneStudio");
@@ -2061,7 +2061,7 @@ export default function HalftoneArtStudio() {
2061
2061
  <div className="relative h-dvh w-full overflow-hidden bg-background text-foreground font-sans">
2062
2062
  <canvas ref={canvasRef} className="absolute inset-0 select-none touch-none" />
2063
2063
 
2064
- {/* One control panel. The pouf `Card` IS the panel — it takes no className,
2064
+ {/* One control panel. The UI's `Card` IS the panel — it takes no className,
2065
2065
  so a plain wrapper carries its placement; the cushion, corner and ink are its own. */}
2066
2066
  <div className="absolute inset-y-4 left-4 w-80 overflow-y-auto">
2067
2067
  <Card>
@@ -2,7 +2,7 @@ export const touchGamesConfig = {
2
2
  name: "touch-games",
3
3
  label: "Touch games",
4
4
  description: "Phone-first controls for anything played or steered in real time — load it beside three-js, voxel, " +
5
- "physics, p5, worlds or pouf-game for every game, 3D scene you move through, or canvas toy: the play area " +
5
+ "physics, p5, worlds or ui-game for every game, 3D scene you move through, or canvas toy: the play area " +
6
6
  "is the controller (select-none touch-none surface, Pointer Events with pointer capture), swipes that fire " +
7
7
  "mid-move with chaining, tap vs swipe on one surface, a floating ghost stick under the thumb, hold-to-boost " +
8
8
  "with drag steering, pull-back-and-release aiming, gesture trails and feedback, keyboard twins for desktop, " +
@@ -1 +1 @@
1
- {"version":3,"file":"touch-games.js","sourceRoot":"","sources":["../../jsr/llms/touch-games.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAc;IACzC,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,aAAa;IACpB,WAAW,EACT,qGAAqG;QACrG,2GAA2G;QAC3G,4GAA4G;QAC5G,6GAA6G;QAC7G,6GAA6G;QAC7G,iHAAiH;QACjH,2DAA2D;QAC3D,uGAAuG;QACvG,mEAAmE;IAKrE,IAAI,EAAE;QACJ,OAAO;QACP,gBAAgB;QAChB,aAAa;QACb,YAAY;QACZ,YAAY;QACZ,aAAa;QACb,cAAc;QACd,aAAa;QACb,UAAU;QACV,QAAQ;QACR,OAAO;QACP,QAAQ;QACR,OAAO;QACP,SAAS;QACT,YAAY;QACZ,gBAAgB;QAChB,SAAS;QACT,aAAa;QACb,aAAa;QACb,OAAO;QACP,SAAS;QACT,WAAW;QACX,SAAS;QACT,WAAW;QACX,UAAU;QACV,QAAQ;QACR,YAAY;QACZ,cAAc;QACd,cAAc;QACd,aAAa;QACb,SAAS;KACV;CACF,CAAC"}
1
+ {"version":3,"file":"touch-games.js","sourceRoot":"","sources":["../../jsr/llms/touch-games.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAc;IACzC,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,aAAa;IACpB,WAAW,EACT,qGAAqG;QACrG,yGAAyG;QACzG,4GAA4G;QAC5G,6GAA6G;QAC7G,6GAA6G;QAC7G,iHAAiH;QACjH,2DAA2D;QAC3D,uGAAuG;QACvG,mEAAmE;IAKrE,IAAI,EAAE;QACJ,OAAO;QACP,gBAAgB;QAChB,aAAa;QACb,YAAY;QACZ,YAAY;QACZ,aAAa;QACb,cAAc;QACd,aAAa;QACb,UAAU;QACV,QAAQ;QACR,OAAO;QACP,QAAQ;QACR,OAAO;QACP,SAAS;QACT,YAAY;QACZ,gBAAgB;QAChB,SAAS;QACT,aAAa;QACb,aAAa;QACb,OAAO;QACP,SAAS;QACT,WAAW;QACX,SAAS;QACT,WAAW;QACX,UAAU;QACV,QAAQ;QACR,YAAY;QACZ,cAAc;QACd,cAAc;QACd,aAAa;QACb,SAAS;KACV;CACF,CAAC"}
@@ -1,7 +1,7 @@
1
1
  # Touch games — the play area is the controller
2
2
 
3
3
  Load this beside whatever draws the game — `three-js`, `voxel`, `physics`, `p5`, `worlds`,
4
- `pouf-game`, a plain `<canvas>` — whenever the app is something you play or steer in real time:
4
+ `ui-game`, a plain `<canvas>` — whenever the app is something you play or steer in real time:
5
5
  a runner, a racer, a flyer, a shooter, a snake, a launcher, a platformer, a pinball table, a
6
6
  marble maze, a 3D scene you move through, a toy you drag around. Most people open a vibe on a
7
7
  phone, one-handed. The game that feels great there is the one where the thumb rests **on the
@@ -208,7 +208,7 @@ orbits, a click is `onTap`, a right-click is `onHold`, and the wheel zooms.
208
208
  import React from "react";
209
209
  import * as THREE from "three";
210
210
  import { useWorldControls } from "use-vibes";
211
- import { Button, Card, Heading, IconButton, Stack, Text } from "@vibes.diy/pouf";
211
+ import { Button, Card, Heading, IconButton, Stack, Text } from "@vibes.diy/ui";
212
212
 
213
213
  const VIEWS = ["Free cam", "First person", "Shoulder view"];
214
214
  const HINT = {
@@ -407,7 +407,7 @@ snake by changing what `move()` does.
407
407
  ### `App.jsx`
408
408
  ```jsx
409
409
  import React from "react";
410
- import { Card, Heading, IconButton, Stack, Text } from "@vibes.diy/pouf";
410
+ import { Card, Heading, IconButton, Stack, Text } from "@vibes.diy/ui";
411
411
 
412
412
  const TUNE = {
413
413
  swipePx: 26, // travel from the anchor before a swipe fires (raise to 30–34 if a resting thumb misfires)
@@ -0,0 +1,2 @@
1
+ import type { LlmConfig } from "./types.js";
2
+ export declare const uiBlogConfig: LlmConfig;
@@ -0,0 +1,7 @@
1
+ export const uiBlogConfig = {
2
+ name: "ui-blog",
3
+ aliases: ["pouf-blog"],
4
+ label: "Blog block",
5
+ description: "Blog with a featured post, category filter, pages and a writer",
6
+ };
7
+ //# sourceMappingURL=ui-blog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-blog.js","sourceRoot":"","sources":["../../jsr/llms/ui-blog.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,CAAC,WAAW,CAAC;IACtB,KAAK,EAAE,YAAY;IACnB,WAAW,EAAE,gEAAgE;CAC9E,CAAC"}
@@ -1,12 +1,12 @@
1
- # Pouf Blog
1
+ # Blog
2
2
 
3
3
  A blog with a front page and a reading view: a bakery's recipe notes, a travel journal, a club's match reports, a studio's news. Reach for it whenever the app's core is posts written by a few people and read by many, newest first, sorted into a handful of categories. Each post is its own document, so the blog is there on the next visit and on every device, and a new post appears for every reader as soon as it is published.
4
4
 
5
- Built from @vibes.diy/pouf components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
5
+ Built from @vibes.diy/ui components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
6
6
 
7
7
  ## The block
8
8
 
9
- Two views, one job each. The front page opens with an `Eyebrow`, the `Heading` and a muted post count beside a `Write a post` button, the front page's one lead, which opens a `Dialog` with the writing form (title, category, body, each in its own `Field` with its own error). The newest post leads on a `Card` laid out with `Grid cols="sidebar"` beside a decorative `orange` `Blob`; under it a `Segmented` category filter (`tone="info"`) narrows a two-column `Grid` of post `Card`s, each with an `info` category `Badge`, the title, an excerpt in muted `Text`, the writer as a `ViewerTag` with a muted date, and a quiet `Read` button; `Pagination` pages through them and an `Empty` stands in when a category has nothing. Opening a post swaps in the reading view: a quiet `IconButton` back, the title as the `Heading`, the byline and the body as `Text` paragraphs, with a quiet `Delete post` (toned `down`) behind a `Confirm` wearing `tone="down"`, both showing `loading` while the delete lands. Every write waits on its `can` verdict from `useVibe("blog")`, the database the posts live in: the write button gives way to a `Skeleton` inside an `aria-busy` wrapper while the verdict resolves, to a quiet `Sign in to write` wired to `useViewer().requestLogin()` for a visitor who has not signed in, and to a sentence in the app's own words when writing is closed; `Delete post` renders only where `can.delete(post).ok`.
9
+ Two views, one job each. The front page opens with an `Eyebrow`, the `Heading` and a muted post count beside a `Write a post` button, the front page's one lead, which opens a `Dialog` with the writing form (title, category, body, each in its own `Field` with its own error). The newest post leads on a `Card` laid out with `Grid cols="sidebar"` beside a decorative `orange` `IconTile`; under it a `Segmented` category filter (`tone="info"`) narrows a two-column `Grid` of post `Card`s, each with an `info` category `Badge`, the title, an excerpt in muted `Text`, the writer as a `ViewerTag` with a muted date, and a quiet `Read` button; `Pagination` pages through them and an `Empty` stands in when a category has nothing. Opening a post swaps in the reading view: a quiet `IconButton` back, the title as the `Heading`, the byline and the body as `Text` paragraphs, with a quiet `Delete post` (toned `down`) behind a `Confirm` wearing `tone="down"`, both showing `loading` while the delete lands. Every write waits on its `can` verdict from `useVibe("blog")`, the database the posts live in: the write button gives way to a `Skeleton` inside an `aria-busy` wrapper while the verdict resolves, to a quiet `Sign in to write` wired to `useViewer().requestLogin()` for a visitor who has not signed in, and to a sentence in the app's own words when writing is closed; `Delete post` renders only where `can.delete(post).ok`.
10
10
 
11
11
  ### `App.jsx`
12
12
  ```jsx
@@ -15,7 +15,7 @@ import { useFireproof } from "use-fireproof";
15
15
  import { useViewer, useVibe } from "use-vibes";
16
16
  import {
17
17
  Badge,
18
- Blob,
18
+ IconTile,
19
19
  Button,
20
20
  Card,
21
21
  Empty,
@@ -33,8 +33,8 @@ import {
33
33
  Stack,
34
34
  Text,
35
35
  Textarea,
36
- } from "@vibes.diy/pouf";
37
- import { Confirm, Dialog, Select, Toaster, toast } from "@vibes.diy/pouf/interactive";
36
+ } from "@vibes.diy/ui";
37
+ import { Confirm, Dialog, Select, Toaster, toast } from "@vibes.diy/ui/interactive";
38
38
 
39
39
  const CATEGORIES = [
40
40
  { value: "recipes", label: "Recipes" },
@@ -164,7 +164,7 @@ export default function App() {
164
164
  </Row>
165
165
  )}
166
166
  </Stack>
167
- <div className="pouf-toasts">
167
+ <div className="ui-toasts">
168
168
  <Toaster />
169
169
  </div>
170
170
  </main>
@@ -246,7 +246,7 @@ export default function App() {
246
246
  </Button>
247
247
  </Row>
248
248
  </Stack>
249
- <Blob icon="sparkle" tone="orange" size="lg" />
249
+ <IconTile icon="sparkle" tone="orange" size="lg" />
250
250
  </Grid>
251
251
  </Card>
252
252
 
@@ -286,7 +286,7 @@ export default function App() {
286
286
  </>
287
287
  )}
288
288
  </Stack>
289
- <div className="pouf-toasts">
289
+ <div className="ui-toasts">
290
290
  <Toaster />
291
291
  </div>
292
292
  </main>
@@ -298,7 +298,7 @@ export default function App() {
298
298
 
299
299
  - Swap `CATEGORIES` for the blog's own sections; the filter and the form's `Select` both read from it, so a new section appears in both. Keep the category `Badge`s on one neutral tone (`info`): a category is a label, not a verdict.
300
300
  - Keep one document per post with its `authorHandle`; the byline is always a `ViewerTag`, never a typed name.
301
- - A cover photo is a `_files` attachment on the post, shown with `Figure` in place of the featured `Blob`; drafts that aren't ready yet are a `status` field filtered out of the front page (the editorial block walks posts through that pipeline).
301
+ - A cover photo is a `_files` attachment on the post, shown with `Figure` in place of the featured `IconTile`; drafts that aren't ready yet are a `status` field filtered out of the front page (the editorial block walks posts through that pipeline).
302
302
  - Editing a post is the same form, prefilled, writing behind `can.edit(post)`; keep `Delete post` quiet and behind its `Confirm`.
303
303
  - A new write surface gets its own verdict: `can.create(draft)` with the fields the write stamps, `can.edit(doc)` or `can.delete(doc)` on the document it changes, always on `useVibe` of the database it writes.
304
304
 
@@ -0,0 +1,2 @@
1
+ import type { LlmConfig } from "./types.js";
2
+ export declare const uiBookingConfig: LlmConfig;
@@ -0,0 +1,7 @@
1
+ export const uiBookingConfig = {
2
+ name: "ui-booking",
3
+ aliases: ["pouf-booking"],
4
+ label: "Booking block",
5
+ description: "Appointment booking: pick a service, day and free slot, confirm",
6
+ };
7
+ //# sourceMappingURL=ui-booking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-booking.js","sourceRoot":"","sources":["../../jsr/llms/ui-booking.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,CAAC,cAAc,CAAC;IACzB,KAAK,EAAE,eAAe;IACtB,WAAW,EAAE,iEAAiE;CAC/E,CAAC"}
@@ -1,12 +1,12 @@
1
- # Pouf Booking
1
+ # Booking
2
2
 
3
3
  An appointment booker: pick a service, a day and a free time, add a name, review, confirm. It fits a massage practice's sessions, a tutor's lessons, a studio's portrait slots or a repair café's drop-in times. Reach for it whenever the app's core is people claiming time slots that only one person can hold. Every booking persists as its own document and availability is worked out from them, so a taken time disappears for everyone and the booker finds their sessions on every visit.
4
4
 
5
- Built from @vibes.diy/pouf components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
5
+ Built from @vibes.diy/ui components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
6
6
 
7
7
  ## The block
8
8
 
9
- Two cards beside each other in a `Grid cols="sidebar"`. The main side opens with an `Eyebrow`, the `Heading` and a muted promise, then the person's own bookings on a `Card`. Each booking shows a `Badge`: `up` when confirmed, `warn` when someone else got the time first. Each one has a quiet `Cancel` behind a `Confirm` wearing `tone="down"`, offered only where `can.delete(booking).ok`. The side holds the wizard, one step at a time under an `Eyebrow` and a `Progress` bar (`tone="info"`): each service is a clickable `RowCard` with a decorative `orange` `Blob`; the day is a `Segmented` (`tone="info"`) and the time a `RadioGroup` of only the free times, with a muted line when a day is full; the details are a name `Input` in a `Field` with its own error (nothing private, because every booking is readable so free times can be worked out); and the review ends in `Confirm booking`, that step's one lead, which shows `loading` while the write lands. Each booking is its own document, never a flag on a shared calendar document. Two people can confirm the same time at once, and sync keeps both documents, so availability is derived: a slot belongs to its earliest booking (by `createdAt`, then `_id`). A later one is shown to its booker as a clash, with a `Pick another time` button that removes it and keeps their details. Confirming waits on its `can` verdict from `useVibe("bookings")`: a `Skeleton` inside an `aria-busy` wrapper while it resolves, and a sentence in the app's own words when booking is closed. For a visitor who has not signed in, the lead is `Sign in to confirm`, wired to `useViewer().requestLogin()`, and their choices stay in place. Sign-in is required here, unlike a local-first note, because a signed-out write stays on the device until sign-in: a booking made that way would never reach the practice or hold the slot against anyone else. Between the write and the live query catching up, the wizard shows a confirming `Skeleton` rather than the review again, so the lead can't book twice; cancelling the booking just made resets the wizard.
9
+ Two cards beside each other in a `Grid cols="sidebar"`. The main side opens with an `Eyebrow`, the `Heading` and a muted promise, then the person's own bookings on a `Card`. Each booking shows a `Badge`: `up` when confirmed, `warn` when someone else got the time first. Each one has a quiet `Cancel` behind a `Confirm` wearing `tone="down"`, offered only where `can.delete(booking).ok`. The side holds the wizard, one step at a time under an `Eyebrow` and a `Progress` bar (`tone="info"`): each service is a clickable `RowCard` with a decorative `orange` `IconTile`; the day is a `Segmented` (`tone="info"`) and the time a `RadioGroup` of only the free times, with a muted line when a day is full; the details are a name `Input` in a `Field` with its own error (nothing private, because every booking is readable so free times can be worked out); and the review ends in `Confirm booking`, that step's one lead, which shows `loading` while the write lands. Each booking is its own document, never a flag on a shared calendar document. Two people can confirm the same time at once, and sync keeps both documents, so availability is derived: a slot belongs to its earliest booking (by `createdAt`, then `_id`). A later one is shown to its booker as a clash, with a `Pick another time` button that removes it and keeps their details. Confirming waits on its `can` verdict from `useVibe("bookings")`: a `Skeleton` inside an `aria-busy` wrapper while it resolves, and a sentence in the app's own words when booking is closed. For a visitor who has not signed in, the lead is `Sign in to confirm`, wired to `useViewer().requestLogin()`, and their choices stay in place. Sign-in is required here, unlike a local-first note, because a signed-out write stays on the device until sign-in: a booking made that way would never reach the practice or hold the slot against anyone else. Between the write and the live query catching up, the wizard shows a confirming `Skeleton` rather than the review again, so the lead can't book twice; cancelling the booking just made resets the wizard.
10
10
 
11
11
  ### `App.jsx`
12
12
  ```jsx
@@ -15,7 +15,7 @@ import { useFireproof } from "use-fireproof";
15
15
  import { useViewer, useVibe } from "use-vibes";
16
16
  import {
17
17
  Badge,
18
- Blob,
18
+ IconTile,
19
19
  Button,
20
20
  Card,
21
21
  Empty,
@@ -31,8 +31,8 @@ import {
31
31
  Spacer,
32
32
  Stack,
33
33
  Text,
34
- } from "@vibes.diy/pouf";
35
- import { Confirm, Progress, RadioGroup, Toaster, toast } from "@vibes.diy/pouf/interactive";
34
+ } from "@vibes.diy/ui";
35
+ import { Confirm, Progress, RadioGroup, Toaster, toast } from "@vibes.diy/ui/interactive";
36
36
 
37
37
  const SERVICES = [
38
38
  { id: "relax", name: "Relaxation massage", blurb: "A slow, full-body session to unwind.", minutes: 60, price: 80, icon: "sparkle" },
@@ -227,7 +227,7 @@ export default function App() {
227
227
  }}
228
228
  >
229
229
  <Row gap={3} wrap={false} align="top">
230
- <Blob icon={s.icon} tone="orange" size="sm" />
230
+ <IconTile icon={s.icon} tone="orange" size="sm" />
231
231
  <Stack gap={1}>
232
232
  <Text>{s.name}</Text>
233
233
  <Text size="sm" muted>
@@ -378,7 +378,7 @@ export default function App() {
378
378
  </Stack>
379
379
  <Card>{wizard}</Card>
380
380
  </Grid>
381
- <div className="pouf-toasts">
381
+ <div className="ui-toasts">
382
382
  <Toaster />
383
383
  </div>
384
384
  </main>
@@ -0,0 +1,2 @@
1
+ import type { LlmConfig } from "./types.js";
2
+ export declare const uiCalendarConfig: LlmConfig;
@@ -0,0 +1,7 @@
1
+ export const uiCalendarConfig = {
2
+ name: "ui-calendar",
3
+ aliases: ["pouf-calendar"],
4
+ label: "Calendar block",
5
+ description: "Calendar agenda/month view UI: month grid, day timeline, saved events",
6
+ };
7
+ //# sourceMappingURL=ui-calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-calendar.js","sourceRoot":"","sources":["../../jsr/llms/ui-calendar.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,gBAAgB,GAAc;IACzC,IAAI,EAAE,aAAa;IACnB,OAAO,EAAE,CAAC,eAAe,CAAC;IAC1B,KAAK,EAAE,gBAAgB;IACvB,WAAW,EAAE,uEAAuE;CACrF,CAAC"}
@@ -1,8 +1,8 @@
1
- # Pouf Calendar
1
+ # Calendar
2
2
 
3
3
  An on-screen calendar of timed events: a studio's class timetable, a family's appointments, a club's practice schedule, a shared room's bookings for the week. Reach for it when the app shows a month at a glance and one day's agenda in time order, with the free gaps between events and a line where "now" falls, and lets people add and remove events. This is the calendar people look at inside the app; a subscribable phone-calendar feed (webcal or `.ics`) is a different job, served from the backend. Each event is its own document, so everyone who opens the app sees the same schedule.
4
4
 
5
- Built from @vibes.diy/pouf components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
5
+ Built from @vibes.diy/ui components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
6
6
 
7
7
  ## The block
8
8
 
@@ -13,8 +13,8 @@ One view with one job: see what is on and add to it. The `Heading` and a muted l
13
13
  import React, { useEffect, useState } from "react";
14
14
  import { useFireproof } from "use-fireproof";
15
15
  import { useViewer, useVibe } from "use-vibes";
16
- import { Badge, Button, Card, Empty, Field, Grid, Heading, Icon, IconButton, Input, Row, RowCard, Skeleton, Stack, Text } from "@vibes.diy/pouf";
17
- import { Confirm, Dialog, Select, Toaster, toast } from "@vibes.diy/pouf/interactive";
16
+ import { Badge, Button, Card, Empty, Field, Grid, Heading, Icon, IconButton, Input, Row, RowCard, Skeleton, Stack, Text } from "@vibes.diy/ui";
17
+ import { Confirm, Dialog, Select, Toaster, toast } from "@vibes.diy/ui/interactive";
18
18
 
19
19
  const pad = (n) => String(n).padStart(2, "0");
20
20
  // Dates are kept as local YYYY-MM-DD strings, so an event never drifts a day across time zones.
@@ -332,7 +332,7 @@ export default function App() {
332
332
  </Stack>
333
333
  </Card>
334
334
  </Stack>
335
- <div className="pouf-toasts">
335
+ <div className="ui-toasts">
336
336
  <Toaster />
337
337
  </div>
338
338
  </main>
@@ -0,0 +1,2 @@
1
+ import type { LlmConfig } from "./types.js";
2
+ export declare const uiChatConfig: LlmConfig;
@@ -0,0 +1,7 @@
1
+ export const uiChatConfig = {
2
+ name: "ui-chat",
3
+ aliases: ["pouf-chat"],
4
+ label: "Chat block",
5
+ description: "Group chat with rooms, live message threads and a composer",
6
+ };
7
+ //# sourceMappingURL=ui-chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-chat.js","sourceRoot":"","sources":["../../jsr/llms/ui-chat.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,CAAC,WAAW,CAAC;IACtB,KAAK,EAAE,YAAY;IACnB,WAAW,EAAE,4DAA4D;CAC1E,CAAC"}
@@ -1,8 +1,8 @@
1
- # Pouf Chat
1
+ # Chat
2
2
 
3
3
  A group conversation split into rooms: a crew's chat with a room per trip, a band's thread per song, a household's rooms for groceries and plans, a class's channel per project. Reach for it whenever the app's core is people sending each other short messages that read top to bottom as they arrive. Rooms and messages persist and arrive live, so everyone in the app sees a new message as soon as it is sent, on every device.
4
4
 
5
- Built from @vibes.diy/pouf components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
5
+ Built from @vibes.diy/ui components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
6
6
 
7
7
  ## The block
8
8
 
@@ -13,8 +13,8 @@ Two views, one job each. The room list opens with the `Heading` and a muted coun
13
13
  import React, { useEffect, useRef, useState } from "react";
14
14
  import { useFireproof } from "use-fireproof";
15
15
  import { useViewer, useVibe } from "use-vibes";
16
- import { Button, Card, Empty, Field, Heading, Icon, IconButton, Input, Row, RowCard, Skeleton, Stack, Text } from "@vibes.diy/pouf";
17
- import { ScrollArea } from "@vibes.diy/pouf/interactive";
16
+ import { Button, Card, Empty, Field, Heading, Icon, IconButton, Input, Row, RowCard, Skeleton, Stack, Text } from "@vibes.diy/ui";
17
+ import { ScrollArea } from "@vibes.diy/ui/interactive";
18
18
 
19
19
  const when = (ms) => new Date(ms).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
20
20
 
@@ -0,0 +1,2 @@
1
+ import type { LlmConfig } from "./types.js";
2
+ export declare const uiContactConfig: LlmConfig;
@@ -0,0 +1,7 @@
1
+ export const uiContactConfig = {
2
+ name: "ui-contact",
3
+ aliases: ["pouf-contact"],
4
+ label: "Contact block",
5
+ description: "Contact form with validation that saves each message for the team",
6
+ };
7
+ //# sourceMappingURL=ui-contact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-contact.js","sourceRoot":"","sources":["../../jsr/llms/ui-contact.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,CAAC,cAAc,CAAC;IACzB,KAAK,EAAE,eAAe;IACtB,WAAW,EAAE,mEAAmE;CACjF,CAAC"}
@@ -1,20 +1,20 @@
1
- # Pouf Contact
1
+ # Contact
2
2
 
3
3
  A get-in-touch section where someone leaves their name, email, a topic and a message for the people behind the app: a photography studio's enquiry form, a community garden's question box, a band's booking request. Reach for it whenever the app's job is to collect a note and say clearly that it arrived. Every message persists as its own document, so the team can read and answer them later (the inbox block is the reading side).
4
4
 
5
- Built from @vibes.diy/pouf components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
5
+ Built from @vibes.diy/ui components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
6
6
 
7
7
  ## The block
8
8
 
9
- One view with one job: send a note. A `Grid cols="sidebar"` puts the pitch beside the form: an `info` `Badge` with the reply time, an `Eyebrow`, the `Heading` and a muted line, then two tight `Card`s that tilt, each fronted by a small `Blob` (`info` mail, `idle` clock). The form sits on its own `Card`: name and email `Input`s, a topic `Select` and a message `Textarea`, each in a `Field`. It is checked in plain state on submit, with each error on its own `Field`, its control `invalid` and focus moved to the first one. `Send message` is the view's one lead and shows `loading` while the write lands. Each message is one document, stamped with the sender's handle when they are signed in. The form waits on its `can` verdict from `useVibe("contact")`: a `Skeleton` inside an `aria-busy` wrapper while it resolves, a `Sign in to send a message` lead wired to `requestLogin()` when sending is closed to a signed-out visitor, and a sentence in the app's own words when it is closed to someone already signed in. Where `access.js` lets a signed-out visitor write, they can still send; their note is kept on this device until they sign in. So their confirmation says that honestly (`Your note is waiting`), and its lead is `Sign in to send it`, wired to `useViewer().requestLogin()`. A signed-in sender sees `Message sent` in an `Empty`, with a quiet `Send another message`.
9
+ One view with one job: send a note. A `Grid cols="sidebar"` puts the pitch beside the form: an `info` `Badge` with the reply time, an `Eyebrow`, the `Heading` and a muted line, then two tight `Card`s that tilt, each fronted by a small `IconTile` (`info` mail, `idle` clock). The form sits on its own `Card`: name and email `Input`s, a topic `Select` and a message `Textarea`, each in a `Field`. It is checked in plain state on submit, with each error on its own `Field`, its control `invalid` and focus moved to the first one. `Send message` is the view's one lead and shows `loading` while the write lands. Each message is one document, stamped with the sender's handle when they are signed in. The form waits on its `can` verdict from `useVibe("contact")`: a `Skeleton` inside an `aria-busy` wrapper while it resolves, a `Sign in to send a message` lead wired to `requestLogin()` when sending is closed to a signed-out visitor, and a sentence in the app's own words when it is closed to someone already signed in. Where `access.js` lets a signed-out visitor write, they can still send; their note is kept on this device until they sign in. So their confirmation says that honestly (`Your note is waiting`), and its lead is `Sign in to send it`, wired to `useViewer().requestLogin()`. A signed-in sender sees `Message sent` in an `Empty`, with a quiet `Send another message`.
10
10
 
11
11
  ### `App.jsx`
12
12
  ```jsx
13
13
  import React, { useRef, useState } from "react";
14
14
  import { useFireproof } from "use-fireproof";
15
15
  import { useViewer, useVibe } from "use-vibes";
16
- import { Badge, Blob, Button, Card, Empty, Eyebrow, Field, Grid, Heading, Input, Row, Skeleton, Stack, Text, Textarea } from "@vibes.diy/pouf";
17
- import { Select } from "@vibes.diy/pouf/interactive";
16
+ import { Badge, IconTile, Button, Card, Empty, Eyebrow, Field, Grid, Heading, Input, Row, Skeleton, Stack, Text, Textarea } from "@vibes.diy/ui";
17
+ import { Select } from "@vibes.diy/ui/interactive";
18
18
 
19
19
  const TOPICS = [
20
20
  { value: "booking", label: "Book a shoot" },
@@ -194,7 +194,7 @@ export default function App() {
194
194
  </Stack>
195
195
  <Card variant="tight" motion="tilt-left">
196
196
  <Row gap={3} wrap={false} align="top">
197
- <Blob icon="mail" tone="info" size="sm" />
197
+ <IconTile icon="mail" tone="info" size="sm" />
198
198
  <Stack gap={1}>
199
199
  <Text>Prefer email?</Text>
200
200
  <Text size="sm" muted>
@@ -205,7 +205,7 @@ export default function App() {
205
205
  </Card>
206
206
  <Card variant="tight" motion="tilt-right">
207
207
  <Row gap={3} wrap={false} align="top">
208
- <Blob icon="clock" tone="idle" size="sm" />
208
+ <IconTile icon="clock" tone="idle" size="sm" />
209
209
  <Stack gap={1}>
210
210
  <Text>Read by a person</Text>
211
211
  <Text size="sm" muted>
@@ -0,0 +1,2 @@
1
+ import type { LlmConfig } from "./types.js";
2
+ export declare const uiCourseConfig: LlmConfig;
@@ -0,0 +1,7 @@
1
+ export const uiCourseConfig = {
2
+ name: "ui-course",
3
+ aliases: ["pouf-course"],
4
+ label: "Course block",
5
+ description: "Course outline with lessons to complete and a progress bar",
6
+ };
7
+ //# sourceMappingURL=ui-course.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-course.js","sourceRoot":"","sources":["../../jsr/llms/ui-course.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,CAAC,aAAa,CAAC;IACxB,KAAK,EAAE,cAAc;IACrB,WAAW,EAAE,4DAA4D;CAC1E,CAAC"}
@@ -1,12 +1,12 @@
1
- # Pouf Course
1
+ # Course
2
2
 
3
3
  A course outline someone works through lesson by lesson: a beginner pottery class, new staff training at a café, a study plan for an exam, a coding bootcamp's first week. Reach for it whenever the app's core is an ordered set of lessons, each with a rough length, that a person marks complete while a bar shows how far along they are. The lessons and each person's completions persist, so progress is waiting on the next visit and on every device, and every learner keeps their own.
4
4
 
5
- Built from @vibes.diy/pouf components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
5
+ Built from @vibes.diy/ui components; persisted state lives in Fireproof. Every write surface is gated on `useVibe(dbName).can`.
6
6
 
7
7
  ## The block
8
8
 
9
- Two views, one job each. The outline opens with the `Heading` and a muted count beside a quiet `Add lesson` button that opens a `Dialog` with the lesson form. A `Card` holds the person's progress: a `Progress` bar toned `up`, the percent and minutes left in `Text`, a `Blob` (`info` target while lessons remain, `up` trophy once they are all done) and a `Continue` button, the outline's one lead, that opens the next unfinished lesson. Each lesson is a clickable `RowCard` with a small `Blob`, a muted line for its kind and length, its title and a `Badge` (`up` done, `idle` to do); an `Empty` stands in before the first lesson. Opening a lesson swaps in the lesson view: a quiet `IconButton` to go back, the kind as an `info` `Badge`, the title as the `Heading`, `Metric`s for the time and the lesson's place in the course, and `Mark complete` as that view's lead (or, once done, a quiet `Mark not done` beside a `Next lesson` lead). A completion is its own document with a deterministic `_id` per lesson and person, so each learner's progress is theirs and marking twice lands on one document. Every write waits on its `can` verdict from `useVibe("course")`: the lesson form and the completion buttons show a `Skeleton` inside an `aria-busy` wrapper while the verdict resolves and a sentence in the app's own words when that write is closed to this visitor. Progress belongs to a person, so a visitor who has not signed in sees a `Sign in to track progress` button wired to `useViewer().requestLogin()` instead of the completion buttons.
9
+ Two views, one job each. The outline opens with the `Heading` and a muted count beside a quiet `Add lesson` button that opens a `Dialog` with the lesson form. A `Card` holds the person's progress: a `Progress` bar toned `up`, the percent and minutes left in `Text`, an `IconTile` (`info` target while lessons remain, `up` trophy once they are all done) and a `Continue` button, the outline's one lead, that opens the next unfinished lesson. Each lesson is a clickable `RowCard` with a small `IconTile`, a muted line for its kind and length, its title and a `Badge` (`up` done, `idle` to do); an `Empty` stands in before the first lesson. Opening a lesson swaps in the lesson view: a quiet `IconButton` to go back, the kind as an `info` `Badge`, the title as the `Heading`, `Metric`s for the time and the lesson's place in the course, and `Mark complete` as that view's lead (or, once done, a quiet `Mark not done` beside a `Next lesson` lead). A completion is its own document with a deterministic `_id` per lesson and person, so each learner's progress is theirs and marking twice lands on one document. Every write waits on its `can` verdict from `useVibe("course")`: the lesson form and the completion buttons show a `Skeleton` inside an `aria-busy` wrapper while the verdict resolves and a sentence in the app's own words when that write is closed to this visitor. Progress belongs to a person, so a visitor who has not signed in sees a `Sign in to track progress` button wired to `useViewer().requestLogin()` instead of the completion buttons.
10
10
 
11
11
  ### `App.jsx`
12
12
  ```jsx
@@ -15,7 +15,7 @@ import { useFireproof } from "use-fireproof";
15
15
  import { useViewer, useVibe } from "use-vibes";
16
16
  import {
17
17
  Badge,
18
- Blob,
18
+ IconTile,
19
19
  Button,
20
20
  Card,
21
21
  Empty,
@@ -32,8 +32,8 @@ import {
32
32
  Spacer,
33
33
  Stack,
34
34
  Text,
35
- } from "@vibes.diy/pouf";
36
- import { Dialog, Progress, Select, Toaster, toast } from "@vibes.diy/pouf/interactive";
35
+ } from "@vibes.diy/ui";
36
+ import { Dialog, Progress, Select, Toaster, toast } from "@vibes.diy/ui/interactive";
37
37
 
38
38
  const KINDS = [
39
39
  { value: "Lesson", label: "Lesson" },
@@ -247,7 +247,7 @@ export default function App() {
247
247
  </Row>
248
248
  )}
249
249
  </Stack>
250
- <Blob icon={finished ? "trophy" : "target"} tone={finished ? "up" : "info"} size="md" />
250
+ <IconTile icon={finished ? "trophy" : "target"} tone={finished ? "up" : "info"} size="md" />
251
251
  </Row>
252
252
  </Card>
253
253
  )}
@@ -263,7 +263,7 @@ export default function App() {
263
263
  return (
264
264
  <RowCard key={lesson._id} onClick={() => setOpenId(lesson._id)}>
265
265
  <Row gap={3} wrap={false}>
266
- <Blob icon={done ? "ok" : lesson.kind === "Quiz" ? "wand" : "play"} tone={done ? "up" : "idle"} size="sm" />
266
+ <IconTile icon={done ? "ok" : lesson.kind === "Quiz" ? "wand" : "play"} tone={done ? "up" : "idle"} size="sm" />
267
267
  <Stack gap={1}>
268
268
  <Text size="sm" muted>
269
269
  {lesson.kind} · {MINUTES.format(lesson.minutes)}
@@ -280,7 +280,7 @@ export default function App() {
280
280
  )}
281
281
  </Stack>
282
282
  )}
283
- <div className="pouf-toasts">
283
+ <div className="ui-toasts">
284
284
  <Toaster />
285
285
  </div>
286
286
  </main>
@@ -0,0 +1,2 @@
1
+ import type { LlmConfig } from "./types.js";
2
+ export declare const uiCrmConfig: LlmConfig;
package/llms/ui-crm.js ADDED
@@ -0,0 +1,7 @@
1
+ export const uiCrmConfig = {
2
+ name: "ui-crm",
3
+ aliases: ["pouf-crm"],
4
+ label: "Crm block",
5
+ description: "Customer list with stages, account details and notes per contact",
6
+ };
7
+ //# sourceMappingURL=ui-crm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-crm.js","sourceRoot":"","sources":["../../jsr/llms/ui-crm.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,WAAW,GAAc;IACpC,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,KAAK,EAAE,WAAW;IAClB,WAAW,EAAE,kEAAkE;CAChF,CAAC"}