page.mdx 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. import { pageMetadata } from "@/lib/page-metadata"
  2. export const metadata = pageMetadata("docs/api/directives")
  3. # @json-render/directives
  4. Pre-built custom directives for `@json-render/core`. Drop them into your catalog and renderer to add formatting, math, string manipulation, and i18n.
  5. ## Install
  6. ```bash
  7. npm install @json-render/directives
  8. ```
  9. ## Quick Start
  10. ```typescript
  11. import { standardDirectives } from '@json-render/directives';
  12. // Wire into prompt generation
  13. const prompt = catalog.prompt({ directives: standardDirectives });
  14. // Wire into the renderer
  15. <JSONUIProvider spec={spec} directives={standardDirectives}>
  16. ...
  17. </JSONUIProvider>
  18. ```
  19. To add factory directives like `createI18nDirective`, spread the array:
  20. ```typescript
  21. import { standardDirectives, createI18nDirective } from '@json-render/directives';
  22. const directives = [...standardDirectives, createI18nDirective(config)];
  23. ```
  24. ## Directives
  25. ### `$format` — Locale-aware value formatting
  26. Formats values using `Intl` formatters. Supports `date`, `currency`, `number`, and `percent`.
  27. ```json
  28. { "$format": "currency", "value": { "$state": "/cart/total" }, "currency": "USD" }
  29. ```
  30. ```json
  31. { "$format": "date", "value": { "$state": "/user/createdAt" } }
  32. ```
  33. ```json
  34. { "$format": "number", "value": 1234567, "notation": "compact" }
  35. ```
  36. ```json
  37. { "$format": "percent", "value": 0.75 }
  38. ```
  39. Relative dates are also supported:
  40. ```json
  41. { "$format": "date", "value": { "$state": "/post/createdAt" }, "style": "relative" }
  42. ```
  43. This returns strings like `"3h ago"`, `"2d from now"`, or `"just now"`.
  44. <table>
  45. <thead>
  46. <tr>
  47. <th>Field</th>
  48. <th>Type</th>
  49. <th>Description</th>
  50. </tr>
  51. </thead>
  52. <tbody>
  53. <tr>
  54. <td><code>$format</code></td>
  55. <td><code>{'\"date\" | \"currency\" | \"number\" | \"percent\"'}</code></td>
  56. <td>Format type.</td>
  57. </tr>
  58. <tr>
  59. <td><code>value</code></td>
  60. <td><code>unknown</code></td>
  61. <td>Value to format. Accepts any dynamic expression.</td>
  62. </tr>
  63. <tr>
  64. <td><code>locale</code></td>
  65. <td><code>string</code></td>
  66. <td>Optional. Locale for formatting (e.g. <code>"en-US"</code>).</td>
  67. </tr>
  68. <tr>
  69. <td><code>currency</code></td>
  70. <td><code>string</code></td>
  71. <td>Optional. Currency code for <code>"currency"</code> format. Default: <code>"USD"</code>.</td>
  72. </tr>
  73. <tr>
  74. <td><code>notation</code></td>
  75. <td><code>string</code></td>
  76. <td>Optional. Notation for <code>"number"</code> format (e.g. <code>"compact"</code>).</td>
  77. </tr>
  78. <tr>
  79. <td><code>style</code></td>
  80. <td><code>string</code></td>
  81. <td>Optional. Set to <code>"relative"</code> for relative date formatting.</td>
  82. </tr>
  83. <tr>
  84. <td><code>options</code></td>
  85. <td><code>{'Record<string, unknown>'}</code></td>
  86. <td>Optional. Extra <code>Intl</code> formatter options.</td>
  87. </tr>
  88. </tbody>
  89. </table>
  90. ### `$math` — Arithmetic operations
  91. Performs arithmetic on one or two operands. Operands accept any dynamic expression.
  92. ```json
  93. { "$math": "add", "a": { "$state": "/subtotal" }, "b": { "$state": "/tax" } }
  94. ```
  95. ```json
  96. { "$math": "round", "a": 3.7 }
  97. ```
  98. <table>
  99. <thead>
  100. <tr>
  101. <th>Field</th>
  102. <th>Type</th>
  103. <th>Description</th>
  104. </tr>
  105. </thead>
  106. <tbody>
  107. <tr>
  108. <td><code>$math</code></td>
  109. <td><code>{'\"add\" | \"subtract\" | \"multiply\" | \"divide\" | \"mod\" | \"min\" | \"max\" | \"round\" | \"floor\" | \"ceil\" | \"abs\"'}</code></td>
  110. <td>Operation to perform.</td>
  111. </tr>
  112. <tr>
  113. <td><code>a</code></td>
  114. <td><code>unknown</code></td>
  115. <td>First operand. Defaults to <code>0</code> if missing.</td>
  116. </tr>
  117. <tr>
  118. <td><code>b</code></td>
  119. <td><code>unknown</code></td>
  120. <td>Second operand (binary ops only). Defaults to <code>0</code> if missing.</td>
  121. </tr>
  122. </tbody>
  123. </table>
  124. Unary operations (`round`, `floor`, `ceil`, `abs`) only use `a`. Division by zero returns `0`.
  125. ### `$concat` — String concatenation
  126. Concatenates multiple values into a single string. Each element is resolved then joined.
  127. ```json
  128. { "$concat": [{ "$state": "/user/firstName" }, " ", { "$state": "/user/lastName" }] }
  129. ```
  130. <table>
  131. <thead>
  132. <tr>
  133. <th>Field</th>
  134. <th>Type</th>
  135. <th>Description</th>
  136. </tr>
  137. </thead>
  138. <tbody>
  139. <tr>
  140. <td><code>$concat</code></td>
  141. <td><code>{'unknown[]'}</code></td>
  142. <td>Array of values to concatenate. Each is resolved, converted to string, and joined.</td>
  143. </tr>
  144. </tbody>
  145. </table>
  146. ### `$count` — Array/string length
  147. Returns the length of an array or string. Returns `0` for other types.
  148. ```json
  149. { "$count": { "$state": "/cart/items" } }
  150. ```
  151. <table>
  152. <thead>
  153. <tr>
  154. <th>Field</th>
  155. <th>Type</th>
  156. <th>Description</th>
  157. </tr>
  158. </thead>
  159. <tbody>
  160. <tr>
  161. <td><code>$count</code></td>
  162. <td><code>unknown</code></td>
  163. <td>Value to count. Accepts arrays and strings.</td>
  164. </tr>
  165. </tbody>
  166. </table>
  167. ### `$truncate` — Text truncation
  168. Truncates text to a maximum length with a configurable suffix.
  169. ```json
  170. { "$truncate": { "$state": "/post/body" }, "length": 140, "suffix": "..." }
  171. ```
  172. <table>
  173. <thead>
  174. <tr>
  175. <th>Field</th>
  176. <th>Type</th>
  177. <th>Description</th>
  178. </tr>
  179. </thead>
  180. <tbody>
  181. <tr>
  182. <td><code>$truncate</code></td>
  183. <td><code>unknown</code></td>
  184. <td>Value to truncate.</td>
  185. </tr>
  186. <tr>
  187. <td><code>length</code></td>
  188. <td><code>number</code></td>
  189. <td>Optional. Max character length. Default: <code>100</code>.</td>
  190. </tr>
  191. <tr>
  192. <td><code>suffix</code></td>
  193. <td><code>string</code></td>
  194. <td>Optional. Suffix to append when truncated. Default: <code>"..."</code>.</td>
  195. </tr>
  196. </tbody>
  197. </table>
  198. ### `$pluralize` — Singular/plural forms
  199. Selects a singular, plural, or zero form based on a count.
  200. ```json
  201. { "$pluralize": { "$state": "/cart/itemCount" }, "one": "item", "other": "items", "zero": "no items" }
  202. ```
  203. Output: `"3 items"`, `"1 item"`, or `"no items"`.
  204. <table>
  205. <thead>
  206. <tr>
  207. <th>Field</th>
  208. <th>Type</th>
  209. <th>Description</th>
  210. </tr>
  211. </thead>
  212. <tbody>
  213. <tr>
  214. <td><code>$pluralize</code></td>
  215. <td><code>unknown</code></td>
  216. <td>Count value. Accepts dynamic expressions.</td>
  217. </tr>
  218. <tr>
  219. <td><code>one</code></td>
  220. <td><code>string</code></td>
  221. <td>Singular form label.</td>
  222. </tr>
  223. <tr>
  224. <td><code>other</code></td>
  225. <td><code>string</code></td>
  226. <td>Plural form label.</td>
  227. </tr>
  228. <tr>
  229. <td><code>zero</code></td>
  230. <td><code>string</code></td>
  231. <td>Optional. Label for count of zero. If omitted, uses <code>"0 {'<other>'}"</code>.</td>
  232. </tr>
  233. </tbody>
  234. </table>
  235. ### `$join` — Join array elements
  236. Joins array elements with a separator string.
  237. ```json
  238. { "$join": { "$state": "/tags" }, "separator": ", " }
  239. ```
  240. <table>
  241. <thead>
  242. <tr>
  243. <th>Field</th>
  244. <th>Type</th>
  245. <th>Description</th>
  246. </tr>
  247. </thead>
  248. <tbody>
  249. <tr>
  250. <td><code>$join</code></td>
  251. <td><code>unknown</code></td>
  252. <td>Array to join. Non-array values are converted to string.</td>
  253. </tr>
  254. <tr>
  255. <td><code>separator</code></td>
  256. <td><code>string</code></td>
  257. <td>Optional. Separator between elements. Default: <code>", "</code>.</td>
  258. </tr>
  259. </tbody>
  260. </table>
  261. ### `createI18nDirective` — Internationalization
  262. Factory function that creates a `$t` directive for translations with `{'{{param}}'}` interpolation.
  263. ```typescript
  264. import { createI18nDirective } from '@json-render/directives';
  265. const tDirective = createI18nDirective({
  266. locale: 'en',
  267. messages: {
  268. en: { "greeting": "Hello, {'{{name}}'}!", "checkout.submit": "Place Order" },
  269. es: { "greeting": "Hola, {'{{name}}'}!", "checkout.submit": "Realizar Pedido" },
  270. },
  271. fallbackLocale: 'en',
  272. });
  273. ```
  274. Usage in specs:
  275. ```json
  276. { "$t": "checkout.submit" }
  277. ```
  278. ```json
  279. { "$t": "greeting", "params": { "name": { "$state": "/user/name" } } }
  280. ```
  281. <table>
  282. <thead>
  283. <tr>
  284. <th>Field</th>
  285. <th>Type</th>
  286. <th>Description</th>
  287. </tr>
  288. </thead>
  289. <tbody>
  290. <tr>
  291. <td><code>$t</code></td>
  292. <td><code>string</code></td>
  293. <td>Translation key.</td>
  294. </tr>
  295. <tr>
  296. <td><code>params</code></td>
  297. <td><code>{'Record<string, unknown>'}</code></td>
  298. <td>Optional. Interpolation parameters. Values accept dynamic expressions.</td>
  299. </tr>
  300. </tbody>
  301. </table>
  302. #### `I18nConfig`
  303. <table>
  304. <thead>
  305. <tr>
  306. <th>Field</th>
  307. <th>Type</th>
  308. <th>Description</th>
  309. </tr>
  310. </thead>
  311. <tbody>
  312. <tr>
  313. <td><code>locale</code></td>
  314. <td><code>string</code></td>
  315. <td>Current locale (e.g. <code>"en"</code>).</td>
  316. </tr>
  317. <tr>
  318. <td><code>messages</code></td>
  319. <td><code>{'Record<string, Record<string, string>>'}</code></td>
  320. <td>Map of locale to key-value translation pairs.</td>
  321. </tr>
  322. <tr>
  323. <td><code>fallbackLocale</code></td>
  324. <td><code>string</code></td>
  325. <td>Optional. Fallback locale when a key is missing in the current locale.</td>
  326. </tr>
  327. </tbody>
  328. </table>
  329. ## Composition
  330. Directives compose naturally. Each resolver calls `resolvePropValue` on its inputs, so you can nest directives:
  331. ```json
  332. {
  333. "$format": "currency",
  334. "value": { "$math": "multiply", "a": { "$state": "/price" }, "b": { "$state": "/qty" } },
  335. "currency": "USD"
  336. }
  337. ```
  338. ```json
  339. {
  340. "$pluralize": { "$count": { "$state": "/items" } },
  341. "one": "item",
  342. "other": "items"
  343. }
  344. ```