@stapel/reviews-react 0.1.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 (164) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/MODULE.md +151 -0
  3. package/README.md +207 -0
  4. package/dist/api/generated/schema.d.ts +360 -0
  5. package/dist/api/generated/schema.d.ts.map +1 -0
  6. package/dist/api/generated/schema.js +2 -0
  7. package/dist/api/generated/schema.js.map +1 -0
  8. package/dist/api/reviewsApi.d.ts +89 -0
  9. package/dist/api/reviewsApi.d.ts.map +1 -0
  10. package/dist/api/reviewsApi.js +51 -0
  11. package/dist/api/reviewsApi.js.map +1 -0
  12. package/dist/api/types.d.ts +127 -0
  13. package/dist/api/types.d.ts.map +1 -0
  14. package/dist/api/types.js +2 -0
  15. package/dist/api/types.js.map +1 -0
  16. package/dist/default/ErrorAlert.d.ts +9 -0
  17. package/dist/default/ErrorAlert.d.ts.map +1 -0
  18. package/dist/default/ErrorAlert.js +27 -0
  19. package/dist/default/ErrorAlert.js.map +1 -0
  20. package/dist/default/RatingBadge.d.ts +17 -0
  21. package/dist/default/RatingBadge.d.ts.map +1 -0
  22. package/dist/default/RatingBadge.js +23 -0
  23. package/dist/default/RatingBadge.js.map +1 -0
  24. package/dist/default/ReviewFormCard.d.ts +25 -0
  25. package/dist/default/ReviewFormCard.d.ts.map +1 -0
  26. package/dist/default/ReviewFormCard.js +42 -0
  27. package/dist/default/ReviewFormCard.js.map +1 -0
  28. package/dist/default/ReviewListPanel.d.ts +29 -0
  29. package/dist/default/ReviewListPanel.d.ts.map +1 -0
  30. package/dist/default/ReviewListPanel.js +47 -0
  31. package/dist/default/ReviewListPanel.js.map +1 -0
  32. package/dist/default/ReviewsPanel.d.ts +33 -0
  33. package/dist/default/ReviewsPanel.d.ts.map +1 -0
  34. package/dist/default/ReviewsPanel.js +17 -0
  35. package/dist/default/ReviewsPanel.js.map +1 -0
  36. package/dist/default/index.d.ts +31 -0
  37. package/dist/default/index.d.ts.map +1 -0
  38. package/dist/default/index.js +25 -0
  39. package/dist/default/index.js.map +1 -0
  40. package/dist/default/theme.d.ts +24 -0
  41. package/dist/default/theme.d.ts.map +1 -0
  42. package/dist/default/theme.js +39 -0
  43. package/dist/default/theme.js.map +1 -0
  44. package/dist/default/types.d.ts +12 -0
  45. package/dist/default/types.d.ts.map +1 -0
  46. package/dist/default/types.js +2 -0
  47. package/dist/default/types.js.map +1 -0
  48. package/dist/headless/ReviewAggregate.d.ts +63 -0
  49. package/dist/headless/ReviewAggregate.d.ts.map +1 -0
  50. package/dist/headless/ReviewAggregate.js +55 -0
  51. package/dist/headless/ReviewAggregate.js.map +1 -0
  52. package/dist/headless/ReviewForm.d.ts +83 -0
  53. package/dist/headless/ReviewForm.d.ts.map +1 -0
  54. package/dist/headless/ReviewForm.js +75 -0
  55. package/dist/headless/ReviewForm.js.map +1 -0
  56. package/dist/headless/ReviewList.d.ts +47 -0
  57. package/dist/headless/ReviewList.d.ts.map +1 -0
  58. package/dist/headless/ReviewList.js +51 -0
  59. package/dist/headless/ReviewList.js.map +1 -0
  60. package/dist/headless/ReviewsProvider.d.ts +19 -0
  61. package/dist/headless/ReviewsProvider.d.ts.map +1 -0
  62. package/dist/headless/ReviewsProvider.js +15 -0
  63. package/dist/headless/ReviewsProvider.js.map +1 -0
  64. package/dist/i18n/errorsMap.d.ts +12 -0
  65. package/dist/i18n/errorsMap.d.ts.map +1 -0
  66. package/dist/i18n/errorsMap.js +22 -0
  67. package/dist/i18n/errorsMap.js.map +1 -0
  68. package/dist/i18n/es.d.ts +19 -0
  69. package/dist/i18n/es.d.ts.map +1 -0
  70. package/dist/i18n/es.js +66 -0
  71. package/dist/i18n/es.js.map +1 -0
  72. package/dist/i18n/generated/errors.es.gen.d.ts +16 -0
  73. package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -0
  74. package/dist/i18n/generated/errors.es.gen.js +58 -0
  75. package/dist/i18n/generated/errors.es.gen.js.map +1 -0
  76. package/dist/i18n/generated/errors.gen.d.ts +341 -0
  77. package/dist/i18n/generated/errors.gen.d.ts.map +1 -0
  78. package/dist/i18n/generated/errors.gen.js +174 -0
  79. package/dist/i18n/generated/errors.gen.js.map +1 -0
  80. package/dist/i18n/generated/errors.ru.gen.d.ts +16 -0
  81. package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -0
  82. package/dist/i18n/generated/errors.ru.gen.js +58 -0
  83. package/dist/i18n/generated/errors.ru.gen.js.map +1 -0
  84. package/dist/i18n/keys.d.ts +59 -0
  85. package/dist/i18n/keys.d.ts.map +1 -0
  86. package/dist/i18n/keys.js +115 -0
  87. package/dist/i18n/keys.js.map +1 -0
  88. package/dist/i18n/ru.d.ts +22 -0
  89. package/dist/i18n/ru.d.ts.map +1 -0
  90. package/dist/i18n/ru.js +70 -0
  91. package/dist/i18n/ru.js.map +1 -0
  92. package/dist/index.d.ts +98 -0
  93. package/dist/index.d.ts.map +1 -0
  94. package/dist/index.js +92 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/model/context.d.ts +11 -0
  97. package/dist/model/context.d.ts.map +1 -0
  98. package/dist/model/context.js +16 -0
  99. package/dist/model/context.js.map +1 -0
  100. package/dist/model/list.d.ts +52 -0
  101. package/dist/model/list.d.ts.map +1 -0
  102. package/dist/model/list.js +60 -0
  103. package/dist/model/list.js.map +1 -0
  104. package/dist/model/mutations.d.ts +32 -0
  105. package/dist/model/mutations.d.ts.map +1 -0
  106. package/dist/model/mutations.js +44 -0
  107. package/dist/model/mutations.js.map +1 -0
  108. package/dist/model/queries.d.ts +65 -0
  109. package/dist/model/queries.d.ts.map +1 -0
  110. package/dist/model/queries.js +80 -0
  111. package/dist/model/queries.js.map +1 -0
  112. package/dist/model/queryKeys.d.ts +27 -0
  113. package/dist/model/queryKeys.d.ts.map +1 -0
  114. package/dist/model/queryKeys.js +14 -0
  115. package/dist/model/queryKeys.js.map +1 -0
  116. package/dist/model/rating.d.ts +57 -0
  117. package/dist/model/rating.d.ts.map +1 -0
  118. package/dist/model/rating.js +47 -0
  119. package/dist/model/rating.js.map +1 -0
  120. package/dist/model/refusals.d.ts +51 -0
  121. package/dist/model/refusals.d.ts.map +1 -0
  122. package/dist/model/refusals.js +103 -0
  123. package/dist/model/refusals.js.map +1 -0
  124. package/dist/model/runtime.d.ts +44 -0
  125. package/dist/model/runtime.d.ts.map +1 -0
  126. package/dist/model/runtime.js +15 -0
  127. package/dist/model/runtime.js.map +1 -0
  128. package/llms.txt +80 -0
  129. package/manifest.json +577 -0
  130. package/package.json +115 -0
  131. package/src/analytics/generated/events.json +7 -0
  132. package/src/api/generated/schema.ts +362 -0
  133. package/src/api/reviewsApi.ts +170 -0
  134. package/src/api/types.ts +140 -0
  135. package/src/default/ErrorAlert.tsx +46 -0
  136. package/src/default/RatingBadge.tsx +81 -0
  137. package/src/default/ReviewFormCard.tsx +139 -0
  138. package/src/default/ReviewListPanel.tsx +204 -0
  139. package/src/default/ReviewsPanel.tsx +74 -0
  140. package/src/default/index.ts +30 -0
  141. package/src/default/theme.tsx +66 -0
  142. package/src/default/types.ts +12 -0
  143. package/src/headless/ReviewAggregate.tsx +94 -0
  144. package/src/headless/ReviewForm.tsx +163 -0
  145. package/src/headless/ReviewList.tsx +99 -0
  146. package/src/headless/ReviewsProvider.tsx +20 -0
  147. package/src/i18n/errorsMap.ts +33 -0
  148. package/src/i18n/es.ts +81 -0
  149. package/src/i18n/generated/errors.es.gen.ts +64 -0
  150. package/src/i18n/generated/errors.gen.ts +205 -0
  151. package/src/i18n/generated/errors.json +387 -0
  152. package/src/i18n/generated/errors.ru.gen.ts +64 -0
  153. package/src/i18n/keys.ts +133 -0
  154. package/src/i18n/ru.ts +85 -0
  155. package/src/index.ts +161 -0
  156. package/src/model/context.tsx +28 -0
  157. package/src/model/list.ts +74 -0
  158. package/src/model/mutations.ts +62 -0
  159. package/src/model/queries.ts +122 -0
  160. package/src/model/queryKeys.ts +45 -0
  161. package/src/model/rating.ts +101 -0
  162. package/src/model/refusals.ts +114 -0
  163. package/src/model/runtime.ts +61 -0
  164. package/tsconfig.json +26 -0
@@ -0,0 +1,44 @@
1
+ import type { CreateModuleRuntimeOptions, ModuleRuntime } from "@stapel/core";
2
+ import type { ReviewsApi } from "../api/reviewsApi.js";
3
+ /**
4
+ * Inclusive rating bounds. These mirror `STAPEL_REVIEWS["RATING_MIN"]` /
5
+ * `["RATING_MAX"]`, whose library defaults are 1 and 5 — and they are
6
+ * OVERRIDABLE here for the same reason cdn-react's size ceilings are: they
7
+ * are deployment knobs, not constants, and a hardwired client would refuse a
8
+ * rating the server would have accepted (a 1..10 deployment) or offer one it
9
+ * would refuse (a 1..3 one).
10
+ *
11
+ * There is no endpoint that reports them, so a host that moves the knob tells
12
+ * this pair too. The mirror is a UI affordance only: the star row draws
13
+ * `max - min + 1` choices, and the server remains the authority
14
+ * (`error.400.reviews_invalid_rating`).
15
+ */
16
+ export interface ReviewRatingBounds {
17
+ readonly min: number;
18
+ readonly max: number;
19
+ }
20
+ /** stapel-reviews' own defaults (`conf.DEFAULTS`). */
21
+ export declare const DEFAULT_RATING_BOUNDS: ReviewRatingBounds;
22
+ /**
23
+ * The wired reviews runtime — core's `ModuleRuntime` bound to this pair's API
24
+ * (slim wave §21/S2), plus the deployment's rating bounds. The returned
25
+ * `client` is what the host injects into core's `StapelConfigProvider` (as the
26
+ * default or the `"reviews"` module client), preserving the client-injection
27
+ * fork seam (frontend-standard §7.2).
28
+ *
29
+ * MEMBER-ONLY, AND THE PAIR SAYS SO. Unlike categories-react, every endpoint
30
+ * behind this runtime is `IsAuthenticated` — a signed-out visitor gets 401 on
31
+ * the review list and on the aggregate. The read hooks are therefore gated on
32
+ * `useActiveSessionReady()` (so a bootstrapping session is not mistaken for an
33
+ * anonymous one) and the 401 is surfaced as a named "sign in to see reviews"
34
+ * state instead of an empty list.
35
+ */
36
+ export type ReviewsRuntime = ModuleRuntime<ReviewsApi> & {
37
+ readonly ratingBounds: ReviewRatingBounds;
38
+ };
39
+ export interface CreateReviewsRuntimeOptions extends CreateModuleRuntimeOptions {
40
+ /** Mirror of the deployment's `RATING_MIN`/`RATING_MAX`. Defaults to 1..5. */
41
+ readonly ratingBounds?: Partial<ReviewRatingBounds>;
42
+ }
43
+ export declare function createReviewsRuntime(options: CreateReviewsRuntimeOptions): ReviewsRuntime;
44
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/model/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,EAAE,kBAAuC,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,CAAC,UAAU,CAAC,GAAG;IACvD,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC;CAC3C,CAAC;AAEF,MAAM,WAAW,2BAA4B,SAAQ,0BAA0B;IAC7E,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACrD;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,2BAA2B,GACnC,cAAc,CAShB"}
@@ -0,0 +1,15 @@
1
+ import { createModuleRuntime } from "@stapel/core";
2
+ import { createReviewsApi } from "../api/reviewsApi.js";
3
+ /** stapel-reviews' own defaults (`conf.DEFAULTS`). */
4
+ export const DEFAULT_RATING_BOUNDS = { min: 1, max: 5 };
5
+ export function createReviewsRuntime(options) {
6
+ const runtime = createModuleRuntime(createReviewsApi, options);
7
+ return {
8
+ ...runtime,
9
+ ratingBounds: {
10
+ min: options.ratingBounds?.min ?? DEFAULT_RATING_BOUNDS.min,
11
+ max: options.ratingBounds?.max ?? DEFAULT_RATING_BOUNDS.max,
12
+ },
13
+ };
14
+ }
15
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/model/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAqBxD,sDAAsD;AACtD,MAAM,CAAC,MAAM,qBAAqB,GAAuB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AAyB5E,MAAM,UAAU,oBAAoB,CAClC,OAAoC;IAEpC,MAAM,OAAO,GAAG,mBAAmB,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAC/D,OAAO;QACL,GAAG,OAAO;QACV,YAAY,EAAE;YACZ,GAAG,EAAE,OAAO,CAAC,YAAY,EAAE,GAAG,IAAI,qBAAqB,CAAC,GAAG;YAC3D,GAAG,EAAE,OAAO,CAAC,YAAY,EAAE,GAAG,IAAI,qBAAqB,CAAC,GAAG;SAC5D;KACF,CAAC;AACJ,CAAC"}
package/llms.txt ADDED
@@ -0,0 +1,80 @@
1
+ # @stapel/reviews-react 0.1.0
2
+
3
+ Headless React flow pair for stapel-reviews (contract >=0.3 <0.4) — business + state, zero visual opinion.
4
+ Built on @stapel/core: typed client + StapelApiError envelope, auth token refresh,
5
+ verification-403 interception, i18n engine, analytics facade, TanStack Query layer.
6
+
7
+ ## The one right way (do this, the rest is a review/lint smell)
8
+ - No raw fetch/axios. The client is injected via <ReviewsProvider>/StapelConfigProvider;
9
+ every hook and flow already carries auth, refresh, and the error envelope.
10
+ - Render errors, never try/catch them: a flow's state carries FlowError{code,params};
11
+ render `t(code, params)` and branch on `explainReviewsError(code)` remediation.
12
+ - Server state = the use* hooks (query layer); keys come only from reviewsQueryKeys.
13
+ - User strings = i18n keys (registerReviewsI18n); never string literals.
14
+ - Sign-in UI = a headless flow component; copy it (shadcn-style) to restyle.
15
+
16
+ ## Layers
17
+ api (typed client) · model (hooks, session) · flows (machines) · headless · i18n
18
+
19
+ ## Documented flows (flows.json — canonical id, steps, endpoints)
20
+
21
+ ## Operations (typed; use the named op, never a path string)
22
+ Request/response schema names are in manifest.json + the generated types.
23
+ Paths are relative to `/reviews/api/v1/`.
24
+ - reviews_api_v1_reviews_aggregate_retrieve: GET /reviews/aggregate
25
+ - reviews_api_v1_reviews_create: POST /reviews
26
+ - reviews_api_v1_reviews_moderate_create: POST /reviews/{review_id}/moderate
27
+ - reviews_api_v1_reviews_response_create: POST /reviews/{review_id}/response
28
+ - reviews_api_v1_reviews_retrieve: GET /reviews
29
+
30
+ ## Query hooks (server state; keys come only from the key factory)
31
+ - useReviewAggregate (query) → aggregate
32
+ - useSubmitReview (mutation) → createReview
33
+
34
+ ## Errors (render t(code, params); UX from remediation)
35
+ 51 keys (full catalog: manifest.json §errors). By remediation: fix_input 22 · retry 16 · verify 5 · wait_and_retry 5 · contact_support 2 · reauthenticate 1.
36
+ Param-bearing keys (interpolation slots matter):
37
+ - error.400.field.blank [400] → fix_input {field}
38
+ - error.400.field.does_not_exist [400] → fix_input {field}
39
+ - error.400.field.invalid [400] → fix_input {field}
40
+ - error.400.field.invalid_choice [400] → fix_input {field}
41
+ - error.400.field.max_length [400] → fix_input {field,max_length}
42
+ - error.400.field.max_value [400] → fix_input {field,max_value}
43
+ - error.400.field.min_length [400] → fix_input {field,min_length}
44
+ - error.400.field.min_value [400] → fix_input {field,min_value}
45
+ - error.400.field.null [400] → fix_input {field}
46
+ - error.400.field.required [400] → fix_input {field}
47
+ - error.400.field.unique [400] → fix_input {field}
48
+ - error.429.rate_limit [429] → wait_and_retry {retry_after_minutes}
49
+
50
+ ## Analytics events (typed; defineEvent → events.json, drift-gated)
51
+ - (no app defineEvent() in this pair — its analytic events are the
52
+ auto-instrumented flow funnels below)
53
+
54
+ ## Flow funnels (auto-instrumented: flow.<id>.<step> {phase})
55
+
56
+ ```tsx
57
+ // Typed event + tracked() click (the one right way; §3.1).
58
+ const planSelected = defineEvent({
59
+ name: "pricing.plan.selected",
60
+ description: "User picked a plan",
61
+ props: { plan: prop.oneOf(["free", "pro", "team"], "Plan code") },
62
+ });
63
+ const { tracked } = useTracked();
64
+ <Button onClick={tracked(planSelected, { plan }, startCheckout)} />
65
+ // A click that STEPS a flow machine is already instrumented — mark it
66
+ // data-analytics="flow" instead; tracked() on top double-counts (§3.2).
67
+ ```
68
+
69
+ ## Demos (defineDemo → manifest.demos; compiled, linted, rendered examples)
70
+ - reviews.aggregate → <ReviewAggregate> [rated|never rated|seller roll-up (supplied)] demo/ReviewAggregate.demo.tsx
71
+ - reviews.form → <ReviewForm> [post-moderation (published)|pre-moderation (pending)|already rated (400)] demo/ReviewForm.demo.tsx
72
+ - reviews.list → <ReviewList> [published|moderator (include=all)|empty (reachable by a guest)] demo/ReviewList.demo.tsx
73
+ Each source file is the canonical usage snippet (open the default variant).
74
+
75
+ ## Snippets
76
+ ```tsx
77
+ // Error rendering + remediation branch (one pattern for every pair).
78
+ const r = explainReviewsError(err.code); // 'wait_and_retry' | 'verify' | ...
79
+ return <Alert action={r}>{t(err.code, err.params)}</Alert>;
80
+ ```