@rightkit/social-ui 0.0.0-stage → 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 (124) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +40 -2
  5. package/dist/appName.d.ts +2 -0
  6. package/dist/appName.js +8 -0
  7. package/dist/components/ScopeSelect.d.ts +7 -0
  8. package/dist/components/ScopeSelect.js +6 -0
  9. package/dist/components/Shared.d.ts +34 -0
  10. package/dist/components/Shared.js +55 -0
  11. package/dist/data/derive.d.ts +21 -0
  12. package/dist/data/derive.js +47 -0
  13. package/dist/data/draftRules.d.ts +10 -0
  14. package/dist/data/draftRules.js +20 -0
  15. package/dist/data/engine/engineDataSource.d.ts +194 -0
  16. package/dist/data/engine/engineDataSource.js +836 -0
  17. package/dist/data/engine/errors.d.ts +13 -0
  18. package/dist/data/engine/errors.js +21 -0
  19. package/dist/data/engine/mapping.d.ts +172 -0
  20. package/dist/data/engine/mapping.js +1487 -0
  21. package/dist/data/engine/protocol.d.ts +910 -0
  22. package/dist/data/engine/protocol.js +67 -0
  23. package/dist/data/index.d.ts +18 -0
  24. package/dist/data/index.js +23 -0
  25. package/dist/data/mock/devSource.d.ts +7 -0
  26. package/dist/data/mock/devSource.js +10 -0
  27. package/dist/data/mock/fixtures-analytics.d.ts +7 -0
  28. package/dist/data/mock/fixtures-analytics.js +123 -0
  29. package/dist/data/mock/fixtures-briefs.d.ts +4 -0
  30. package/dist/data/mock/fixtures-briefs.js +230 -0
  31. package/dist/data/mock/fixtures-content.d.ts +4 -0
  32. package/dist/data/mock/fixtures-content.js +89 -0
  33. package/dist/data/mock/fixtures-digests.d.ts +3 -0
  34. package/dist/data/mock/fixtures-digests.js +40 -0
  35. package/dist/data/mock/fixtures-drafts.d.ts +2 -0
  36. package/dist/data/mock/fixtures-drafts.js +74 -0
  37. package/dist/data/mock/fixtures-gate.d.ts +3 -0
  38. package/dist/data/mock/fixtures-gate.js +49 -0
  39. package/dist/data/mock/fixtures-hooks.d.ts +2 -0
  40. package/dist/data/mock/fixtures-hooks.js +103 -0
  41. package/dist/data/mock/fixtures-inbox.d.ts +11 -0
  42. package/dist/data/mock/fixtures-inbox.js +213 -0
  43. package/dist/data/mock/fixtures-links.d.ts +5 -0
  44. package/dist/data/mock/fixtures-links.js +89 -0
  45. package/dist/data/mock/fixtures-memory.d.ts +3 -0
  46. package/dist/data/mock/fixtures-memory.js +148 -0
  47. package/dist/data/mock/fixtures-ops.d.ts +15 -0
  48. package/dist/data/mock/fixtures-ops.js +403 -0
  49. package/dist/data/mock/fixtures-optimise.d.ts +18 -0
  50. package/dist/data/mock/fixtures-optimise.js +221 -0
  51. package/dist/data/mock/fixtures-pacing.d.ts +5 -0
  52. package/dist/data/mock/fixtures-pacing.js +285 -0
  53. package/dist/data/mock/fixtures-publish.d.ts +2 -0
  54. package/dist/data/mock/fixtures-publish.js +129 -0
  55. package/dist/data/mock/fixtures-store.d.ts +10 -0
  56. package/dist/data/mock/fixtures-store.js +13 -0
  57. package/dist/data/mock/fixtures-variants.d.ts +5 -0
  58. package/dist/data/mock/fixtures-variants.js +138 -0
  59. package/dist/data/mock/fixtures.d.ts +6 -0
  60. package/dist/data/mock/fixtures.js +420 -0
  61. package/dist/data/mock/mockDataSource.d.ts +98 -0
  62. package/dist/data/mock/mockDataSource.js +903 -0
  63. package/dist/data/money.d.ts +14 -0
  64. package/dist/data/money.js +36 -0
  65. package/dist/data/platforms.d.ts +12 -0
  66. package/dist/data/platforms.js +26 -0
  67. package/dist/data/source.d.ts +196 -0
  68. package/dist/data/source.js +1 -0
  69. package/dist/data/time.d.ts +23 -0
  70. package/dist/data/time.js +86 -0
  71. package/dist/data/types.d.ts +1092 -0
  72. package/dist/data/types.js +3 -0
  73. package/dist/env.d.ts +59 -0
  74. package/dist/hooks/useAsync.d.ts +19 -0
  75. package/dist/hooks/useAsync.js +25 -0
  76. package/dist/index.d.ts +56 -0
  77. package/dist/index.js +58 -0
  78. package/dist/lib/host.d.ts +21 -0
  79. package/dist/lib/host.js +32 -0
  80. package/dist/lib/shell.d.ts +156 -0
  81. package/dist/lib/shell.js +16 -0
  82. package/dist/screens/AccountsScreen.d.ts +8 -0
  83. package/dist/screens/AccountsScreen.js +100 -0
  84. package/dist/screens/AnalyticsScreen.d.ts +7 -0
  85. package/dist/screens/AnalyticsScreen.js +64 -0
  86. package/dist/screens/ApprovalsScreen.d.ts +10 -0
  87. package/dist/screens/ApprovalsScreen.js +144 -0
  88. package/dist/screens/BriefsScreen.d.ts +7 -0
  89. package/dist/screens/BriefsScreen.js +83 -0
  90. package/dist/screens/CalendarScreen.d.ts +10 -0
  91. package/dist/screens/CalendarScreen.js +143 -0
  92. package/dist/screens/CampaignsScreen.d.ts +7 -0
  93. package/dist/screens/CampaignsScreen.js +52 -0
  94. package/dist/screens/ChannelMemoryScreen.d.ts +7 -0
  95. package/dist/screens/ChannelMemoryScreen.js +109 -0
  96. package/dist/screens/ContentScreen.d.ts +7 -0
  97. package/dist/screens/ContentScreen.js +64 -0
  98. package/dist/screens/DigestsScreen.d.ts +7 -0
  99. package/dist/screens/DigestsScreen.js +53 -0
  100. package/dist/screens/DraftsScreen.d.ts +10 -0
  101. package/dist/screens/DraftsScreen.js +108 -0
  102. package/dist/screens/FailuresScreen.d.ts +8 -0
  103. package/dist/screens/FailuresScreen.js +111 -0
  104. package/dist/screens/HookTestsScreen.d.ts +7 -0
  105. package/dist/screens/HookTestsScreen.js +54 -0
  106. package/dist/screens/InboxScreen.d.ts +12 -0
  107. package/dist/screens/InboxScreen.js +76 -0
  108. package/dist/screens/LinksScreen.d.ts +7 -0
  109. package/dist/screens/LinksScreen.js +52 -0
  110. package/dist/screens/PacingScreen.d.ts +7 -0
  111. package/dist/screens/PacingScreen.js +88 -0
  112. package/dist/screens/PublishJobsScreen.d.ts +7 -0
  113. package/dist/screens/PublishJobsScreen.js +66 -0
  114. package/dist/screens/SuggestionsScreen.d.ts +8 -0
  115. package/dist/screens/SuggestionsScreen.js +94 -0
  116. package/dist/screens/TextGateScreen.d.ts +7 -0
  117. package/dist/screens/TextGateScreen.js +111 -0
  118. package/dist/screens/ThreadsScreen.d.ts +8 -0
  119. package/dist/screens/ThreadsScreen.js +113 -0
  120. package/dist/screens/TypedBriefsScreen.d.ts +7 -0
  121. package/dist/screens/TypedBriefsScreen.js +75 -0
  122. package/dist/screens/labels.d.ts +121 -0
  123. package/dist/screens/labels.js +272 -0
  124. package/package.json +56 -3
@@ -0,0 +1,272 @@
1
+ import { daysUntil, formatCount, isSocialPlatform, remaining } from "../data/index.js";
2
+ import { hostAppName } from "../appName.js";
3
+ /** The ordinary name of each account platform. Exhaustive over SocialPlatform: a new id fails to compile until it is named. */
4
+ export const PLATFORM_LABEL = {
5
+ instagram: "Instagram",
6
+ facebook: "Facebook",
7
+ threads: "Threads",
8
+ youtube: "YouTube",
9
+ tiktok: "TikTok",
10
+ x: "X",
11
+ linkedin: "LinkedIn",
12
+ pinterest: "Pinterest",
13
+ bluesky: "Bluesky",
14
+ mastodon: "Mastodon",
15
+ };
16
+ /** Draft-only platform the engine accepts for manual drafts (DRAFT_ONLY_PLATFORMS, crates/protocol/src/drafts.rs:23). */
17
+ const DRAFT_ONLY_LABEL = new Map([["reddit", "Reddit"]]);
18
+ /**
19
+ * The display name for any platform id a stored row carries. A known id gets its name. An id the desktop does
20
+ * not know (a newer engine) is shown with its raw id and the words "unknown platform", never dropped.
21
+ */
22
+ export function platformName(platform) {
23
+ if (isSocialPlatform(platform))
24
+ return PLATFORM_LABEL[platform];
25
+ return DRAFT_ONLY_LABEL.get(platform) ?? `${platform} (unknown platform)`;
26
+ }
27
+ export const FORMAT_LABEL = {
28
+ reel: "Reel",
29
+ carousel: "Carousel",
30
+ photo: "Photo",
31
+ short: "Short",
32
+ video: "Video",
33
+ text_post: "Text post",
34
+ remake: "Remake (draft)",
35
+ };
36
+ /** Suggestion states. Text carries the meaning; the tone is a secondary cue. */
37
+ export const OPTIMISE_STATE_LABEL = {
38
+ proposed: { text: "Waiting for your decision", tone: "warn" },
39
+ accepted: { text: "Accepted: draft calendar entry created", tone: "ok" },
40
+ dismissed: { text: "Dismissed", tone: "neutral" },
41
+ };
42
+ /** Hook test states. An open set is read on the daemon host, so the label says so. */
43
+ export const HOOK_STATE_LABEL = {
44
+ open: { text: "Open: not decided yet", tone: "warn" },
45
+ decided: { text: "Decided", tone: "ok" },
46
+ };
47
+ /** Opening roles in a decided hook test. Null (not decided) is written by the screen. */
48
+ export const HOOK_ROLE_LABEL = {
49
+ promoted: "Promoted: the winner",
50
+ archived: "Archived",
51
+ };
52
+ export const STATE_LABEL = {
53
+ draft: { text: "Draft", tone: "neutral" },
54
+ media_pending: { text: "Media pending", tone: "warn" },
55
+ ready: { text: "Media ready", tone: "accent" },
56
+ scheduled: { text: "Scheduled", tone: "ok" },
57
+ publishing: { text: "Publishing", tone: "accent" },
58
+ published: { text: "Published", tone: "ok" },
59
+ outcome_unknown: { text: "Outcome unknown", tone: "bad" },
60
+ failed: { text: "Failed", tone: "bad" },
61
+ late: { text: "Late", tone: "warn" },
62
+ paused: { text: "Paused", tone: "warn" },
63
+ };
64
+ /** The daemon's publish job state, shown beside the calendar state. Text carries the meaning. */
65
+ export const PUBLISH_STATE_LABEL = {
66
+ queued: { text: "Queued on the daemon", tone: "neutral" },
67
+ running: { text: "Publishing now", tone: "accent" },
68
+ waiting: { text: "Waiting to retry", tone: "warn" },
69
+ published: { text: "Published by the daemon", tone: "ok" },
70
+ failed: { text: "Publish failed", tone: "bad" },
71
+ outcome_unknown: { text: "Outcome unknown", tone: "bad" },
72
+ cancelled: { text: "Publish cancelled", tone: "neutral" },
73
+ };
74
+ /** A person's recorded decision on an outcome_unknown job, in words. */
75
+ export const PUBLISH_RESOLUTION_LABEL = {
76
+ posted: "recorded as posted by hand",
77
+ not_posted: "recorded as not posted",
78
+ };
79
+ /** The plain explanation shown on every outcome_unknown failure. The wording is fixed. */
80
+ export const OUTCOME_UNKNOWN_EXPLANATION = `The platform may have accepted this post. ${hostAppName()} will not retry until the daemon has checked.`;
81
+ export const REJECT_LABEL = {
82
+ wrong_content: "Wrong content",
83
+ wrong_account: "Wrong account",
84
+ timing: "Timing",
85
+ media_issue: "Media issue",
86
+ other: "Other (note required)",
87
+ };
88
+ export const MEDIA_STATUS_LABEL = {
89
+ ready: "Ready",
90
+ uploading: "Uploading",
91
+ missing: "Missing",
92
+ };
93
+ export function approvalText(approval) {
94
+ switch (approval.status) {
95
+ case "none":
96
+ return { text: "No approval requested", tone: "neutral" };
97
+ case "pending":
98
+ return { text: "Awaiting approval", tone: "warn" };
99
+ case "approved":
100
+ return { text: `Approved at revision ${approval.approvedRevision}`, tone: "ok" };
101
+ case "rejected":
102
+ return { text: `Rejected: ${REJECT_LABEL[approval.reason].replace(" (note required)", "")}`, tone: "bad" };
103
+ case "invalidated":
104
+ return { text: "Approval invalidated: re-approval needed", tone: "bad" };
105
+ }
106
+ }
107
+ export function tokenText(token, nowUtc) {
108
+ switch (token.status) {
109
+ case "valid":
110
+ return { text: `Valid, expires in ${daysUntil(token.expiresOn, nowUtc)} days`, tone: "ok", mark: "OK" };
111
+ case "expiring": {
112
+ const days = daysUntil(token.expiresOn, nowUtc);
113
+ return { text: `Expires in ${days} day${days === 1 ? "" : "s"}. Reconnect before then.`, tone: "warn", mark: "Expiring" };
114
+ }
115
+ case "refresh_failed":
116
+ return { text: "Refresh failed. Publishing is blocked until reconnect.", tone: "bad", mark: "Failed" };
117
+ case "revoked":
118
+ return { text: "Revoked at the provider. Reconnect required.", tone: "bad", mark: "Revoked" };
119
+ }
120
+ }
121
+ export const ENTITLEMENT_LABEL = {
122
+ sandbox_mechanics: { text: "Sandbox mechanics", hint: "Tested with test users only. Not visible to the audience." },
123
+ review_submitted: { text: "Review submitted", hint: "Submitted to the platform. Not yet audience-visible." },
124
+ audience_visible: { text: "Audience-visible", hint: "Posts reach the public audience." },
125
+ };
126
+ export function cooldownText(until, nowUtc) {
127
+ if (!until)
128
+ return "None";
129
+ const left = remaining(until, nowUtc);
130
+ return left === "now" ? "Cooldown has ended" : `Waiting, ${left} left`;
131
+ }
132
+ export function countText(n) {
133
+ return formatCount(n);
134
+ }
135
+ /** Content record states. Withdrawn is final; expired is derived from the clock and never stored. */
136
+ export const CONTENT_STATE_LABEL = {
137
+ active: { text: "Active", tone: "ok" },
138
+ withdrawn: { text: "Withdrawn: final", tone: "bad" },
139
+ expired: { text: "Expired: cannot be planned", tone: "warn" },
140
+ };
141
+ export const CONTENT_MEDIA_KIND_LABEL = {
142
+ image: "Image",
143
+ video: "Video",
144
+ };
145
+ export const CONTENT_VARIANT_KIND_LABEL = {
146
+ caption: "Caption",
147
+ cta: "Call to action",
148
+ };
149
+ /** The engine's experiment verdict in words. Neither verdict names a winner. */
150
+ export const CONTENT_VERDICT_LABEL = {
151
+ insufficient_evidence: { text: "Insufficient evidence: no winner is shown", tone: "warn" },
152
+ evidence_sufficient: { text: "Evidence sufficient: the engine names no winner", tone: "ok" },
153
+ };
154
+ /** The text gate's overall result. The words say what happens next; the tone is a secondary cue only. */
155
+ export const GATE_DISPOSITION_LABEL = {
156
+ pass: { text: "Pass: no rule blocks this script", tone: "ok" },
157
+ hold: { text: "Hold: a person must decide", tone: "warn" },
158
+ block: { text: "Block: a rule stops this script", tone: "bad" },
159
+ };
160
+ /** One rule's verdict in words. */
161
+ export const GATE_VERDICT_LABEL = {
162
+ pass: "Pass",
163
+ fail: "Fail",
164
+ inconclusive: "Inconclusive",
165
+ unverified: "Unverified",
166
+ hold: "Hold",
167
+ not_applicable: "Not applicable",
168
+ };
169
+ /** Outgoing brief states. An issued brief has no delivery yet; a partial one has only some of what was requested. */
170
+ export const BRIEF_STATE_LABEL = {
171
+ issued: { text: "Issued: no delivery yet", tone: "warn" },
172
+ partial: { text: "Partly delivered: some deliverables were skipped or refused", tone: "warn" },
173
+ delivered: { text: "Delivered", tone: "ok" },
174
+ };
175
+ /** Dispatch attempt outcomes. Each names what happened to the run, in words. */
176
+ export const DISPATCH_OUTCOME_LABEL = {
177
+ running: { text: "Running now", tone: "accent" },
178
+ delivered: { text: "Delivered", tone: "ok" },
179
+ partial: { text: "Partly delivered: the engine skipped or refused some deliverables", tone: "warn" },
180
+ awaiting_approval: { text: `Waiting for approval in the producer's app (${hostAppName()} or ${hostAppName()}): approve the assets there, then run the brief again`, tone: "warn" },
181
+ engine_failed: { text: "Engine failed", tone: "bad" },
182
+ timed_out: { text: "Timed out: the run was killed", tone: "bad" },
183
+ delivery_invalid: { text: "Finished, but no usable envelope", tone: "bad" },
184
+ engine_missing: { text: "Engine not found: nothing ran", tone: "warn" },
185
+ interrupted: { text: "Interrupted: the result is not known", tone: "bad" },
186
+ };
187
+ /** Heartbeat states in words. "Stale" and "unreadable" are never shown as alive. */
188
+ export const HEARTBEAT_STATE_LABEL = {
189
+ alive: { text: "Alive", tone: "ok" },
190
+ stale: { text: "Stale: older than the threshold", tone: "bad" },
191
+ missing: { text: "Missing: no heartbeat has been recorded", tone: "bad" },
192
+ unreadable: { text: "Unreadable: the file could not be read", tone: "bad" },
193
+ };
194
+ /** Proof statuses in words. Only an approved proof can be cited by a script; the tone is a secondary cue only. */
195
+ export const PROOF_STATUS_LABEL = {
196
+ collected: { text: "Collected: not approved, so no script can cite it", tone: "neutral" },
197
+ approved: { text: "Approved: a script can cite it", tone: "ok" },
198
+ withdrawn: { text: "Withdrawn: no script can cite it", tone: "bad" },
199
+ superseded: { text: "Superseded: replaced by another proof", tone: "neutral" },
200
+ };
201
+ /** Typed brief types in words. The type is text; no colour is used. */
202
+ export const BRIEF_TYPE_LABEL = {
203
+ talking_head: "Talking head",
204
+ faceless_cartoon_short: "Faceless cartoon short",
205
+ explainer: "Explainer",
206
+ carousel: "Carousel",
207
+ ugc_character_review: "UGC character review",
208
+ product_pitch: "Product pitch",
209
+ product_demo: "Product demo",
210
+ };
211
+ /** Where a platform places a link, in words. "none" means the platform carries no link. */
212
+ export const LINK_PLACEMENT_LABEL = {
213
+ caption: "In the caption",
214
+ bio: "In the bio",
215
+ first_comment: "In the first comment",
216
+ none: "None: this platform carries no link",
217
+ };
218
+ /** A stored metric the platform does not provide. It is never shown as zero. */
219
+ export const ANALYTICS_UNAVAILABLE = "Not available from this platform";
220
+ /** Where a stored number came from, in words. An API row names its pull elsewhere; a manual row names its import. */
221
+ export function analyticsSourceText(source, importId) {
222
+ if (source === "api")
223
+ return "from the platform's API";
224
+ return importId === null ? "from a file the owner exported" : `from a file the owner exported (import ${importId})`;
225
+ }
226
+ /** A post's age at an observation: the exact seconds, then the same span in days, hours and minutes. */
227
+ export function postAgeText(seconds) {
228
+ const days = Math.floor(seconds / 86_400);
229
+ const hours = Math.floor((seconds % 86_400) / 3_600);
230
+ const minutes = Math.floor((seconds % 3_600) / 60);
231
+ return `${seconds} seconds (${span(days, "day")}, ${span(hours, "hour")}, ${span(minutes, "minute")})`;
232
+ }
233
+ /** Inbox event kinds in words. The kind is text; no colour is used. */
234
+ export const INBOX_KIND_LABEL = {
235
+ comment: "Comment",
236
+ message: "Message",
237
+ mention: "Mention",
238
+ other: "Other",
239
+ };
240
+ /** Inbox event states in words. The state is set by a person on the server; this screen only shows it. */
241
+ export const INBOX_STATE_LABEL = {
242
+ open: { text: "Open: not handled yet", tone: "warn" },
243
+ handled: { text: "Handled", tone: "ok" },
244
+ ignored: { text: "Ignored", tone: "neutral" },
245
+ };
246
+ /** Why a publish job may not run now, in words. Every reason the daemon can give has a line here. */
247
+ export const PACING_REASON_LABEL = {
248
+ not_due: "Not due yet",
249
+ outcome_unknown_on_account: "Held: another job on this account has an unknown outcome, and a person must resolve it",
250
+ account_not_ready: "Account not ready to publish",
251
+ account_paused: "Account paused by a person",
252
+ rate_limited_until: "The platform asked us to wait",
253
+ daily_cap: "Daily cap reached for this account",
254
+ account_gap: "Too soon after the last post on this account",
255
+ };
256
+ function isInboxKind(kind) {
257
+ return Object.prototype.hasOwnProperty.call(INBOX_KIND_LABEL, kind);
258
+ }
259
+ function isInboxState(state) {
260
+ return Object.prototype.hasOwnProperty.call(INBOX_STATE_LABEL, state);
261
+ }
262
+ /** An inbox kind as stored. A kind the desktop does not show is named as such, never dropped. */
263
+ export function inboxKindText(kind) {
264
+ return isInboxKind(kind) ? INBOX_KIND_LABEL[kind] : `Kind not shown by the desktop: ${kind}`;
265
+ }
266
+ /** An inbox state as stored. A state the desktop does not show is named as such. */
267
+ export function inboxStateText(state) {
268
+ return isInboxState(state) ? INBOX_STATE_LABEL[state] : { text: `State not shown by the desktop: ${state}`, tone: "bad" };
269
+ }
270
+ function span(count, word) {
271
+ return `${count} ${word}${count === 1 ? "" : "s"}`;
272
+ }
package/package.json CHANGED
@@ -1,6 +1,59 @@
1
1
  {
2
2
  "name": "@rightkit/social-ui",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Social media management UI: accounts, drafts, approvals and analytics screens with their data layer.",
5
+ "license": "MIT OR Apache-2.0",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "CHANGELOG.md",
20
+ "LICENSE-MIT",
21
+ "LICENSE-APACHE"
22
+ ],
23
+ "sideEffects": [
24
+ "*.css"
25
+ ],
26
+ "dependencies": {
27
+ "@rightkit/platform-ui": "^0.4.0",
28
+ "@rightkit/react-shell": "^0.7.2",
29
+ "@rightkit/tauri-shell": "^0.1.3",
30
+ "@tauri-apps/api": "^2.12.4"
31
+ },
32
+ "peerDependencies": {
33
+ "react": ">=18 <21"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^26.6.6",
37
+ "@types/react": "^19.3.0",
38
+ "@types/react-dom": "^19.3.0",
39
+ "react": "^19.3.1",
40
+ "react-dom": "^19.3.1",
41
+ "typescript": "^7.0.2",
42
+ "vite": "^8.3.4",
43
+ "vitest": "^5.0.5"
44
+ },
45
+ "publishConfig": {
46
+ "registry": "https://registry.npmjs.org",
47
+ "access": "public"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/bogusyogi/rightkit.git",
52
+ "directory": "packages/social-ui"
53
+ },
54
+ "scripts": {
55
+ "build": "tsc -p tsconfig.json && node scripts/copy-assets.mjs",
56
+ "typecheck": "tsc -p tsconfig.json --noEmit",
57
+ "test": "pnpm --filter \"@rightkit/social-ui^...\" run build && vitest run"
58
+ }
6
59
  }