@base316/react 0.1.0 → 0.2.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 (70) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +15 -15
  3. package/dist/index.cjs +4150 -160
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +48 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +4136 -165
  8. package/dist/index.js.map +1 -1
  9. package/dist/manifest.json +1161 -0
  10. package/dist/src/AcceptInvitation.d.ts +27 -0
  11. package/dist/src/AcceptInvitation.d.ts.map +1 -0
  12. package/dist/src/ActiveSessions.d.ts +21 -0
  13. package/dist/src/ActiveSessions.d.ts.map +1 -0
  14. package/dist/src/ApiKeyManager.d.ts +22 -0
  15. package/dist/src/ApiKeyManager.d.ts.map +1 -0
  16. package/dist/src/Chart.d.ts +42 -0
  17. package/dist/src/Chart.d.ts.map +1 -0
  18. package/dist/src/DataTable.d.ts +56 -0
  19. package/dist/src/DataTable.d.ts.map +1 -0
  20. package/dist/src/DeviceApproval.d.ts +30 -0
  21. package/dist/src/DeviceApproval.d.ts.map +1 -0
  22. package/dist/src/ForgotPassword.d.ts +24 -0
  23. package/dist/src/ForgotPassword.d.ts.map +1 -0
  24. package/dist/src/Invoices.d.ts.map +1 -1
  25. package/dist/src/Kanban.d.ts +40 -0
  26. package/dist/src/Kanban.d.ts.map +1 -0
  27. package/dist/src/PasskeyManager.d.ts.map +1 -1
  28. package/dist/src/PayInvoice.d.ts +41 -0
  29. package/dist/src/PayInvoice.d.ts.map +1 -0
  30. package/dist/src/PricingTable.d.ts +43 -11
  31. package/dist/src/PricingTable.d.ts.map +1 -1
  32. package/dist/src/PrivacyControls.d.ts +28 -0
  33. package/dist/src/PrivacyControls.d.ts.map +1 -0
  34. package/dist/src/RecordDetail.d.ts +31 -0
  35. package/dist/src/RecordDetail.d.ts.map +1 -0
  36. package/dist/src/RecordForm.d.ts +32 -0
  37. package/dist/src/RecordForm.d.ts.map +1 -0
  38. package/dist/src/RelationPicker.d.ts +23 -0
  39. package/dist/src/RelationPicker.d.ts.map +1 -0
  40. package/dist/src/ResetPassword.d.ts +24 -0
  41. package/dist/src/ResetPassword.d.ts.map +1 -0
  42. package/dist/src/SignIn.d.ts +11 -1
  43. package/dist/src/SignIn.d.ts.map +1 -1
  44. package/dist/src/SignUp.d.ts.map +1 -1
  45. package/dist/src/SubscriptionManager.d.ts.map +1 -1
  46. package/dist/src/TeamMembers.d.ts +49 -0
  47. package/dist/src/TeamMembers.d.ts.map +1 -0
  48. package/dist/src/TwoFactorManager.d.ts +29 -0
  49. package/dist/src/TwoFactorManager.d.ts.map +1 -0
  50. package/dist/src/VerifyEmail.d.ts +24 -0
  51. package/dist/src/VerifyEmail.d.ts.map +1 -0
  52. package/dist/src/appearance.d.ts +2 -2
  53. package/dist/src/appearance.d.ts.map +1 -1
  54. package/dist/src/confirm.d.ts +32 -0
  55. package/dist/src/confirm.d.ts.map +1 -0
  56. package/dist/src/fields.d.ts +44 -0
  57. package/dist/src/fields.d.ts.map +1 -0
  58. package/dist/src/manifest.d.ts +84 -0
  59. package/dist/src/manifest.d.ts.map +1 -0
  60. package/dist/src/test/harness.d.ts +204 -0
  61. package/dist/src/test/harness.d.ts.map +1 -0
  62. package/dist/src/test/setup.d.ts +2 -0
  63. package/dist/src/test/setup.d.ts.map +1 -0
  64. package/dist/src/useCollection.d.ts +79 -0
  65. package/dist/src/useCollection.d.ts.map +1 -0
  66. package/dist/src/usePaymentLink.d.ts +41 -0
  67. package/dist/src/usePaymentLink.d.ts.map +1 -0
  68. package/dist/src/usePlans.d.ts +66 -0
  69. package/dist/src/usePlans.d.ts.map +1 -0
  70. package/package.json +36 -28
@@ -0,0 +1,1161 @@
1
+ {
2
+ "version": 1,
3
+ "composition": {
4
+ "rules": [
5
+ "Everything must be inside Base316Provider. Outside it, hooks throw.",
6
+ "Most components need a signed-in user. Gate on useSession and render SignIn when there is none — see `requires: session` on each entry.",
7
+ "A collection must exist before anything can bind to it. Define one in the dashboard under Collections, or through POST /v1/collections with a secret key.",
8
+ "No component takes a prop you must supply to make it behave. Naming the subject is different: a collection component needs `collection` and a detail view needs `recordId`, because those say *what* to show rather than patch *how* it works. Everything else has a default.",
9
+ "Each component bound to a collection holds its own data — DataTable, Kanban, Chart, RecordForm, RecordDetail, every one. None of them share a cache, so a write in one leaves the others showing what they already had. Put the form inside the table, where New and Edit refresh it; pass `onChanged` to refresh a sibling such as a Chart; or lift `useCollection` and render your own, which is what the hook is for.",
10
+ "Next.js App Router: put Base316Provider in a Client Component wrapper used by the root layout. Every component here is a Client Component; none of them run on the server."
11
+ ],
12
+ "example": "import { Base316Provider, DataTable, RecordForm, SignIn, useSession } from \"@base316/react\";\n\nfunction Jobs() {\n const session = useSession();\n\n // Without this the table renders nothing and looks broken.\n if (!session) return <SignIn />;\n\n return (\n <>\n <DataTable collection=\"jobs\" onSelect={(record) => console.log(record.id)} />\n <RecordForm collection=\"jobs\" />\n </>\n );\n}\n\nexport function App() {\n return (\n <Base316Provider publishableKey={process.env.NEXT_PUBLIC_BASE316_PUBLISHABLE_KEY!}>\n <Jobs />\n </Base316Provider>\n );\n}"
13
+ },
14
+ "components": [
15
+ {
16
+ "name": "Base316Provider",
17
+ "kind": "provider",
18
+ "summary": "Holds the client, the session and the theme. Everything else must be inside it.",
19
+ "useWhen": "Once, around the part of the application that uses any other export here.",
20
+ "requires": [],
21
+ "props": [
22
+ {
23
+ "name": "publishableKey",
24
+ "summary": "The environment's publishable key.",
25
+ "required": true
26
+ },
27
+ {
28
+ "name": "baseUrl",
29
+ "summary": "Where the API lives. Defaults to production.",
30
+ "required": false
31
+ },
32
+ {
33
+ "name": "token",
34
+ "summary": "Supply to own session storage yourself. Left out, the session is kept in localStorage.",
35
+ "required": false
36
+ },
37
+ {
38
+ "name": "onTokenChange",
39
+ "summary": "Called when the session changes. Pair with `token` for an httpOnly cookie.",
40
+ "required": false
41
+ },
42
+ {
43
+ "name": "appearance",
44
+ "summary": "Colours, radius and font as tokens. Restyles everything at once.",
45
+ "required": false
46
+ },
47
+ {
48
+ "name": "className",
49
+ "summary": "Your own classes on the wrapper.",
50
+ "required": false
51
+ },
52
+ {
53
+ "name": "style",
54
+ "summary": "Inline styles on the wrapper.",
55
+ "required": false
56
+ }
57
+ ],
58
+ "seeAlso": [
59
+ "useBase316",
60
+ "useSession"
61
+ ]
62
+ },
63
+ {
64
+ "name": "useBase316",
65
+ "kind": "hook",
66
+ "summary": "The client, the session token and the branding, from inside the provider.",
67
+ "useWhen": "Writing a component of your own that needs to call the API directly.",
68
+ "requires": [],
69
+ "props": [],
70
+ "seeAlso": [
71
+ "Base316Provider"
72
+ ]
73
+ },
74
+ {
75
+ "name": "useSession",
76
+ "kind": "hook",
77
+ "summary": "The resolved session, or null. Carries `userId`, `user` (id, email, name, image, and the customer's own declared fields) and `tenants` — every team this person is in, each with their role.",
78
+ "useWhen": "Deciding what to render for a signed-in versus a signed-out visitor.",
79
+ "requires": [],
80
+ "props": []
81
+ },
82
+ {
83
+ "name": "SignIn",
84
+ "kind": "component",
85
+ "summary": "Password, passkey and magic-link sign-in in one form.",
86
+ "useWhen": "The application renders its own sign-in rather than redirecting to the hosted page.",
87
+ "requires": [],
88
+ "props": [
89
+ {
90
+ "name": "onSignedIn",
91
+ "summary": "Called once a session exists.",
92
+ "required": false
93
+ },
94
+ {
95
+ "name": "passkeys",
96
+ "summary": "Offer passkeys where supported. On by default.",
97
+ "required": false
98
+ },
99
+ {
100
+ "name": "magicLinkRedirectUrl",
101
+ "summary": "Where an emailed link lands, which must be registered on the environment. Without it, magic link is not offered at all.",
102
+ "required": false
103
+ },
104
+ {
105
+ "name": "className",
106
+ "summary": "Your own classes on the wrapper.",
107
+ "required": false
108
+ },
109
+ {
110
+ "name": "style",
111
+ "summary": "Inline styles on the wrapper.",
112
+ "required": false
113
+ }
114
+ ],
115
+ "seeAlso": [
116
+ "SignUp",
117
+ "ForgotPassword"
118
+ ]
119
+ },
120
+ {
121
+ "name": "SignUp",
122
+ "kind": "component",
123
+ "summary": "Create an account with an email and a password.",
124
+ "useWhen": "Alongside SignIn, on a page that registers new users.",
125
+ "requires": [],
126
+ "props": [
127
+ {
128
+ "name": "onSignedUp",
129
+ "summary": "Called after the account is created.",
130
+ "required": false
131
+ },
132
+ {
133
+ "name": "className",
134
+ "summary": "Your own classes on the wrapper.",
135
+ "required": false
136
+ },
137
+ {
138
+ "name": "style",
139
+ "summary": "Inline styles on the wrapper.",
140
+ "required": false
141
+ }
142
+ ],
143
+ "seeAlso": [
144
+ "SignIn",
145
+ "VerifyEmail"
146
+ ]
147
+ },
148
+ {
149
+ "name": "ForgotPassword",
150
+ "kind": "component",
151
+ "summary": "Ask for a reset link by email.",
152
+ "useWhen": "Linked from a sign-in form.",
153
+ "requires": [],
154
+ "props": [
155
+ {
156
+ "name": "onSent",
157
+ "summary": "Called with the address after the request.",
158
+ "required": false
159
+ },
160
+ {
161
+ "name": "signInUrl",
162
+ "summary": "Renders a link back to sign-in.",
163
+ "required": false
164
+ },
165
+ {
166
+ "name": "className",
167
+ "summary": "Your own classes on the wrapper.",
168
+ "required": false
169
+ },
170
+ {
171
+ "name": "style",
172
+ "summary": "Inline styles on the wrapper.",
173
+ "required": false
174
+ }
175
+ ],
176
+ "seeAlso": [
177
+ "ResetPassword"
178
+ ]
179
+ },
180
+ {
181
+ "name": "ResetPassword",
182
+ "kind": "component",
183
+ "summary": "Set a new password from an emailed link.",
184
+ "useWhen": "On the page the reset link lands on.",
185
+ "requires": [],
186
+ "props": [
187
+ {
188
+ "name": "token",
189
+ "summary": "Read from `?token=` when omitted, and removed from the URL.",
190
+ "required": false
191
+ },
192
+ {
193
+ "name": "onReset",
194
+ "summary": "Called once the password is changed.",
195
+ "required": false
196
+ },
197
+ {
198
+ "name": "signInUrl",
199
+ "summary": "Renders a link onward to sign-in.",
200
+ "required": false
201
+ },
202
+ {
203
+ "name": "className",
204
+ "summary": "Your own classes on the wrapper.",
205
+ "required": false
206
+ },
207
+ {
208
+ "name": "style",
209
+ "summary": "Inline styles on the wrapper.",
210
+ "required": false
211
+ }
212
+ ],
213
+ "whenUnmet": "With no token in the URL or props, explains that the link is needed.",
214
+ "seeAlso": [
215
+ "ForgotPassword"
216
+ ]
217
+ },
218
+ {
219
+ "name": "VerifyEmail",
220
+ "kind": "component",
221
+ "summary": "Confirm an address from an emailed link.",
222
+ "useWhen": "On the page the verification link lands on.",
223
+ "requires": [],
224
+ "props": [
225
+ {
226
+ "name": "token",
227
+ "summary": "Read from `?token=` when omitted, and removed from the URL.",
228
+ "required": false
229
+ },
230
+ {
231
+ "name": "onVerified",
232
+ "summary": "Called once confirmed.",
233
+ "required": false
234
+ },
235
+ {
236
+ "name": "continueUrl",
237
+ "summary": "Renders a link onward.",
238
+ "required": false
239
+ },
240
+ {
241
+ "name": "className",
242
+ "summary": "Your own classes on the wrapper.",
243
+ "required": false
244
+ },
245
+ {
246
+ "name": "style",
247
+ "summary": "Inline styles on the wrapper.",
248
+ "required": false
249
+ }
250
+ ],
251
+ "seeAlso": [
252
+ "SignUp"
253
+ ]
254
+ },
255
+ {
256
+ "name": "UserProfile",
257
+ "kind": "component",
258
+ "summary": "Name, email and the customer's own declared fields.",
259
+ "useWhen": "An account settings page.",
260
+ "requires": [
261
+ "session"
262
+ ],
263
+ "props": [],
264
+ "whenUnmet": "Renders nothing without a session.",
265
+ "seeAlso": [
266
+ "ActiveSessions",
267
+ "TwoFactorManager",
268
+ "PasskeyManager"
269
+ ]
270
+ },
271
+ {
272
+ "name": "ActiveSessions",
273
+ "kind": "component",
274
+ "summary": "Where the account is signed in, and a button to end the other devices.",
275
+ "useWhen": "A security settings page.",
276
+ "requires": [
277
+ "session"
278
+ ],
279
+ "props": [
280
+ {
281
+ "name": "onRevoked",
282
+ "summary": "Called with the number of sessions ended.",
283
+ "required": false
284
+ },
285
+ {
286
+ "name": "className",
287
+ "summary": "Your own classes on the wrapper.",
288
+ "required": false
289
+ },
290
+ {
291
+ "name": "style",
292
+ "summary": "Inline styles on the wrapper.",
293
+ "required": false
294
+ }
295
+ ],
296
+ "whenUnmet": "Renders nothing without a session.",
297
+ "seeAlso": [
298
+ "TwoFactorManager"
299
+ ]
300
+ },
301
+ {
302
+ "name": "DeviceApproval",
303
+ "kind": "component",
304
+ "summary": "Approve a sign-in that started on a CLI, a TV, or anything with no browser.",
305
+ "useWhen": "You point a device's verification URI at a page in your own app. Put this on that page.",
306
+ "requires": [
307
+ "session"
308
+ ],
309
+ "props": [
310
+ {
311
+ "name": "userCode",
312
+ "summary": "The code, when the URL already carries it. Skips the entry step; without it the person types the code.",
313
+ "required": false
314
+ },
315
+ {
316
+ "name": "onDecided",
317
+ "summary": "Called with whether they approved.",
318
+ "required": false
319
+ },
320
+ {
321
+ "name": "className",
322
+ "summary": "Your own classes on the wrapper.",
323
+ "required": false
324
+ },
325
+ {
326
+ "name": "style",
327
+ "summary": "Inline styles on the wrapper.",
328
+ "required": false
329
+ }
330
+ ],
331
+ "whenUnmet": "Renders nothing without a session — there is nobody to approve as, and collecting a code first would fail at the step that matters.",
332
+ "seeAlso": [
333
+ "SignIn",
334
+ "ActiveSessions"
335
+ ]
336
+ },
337
+ {
338
+ "name": "PrivacyControls",
339
+ "kind": "component",
340
+ "summary": "Download a copy of everything held about you, or delete your account.",
341
+ "useWhen": "An account settings page. These are the two things a privacy notice promises and most products never build.",
342
+ "requires": [
343
+ "session"
344
+ ],
345
+ "props": [
346
+ {
347
+ "name": "confirmWord",
348
+ "summary": "What must be typed to confirm deletion. Defaults to the English word, which is wrong in every other language.",
349
+ "required": false
350
+ },
351
+ {
352
+ "name": "onErased",
353
+ "summary": "Called once the account is gone. Sign them out and send them somewhere.",
354
+ "required": false
355
+ },
356
+ {
357
+ "name": "className",
358
+ "summary": "Your own classes on the wrapper.",
359
+ "required": false
360
+ },
361
+ {
362
+ "name": "style",
363
+ "summary": "Inline styles on the wrapper.",
364
+ "required": false
365
+ }
366
+ ],
367
+ "whenUnmet": "Renders nothing without a session.",
368
+ "seeAlso": [
369
+ "UserProfile",
370
+ "ActiveSessions"
371
+ ]
372
+ },
373
+ {
374
+ "name": "TwoFactorManager",
375
+ "kind": "component",
376
+ "summary": "Turn two-factor authentication on or off, by authenticator app or a code to the inbox.",
377
+ "useWhen": "A security settings page. Offers both factors; the app is stronger, the emailed code is the one people who will not install an app actually use.",
378
+ "requires": [
379
+ "session"
380
+ ],
381
+ "props": [
382
+ {
383
+ "name": "enabled",
384
+ "summary": "Whether a factor already exists, which decides which side is shown.",
385
+ "required": false
386
+ },
387
+ {
388
+ "name": "onEnabled",
389
+ "summary": "Called once a factor is confirmed.",
390
+ "required": false
391
+ },
392
+ {
393
+ "name": "onDisabled",
394
+ "summary": "Called once it is removed.",
395
+ "required": false
396
+ },
397
+ {
398
+ "name": "className",
399
+ "summary": "Your own classes on the wrapper.",
400
+ "required": false
401
+ },
402
+ {
403
+ "name": "style",
404
+ "summary": "Inline styles on the wrapper.",
405
+ "required": false
406
+ }
407
+ ],
408
+ "whenUnmet": "Renders nothing without a session.",
409
+ "seeAlso": [
410
+ "ActiveSessions",
411
+ "PasskeyManager"
412
+ ]
413
+ },
414
+ {
415
+ "name": "PasskeyManager",
416
+ "kind": "component",
417
+ "summary": "Add and remove passkeys.",
418
+ "useWhen": "A security settings page, beside two-factor.",
419
+ "requires": [
420
+ "session"
421
+ ],
422
+ "props": [
423
+ {
424
+ "name": "title",
425
+ "summary": "Heading text.",
426
+ "required": false
427
+ },
428
+ {
429
+ "name": "className",
430
+ "summary": "Your own classes on the wrapper.",
431
+ "required": false
432
+ },
433
+ {
434
+ "name": "style",
435
+ "summary": "Inline styles on the wrapper.",
436
+ "required": false
437
+ }
438
+ ],
439
+ "whenUnmet": "Renders nothing without a session.",
440
+ "seeAlso": [
441
+ "TwoFactorManager"
442
+ ]
443
+ },
444
+ {
445
+ "name": "Branding",
446
+ "kind": "component",
447
+ "summary": "The environment's logo, name and tagline.",
448
+ "useWhen": "Above a sign-in form, so your pages match the hosted ones.",
449
+ "requires": [],
450
+ "props": [
451
+ {
452
+ "name": "showTagline",
453
+ "summary": "Include the tagline under the name.",
454
+ "required": false
455
+ },
456
+ {
457
+ "name": "className",
458
+ "summary": "Your own classes on the wrapper.",
459
+ "required": false
460
+ },
461
+ {
462
+ "name": "style",
463
+ "summary": "Inline styles on the wrapper.",
464
+ "required": false
465
+ }
466
+ ]
467
+ },
468
+ {
469
+ "name": "TeamMembers",
470
+ "kind": "component",
471
+ "summary": "Who is in a team, who has been invited, and the way in and out.",
472
+ "useWhen": "A Team or Members settings page. One component covers the list, the pending invitations, the invite box and leaving.",
473
+ "requires": [
474
+ "session"
475
+ ],
476
+ "props": [
477
+ {
478
+ "name": "organizationId",
479
+ "summary": "Which team. Defaults to the only one this person is in; with several it says so rather than guessing.",
480
+ "required": false
481
+ },
482
+ {
483
+ "name": "onInvited",
484
+ "summary": "Called with `{ email, token, url }` — the address invited, the raw token, and the accept URL when `acceptUrl` was given. This is where your application sends the email. Without a handler the link is shown on screen instead, because the token is returned once and cannot be fetched again.",
485
+ "required": false
486
+ },
487
+ {
488
+ "name": "acceptUrl",
489
+ "summary": "The page hosting AcceptInvitation. The component appends `?invitation=<token>` and hands the finished link back as `url` on onInvited; without it, onInvited gets the raw token and you build the link yourself.",
490
+ "required": false
491
+ },
492
+ {
493
+ "name": "onLeft",
494
+ "summary": "Called after the viewer leaves the team.",
495
+ "required": false
496
+ },
497
+ {
498
+ "name": "className",
499
+ "summary": "Your own classes on the wrapper.",
500
+ "required": false
501
+ },
502
+ {
503
+ "name": "style",
504
+ "summary": "Inline styles on the wrapper.",
505
+ "required": false
506
+ }
507
+ ],
508
+ "whenUnmet": "Renders nothing without a session. Inviting and removing appear only for somebody whose role grants team.manage.",
509
+ "seeAlso": [
510
+ "AcceptInvitation"
511
+ ]
512
+ },
513
+ {
514
+ "name": "AcceptInvitation",
515
+ "kind": "component",
516
+ "summary": "The other end of an invitation: what it is for, and joining.",
517
+ "useWhen": "On the page an invitation link lands on.",
518
+ "requires": [],
519
+ "props": [
520
+ {
521
+ "name": "token",
522
+ "summary": "Read from `?invitation=` when omitted.",
523
+ "required": false
524
+ },
525
+ {
526
+ "name": "onAccepted",
527
+ "summary": "Called with the organizationId once they have joined.",
528
+ "required": false
529
+ },
530
+ {
531
+ "name": "signUpUrl",
532
+ "summary": "For somebody with no account yet.",
533
+ "required": false
534
+ },
535
+ {
536
+ "name": "signInUrl",
537
+ "summary": "For somebody who has one.",
538
+ "required": false
539
+ },
540
+ {
541
+ "name": "className",
542
+ "summary": "Your own classes on the wrapper.",
543
+ "required": false
544
+ },
545
+ {
546
+ "name": "style",
547
+ "summary": "Inline styles on the wrapper.",
548
+ "required": false
549
+ }
550
+ ],
551
+ "whenUnmet": "Says what the invitation is for without a session, since the point is that they may have no account. Names the address to sign in as when the signed-in one does not match.",
552
+ "seeAlso": [
553
+ "TeamMembers",
554
+ "SignUp"
555
+ ]
556
+ },
557
+ {
558
+ "name": "PricingTable",
559
+ "kind": "component",
560
+ "summary": "The published plans, and completing the purchase.",
561
+ "useWhen": "A pricing page, or an upgrade screen.",
562
+ "requires": [
563
+ "plans",
564
+ "paymentAccount"
565
+ ],
566
+ "props": [
567
+ {
568
+ "name": "onSelectPlan",
569
+ "summary": "Take over what Choose does. Left out, the component changes the plan or starts a checkout itself.",
570
+ "required": false
571
+ },
572
+ {
573
+ "name": "currentPlanVersionId",
574
+ "summary": "Marks the current plan. Discovered from the session when omitted.",
575
+ "required": false
576
+ },
577
+ {
578
+ "name": "featuredPlanKey",
579
+ "summary": "Which plan to present as the default.",
580
+ "required": false
581
+ },
582
+ {
583
+ "name": "signInUrl",
584
+ "summary": "Where a signed-out visitor goes on choosing. Without it the button says so rather than failing.",
585
+ "required": false
586
+ },
587
+ {
588
+ "name": "className",
589
+ "summary": "Your own classes on the wrapper.",
590
+ "required": false
591
+ },
592
+ {
593
+ "name": "style",
594
+ "summary": "Inline styles on the wrapper.",
595
+ "required": false
596
+ }
597
+ ],
598
+ "whenUnmet": "Says plans are unavailable when the catalog is empty.",
599
+ "seeAlso": [
600
+ "SubscriptionManager",
601
+ "usePlans"
602
+ ]
603
+ },
604
+ {
605
+ "name": "usePlans",
606
+ "kind": "hook",
607
+ "summary": "The plans, the current one, and the prorate-or-checkout branch — without markup.",
608
+ "useWhen": "You want your own pricing table but not your own billing logic.",
609
+ "requires": [
610
+ "plans"
611
+ ],
612
+ "props": [],
613
+ "seeAlso": [
614
+ "PricingTable"
615
+ ]
616
+ },
617
+ {
618
+ "name": "SubscriptionManager",
619
+ "kind": "component",
620
+ "summary": "The current plan, its renewal date, and cancelling.",
621
+ "useWhen": "A billing settings page.",
622
+ "requires": [
623
+ "session"
624
+ ],
625
+ "props": [],
626
+ "whenUnmet": "Renders nothing without a session.",
627
+ "seeAlso": [
628
+ "PricingTable",
629
+ "Invoices"
630
+ ]
631
+ },
632
+ {
633
+ "name": "Invoices",
634
+ "kind": "component",
635
+ "summary": "The signed-in user's invoices, newest first.",
636
+ "useWhen": "A billing settings page.",
637
+ "requires": [
638
+ "session"
639
+ ],
640
+ "props": [],
641
+ "whenUnmet": "Renders nothing without a session.",
642
+ "seeAlso": [
643
+ "SubscriptionManager"
644
+ ]
645
+ },
646
+ {
647
+ "name": "PayInvoice",
648
+ "kind": "component",
649
+ "summary": "Pay one invoice from a link, with no account needed.",
650
+ "useWhen": "A page reached from a payment link or a QR code — a walk-up customer.",
651
+ "requires": [
652
+ "paymentAccount"
653
+ ],
654
+ "props": [
655
+ {
656
+ "name": "token",
657
+ "summary": "The link token, from the URL.",
658
+ "required": false
659
+ },
660
+ {
661
+ "name": "environmentId",
662
+ "summary": "Which environment the link belongs to.",
663
+ "required": false
664
+ },
665
+ {
666
+ "name": "onPaid",
667
+ "summary": "Called once payment succeeds.",
668
+ "required": false
669
+ },
670
+ {
671
+ "name": "className",
672
+ "summary": "Your own classes on the wrapper.",
673
+ "required": false
674
+ },
675
+ {
676
+ "name": "style",
677
+ "summary": "Inline styles on the wrapper.",
678
+ "required": false
679
+ }
680
+ ],
681
+ "seeAlso": [
682
+ "usePaymentLink"
683
+ ]
684
+ },
685
+ {
686
+ "name": "usePaymentLink",
687
+ "kind": "hook",
688
+ "summary": "Watches a payment link and reports when it is paid.",
689
+ "useWhen": "Showing your own waiting screen beside a QR code.",
690
+ "requires": [],
691
+ "props": [],
692
+ "seeAlso": [
693
+ "PayInvoice"
694
+ ]
695
+ },
696
+ {
697
+ "name": "ApiKeyManager",
698
+ "kind": "component",
699
+ "summary": "A customer managing their own API credentials and seeing their rate limits.",
700
+ "useWhen": "A developer-settings page inside your application.",
701
+ "requires": [
702
+ "session",
703
+ "apiResource"
704
+ ],
705
+ "props": [
706
+ {
707
+ "name": "audience",
708
+ "summary": "Limit to one protected API. All of them when omitted.",
709
+ "required": false
710
+ },
711
+ {
712
+ "name": "className",
713
+ "summary": "Your own classes on the wrapper.",
714
+ "required": false
715
+ },
716
+ {
717
+ "name": "style",
718
+ "summary": "Inline styles on the wrapper.",
719
+ "required": false
720
+ }
721
+ ],
722
+ "whenUnmet": "Renders nothing without a session; says so when no API resource is defined."
723
+ },
724
+ {
725
+ "name": "DataTable",
726
+ "kind": "component",
727
+ "summary": "A table of a collection's records, with columns derived from its fields.",
728
+ "useWhen": "Listing records. Reach for Kanban instead to group them by a status, or Chart to count or total them over time.",
729
+ "requires": [
730
+ "session",
731
+ "collection"
732
+ ],
733
+ "bindsToCollection": true,
734
+ "props": [
735
+ {
736
+ "name": "collection",
737
+ "summary": "The collection key. Required in practice.",
738
+ "required": false
739
+ },
740
+ {
741
+ "name": "columns",
742
+ "summary": "Which fields to show, in order. Every field when omitted.",
743
+ "required": false
744
+ },
745
+ {
746
+ "name": "renderCell",
747
+ "summary": "Replace the cell for one field.",
748
+ "required": false
749
+ },
750
+ {
751
+ "name": "onSelect",
752
+ "summary": "Row click. Rows are inert without it.",
753
+ "required": false
754
+ },
755
+ {
756
+ "name": "onChanged",
757
+ "summary": "Called after this table creates, edits or deletes a record. The table refreshes itself; use this to refresh anything else on the page bound to the same collection, such as a Chart.",
758
+ "required": false
759
+ },
760
+ {
761
+ "name": "hideSearch",
762
+ "summary": "Hide the search box.",
763
+ "required": false
764
+ },
765
+ {
766
+ "name": "readOnly",
767
+ "summary": "Hide New, Edit and Delete even for a writer.",
768
+ "required": false
769
+ },
770
+ {
771
+ "name": "emptyState",
772
+ "summary": "Shown when there is nothing to list.",
773
+ "required": false
774
+ },
775
+ {
776
+ "name": "className",
777
+ "summary": "Your own classes on the wrapper.",
778
+ "required": false
779
+ },
780
+ {
781
+ "name": "style",
782
+ "summary": "Inline styles on the wrapper.",
783
+ "required": false
784
+ }
785
+ ],
786
+ "whenUnmet": "Without the read permission it says which permission is missing, rather than showing an empty table.",
787
+ "seeAlso": [
788
+ "Kanban",
789
+ "Chart",
790
+ "RecordDetail",
791
+ "RecordForm",
792
+ "useCollection"
793
+ ]
794
+ },
795
+ {
796
+ "name": "Kanban",
797
+ "kind": "component",
798
+ "summary": "A board, grouped by a choice field it finds on its own.",
799
+ "useWhen": "The records move through stages — a status, a pipeline.",
800
+ "requires": [
801
+ "session",
802
+ "collection"
803
+ ],
804
+ "bindsToCollection": true,
805
+ "props": [
806
+ {
807
+ "name": "collection",
808
+ "summary": "The collection key. Required in practice.",
809
+ "required": false
810
+ },
811
+ {
812
+ "name": "groupBy",
813
+ "summary": "Which field makes the columns. Discovered when omitted.",
814
+ "required": false
815
+ },
816
+ {
817
+ "name": "cardFields",
818
+ "summary": "What to show on a card.",
819
+ "required": false
820
+ },
821
+ {
822
+ "name": "onSelect",
823
+ "summary": "Card click.",
824
+ "required": false
825
+ },
826
+ {
827
+ "name": "emptyState",
828
+ "summary": "Shown in a column with nothing in it.",
829
+ "required": false
830
+ },
831
+ {
832
+ "name": "className",
833
+ "summary": "Your own classes on the wrapper.",
834
+ "required": false
835
+ },
836
+ {
837
+ "name": "style",
838
+ "summary": "Inline styles on the wrapper.",
839
+ "required": false
840
+ }
841
+ ],
842
+ "whenUnmet": "A collection with no groupable field says to add a choice field, rather than drawing one column.",
843
+ "seeAlso": [
844
+ "DataTable",
845
+ "Chart"
846
+ ]
847
+ },
848
+ {
849
+ "name": "Chart",
850
+ "kind": "component",
851
+ "summary": "Records over time, counted or totalled.",
852
+ "useWhen": "The question is how many or how much, by day, week or month.",
853
+ "requires": [
854
+ "session",
855
+ "collection"
856
+ ],
857
+ "bindsToCollection": true,
858
+ "props": [
859
+ {
860
+ "name": "collection",
861
+ "summary": "The collection key. Required in practice.",
862
+ "required": false
863
+ },
864
+ {
865
+ "name": "x",
866
+ "summary": "The date field. Discovered when omitted.",
867
+ "required": false
868
+ },
869
+ {
870
+ "name": "y",
871
+ "summary": "What to measure. Counts the records when omitted.",
872
+ "required": false
873
+ },
874
+ {
875
+ "name": "aggregate",
876
+ "summary": "sum, avg, min or max. Defaults to sum.",
877
+ "required": false
878
+ },
879
+ {
880
+ "name": "bucket",
881
+ "summary": "day, week or month. Defaults to day.",
882
+ "required": false
883
+ },
884
+ {
885
+ "name": "title",
886
+ "summary": "Overrides the derived caption.",
887
+ "required": false
888
+ },
889
+ {
890
+ "name": "height",
891
+ "summary": "Plot height in pixels.",
892
+ "required": false
893
+ },
894
+ {
895
+ "name": "className",
896
+ "summary": "Your own classes on the wrapper.",
897
+ "required": false
898
+ },
899
+ {
900
+ "name": "style",
901
+ "summary": "Inline styles on the wrapper.",
902
+ "required": false
903
+ }
904
+ ],
905
+ "whenUnmet": "A collection with no date field says so. A field that cannot be summed is refused rather than quietly counted.",
906
+ "seeAlso": [
907
+ "DataTable",
908
+ "Kanban"
909
+ ]
910
+ },
911
+ {
912
+ "name": "RecordDetail",
913
+ "kind": "component",
914
+ "summary": "One record in full, including the fields a table truncates.",
915
+ "useWhen": "After a row or card is clicked.",
916
+ "requires": [
917
+ "session",
918
+ "collection"
919
+ ],
920
+ "bindsToCollection": true,
921
+ "props": [
922
+ {
923
+ "name": "collection",
924
+ "summary": "The collection key. Required in practice.",
925
+ "required": false
926
+ },
927
+ {
928
+ "name": "recordId",
929
+ "summary": "Which record. Required in practice.",
930
+ "required": false
931
+ },
932
+ {
933
+ "name": "tenant",
934
+ "summary": "Only when the user is in several.",
935
+ "required": false
936
+ },
937
+ {
938
+ "name": "readOnly",
939
+ "summary": "Hide Edit and Delete.",
940
+ "required": false
941
+ },
942
+ {
943
+ "name": "onDeleted",
944
+ "summary": "Called after deletion.",
945
+ "required": false
946
+ },
947
+ {
948
+ "name": "onClose",
949
+ "summary": "Renders a Close button when given.",
950
+ "required": false
951
+ },
952
+ {
953
+ "name": "children",
954
+ "summary": "Rendered under the fields.",
955
+ "required": false
956
+ },
957
+ {
958
+ "name": "className",
959
+ "summary": "Your own classes on the wrapper.",
960
+ "required": false
961
+ },
962
+ {
963
+ "name": "style",
964
+ "summary": "Inline styles on the wrapper.",
965
+ "required": false
966
+ }
967
+ ],
968
+ "seeAlso": [
969
+ "DataTable",
970
+ "RecordForm"
971
+ ]
972
+ },
973
+ {
974
+ "name": "RecordForm",
975
+ "kind": "component",
976
+ "summary": "Create or edit a record, with inputs derived from the field types.",
977
+ "useWhen": "Adding a record, or editing one outside the detail view.",
978
+ "requires": [
979
+ "session",
980
+ "collection"
981
+ ],
982
+ "bindsToCollection": true,
983
+ "props": [
984
+ {
985
+ "name": "collection",
986
+ "summary": "The collection key. Required in practice.",
987
+ "required": false
988
+ },
989
+ {
990
+ "name": "recordId",
991
+ "summary": "Omit to create, supply to edit.",
992
+ "required": false
993
+ },
994
+ {
995
+ "name": "tenant",
996
+ "summary": "Only when the user is in several.",
997
+ "required": false
998
+ },
999
+ {
1000
+ "name": "onSaved",
1001
+ "summary": "Called with the record id. Does not refresh a sibling table — see the composition rules.",
1002
+ "required": false
1003
+ },
1004
+ {
1005
+ "name": "onCancel",
1006
+ "summary": "Renders a Cancel button when given.",
1007
+ "required": false
1008
+ },
1009
+ {
1010
+ "name": "defaults",
1011
+ "summary": "Values to start with. Ignored when editing.",
1012
+ "required": false
1013
+ },
1014
+ {
1015
+ "name": "className",
1016
+ "summary": "Your own classes on the wrapper.",
1017
+ "required": false
1018
+ },
1019
+ {
1020
+ "name": "style",
1021
+ "summary": "Inline styles on the wrapper.",
1022
+ "required": false
1023
+ }
1024
+ ],
1025
+ "whenUnmet": "Computed fields get no input at all, because the server produces them.",
1026
+ "seeAlso": [
1027
+ "RecordDetail",
1028
+ "RelationPicker"
1029
+ ]
1030
+ },
1031
+ {
1032
+ "name": "RelationPicker",
1033
+ "kind": "component",
1034
+ "summary": "Choose a record in another collection by typing its name.",
1035
+ "useWhen": "Building your own form. RecordForm uses this for relation fields already.",
1036
+ "requires": [
1037
+ "session",
1038
+ "collection"
1039
+ ],
1040
+ "props": [
1041
+ {
1042
+ "name": "field",
1043
+ "summary": "The relation field descriptor.",
1044
+ "required": true
1045
+ },
1046
+ {
1047
+ "name": "value",
1048
+ "summary": "The chosen record id, or null.",
1049
+ "required": true
1050
+ },
1051
+ {
1052
+ "name": "onChange",
1053
+ "summary": "Called with the new id.",
1054
+ "required": true
1055
+ },
1056
+ {
1057
+ "name": "error",
1058
+ "summary": "Message shown under the input.",
1059
+ "required": false
1060
+ },
1061
+ {
1062
+ "name": "disabled",
1063
+ "summary": "Read-only.",
1064
+ "required": false
1065
+ },
1066
+ {
1067
+ "name": "tenant",
1068
+ "summary": "Only when the user is in several.",
1069
+ "required": false
1070
+ }
1071
+ ],
1072
+ "seeAlso": [
1073
+ "RecordForm"
1074
+ ]
1075
+ },
1076
+ {
1077
+ "name": "useCollection",
1078
+ "kind": "hook",
1079
+ "summary": "A collection's schema, records, filters, paging, permissions and writes — without markup.",
1080
+ "useWhen": "You want your own table, board or form but not your own data layer.",
1081
+ "requires": [
1082
+ "session",
1083
+ "collection"
1084
+ ],
1085
+ "bindsToCollection": true,
1086
+ "props": [],
1087
+ "seeAlso": [
1088
+ "DataTable",
1089
+ "FieldCell",
1090
+ "FieldInput"
1091
+ ]
1092
+ },
1093
+ {
1094
+ "name": "FieldCell",
1095
+ "kind": "component",
1096
+ "summary": "One field value, rendered the way the tables render it.",
1097
+ "useWhen": "Building your own table over useCollection.",
1098
+ "requires": [],
1099
+ "props": [
1100
+ {
1101
+ "name": "value",
1102
+ "summary": "The stored value.",
1103
+ "required": true
1104
+ },
1105
+ {
1106
+ "name": "field",
1107
+ "summary": "The field descriptor.",
1108
+ "required": true
1109
+ },
1110
+ {
1111
+ "name": "related",
1112
+ "summary": "A relation's resolved label.",
1113
+ "required": false
1114
+ }
1115
+ ],
1116
+ "seeAlso": [
1117
+ "FieldInput",
1118
+ "useCollection"
1119
+ ]
1120
+ },
1121
+ {
1122
+ "name": "FieldInput",
1123
+ "kind": "component",
1124
+ "summary": "The input for one field, chosen by its type.",
1125
+ "useWhen": "Building your own form over useCollection.",
1126
+ "requires": [],
1127
+ "props": [
1128
+ {
1129
+ "name": "value",
1130
+ "summary": "The current value.",
1131
+ "required": true
1132
+ },
1133
+ {
1134
+ "name": "field",
1135
+ "summary": "The field descriptor.",
1136
+ "required": true
1137
+ },
1138
+ {
1139
+ "name": "onChange",
1140
+ "summary": "Called with the new value.",
1141
+ "required": true
1142
+ },
1143
+ {
1144
+ "name": "error",
1145
+ "summary": "Message shown under the input.",
1146
+ "required": false
1147
+ },
1148
+ {
1149
+ "name": "disabled",
1150
+ "summary": "Read-only.",
1151
+ "required": false
1152
+ }
1153
+ ],
1154
+ "whenUnmet": "Renders nothing for a computed field — the server produces those.",
1155
+ "seeAlso": [
1156
+ "FieldCell",
1157
+ "RecordForm"
1158
+ ]
1159
+ }
1160
+ ]
1161
+ }