@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
@@ -1 +1 @@
1
- {"version":3,"file":"SignUp.d.ts","sourceRoot":"","sources":["../../src/SignUp.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAKrE;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,EACtB,UAAU,EACV,SAAS,EACT,KAAK,GACL,EAAE;IACF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAqFA"}
1
+ {"version":3,"file":"SignUp.d.ts","sourceRoot":"","sources":["../../src/SignUp.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAKrE;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,EACtB,UAAU,EACV,SAAS,EACT,KAAK,GACL,EAAE;IACF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAyFA"}
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionManager.d.ts","sourceRoot":"","sources":["../../src/SubscriptionManager.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAU7E;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,SAAS,EACT,KAAK,GACL,EAAE;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAmGA"}
1
+ {"version":3,"file":"SubscriptionManager.d.ts","sourceRoot":"","sources":["../../src/SubscriptionManager.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAU7E;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,SAAS,EACT,KAAK,GACL,EAAE;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BA2HA"}
@@ -0,0 +1,49 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * Who is in a team, who has been invited, and the way in and out.
4
+ *
5
+ * One component rather than four, because these are one screen everywhere they
6
+ * appear: a list of people, a list of people who have not arrived yet, a box to
7
+ * add another, and a way to leave. Splitting them would make the common case —
8
+ * a Team settings page — four imports and some layout, which is exactly the
9
+ * assembly work the catalogue exists to remove.
10
+ *
11
+ * What it offers depends on what the viewer may do, and that is the server's
12
+ * answer rather than this component's guess: inviting and removing are gated on
13
+ * a permission the customer's own roles grant, so a member who cannot manage
14
+ * the team simply is not shown those controls.
15
+ *
16
+ * Sending the invitation email is the application's job. The token comes back
17
+ * once from the API and is never recoverable, so `onInvited` is where it goes —
18
+ * without a handler, the link is shown on screen to be copied, which is honest
19
+ * rather than silently losing it.
20
+ */
21
+ export interface TeamMembersProps {
22
+ /**
23
+ * Which team. Defaults to the only one this person is in.
24
+ *
25
+ * Left out with several, the component says which is which rather than
26
+ * guessing — picking one at random is how somebody invites a colleague into
27
+ * the wrong company.
28
+ */
29
+ organizationId?: string;
30
+ /**
31
+ * Called with the invitation link after inviting.
32
+ *
33
+ * Where an application sends the email. Without it the link is shown on
34
+ * screen instead, because the token is returned once and cannot be fetched
35
+ * again.
36
+ */
37
+ onInvited?: (invitation: {
38
+ email: string;
39
+ token: string;
40
+ url?: string;
41
+ }) => void;
42
+ /** Where an invitation link should point. Used to build the URL for `onInvited`. */
43
+ acceptUrl?: string;
44
+ onLeft?: () => void;
45
+ className?: string;
46
+ style?: CSSProperties;
47
+ }
48
+ export declare function TeamMembers({ organizationId, onInvited, acceptUrl, onLeft, className, style, }: TeamMembersProps): import("react").JSX.Element | null;
49
+ //# sourceMappingURL=TeamMembers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TeamMembers.d.ts","sourceRoot":"","sources":["../../src/TeamMembers.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAM7E;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,gBAAgB;IAChC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACjF,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,wBAAgB,WAAW,CAAC,EAC3B,cAAc,EACd,SAAS,EACT,SAAS,EACT,MAAM,EACN,SAAS,EACT,KAAK,GACL,EAAE,gBAAgB,sCA+PlB"}
@@ -0,0 +1,29 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * Turning on two-factor authentication.
4
+ *
5
+ * Two ways in: an authenticator app, and a code to the inbox. The app is the
6
+ * stronger of the two and is offered first, but the email option is the one
7
+ * people who will not install anything actually use — and a factor somebody
8
+ * turns on beats a stronger one they decline.
9
+ *
10
+ * Three steps, kept separate because the middle one is what stops people
11
+ * locking themselves out: enrolling produces a secret that is useless until a
12
+ * code proves the app actually holds it. Activating on enrolment would mean a
13
+ * QR code that failed to scan leaves somebody unable to sign in, with no way
14
+ * back.
15
+ *
16
+ * The recovery codes are shown once. They are password equivalents, so nothing
17
+ * stores them anywhere they can be read back — which makes "I have saved these"
18
+ * a real step rather than a formality, and the dialog says so.
19
+ */
20
+ export interface TwoFactorManagerProps {
21
+ /** Whether this account already has a factor. Drives which side is shown. */
22
+ enabled?: boolean;
23
+ onEnabled?: () => void;
24
+ onDisabled?: () => void;
25
+ className?: string;
26
+ style?: CSSProperties;
27
+ }
28
+ export declare function TwoFactorManager({ enabled, onEnabled, onDisabled, className, style, }: TwoFactorManagerProps): import("react").JSX.Element | null;
29
+ //# sourceMappingURL=TwoFactorManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TwoFactorManager.d.ts","sourceRoot":"","sources":["../../src/TwoFactorManager.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAMrD;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,qBAAqB;IACrC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AASD,wBAAgB,gBAAgB,CAAC,EAChC,OAAe,EACf,SAAS,EACT,UAAU,EACV,SAAS,EACT,KAAK,GACL,EAAE,qBAAqB,sCAmOvB"}
@@ -0,0 +1,24 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * Confirming an address from an emailed link.
4
+ *
5
+ * The whole component is one effect: read `?token=`, spend it, say what
6
+ * happened. Two details carry it.
7
+ *
8
+ * The token is removed from the URL before it is spent, so it does not sit in
9
+ * browser history or leak through a referrer. And the effect runs exactly once
10
+ * — the token is single-use, so a re-run in development's double-invoked
11
+ * effects would spend it and then report that it was invalid, which looks like
12
+ * a broken link to everybody who sees it.
13
+ */
14
+ export interface VerifyEmailProps {
15
+ /** Supply the token directly. Read from `?token=` when omitted. */
16
+ token?: string;
17
+ onVerified?: () => void;
18
+ /** Where to go next. Rendered as a link when given. */
19
+ continueUrl?: string;
20
+ className?: string;
21
+ style?: CSSProperties;
22
+ }
23
+ export declare function VerifyEmail({ token: supplied, onVerified, continueUrl, className, style, }: VerifyEmailProps): import("react").JSX.Element;
24
+ //# sourceMappingURL=VerifyEmail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VerifyEmail.d.ts","sourceRoot":"","sources":["../../src/VerifyEmail.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAKxE;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,gBAAgB;IAChC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAID,wBAAgB,WAAW,CAAC,EAC3B,KAAK,EAAE,QAAQ,EACf,UAAU,EACV,WAAW,EACX,SAAS,EACT,KAAK,GACL,EAAE,gBAAgB,+BAiFlB"}
@@ -50,7 +50,7 @@ export declare const STYLE_ELEMENT_ID = "base316-components";
50
50
  * never sets a token still gets a coherent look, and one that sets tokens on a
51
51
  * parent still wins through normal inheritance.
52
52
  */
53
- export declare const STYLESHEET = "\n.b316-root {\n --b316-color-primary: #111827;\n --b316-color-primary-text: #ffffff;\n --b316-color-text: #111827;\n --b316-color-muted: #6b7280;\n --b316-color-background: #ffffff;\n --b316-color-border: #e5e7eb;\n --b316-color-danger: #991b1b;\n --b316-color-danger-bg: #fef2f2;\n --b316-color-success: #166534;\n --b316-radius: 12px;\n --b316-font: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n --b316-font-size: 15px;\n --b316-spacing: 12px;\n\n font-family: var(--b316-font);\n font-size: var(--b316-font-size);\n line-height: 1.5;\n color: var(--b316-color-text);\n}\n\n.b316-card {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n padding: calc(var(--b316-spacing) * 1.6);\n background: var(--b316-color-background);\n}\n\n.b316-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--b316-spacing); }\n.b316-label { font-size: 0.87em; color: var(--b316-color-muted); }\n\n.b316-input {\n padding: 9px 11px;\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) / 1.6);\n font: inherit;\n color: inherit;\n background: var(--b316-color-background);\n}\n.b316-input:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n\n.b316-button {\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.b316-button:hover:not([disabled]) { filter: brightness(1.12); }\n.b316-button:active:not([disabled]) { transform: translateY(1px); }\n.b316-button:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n.b316-button[disabled] { opacity: .55; cursor: not-allowed; }\n\n.b316-button-secondary {\n width: auto;\n transition: background-color .12s ease;\n background: var(--b316-color-background);\n color: var(--b316-color-text);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n}\n\n.b316-button-link {\n width: auto;\n background: none;\n border: 0;\n padding: 0;\n color: var(--b316-color-primary);\n font: inherit;\n cursor: pointer;\n text-decoration: underline;\n}\n\n.b316-error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-muted { color: var(--b316-color-muted); font-size: 0.87em; }\n.b316-success { color: var(--b316-color-success); }\n\n.b316-plans {\n display: grid;\n gap: calc(var(--b316-spacing) * 1.3);\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n align-items: stretch;\n}\n\n.b316-plan {\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n}\n\n/* The recommended plan. Lifted rather than merely tinted: on a pricing table\n the eye needs one obvious default, and colour alone does not survive being\n viewed in greyscale or by someone who cannot distinguish the accent. */\n.b316-plan-featured {\n border-color: var(--b316-color-primary);\n box-shadow: 0 0 0 1px var(--b316-color-primary);\n}\n\n.b316-plan-badge {\n display: inline-block;\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n border-radius: 999px;\n padding: 2px 9px;\n font-size: 0.75em;\n font-weight: 600;\n letter-spacing: .02em;\n margin-bottom: 8px;\n}\n\n/* Occupies the badge's height without drawing anything, so a featured card\n does not push its own price and features out of line with the others. */\n.b316-plan-badge-spacer {\n display: inline-block;\n padding: 2px 9px;\n font-size: 0.75em;\n margin-bottom: 8px;\n visibility: hidden;\n}\n\n.b316-plan-head { padding: calc(var(--b316-spacing) * 1.6); padding-bottom: 0; }\n.b316-plan-name { font-weight: 600; font-size: 1.06em; }\n.b316-plan-desc { color: var(--b316-color-muted); font-size: 0.87em; margin-top: 2px; }\n\n.b316-plan-pricing { padding: 0 calc(var(--b316-spacing) * 1.6) calc(var(--b316-spacing) * 1.4); }\n\n.b316-plan-price {\n font-size: 2.1em;\n font-weight: 640;\n letter-spacing: -.02em;\n margin-top: calc(var(--b316-spacing) * 0.7);\n /* Lining figures of even width, so prices do not shimmer between cards. */\n font-variant-numeric: tabular-nums lining-nums;\n}\n\n.b316-plan-cadence { color: var(--b316-color-muted); font-size: 0.87em; min-height: 1.35em; }\n.b316-plan-trial { color: var(--b316-color-success); font-size: 0.87em; min-height: 1.35em; }\n\n.b316-plan-features {\n list-style: none;\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n margin: 0;\n flex: 1;\n border-top: 1px solid var(--b316-color-border);\n}\n.b316-plan-feature {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding: 5px 0;\n font-size: 0.94em;\n}\n.b316-plan-feature-value { color: var(--b316-color-muted); font-variant-numeric: tabular-nums; }\n\n.b316-plan-action {\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n border-top: 1px solid var(--b316-color-border);\n}\n\n/* The plan already held. A faded primary button reads as broken rather than\n as \"you are here\", so this is a flat, quiet, genuinely inert surface. */\n.b316-button-current,\n.b316-button-current[disabled] {\n background: transparent;\n color: var(--b316-color-muted);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n opacity: 1;\n cursor: default;\n}\n\n.b316-row { display: flex; justify-content: space-between; gap: 16px; align-items: center; }\n";
53
+ export declare const STYLESHEET = "\n.b316-root {\n --b316-color-primary: #111827;\n --b316-color-primary-text: #ffffff;\n --b316-color-text: #111827;\n --b316-color-muted: #6b7280;\n --b316-color-background: #ffffff;\n --b316-color-border: #e5e7eb;\n --b316-color-danger: #991b1b;\n --b316-color-danger-bg: #fef2f2;\n --b316-color-success: #166534;\n --b316-radius: 12px;\n --b316-font: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n --b316-font-size: 15px;\n --b316-spacing: 12px;\n\n font-family: var(--b316-font);\n font-size: var(--b316-font-size);\n line-height: 1.5;\n color: var(--b316-color-text);\n}\n\n.b316-card {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n padding: calc(var(--b316-spacing) * 1.6);\n background: var(--b316-color-background);\n}\n\n.b316-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--b316-spacing); }\n.b316-label { font-size: 0.87em; color: var(--b316-color-muted); }\n\n.b316-input {\n padding: 9px 11px;\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) / 1.6);\n font: inherit;\n color: inherit;\n background: var(--b316-color-background);\n}\n.b316-input:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n\n.b316-button {\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.b316-button:hover:not([disabled]) { filter: brightness(1.12); }\n.b316-button:active:not([disabled]) { transform: translateY(1px); }\n.b316-button:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n.b316-button[disabled] { opacity: .55; cursor: not-allowed; }\n\n.b316-button-secondary {\n width: auto;\n transition: background-color .12s ease;\n background: var(--b316-color-background);\n color: var(--b316-color-text);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n}\n\n.b316-button-link {\n width: auto;\n background: none;\n border: 0;\n padding: 0;\n color: var(--b316-color-primary);\n font: inherit;\n cursor: pointer;\n text-decoration: underline;\n}\n\n/*\n * An armed confirmation: the question and its way out, side by side.\n *\n * Inline rather than a dialog, because a sandboxed iframe does not get dialogs\n * and these components are meant to be embedded in one.\n */\n.b316-confirm {\n display: inline-flex;\n gap: .4rem;\n align-items: center;\n}\n\n.b316-error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-muted { color: var(--b316-color-muted); font-size: 0.87em; }\n.b316-success { color: var(--b316-color-success); }\n\n.b316-plans {\n display: grid;\n gap: calc(var(--b316-spacing) * 1.3);\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n align-items: stretch;\n}\n\n.b316-plan {\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n}\n\n/* The recommended plan. Lifted rather than merely tinted: on a pricing table\n the eye needs one obvious default, and colour alone does not survive being\n viewed in greyscale or by someone who cannot distinguish the accent. */\n.b316-plan-featured {\n border-color: var(--b316-color-primary);\n box-shadow: 0 0 0 1px var(--b316-color-primary);\n}\n\n.b316-plan-badge {\n display: inline-block;\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n border-radius: 999px;\n padding: 2px 9px;\n font-size: 0.75em;\n font-weight: 600;\n letter-spacing: .02em;\n margin-bottom: 8px;\n}\n\n/* Occupies the badge's height without drawing anything, so a featured card\n does not push its own price and features out of line with the others. */\n.b316-plan-badge-spacer {\n display: inline-block;\n padding: 2px 9px;\n font-size: 0.75em;\n margin-bottom: 8px;\n visibility: hidden;\n}\n\n.b316-plan-head { padding: calc(var(--b316-spacing) * 1.6); padding-bottom: 0; }\n.b316-plan-name { font-weight: 600; font-size: 1.06em; }\n.b316-plan-desc { color: var(--b316-color-muted); font-size: 0.87em; margin-top: 2px; }\n\n.b316-plan-pricing { padding: 0 calc(var(--b316-spacing) * 1.6) calc(var(--b316-spacing) * 1.4); }\n\n.b316-plan-price {\n font-size: 2.1em;\n font-weight: 640;\n letter-spacing: -.02em;\n margin-top: calc(var(--b316-spacing) * 0.7);\n /* Lining figures of even width, so prices do not shimmer between cards. */\n font-variant-numeric: tabular-nums lining-nums;\n}\n\n.b316-plan-cadence { color: var(--b316-color-muted); font-size: 0.87em; min-height: 1.35em; }\n.b316-plan-trial { color: var(--b316-color-success); font-size: 0.87em; min-height: 1.35em; }\n\n.b316-plan-features {\n list-style: none;\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n margin: 0;\n flex: 1;\n border-top: 1px solid var(--b316-color-border);\n}\n.b316-plan-feature {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding: 5px 0;\n font-size: 0.94em;\n}\n.b316-plan-feature-value { color: var(--b316-color-muted); font-variant-numeric: tabular-nums; }\n\n.b316-plan-action {\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n border-top: 1px solid var(--b316-color-border);\n}\n\n/* The plan already held. A faded primary button reads as broken rather than\n as \"you are here\", so this is a flat, quiet, genuinely inert surface. */\n.b316-button-current,\n.b316-button-current[disabled] {\n background: transparent;\n color: var(--b316-color-muted);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n opacity: 1;\n cursor: default;\n}\n\n.b316-row { display: flex; justify-content: space-between; gap: 16px; align-items: center; }\n\n/* Credential lists. A row is a thing plus the actions on it, and the actions\n stay put as names vary in length, so the eye tracks one column not two. */\n.b316-list { list-style: none; margin: 0; padding: 0; }\n\n.b316-list-item {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n padding: 12px 0;\n border-top: 1px solid var(--b316-color-border);\n}\n\n.b316-list-item:first-child { border-top: none; }\n\n/* Carries a secret shown exactly once, so it has to read as different from the\n rest of the card rather than as another paragraph. */\n.b316-notice {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n background: var(--b316-color-subtle, rgba(0,0,0,0.03));\n padding: 12px;\n font-size: 0.93em;\n}\n\n.b316-checkbox {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 4px 0;\n cursor: pointer;\n}\n\n.b316-checkbox input[disabled] { cursor: default; }\n.b316-checkbox.b316-muted { cursor: default; }\n";
54
54
  /** Join the component's own class with any the host passed in. */
55
55
  export declare function cls(base: string, extra?: string): string;
56
56
  /**
@@ -59,5 +59,5 @@ export declare function cls(base: string, extra?: string): string;
59
59
  * Appended as a second block so the print rules stay next to the invoice they
60
60
  * apply to, rather than being buried in the middle of the component styles.
61
61
  */
62
- export declare const STYLESHEET_EXTRA = "\n.b316-branding { display: flex; flex-direction: column; gap: 4px; }\n.b316-branding-logo { max-height: 40px; width: auto; align-self: flex-start; }\n.b316-branding-name { font-size: 1.5em; font-weight: 650; letter-spacing: -.01em; }\n.b316-branding-tagline { color: var(--b316-color-muted); }\n\n.b316-invoice-table { width: 100%; border-collapse: collapse; font-size: 0.94em; }\n.b316-invoice-table th {\n text-align: left;\n font-weight: 500;\n color: var(--b316-color-muted);\n font-size: 0.85em;\n padding: 0 0 6px;\n border-bottom: 1px solid var(--b316-color-border);\n}\n.b316-invoice-table td { padding: 9px 0; border-bottom: 1px solid var(--b316-color-border); }\n/* Columns need breathing room or the amount runs straight into the action \u2014\n \"$49.00View\" \u2014 which is what happens when only the row has padding. */\n.b316-invoice-table th + th,\n.b316-invoice-table td + td { padding-left: 16px; }\n.b316-invoice-table td:last-child,\n.b316-invoice-table th:last-child { text-align: right; width: 1%; white-space: nowrap; }\n.b316-invoice-table tr:last-child td { border-bottom: 0; }\n.b316-num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.b316-invoice-view {\n margin-top: calc(var(--b316-spacing) * 1.4);\n border-top: 1px solid var(--b316-color-border);\n padding-top: calc(var(--b316-spacing) * 1.4);\n}\n.b316-invoice-actions { display: flex; gap: 8px; justify-content: flex-end; margin-bottom: var(--b316-spacing); }\n.b316-invoice-doc { display: flex; flex-direction: column; gap: calc(var(--b316-spacing) * 1.4); }\n.b316-invoice-meta { display: grid; grid-template-columns: 1fr 1fr; gap: var(--b316-spacing); }\n.b316-invoice-totals { display: flex; flex-direction: column; gap: 6px; margin-left: auto; min-width: 240px; }\n.b316-invoice-total { font-weight: 650; border-top: 1px solid var(--b316-color-border); padding-top: 6px; }\n\n/* Printing emits the invoice alone. Without this the browser would paginate the\n whole application around it, which is not something anyone wants to file. */\n@media print {\n body * { visibility: hidden; }\n .b316-invoice-doc, .b316-invoice-doc * { visibility: visible; }\n .b316-invoice-doc {\n position: absolute;\n inset: 0 auto auto 0;\n width: 100%;\n padding: 24px;\n }\n .b316-invoice-actions { display: none; }\n}\n";
62
+ export declare const STYLESHEET_EXTRA = "\n.b316-pay__element { margin-bottom: var(--b316-spacing); min-height: 40px; }\n\n.b316-pay__submit {\n width: 100%;\n padding: 11px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: #fff;\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n\n.b316-pay__submit[disabled] { opacity: 0.55; cursor: progress; }\n\n.b316-pay__error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-pay__done {\n background: var(--b316-color-success-bg, #f0fdf4);\n color: var(--b316-color-success);\n padding: 12px 14px;\n border-radius: calc(var(--b316-radius) / 2);\n text-align: center;\n margin: 0;\n}\n\n.b316-tabs { display: flex; gap: 4px; margin-bottom: 16px; border-bottom: 1px solid var(--b316-color-border); }\n.b316-tab {\n flex: 1; padding: 8px 4px; background: none; border: 0; cursor: pointer;\n font: inherit; font-size: .95em; color: var(--b316-color-muted);\n border-bottom: 2px solid transparent; margin-bottom: -1px;\n}\n.b316-tab-on { color: var(--b316-color-text); border-bottom-color: var(--b316-color-primary); }\n.b316-branding { display: flex; flex-direction: column; gap: 4px; }\n.b316-branding-logo { max-height: 40px; width: auto; align-self: flex-start; }\n.b316-branding-name { font-size: 1.5em; font-weight: 650; letter-spacing: -.01em; }\n.b316-branding-tagline { color: var(--b316-color-muted); }\n\n.b316-invoice-table { width: 100%; border-collapse: collapse; font-size: 0.94em; }\n.b316-invoice-table th {\n text-align: left;\n font-weight: 500;\n color: var(--b316-color-muted);\n font-size: 0.85em;\n padding: 0 0 6px;\n border-bottom: 1px solid var(--b316-color-border);\n}\n.b316-invoice-table td { padding: 9px 0; border-bottom: 1px solid var(--b316-color-border); }\n/* Columns need breathing room or the amount runs straight into the action \u2014\n \"$49.00View\" \u2014 which is what happens when only the row has padding. */\n.b316-invoice-table th + th,\n.b316-invoice-table td + td { padding-left: 16px; }\n.b316-invoice-table td:last-child,\n.b316-invoice-table th:last-child { text-align: right; width: 1%; white-space: nowrap; }\n.b316-invoice-table tr:last-child td { border-bottom: 0; }\n.b316-num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.b316-invoice-view {\n margin-top: calc(var(--b316-spacing) * 1.4);\n border-top: 1px solid var(--b316-color-border);\n padding-top: calc(var(--b316-spacing) * 1.4);\n}\n.b316-invoice-actions { display: flex; gap: 8px; justify-content: flex-end; margin-bottom: var(--b316-spacing); }\n.b316-invoice-doc { display: flex; flex-direction: column; gap: calc(var(--b316-spacing) * 1.4); }\n.b316-invoice-meta { display: grid; grid-template-columns: 1fr 1fr; gap: var(--b316-spacing); }\n.b316-invoice-totals { display: flex; flex-direction: column; gap: 6px; margin-left: auto; min-width: 240px; }\n.b316-invoice-total { font-weight: 650; border-top: 1px solid var(--b316-color-border); padding-top: 6px; }\n\n/* Printing an invoice emits the invoice alone, and printing anything else is\n none of this package's business.\n\n This used to start with a bare \"body * { visibility: hidden }\", which is the\n usual recipe for printing one element \u2014 and it is scoped to the document,\n not to us. The stylesheet is injected into the host page's head the first\n time any Base316 component mounts, so from that moment every print in the\n host application came out blank unless the content happened to sit inside\n .b316-invoice-doc. A customer printing their own page had no way to connect\n it back to us.\n\n Scoped to a root the invoice sets on <html> while it is being printed\n instead, so nothing applies unless an invoice asked for it. */\n@media print {\n [data-b316-printing] body * { visibility: hidden; }\n [data-b316-printing] .b316-invoice-doc,\n [data-b316-printing] .b316-invoice-doc * { visibility: visible; }\n [data-b316-printing] .b316-invoice-doc {\n position: absolute;\n inset: 0 auto auto 0;\n width: 100%;\n padding: 24px;\n }\n .b316-invoice-actions { display: none; }\n}\n\n/* --- Collections: tables, forms and detail views ------------------------- */\n\n.b316-table-wrap { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-table-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); flex-wrap: wrap; }\n.b316-table-actions { display: flex; align-items: center; gap: var(--b316-spacing); }\n\n/* The table scrolls inside its own box rather than pushing the page sideways:\n a collection with twenty fields is normal, and a horizontally scrolling page\n makes every other component on it unreachable. */\n.b316-table-scroll { overflow-x: auto; border: 1px solid var(--b316-color-border); border-radius: var(--b316-radius); }\n.b316-table { width: 100%; border-collapse: collapse; font-size: 0.95em; }\n.b316-table th, .b316-table td { padding: 10px 12px; text-align: left; vertical-align: top; white-space: nowrap; }\n.b316-table thead th { background: var(--b316-color-surface-muted, rgba(0,0,0,.03)); font-weight: 600; font-size: 0.87em; color: var(--b316-color-muted); border-bottom: 1px solid var(--b316-color-border); }\n.b316-table tbody tr + tr td { border-top: 1px solid var(--b316-color-border); }\n.b316-row-clickable { cursor: pointer; }\n.b316-row-clickable:hover td { background: var(--b316-color-surface-muted, rgba(0,0,0,.02)); }\n.b316-table-rowactions { text-align: right; white-space: nowrap; }\n.b316-table-more { display: flex; justify-content: center; }\n\n.b316-sort { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }\n.b316-sort:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n\n.b316-empty { padding: calc(var(--b316-spacing) * 2); text-align: center; color: var(--b316-color-muted); }\n\n.b316-button-quiet {\n background: none;\n border: 0;\n padding: 4px 6px;\n font: inherit;\n font-size: 0.9em;\n color: var(--b316-color-primary);\n cursor: pointer;\n border-radius: calc(var(--b316-radius) / 2);\n}\n.b316-button-quiet:hover:not([disabled]) { background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); }\n.b316-button-quiet:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n.b316-button-quiet[disabled] { opacity: .55; cursor: not-allowed; }\n.b316-danger { color: var(--b316-color-danger, #b42318); }\n\n.b316-chip {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 999px;\n background: var(--b316-color-surface-muted, rgba(0,0,0,.05));\n font-size: 0.87em;\n}\n.b316-chips { display: inline-flex; gap: 4px; flex-wrap: wrap; }\n\n.b316-form { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-form-title { margin: 0; font-size: 1.05em; }\n.b316-form-actions { display: flex; justify-content: flex-end; gap: 8px; }\n.b316-field { display: flex; flex-direction: column; gap: 4px; }\n.b316-hint { font-size: 0.82em; color: var(--b316-color-muted); }\n.b316-input-invalid { border-color: var(--b316-color-danger, #b42318); }\n.b316-choices { display: flex; flex-wrap: wrap; gap: 10px; }\n.b316-choice { display: inline-flex; align-items: center; gap: 6px; font-size: 0.95em; }\n.b316-suffixed { display: flex; align-items: center; gap: 8px; }\n.b316-address { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }\n\n.b316-relation-chosen { display: flex; align-items: center; gap: 8px; }\n.b316-relation-results {\n list-style: none;\n margin: 4px 0 0;\n padding: 4px;\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n max-height: 220px;\n overflow-y: auto;\n background: var(--b316-color-surface, #fff);\n}\n.b316-relation-result { display: block; width: 100%; text-align: left; background: none; border: 0; padding: 6px 8px; font: inherit; cursor: pointer; border-radius: calc(var(--b316-radius) / 2); }\n.b316-relation-result:hover, .b316-relation-result:focus-visible { background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); outline: none; }\n.b316-relation-empty { padding: 6px 8px; }\n\n.b316-detail { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-detail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--b316-spacing); }\n.b316-detail-title { margin: 0; font-size: 1.1em; }\n.b316-detail-actions { display: flex; gap: 4px; }\n.b316-detail-fields { display: grid; grid-template-columns: minmax(120px, 200px) 1fr; gap: 8px var(--b316-spacing); margin: 0; }\n.b316-detail-row { display: contents; }\n.b316-detail-fields dd { margin: 0; }\n\n/* One column on a narrow screen. A label column of 200px beside a value leaves\n nothing for the value on a phone. */\n/* --- Teams --------------------------------------------------------------- */\n\n.b316-team { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-team-title { margin: 0; font-size: 1em; font-weight: 600; }\n.b316-team-subtitle { margin: 0; font-size: .9em; font-weight: 600; color: var(--b316-color-muted); }\n.b316-team-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }\n.b316-team-member { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); }\n.b316-team-member-side { display: flex; align-items: center; gap: 8px; }\n.b316-team-invite { display: flex; flex-direction: column; gap: 4px; }\n.b316-team-invite-row { display: flex; gap: 8px; }\n.b316-team-invite-row input { flex: 1; }\n/* Selectable and wrapping: this is copied by hand and pasted into an email. */\n.b316-team-link { display: flex; flex-direction: column; gap: 4px; }\n.b316-team-link code { word-break: break-all; user-select: all; padding: 8px; border: 1px solid var(--b316-color-border); border-radius: var(--b316-radius); }\n\n.b316-invitation { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-invitation-actions { display: flex; align-items: center; gap: var(--b316-spacing); }\n\n/* --- Sessions, two-factor and the password flows ------------------------- */\n\n.b316-sessions { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-sessions-head { display: flex; align-items: center; justify-content: space-between; gap: var(--b316-spacing); flex-wrap: wrap; }\n.b316-sessions-title, .b316-mfa-title { margin: 0; font-size: 1em; font-weight: 600; }\n.b316-sessions-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }\n.b316-session { display: flex; flex-direction: column; gap: 2px; }\n.b316-session-device { display: flex; align-items: center; gap: 6px; font-size: 0.95em; }\n\n.b316-device { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-device-title { margin: 0; font-size: 1em; font-weight: 600; }\n/* What is being granted, listed rather than run together: somebody is deciding\n on this, and a comma-separated line is read as one thing. */\n.b316-device-scopes { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }\n.b316-device-scopes li { padding: 2px 8px; border-radius: 999px; font-size: 0.85em; background: var(--b316-color-surface-muted, rgba(0,0,0,.05)); }\n.b316-device-actions { display: flex; gap: 8px; }\n\n.b316-privacy { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-privacy-title { margin: 0; font-size: 1em; font-weight: 600; }\n/* Wraps rather than squeezes: the explanation beside each control is the part\n that matters, and on a narrow screen it belongs above the button. */\n.b316-privacy-row { display: flex; flex-wrap: wrap; align-items: start; justify-content: space-between; gap: 10px; }\n.b316-privacy-row p { margin: 0; }\n.b316-privacy-confirm { display: flex; flex-direction: column; gap: 8px; }\n.b316-privacy-actions { display: flex; justify-content: flex-end; gap: 8px; }\n\n.b316-mfa { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-mfa-enrol, .b316-mfa-codes, .b316-mfa-on, .b316-mfa-off { display: flex; flex-direction: column; gap: 10px; }\n.b316-mfa-actions { display: flex; justify-content: flex-end; gap: 8px; }\n/* Selectable and wrapping: this is copied by hand on the device that cannot\n scan its own screen. */\n.b316-mfa-secret code {\n display: block;\n padding: 10px;\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n font-size: 1.05em;\n letter-spacing: .08em;\n word-break: break-all;\n user-select: all;\n}\n.b316-mfa-uri { font-size: 0.9em; }\n.b316-mfa-code-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }\n.b316-mfa-code-list code { user-select: all; }\n\n@media (max-width: 560px) {\n .b316-mfa-code-list { grid-template-columns: 1fr; }\n .b316-detail-fields { grid-template-columns: 1fr; }\n .b316-detail-row { display: block; margin-bottom: 10px; }\n .b316-address { grid-template-columns: 1fr; }\n}\n\n/* --- Board --------------------------------------------------------------- */\n\n.b316-board-wrap { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n/* The board scrolls sideways inside itself. Six columns is normal and a page\n that scrolls horizontally puts everything else on it out of reach. */\n.b316-board { display: flex; gap: var(--b316-spacing); overflow-x: auto; align-items: flex-start; padding-bottom: 4px; }\n.b316-board-column {\n flex: 0 0 260px;\n background: var(--b316-color-surface-muted, rgba(0,0,0,.03));\n border: 1px solid transparent;\n border-radius: var(--b316-radius);\n padding: 10px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.b316-board-over { border-color: var(--b316-color-primary); }\n.b316-board-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n.b316-board-title { font-weight: 600; font-size: 0.92em; }\n.b316-board-cards { display: flex; flex-direction: column; gap: 8px; min-height: 40px; }\n.b316-board-card {\n background: var(--b316-color-surface, #fff);\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) * .8);\n padding: 10px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n font-size: 0.9em;\n}\n.b316-board-card[draggable=\"true\"] { cursor: grab; }\n.b316-board-card-title { font-weight: 600; }\n.b316-board-card-field { display: flex; justify-content: space-between; gap: 8px; }\n.b316-board-move { display: flex; align-items: center; gap: 6px; margin-top: 2px; }\n.b316-board-move select { flex: 1; font-size: 0.9em; padding: 2px 4px; }\n.b316-board-empty { color: var(--b316-color-muted); font-size: 0.87em; padding: 6px 2px; }\n\n/* --- Chart --------------------------------------------------------------- */\n\n.b316-chart { display: flex; flex-direction: column; gap: var(--b316-spacing); }\n.b316-chart-title { font-weight: 600; font-size: 0.95em; }\n.b316-chart-plot { display: flex; align-items: flex-end; gap: 4px; overflow-x: auto; }\n.b316-chart-col { flex: 1 0 24px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; gap: 4px; }\n.b316-chart-bar { width: 100%; background: var(--b316-color-primary); border-radius: 3px 3px 0 0; min-height: 2px; }\n.b316-chart-label { font-size: 0.7em; color: var(--b316-color-muted); white-space: nowrap; transform: rotate(-45deg); transform-origin: top left; height: 1.6em; }\n.b316-chart-data summary { cursor: pointer; font-size: 0.87em; color: var(--b316-color-muted); }\n.b316-chart-data table { margin-top: 8px; }\n";
63
63
  //# sourceMappingURL=appearance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"appearance.d.ts","sourceRoot":"","sources":["../../src/appearance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,iBAAiB;IACjC,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAkBD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAgB/E;AAED,eAAO,MAAM,gBAAgB,uBAAuB,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,6lLA0LtB,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,wyEAiD5B,CAAC"}
1
+ {"version":3,"file":"appearance.d.ts","sourceRoot":"","sources":["../../src/appearance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,iBAAiB;IACjC,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAkBD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAgB/E;AAED,eAAO,MAAM,gBAAgB,uBAAuB,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,o5NA0OtB,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,+gfAgT5B,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * Asking "are you sure" without `window.confirm`.
4
+ *
5
+ * These components are embedded in the customer's own page, and a page that
6
+ * embeds them in a sandboxed iframe — which is the recommended way to embed
7
+ * anything — does not get modal dialogs unless `allow-modals` is set. Chrome
8
+ * and Firefox both block the call and return `false`.
9
+ *
10
+ * So `window.confirm` in this package was not a confirmation. It was a silent
11
+ * no: somebody clicked Revoke, the browser suppressed the dialog, the function
12
+ * returned false, and the component did nothing at all. No error, no dialog,
13
+ * nothing — the worst failure shape there is, because the user's next move is
14
+ * to click it again.
15
+ *
16
+ * The replacement asks in the page itself. One click arms it, a second
17
+ * confirms, and anywhere else cancels. No portal, no modal, no dependency on
18
+ * what the embedding page allows.
19
+ */
20
+ export interface ConfirmButtonProps {
21
+ /** What the button says at rest. */
22
+ children: ReactNode;
23
+ /** What it says once armed. Make it name the consequence. */
24
+ confirmLabel: string;
25
+ onConfirm: () => void | Promise<void>;
26
+ className?: string;
27
+ disabled?: boolean;
28
+ /** How long the armed state survives without an answer. */
29
+ timeoutMs?: number;
30
+ }
31
+ export declare function ConfirmButton({ children, confirmLabel, onConfirm, className, disabled, timeoutMs, }: ConfirmButtonProps): import("react").JSX.Element;
32
+ //# sourceMappingURL=confirm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../../src/confirm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpE;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,kBAAkB;IAClC,oCAAoC;IACpC,QAAQ,EAAE,SAAS,CAAC;IACpB,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD,wBAAgB,aAAa,CAAC,EAC7B,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAA8B,GAC9B,EAAE,kBAAkB,+BAwDpB"}
@@ -0,0 +1,44 @@
1
+ import { type FieldDescriptor, type FieldValue } from "@base316/sdk";
2
+ import type { ReactNode } from "react";
3
+ /**
4
+ * How each field type looks, and how each is edited.
5
+ *
6
+ * The other half of the registry. `@base316/sdk`'s `fields.ts` says what a
7
+ * field *is* — groupable, summable, searchable — and this says what it looks
8
+ * like. They are split because the server needs the first and must never
9
+ * import React, and because a customer replacing the rendering should not have
10
+ * to restate the semantics.
11
+ *
12
+ * Every component goes through here rather than switching on types itself.
13
+ * That is what makes a new field type cheap: one entry in the SDK registry,
14
+ * one here, and the table, the form, the detail view and anything built later
15
+ * all understand it without being touched.
16
+ */
17
+ export interface CellProps {
18
+ value: FieldValue;
19
+ field: FieldDescriptor;
20
+ /** A relation's resolved label, when this field is one. */
21
+ related?: {
22
+ id: string;
23
+ title: string | null;
24
+ };
25
+ }
26
+ export interface InputProps {
27
+ value: FieldValue;
28
+ field: FieldDescriptor;
29
+ onChange: (value: FieldValue) => void;
30
+ /** Rendered under the input. Set when the server rejected this field. */
31
+ error?: string | null;
32
+ disabled?: boolean;
33
+ }
34
+ /** The cell for one field. Null and empty render as a dash, never as "null". */
35
+ export declare function FieldCell({ value, field, related }: CellProps): ReactNode;
36
+ /**
37
+ * The input for one field.
38
+ *
39
+ * Returns null for a computed field: an AUTONUMBER, LOOKUP or ROLLUP is
40
+ * produced by the server, and offering an input for one invites somebody to
41
+ * type a value that will be silently discarded.
42
+ */
43
+ export declare function FieldInput({ value, field, onChange, error, disabled }: InputProps): ReactNode;
44
+ //# sourceMappingURL=fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/fields.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEN,KAAK,eAAe,EACpB,KAAK,UAAU,EAGf,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,eAAe,CAAC;IACvB,2DAA2D;IAC3D,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CAC/C;AAED,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAoCD,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,SAAS,GAAG,SAAS,CA8FzE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,UAAU,GAAG,SAAS,CAwP7F"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * What is in this package, described so that something assembling a page does
3
+ * not have to guess.
4
+ *
5
+ * The audience is an agent building an application, and a drag-and-drop canvas
6
+ * later. Both need the same four answers, and none of them can be had by
7
+ * reading a type definition:
8
+ *
9
+ * 1. **What exists.** Otherwise a component gets invented, and the failure is a
10
+ * build error nobody can act on.
11
+ * 2. **What it needs before it works.** This is the big one. Almost everything
12
+ * here renders nothing without a signed-in user — which looks like a broken
13
+ * component rather than a missing precondition, and is the single most
14
+ * expensive way to lose an hour with this package.
15
+ * 3. **Which sibling to reach for.** A table, a board and a chart all bind to a
16
+ * collection and answer different questions.
17
+ * 4. **What the props actually are.** Not their types — TypeScript has those —
18
+ * but what they mean and what happens when they are left out.
19
+ *
20
+ * Every component here takes no required props. That is a rule rather than a
21
+ * coincidence: a thing that cannot be dropped in as `<Thing />` is a thing an
22
+ * agent has to be taught, and the whole point is that it does not.
23
+ *
24
+ * **This file drifts if nobody stops it**, so `manifest.test.ts` fails when an
25
+ * export is added or removed without a matching entry. A manifest that lies is
26
+ * worse than no manifest, because both an agent and a person will believe it.
27
+ */
28
+ /**
29
+ * What must already be true, or the component renders nothing useful.
30
+ *
31
+ * Ordered by how often each one is the answer to "why is this blank".
32
+ */
33
+ export type Requirement =
34
+ /** A signed-in end user. Without one, most of these render nothing at all. */
35
+ "session"
36
+ /** A collection defined in this environment, named by the `collection` prop. */
37
+ | "collection"
38
+ /** At least one published plan in the catalog. */
39
+ | "plans"
40
+ /** A connected payment account, or checkout refuses before a card is asked for. */
41
+ | "paymentAccount"
42
+ /** An API resource defined, so there are credentials to manage. */
43
+ | "apiResource";
44
+ export interface PropEntry {
45
+ name: string;
46
+ /** What it does, and what happens without it. */
47
+ summary: string;
48
+ /** True for none of them, by design. Present so the rule is machine-checkable. */
49
+ required: boolean;
50
+ }
51
+ export interface ManifestEntry {
52
+ name: string;
53
+ kind: "component" | "hook" | "provider";
54
+ /** One line: what this is. */
55
+ summary: string;
56
+ /** When to reach for this one rather than a sibling. */
57
+ useWhen: string;
58
+ requires: Requirement[];
59
+ /** Parameterised by a collection defined at runtime. */
60
+ bindsToCollection?: boolean;
61
+ props: PropEntry[];
62
+ /** What appears when a requirement is not met. The answer to "why is it blank". */
63
+ whenUnmet?: string;
64
+ seeAlso?: string[];
65
+ }
66
+ export declare const MANIFEST: ManifestEntry[];
67
+ /**
68
+ * How the pieces go together.
69
+ *
70
+ * Listed separately from the entries because it is not a fact about any one of
71
+ * them, and it is the thing most often got wrong: a component dropped outside
72
+ * the provider throws, and one dropped on a page with no signed-in user renders
73
+ * nothing and reads as broken. Neither is discoverable from a prop list.
74
+ */
75
+ export declare const COMPOSITION: {
76
+ readonly rules: readonly ["Everything must be inside Base316Provider. Outside it, hooks throw.", "Most components need a signed-in user. Gate on useSession and render SignIn when there is none — see `requires: session` on each entry.", "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.", "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.", "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.", "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."];
77
+ /** The shape almost every application ends up with. */
78
+ readonly example: string;
79
+ };
80
+ /** Look one up by name. */
81
+ export declare function describeComponent(name: string): ManifestEntry | undefined;
82
+ /** Everything that needs a particular precondition — the "why is this blank" list. */
83
+ export declare function componentsRequiring(requirement: Requirement): ManifestEntry[];
84
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;;GAIG;AACH,MAAM,MAAM,WAAW;AACtB,8EAA8E;AAC5E,SAAS;AACX,gFAAgF;GAC9E,YAAY;AACd,kDAAkD;GAChD,OAAO;AACT,mFAAmF;GACjF,gBAAgB;AAClB,mEAAmE;GACjE,aAAa,CAAC;AAEjB,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;IACxC,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAOD,eAAO,MAAM,QAAQ,EAAE,aAAa,EAqlBnC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;aACvB,KAAK,YACJ,qEAAqE,EACrE,yIAAyI,EACzI,2JAA2J,EAC3J,+QAA+Q,EAC/Q,0ZAA0Z,EAC1Z,4KAA4K;IAE7K,uDAAuD;aACvD,OAAO;CAyBE,CAAC;AAEX,2BAA2B;AAC3B,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEzE;AAED,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE,CAE7E"}
@@ -0,0 +1,204 @@
1
+ import { type RenderResult } from "@testing-library/react";
2
+ import type { ReactElement } from "react";
3
+ /**
4
+ * Rendering a component the way a customer's page does.
5
+ *
6
+ * `fetch` is stubbed rather than the client injected, and that is deliberate:
7
+ * adding a `client` prop to the provider purely so tests could reach inside it
8
+ * would widen the public API for the convenience of this file. Stubbing the
9
+ * network instead exercises the real client and the real transport, so a test
10
+ * fails when the SDK builds the wrong URL — which is most of what these
11
+ * components do wrong.
12
+ */
13
+ /** Parseable by `requireKey`: four parts, `b316`, a known type, a band, base62. */
14
+ export declare const TEST_KEY = "b316_pk_sandbox_0123456789abcdefgh";
15
+ /** Any non-empty string. The stubbed API never checks it. */
16
+ export declare const TEST_SESSION = "test-session";
17
+ export interface Route {
18
+ /** Matched against the path and query, e.g. "/v1/collections/jobs/records". */
19
+ match: (url: string, method: string) => boolean;
20
+ /** The JSON body, or a function of the request for a route that varies. */
21
+ respond: (url: string, init: RequestInit | undefined) => unknown;
22
+ status?: number;
23
+ }
24
+ export interface StubbedFetch {
25
+ /** Every request made, in order. Assert on what a component asked for. */
26
+ calls: {
27
+ url: string;
28
+ method: string;
29
+ body: unknown;
30
+ }[];
31
+ restore: () => void;
32
+ }
33
+ /**
34
+ * Answer only what a test declares, and fail loudly on anything else.
35
+ *
36
+ * An unmatched request resolves to a 404 rather than hanging or throwing, so a
37
+ * component that fetches something unexpected renders its error state and the
38
+ * test says which URL was not covered instead of timing out.
39
+ */
40
+ export declare function stubFetch(routes: Route[]): StubbedFetch;
41
+ /**
42
+ * Render inside a provider holding a session.
43
+ *
44
+ * `token` is passed as a controlled prop rather than written to localStorage:
45
+ * the provider treats a supplied token as owned by the host application, which
46
+ * skips the storage read and the session refresh a test does not care about.
47
+ */
48
+ export declare function renderWithProvider(ui: ReactElement, { token }?: {
49
+ token?: string | null;
50
+ }): RenderResult;
51
+ /**
52
+ * A collection resembling something somebody would define.
53
+ *
54
+ * Deliberately contains a field of each awkward kind: one that cannot be
55
+ * sorted, one that cannot be edited, and one whose value lives elsewhere.
56
+ */
57
+ export declare const JOB_SCHEMA: {
58
+ key: string;
59
+ name: string;
60
+ namePlural: string;
61
+ description: null;
62
+ scope: "TENANT";
63
+ canWrite: boolean;
64
+ fields: ({
65
+ key: string;
66
+ label: string;
67
+ type: "TEXT";
68
+ required: boolean;
69
+ position: number;
70
+ options?: undefined;
71
+ relationTo?: undefined;
72
+ } | {
73
+ required?: undefined;
74
+ key: string;
75
+ label: string;
76
+ type: "SELECT";
77
+ options: string[];
78
+ position: number;
79
+ relationTo?: undefined;
80
+ } | {
81
+ required?: undefined;
82
+ options?: undefined;
83
+ key: string;
84
+ label: string;
85
+ type: "MONEY";
86
+ position: number;
87
+ relationTo?: undefined;
88
+ } | {
89
+ required?: undefined;
90
+ options?: undefined;
91
+ key: string;
92
+ label: string;
93
+ type: "LONGTEXT";
94
+ position: number;
95
+ relationTo?: undefined;
96
+ } | {
97
+ required?: undefined;
98
+ options?: undefined;
99
+ key: string;
100
+ label: string;
101
+ type: "RELATION";
102
+ relationTo: string;
103
+ position: number;
104
+ } | {
105
+ required?: undefined;
106
+ options?: undefined;
107
+ relationTo?: undefined;
108
+ key: string;
109
+ label: string;
110
+ type: "AUTONUMBER";
111
+ position: number;
112
+ })[];
113
+ };
114
+ export declare function jobRecord(id: string, fields: Record<string, unknown>, related?: Record<string, {
115
+ id: string;
116
+ title: string | null;
117
+ }>): {
118
+ id: string;
119
+ title: string;
120
+ fields: Record<string, unknown>;
121
+ related: Record<string, {
122
+ id: string;
123
+ title: string | null;
124
+ }>;
125
+ createdAt: string;
126
+ updatedAt: string;
127
+ createdBy: null;
128
+ updatedBy: null;
129
+ };
130
+ /** The two routes every collection component needs before it renders anything. */
131
+ export declare function collectionRoutes({ schema, records, extra, }?: {
132
+ extra?: Route[] | undefined;
133
+ records?: {
134
+ id: string;
135
+ title: string;
136
+ fields: Record<string, unknown>;
137
+ related: Record<string, {
138
+ id: string;
139
+ title: string | null;
140
+ }>;
141
+ createdAt: string;
142
+ updatedAt: string;
143
+ createdBy: null;
144
+ updatedBy: null;
145
+ }[] | undefined;
146
+ schema?: {
147
+ key: string;
148
+ name: string;
149
+ namePlural: string;
150
+ description: null;
151
+ scope: "TENANT";
152
+ canWrite: boolean;
153
+ fields: ({
154
+ key: string;
155
+ label: string;
156
+ type: "TEXT";
157
+ required: boolean;
158
+ position: number;
159
+ options?: undefined;
160
+ relationTo?: undefined;
161
+ } | {
162
+ required?: undefined;
163
+ key: string;
164
+ label: string;
165
+ type: "SELECT";
166
+ options: string[];
167
+ position: number;
168
+ relationTo?: undefined;
169
+ } | {
170
+ required?: undefined;
171
+ options?: undefined;
172
+ key: string;
173
+ label: string;
174
+ type: "MONEY";
175
+ position: number;
176
+ relationTo?: undefined;
177
+ } | {
178
+ required?: undefined;
179
+ options?: undefined;
180
+ key: string;
181
+ label: string;
182
+ type: "LONGTEXT";
183
+ position: number;
184
+ relationTo?: undefined;
185
+ } | {
186
+ required?: undefined;
187
+ options?: undefined;
188
+ key: string;
189
+ label: string;
190
+ type: "RELATION";
191
+ relationTo: string;
192
+ position: number;
193
+ } | {
194
+ required?: undefined;
195
+ options?: undefined;
196
+ relationTo?: undefined;
197
+ key: string;
198
+ label: string;
199
+ type: "AUTONUMBER";
200
+ position: number;
201
+ })[];
202
+ } | undefined;
203
+ }): Route[];
204
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../../src/test/harness.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1C;;;;;;;;;GASG;AAEH,mFAAmF;AACnF,eAAO,MAAM,QAAQ,uCAAuC,CAAC;AAC7D,6DAA6D;AAC7D,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,MAAM,WAAW,KAAK;IACrB,+EAA+E;IAC/E,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD,2EAA2E;IAC3E,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,SAAS,KAAK,OAAO,CAAC;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC5B,0EAA0E;IAC1E,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IACxD,OAAO,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,CAwCvD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CACjC,EAAE,EAAE,YAAY,EAGhB,EAAE,KAAoB,EAAE,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GACtD,YAAY,CAMd;AAID;;;;;GAKG;AACH,eAAO,MAAM,UAAU;;;;;WAKf,QAAQ;;;;;cAGwB,MAAM;;;;;;;;;cAIrC,QAAQ;;;;;;;;;cAIuB,OAAO;;;;;;;;cACP,UAAU;;;;;;;;cAIzC,UAAU;;;;;;;;;cAI6B,YAAY;;;CAE3D,CAAC;AAEF,wBAAgB,SAAS,CACxB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAM;;;;;YAApC,MAAM;eAAS,MAAM,GAAG,IAAI;;;;;;EAY1D;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,EAChC,MAAmB,EACnB,OAA8C,EAC9C,KAAqB,GACrB;;;;;;;gBAnB8B,MAAM;mBAAS,MAAM,GAAG,IAAI;;;;;;;;;;;;eA3BnD,QAAQ;;;;;kBAGwB,MAAM;;;;;;;;;kBAIrC,QAAQ;;;;;;;;;kBAIuB,OAAO;;;;;;;;kBACP,UAAU;;;;;;;;kBAIzC,UAAU;;;;;;;;;kBAI6B,YAAY;;;;CA0BtD,GAAG,KAAK,EAAE,CAYf"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/test/setup.ts"],"names":[],"mappings":""}