headroom-cms 0.1.11 → 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 (126) hide show
  1. package/admin/.well-known/headroom.json +9 -0
  2. package/admin/assets/{AdminsPage-BnzH9TL3.js → AdminsPage-DUMTsCEp.js} +1 -1
  3. package/admin/assets/{AllContentPage-BtObN6oy.js → AllContentPage-D5ey5AOV.js} +1 -1
  4. package/admin/assets/{ApiKeysPage-DEAa8eyC.js → ApiKeysPage-CzUOSoz_.js} +1 -1
  5. package/admin/assets/{AuditPage-BN9yNsxh.js → AuditPage-CYAg4dbI.js} +1 -1
  6. package/admin/assets/BackupsPage-04_oMy3v.js +1 -0
  7. package/admin/assets/{BlockEditor-3wnisTOZ.js → BlockEditor-s0CRZsjy.js} +3 -3
  8. package/admin/assets/BlockTypeEditPage-D1OFIlJZ.js +1 -0
  9. package/admin/assets/{BlockTypesPage-Dhkho6T_.js → BlockTypesPage-cJNR25fN.js} +1 -1
  10. package/admin/assets/{BulkActionBar-BxdfUSrN.js → BulkActionBar-BWysX7Wo.js} +1 -1
  11. package/admin/assets/{CollectionEditPage-lOb4hEZy.js → CollectionEditPage-DRmCA_73.js} +1 -1
  12. package/admin/assets/{CollectionsPage-CgtOloa1.js → CollectionsPage-CeQB5e9u.js} +1 -1
  13. package/admin/assets/{ContentCreatePage-LeQjahp_.js → ContentCreatePage-Cq8Pi8EF.js} +1 -1
  14. package/admin/assets/ContentEditPage-CEJ7I3WH.js +1 -0
  15. package/admin/assets/{ContentField-pilCbdnA.js → ContentField-BZT4OUfI.js} +1 -1
  16. package/admin/assets/ContentListPage-BCEQrYVs.js +1 -0
  17. package/admin/assets/{CustomBlockPreview-DNnTFM0z.js → CustomBlockPreview-Kc6bb3oq.js} +1 -1
  18. package/admin/assets/FieldRenderer-CT-DgCbC.js +2 -0
  19. package/admin/assets/FileTypeIcon-CNHtffHC.js +1 -0
  20. package/admin/assets/FloatingComposerController-D4uLQfUX-0_Y8mkGU.js +1 -0
  21. package/admin/assets/{IconPicker-CpIgiQTC.js → IconPicker-BpPlHJO0.js} +2 -2
  22. package/admin/assets/{LoginPage-D9ZsGLIi.js → LoginPage-Dya8sF_P.js} +1 -1
  23. package/admin/assets/MediaField-C3qFf3g5.js +1 -0
  24. package/admin/assets/MediaPage-BNxc0wLq.js +1 -0
  25. package/admin/assets/{Pagination-Df9nQ7Z0.js → Pagination-Dx8h11Rn.js} +1 -1
  26. package/admin/assets/{RelationshipPicker-B3Ftmqxp.js → RelationshipPicker-C2MTxrhl.js} +1 -1
  27. package/admin/assets/{SiteSettingsPage-6NvH7CiQ.js → SiteSettingsPage-BDZaUBmf.js} +1 -1
  28. package/admin/assets/{SiteUserEditPage-D5VaQ1Xq.js → SiteUserEditPage-MfzhPW7v.js} +1 -1
  29. package/admin/assets/{SiteUsersPage-BYVduiqs.js → SiteUsersPage-CrYugXpx.js} +1 -1
  30. package/admin/assets/{SitesPage-rfWWE0yK.js → SitesPage-Cl8V3Hb7.js} +1 -1
  31. package/admin/assets/SubmissionDetailPage-BnVlsGb-.js +1 -0
  32. package/admin/assets/SubmissionEditPage-B0Kq52fb.js +1 -0
  33. package/admin/assets/SubmissionListPage-K665VwMp.js +1 -0
  34. package/admin/assets/{TagInput-57c4DG1w.js → TagInput-C6tcB5Xw.js} +1 -1
  35. package/admin/assets/{TagsPage-BEO5AwCv.js → TagsPage-BONR6bSu.js} +1 -1
  36. package/admin/assets/{UsersPage-BpIRorJ1.js → UsersPage-C2iCy0UR.js} +1 -1
  37. package/admin/assets/{WebhookEditPage-D5xgi56h.js → WebhookEditPage-DjZFxT72.js} +1 -1
  38. package/admin/assets/{WebhooksPage-BY7AaiGr.js → WebhooksPage-g_a224a4.js} +1 -1
  39. package/admin/assets/{card-C9hfyHXf.js → card-DlfsF8lU.js} +1 -1
  40. package/admin/assets/{checkbox-DVJcwUt1.js → checkbox-BX8EcGFf.js} +1 -1
  41. package/admin/assets/{command-Bfmj0MEL.js → command-DaTsImUa.js} +1 -1
  42. package/admin/assets/{contentStatus-CkPi9Dh6.js → contentStatus-WXGfd7vX.js} +1 -1
  43. package/admin/assets/format-BRcflvs9.js +1 -0
  44. package/admin/assets/index-9sbb3-yI.css +1 -0
  45. package/admin/assets/{index-Ce5pmRMj.js → index-DC1UyCW2.js} +10 -10
  46. package/admin/assets/listCellValue-CBqXAwce.js +1 -0
  47. package/admin/assets/{popover-CzaQYEEP.js → popover-BA-47SRI.js} +1 -1
  48. package/admin/assets/{select-CrRhFGIi.js → select-waaVyoQ5.js} +1 -1
  49. package/admin/assets/{serializeToText-2VrsuRUh.js → serializeToText-CjHhyvXp.js} +1 -1
  50. package/admin/assets/{table-_3bMY0_z.js → table-Br-QgtTL.js} +1 -1
  51. package/admin/assets/{textarea-6fq0R6VV.js → textarea-BILv1DQB.js} +1 -1
  52. package/admin/assets/useAdminResolver-CbDzGoDp.js +1 -0
  53. package/admin/assets/useContent-Bp4f9qe0.js +1 -0
  54. package/admin/assets/{useContentSearch-B3aTjuCu.js → useContentSearch-DbiA8aG-.js} +1 -1
  55. package/admin/assets/{usePageTitle-C1r1-C00.js → usePageTitle-DOEFrHbj.js} +1 -1
  56. package/admin/assets/{useSiteUsers-DIaqgNSp.js → useSiteUsers-BFYAbJNT.js} +1 -1
  57. package/admin/assets/{useTags-B-HgMVwo.js → useTags-DJlXwDyc.js} +1 -1
  58. package/admin/assets/{useWebhooks-BvZjUJkJ.js → useWebhooks-BkpJKNLN.js} +1 -1
  59. package/admin/index.html +2 -2
  60. package/admin/sw.js +1 -1
  61. package/admin/workbox-362996ec.js +1 -0
  62. package/dist/admin-site.d.ts.map +1 -1
  63. package/dist/admin-site.js +46 -3
  64. package/dist/admin-site.js.map +1 -1
  65. package/dist/api.d.ts +2 -0
  66. package/dist/api.d.ts.map +1 -1
  67. package/dist/api.js +57 -5
  68. package/dist/api.js.map +1 -1
  69. package/dist/backup.d.ts +29 -0
  70. package/dist/backup.d.ts.map +1 -0
  71. package/dist/backup.js +95 -0
  72. package/dist/backup.js.map +1 -0
  73. package/dist/cdn-api.d.ts.map +1 -1
  74. package/dist/cdn-api.js +20 -19
  75. package/dist/cdn-api.js.map +1 -1
  76. package/dist/image.d.ts +8 -1
  77. package/dist/image.d.ts.map +1 -1
  78. package/dist/image.js +26 -6
  79. package/dist/image.js.map +1 -1
  80. package/dist/index.d.ts +3 -0
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +33 -1
  83. package/dist/index.js.map +1 -1
  84. package/dist/storage.d.ts +1 -0
  85. package/dist/storage.d.ts.map +1 -1
  86. package/dist/storage.js +21 -0
  87. package/dist/storage.js.map +1 -1
  88. package/dist/webhooks.d.ts +4 -3
  89. package/dist/webhooks.d.ts.map +1 -1
  90. package/dist/webhooks.js +22 -35
  91. package/dist/webhooks.js.map +1 -1
  92. package/lambda/api/bootstrap +0 -0
  93. package/lambda/backup-worker/bootstrap +0 -0
  94. package/lambda/image-lambda/index.mjs +30 -6
  95. package/lambda/image-lambda/node_modules/.package-lock.json +3 -3
  96. package/lambda/image-lambda/node_modules/semver/classes/range.js +7 -0
  97. package/lambda/image-lambda/node_modules/semver/package.json +1 -1
  98. package/lambda/image-lambda/node_modules/semver/ranges/subset.js +2 -2
  99. package/lambda/webhook-worker/bootstrap +0 -0
  100. package/package.json +1 -1
  101. package/src/admin-site.ts +46 -3
  102. package/src/api.ts +58 -5
  103. package/src/backup.ts +114 -0
  104. package/src/cdn-api.ts +20 -22
  105. package/src/image.ts +30 -6
  106. package/src/index.ts +37 -1
  107. package/src/sst-env.d.ts +4 -0
  108. package/src/storage.ts +22 -0
  109. package/src/webhooks.ts +22 -39
  110. package/admin/assets/BlockTypeEditPage-C2evAESK.js +0 -1
  111. package/admin/assets/ContentEditPage-xczr4d_h.js +0 -1
  112. package/admin/assets/ContentListPage-BAKDn1Xy.js +0 -1
  113. package/admin/assets/FieldRenderer-DiOKvkWV.js +0 -2
  114. package/admin/assets/FilterBar-BZoa63zh.js +0 -1
  115. package/admin/assets/FloatingComposerController-D4uLQfUX-BMIvFCoE.js +0 -1
  116. package/admin/assets/MediaField-CxccCFGQ.js +0 -1
  117. package/admin/assets/MediaPage-QvMaH2YJ.js +0 -1
  118. package/admin/assets/SubmissionDetailPage-BSUR685F.js +0 -1
  119. package/admin/assets/SubmissionEditPage-DjLXHjWU.js +0 -1
  120. package/admin/assets/SubmissionListPage-DBxNEvde.js +0 -1
  121. package/admin/assets/format-C88SDH8g.js +0 -1
  122. package/admin/assets/index-BB9Syqw2.css +0 -1
  123. package/admin/assets/useAdminResolver-BJNPz3OG.js +0 -1
  124. package/admin/assets/useContent-Bs7nel7C.js +0 -1
  125. package/admin/assets/useMedia-ae3s_ajC.js +0 -1
  126. package/admin/workbox-7d58179f.js +0 -1
package/src/image.ts CHANGED
@@ -3,6 +3,12 @@
3
3
  *
4
4
  * Sharp-based image transformation Lambda with HMAC-signed URLs.
5
5
  * Supports dev mode (Node.js source) and package mode (pre-bundled handler).
6
+ *
7
+ * The signing key is per-site: the Lambda derives it from a master KDF
8
+ * input (HMAC-SHA256(master, site)) so leaking one site's key cannot be
9
+ * used to forge URLs for another site. The OLD master is an opt-in
10
+ * fallback for smooth rotation — the Sharp Lambda accepts either, the Go
11
+ * API only signs with the primary.
6
12
  */
7
13
 
8
14
  import path from "path";
@@ -18,7 +24,15 @@ export interface ImageArgs {
18
24
  }
19
25
 
20
26
  export function createImage(name: string, args: ImageArgs) {
21
- const imageSigningSecret = new sst.Secret(`${name}ImageSigningSecret`);
27
+ const imageSigningMasterSecret = new sst.Secret(
28
+ `${name}ImageSigningMasterSecret`,
29
+ );
30
+ // Optional fallback master used during rotation. SST treats unset
31
+ // secrets as empty strings, which the Lambda's deriveSiteSecret turns
32
+ // into a null per-site key — disabling the fallback path entirely.
33
+ const imageSigningMasterSecretOld = new sst.Secret(
34
+ `${name}ImageSigningMasterSecretOld`,
35
+ );
22
36
 
23
37
  let imageLambda: sst.aws.Function;
24
38
  if (args.dev) {
@@ -36,9 +50,14 @@ export function createImage(name: string, args: ImageArgs) {
36
50
  },
37
51
  environment: {
38
52
  CONTENT_BUCKET: args.contentBucket.name,
39
- IMAGE_SIGNING_SECRET: imageSigningSecret.value,
53
+ IMAGE_SIGNING_MASTER_SECRET: imageSigningMasterSecret.value,
54
+ IMAGE_SIGNING_MASTER_SECRET_OLD: imageSigningMasterSecretOld.value,
40
55
  },
41
- link: [args.contentBucket, imageSigningSecret],
56
+ link: [
57
+ args.contentBucket,
58
+ imageSigningMasterSecret,
59
+ imageSigningMasterSecretOld,
60
+ ],
42
61
  });
43
62
  } else {
44
63
  imageLambda = new sst.aws.Function(`${name}ImageLambda`, {
@@ -53,13 +72,18 @@ export function createImage(name: string, args: ImageArgs) {
53
72
  },
54
73
  environment: {
55
74
  CONTENT_BUCKET: args.contentBucket.name,
56
- IMAGE_SIGNING_SECRET: imageSigningSecret.value,
75
+ IMAGE_SIGNING_MASTER_SECRET: imageSigningMasterSecret.value,
76
+ IMAGE_SIGNING_MASTER_SECRET_OLD: imageSigningMasterSecretOld.value,
57
77
  },
58
- link: [args.contentBucket, imageSigningSecret],
78
+ link: [
79
+ args.contentBucket,
80
+ imageSigningMasterSecret,
81
+ imageSigningMasterSecretOld,
82
+ ],
59
83
  });
60
84
  }
61
85
 
62
- return { imageSigningSecret, imageLambda };
86
+ return { imageSigningMasterSecret, imageSigningMasterSecretOld, imageLambda };
63
87
  }
64
88
 
65
89
  export type ImageResources = ReturnType<typeof createImage>;
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ import path from "path";
10
10
  import { createStorage } from "./storage.js";
11
11
  import { createAuth } from "./auth.js";
12
12
  import { createWebhooks } from "./webhooks.js";
13
+ import { createBackup } from "./backup.js";
13
14
  import { createImage } from "./image.js";
14
15
  import { createApi } from "./api.js";
15
16
  import { createApiCdn } from "./cdn-api.js";
@@ -48,6 +49,7 @@ function resolvePkgRoot(): string {
48
49
  export type { StorageResources } from "./storage.js";
49
50
  export type { AuthResources } from "./auth.js";
50
51
  export type { WebhookResources } from "./webhooks.js";
52
+ export type { BackupResources } from "./backup.js";
51
53
  export type { ImageResources } from "./image.js";
52
54
  export type { ApiResources } from "./api.js";
53
55
  export type { ApiCdnResources } from "./cdn-api.js";
@@ -127,6 +129,8 @@ export interface HeadroomCMSArgs {
127
129
  apiHandler: string;
128
130
  /** Go source path for webhook worker, e.g. "packages/webhook-worker" */
129
131
  webhookWorkerHandler: string;
132
+ /** Go source path for backup worker, e.g. "packages/backup-worker" */
133
+ backupWorkerHandler: string;
130
134
  /** SST handler for custom message function, e.g. "packages/functions/custom-message.handler" */
131
135
  customMessageHandler: string;
132
136
  /** SST handler for image Lambda, e.g. "packages/image-lambda/index.handler" */
@@ -177,7 +181,7 @@ export class HeadroomCMS {
177
181
  : undefined,
178
182
  });
179
183
 
180
- // 3. Webhooks (DynamoDB tables, SQS queues, worker Lambda)
184
+ // 3. Webhooks (DynamoDB tables, DLQ, worker Lambda)
181
185
  const webhooks = createWebhooks(name, {
182
186
  sites: storage.sites,
183
187
  pkgRoot,
@@ -186,6 +190,18 @@ export class HeadroomCMS {
186
190
  : undefined,
187
191
  });
188
192
 
193
+ // 3b. Backup worker Lambda (export + restore). Needs access to every
194
+ // site-scoped table plus the content + backup buckets. Created after
195
+ // webhooks so it can link the webhooks table for backup payloads.
196
+ const backup = createBackup(name, {
197
+ storage,
198
+ webhooks,
199
+ pkgRoot,
200
+ dev: args.dev
201
+ ? { handler: args.dev.backupWorkerHandler }
202
+ : undefined,
203
+ });
204
+
189
205
  // 4. Image Lambda (Sharp transform with HMAC-signed URLs)
190
206
  const image = createImage(name, {
191
207
  contentBucket: storage.contentBucket,
@@ -204,6 +220,7 @@ export class HeadroomCMS {
204
220
  storage,
205
221
  auth,
206
222
  webhooks,
223
+ backup,
207
224
  image,
208
225
  collab: collabTable,
209
226
  senderEmail: args.senderEmail,
@@ -289,6 +306,25 @@ export class HeadroomCMS {
289
306
  userPoolId: auth.userPool.id,
290
307
  userPoolClientId: auth.userPoolClient.id,
291
308
  collabWs: collab.wsUrl,
309
+ // DynamoDB table names (with Pulumi-generated random suffixes baked
310
+ // in). Exposed so consumers — notably the Phase 6 E2E test harness —
311
+ // can discover real table names rather than guess them from the
312
+ // `<app>-<stage>-<Name>` template (which omits the random suffix).
313
+ // Per CLAUDE.md, `.sst/outputs.json` IS the supported interface for
314
+ // post-deploy discovery.
315
+ sitesTable: storage.sites.name,
316
+ contentTable: storage.content.name,
317
+ draftContentTable: storage.draftContent.name,
318
+ blocksTable: storage.blocks.name,
319
+ mediaTable: storage.media.name,
320
+ collectionsTable: storage.collections.name,
321
+ blockTypesTable: storage.blockTypes.name,
322
+ adminAuditTable: storage.adminAudit.name,
323
+ relationshipsTable: storage.relationships.name,
324
+ siteUsersTable: storage.siteUsers.name,
325
+ webhooksTable: webhooks.webhooks.name,
326
+ contentBucket: storage.contentBucket.name,
327
+ backupBucket: storage.backupBucket.name,
292
328
  };
293
329
  }
294
330
  }
package/src/sst-env.d.ts CHANGED
@@ -154,6 +154,10 @@ declare namespace aws {
154
154
  class EventSourceMapping {
155
155
  constructor(name: string, args?: any, opts?: any);
156
156
  }
157
+
158
+ class FunctionEventInvokeConfig {
159
+ constructor(name: string, args?: any, opts?: any);
160
+ }
157
161
  }
158
162
  }
159
163
 
package/src/storage.ts CHANGED
@@ -39,15 +39,23 @@ export function createStorage(name: string) {
39
39
  fields: {
40
40
  pk: "string",
41
41
  sk: "string",
42
+ siteHost: "string",
42
43
  },
43
44
  primaryIndex: { hashKey: "pk", rangeKey: "sk" },
45
+ globalIndexes: {
46
+ bySite: { hashKey: "siteHost", rangeKey: "sk" },
47
+ },
44
48
  });
45
49
 
46
50
  const blocks = new sst.aws.Dynamo(`${name}Blocks`, {
47
51
  fields: {
48
52
  pk: "string",
53
+ siteHost: "string",
49
54
  },
50
55
  primaryIndex: { hashKey: "pk" },
56
+ globalIndexes: {
57
+ bySite: { hashKey: "siteHost", rangeKey: "pk" },
58
+ },
51
59
  });
52
60
 
53
61
  const media = new sst.aws.Dynamo(`${name}Media`, {
@@ -94,10 +102,12 @@ export function createStorage(name: string) {
94
102
  sk: "string",
95
103
  targetPk: "string",
96
104
  targetSk: "string",
105
+ siteHost: "string",
97
106
  },
98
107
  primaryIndex: { hashKey: "pk", rangeKey: "sk" },
99
108
  globalIndexes: {
100
109
  byTarget: { hashKey: "targetPk", rangeKey: "targetSk" },
110
+ bySite: { hashKey: "siteHost", rangeKey: "sk" },
101
111
  },
102
112
  });
103
113
 
@@ -106,14 +116,25 @@ export function createStorage(name: string) {
106
116
  pk: "string",
107
117
  sk: "string",
108
118
  userId: "string",
119
+ siteHost: "string",
109
120
  },
110
121
  primaryIndex: { hashKey: "pk", rangeKey: "sk" },
111
122
  globalIndexes: {
112
123
  byUserId: { hashKey: "userId", rangeKey: "sk" },
124
+ bySite: { hashKey: "siteHost", rangeKey: "sk" },
113
125
  },
114
126
  ttl: "expiresAt",
115
127
  });
116
128
 
129
+ // Backup bucket: archives of full site exports written by the backup worker.
130
+ // Layout: backups/{host}/{timestamp}.tar.gz + backups/{host}/latest.json.
131
+ // Versioning disabled — archives are immutable by convention (a new timestamp
132
+ // is a new object). No CloudFront origin — admin endpoints serve presigned
133
+ // URLs directly off S3.
134
+ const backupBucket = new sst.aws.Bucket(`${name}BackupBucket`, {
135
+ versioning: false,
136
+ });
137
+
117
138
  const contentBucket = new sst.aws.Bucket(`${name}ContentBucket`, {
118
139
  versioning: true,
119
140
  access: "cloudfront",
@@ -181,6 +202,7 @@ export function createStorage(name: string) {
181
202
  relationships,
182
203
  siteUsers,
183
204
  contentBucket,
205
+ backupBucket,
184
206
  collabStateBucket,
185
207
  kvs,
186
208
  internalSecret,
package/src/webhooks.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Webhook Infrastructure
3
3
  *
4
- * 2 DynamoDB tables + 2 SQS queues + webhook worker Lambda.
5
- * Supports dev mode (Go source) and package mode (pre-compiled binary).
4
+ * 2 DynamoDB tables + webhook worker Lambda (async-invoked by the API) + DLQ
5
+ * (Lambda async on-failure destination). The API directly invokes the worker
6
+ * via lambda:InvokeFunction; there is no SQS queue between them.
6
7
  */
7
8
 
8
9
  import path from "path";
@@ -35,6 +36,9 @@ export function createWebhooks(name: string, args: WebhookArgs) {
35
36
  ttl: "ttl",
36
37
  });
37
38
 
39
+ // DLQ retained as Lambda async OnFailure destination. Lambda writes a
40
+ // failure envelope (not the original payload verbatim) when retries are
41
+ // exhausted. No consumer polls this queue — it's a sink only.
38
42
  const webhookDeliveryDLQ = new sst.aws.Queue(`${name}WebhookDeliveryDLQ`, {
39
43
  transform: {
40
44
  queue: (queueArgs: any) => {
@@ -43,26 +47,6 @@ export function createWebhooks(name: string, args: WebhookArgs) {
43
47
  },
44
48
  });
45
49
 
46
- const webhookDeliveryQueue = new sst.aws.Queue(
47
- `${name}WebhookDeliveryQueue`,
48
- {
49
- dlq: {
50
- queue: webhookDeliveryDLQ.arn,
51
- retry: 5,
52
- },
53
- transform: {
54
- queue: (queueArgs: any) => {
55
- queueArgs.visibilityTimeoutSeconds = 60;
56
- queueArgs.messageRetentionSeconds = 4 * 24 * 60 * 60; // 4 days
57
- },
58
- },
59
- },
60
- );
61
-
62
- // Webhook worker Lambda: processes SQS messages and delivers webhooks.
63
- // Note: We use a manual Function + EventSourceMapping instead of
64
- // queue.subscribe() to avoid a duplicate LambdaEncryptionKey issue
65
- // caused by SST's dynamic import creating a separate Function class instance.
66
50
  const workerConfig = args.dev
67
51
  ? {
68
52
  handler: args.dev.handler,
@@ -81,32 +65,31 @@ export function createWebhooks(name: string, args: WebhookArgs) {
81
65
  timeout: "30 seconds",
82
66
  environment: {
83
67
  WEBHOOK_DELIVERIES_TABLE: webhookDeliveries.name,
84
- WEBHOOKS_TABLE: webhooks.name,
85
- SITES_TABLE: args.sites.name,
86
68
  },
87
- link: [webhookDeliveries, webhooks, args.sites],
88
- permissions: [
89
- {
90
- actions: [
91
- "sqs:ReceiveMessage",
92
- "sqs:DeleteMessage",
93
- "sqs:GetQueueAttributes",
94
- ],
95
- resources: [webhookDeliveryQueue.arn],
96
- },
97
- ],
69
+ // webhookDeliveryDLQ is linked so SST auto-grants sqs:SendMessage on the
70
+ // worker's execution role. Lambda async OnFailure delivery uses the
71
+ // function's own role to write the failure envelope to the DLQ — without
72
+ // this grant, AWS accepts the FunctionEventInvokeConfig at deploy time but
73
+ // silently drops failure envelopes at runtime.
74
+ link: [webhookDeliveries, webhookDeliveryDLQ],
98
75
  });
99
76
 
100
- new aws.lambda.EventSourceMapping(`${name}WebhookWorkerEventSource`, {
101
- eventSourceArn: webhookDeliveryQueue.arn,
77
+ // Lambda async retry + DLQ on terminal failure. MaximumRetryAttempts is
78
+ // 0–2 (industry standard for webhook delivery — Stripe/GitHub publish
79
+ // similar caps). Total attempts = initial + 2 retries = 3.
80
+ new aws.lambda.FunctionEventInvokeConfig(`${name}WebhookWorkerAsyncConfig`, {
102
81
  functionName: webhookWorker.name,
103
- batchSize: 1,
82
+ maximumRetryAttempts: 2,
83
+ maximumEventAgeInSeconds: 6 * 60 * 60, // 6 hours
84
+ destinationConfig: {
85
+ onFailure: { destination: webhookDeliveryDLQ.arn },
86
+ },
104
87
  });
105
88
 
106
89
  return {
107
90
  webhooks,
108
91
  webhookDeliveries,
109
- webhookDeliveryQueue,
92
+ webhookWorker,
110
93
  webhookDeliveryDLQ,
111
94
  };
112
95
  }
@@ -1 +0,0 @@
1
- import{j as e}from"./tanstack-Bs3zYPPV.js";import{u as R,f as U,r as o}from"./react-vendor-C2CvUxFh.js";import{W as b,aF as V,S as T,aG as G,aH as W,aI as z,x as J,L as u,I as K,a0 as B,B as x,a as Q,D as X,i as Y,T as Z,k as ee,l as se,m as te,n as ae,o as ie,v as h}from"./index-Ce5pmRMj.js";import{I as ne,a as re,F as le}from"./IconPicker-CpIgiQTC.js";import{i as oe}from"./format-C88SDH8g.js";import{T as ce}from"./textarea-6fq0R6VV.js";import{C as de,a as me,b as pe,c as ue}from"./card-C9hfyHXf.js";import{C as $,a as D,b as F}from"./collapsible-D3d29uJp.js";import{C as xe}from"./CustomBlockPreview-DNnTFM0z.js";import{F as he}from"./FieldRenderer-DiOKvkWV.js";import{u as N}from"./useContentSearch-B3aTjuCu.js";import{u as je}from"./usePageTitle-C1r1-C00.js";import"./radix-C5ZmWuuL.js";import"./core.esm-DdQHdRkd.js";import"./sortable.esm-qVEMoaTg.js";import"./select-CrRhFGIi.js";import"./checkbox-DVJcwUt1.js";import"./popover-CzaQYEEP.js";import"./media-url-DdCoIedP.js";import"./MediaField-CxccCFGQ.js";import"./useMedia-ae3s_ajC.js";import"./ContentField-pilCbdnA.js";import"./command-Bfmj0MEL.js";function fe({fields:a,previewTemplate:s,previewData:t,onPreviewDataChange:i,blockTypeName:l,blockTypeLabel:d,blockTypeIcon:v}){const n=N(s,300),g=N(t,300);return e.jsxs("div",{className:"space-y-4",children:[e.jsx(he,{fields:a,values:t,onChange:i}),e.jsx(b,{}),e.jsx("div",{className:"overflow-hidden rounded-md border p-4",children:e.jsx(xe,{blockType:{name:l,label:d,icon:v,fields:a,previewTemplate:n},props:g,blocksToHTML:()=>""})})]})}function Ue(){const{host:a,name:s}=R(),t=s==="new",{data:i,isLoading:l}=V(a,t?"":s);return!t&&l?e.jsxs("div",{className:"space-y-4",children:[e.jsx(T,{className:"h-8 w-64"}),e.jsx(T,{className:"h-64 w-full"})]}):t?e.jsx(C,{host:a,isNew:!0}):i?e.jsx(C,{host:a,isNew:!1,blockType:i},i.name):e.jsx("p",{className:"text-muted-foreground",children:"Block type not found."})}function C({host:a,isNew:s,blockType:t}){const i=U(),l=G(a),d=W(a,t?.name??""),v=z(a,t?.name??""),[n,g]=o.useState(t?.name??""),[j,y]=o.useState(t?.label??""),[f,P]=o.useState(t?.icon??""),[S,L]=o.useState(!s),I=new Set((t?.fields??[]).map(r=>r.name).filter(Boolean)),[c,E]=o.useState(t?.fields??[]),[m,O]=o.useState(t?.previewTemplate??""),[p,q]=o.useState(t?.previewData??{}),[H,w]=o.useState(!1),_=J();je({title:s?"New Block Type":t?.label??n,showBack:!0,backTo:`/sites/${a}/settings/block-types`});async function A(r){r.preventDefault();try{s?(await l.mutateAsync({name:n,label:j,icon:f,fields:c,previewTemplate:m||void 0,previewData:Object.keys(p).length>0?p:void 0}),h.success("Block type created"),i(`/sites/${a}/settings/block-types/${n}`)):(await d.mutateAsync({label:j,icon:f,fields:c,previewTemplate:m||void 0,previewData:Object.keys(p).length>0?p:void 0}),h.success("Block type updated"))}catch(k){h.error(s?"Failed to create":"Failed to update",{description:k instanceof Error?k.message:void 0})}}async function M(){try{await v.mutateAsync(),h.success("Block type deleted"),i(`/sites/${a}/settings/block-types`)}catch(r){h.error("Failed to delete",{description:r instanceof Error?r.message:void 0})}}return e.jsxs("div",{className:"mx-auto max-w-2xl",children:[!_&&e.jsx("h1",{className:"mb-6 text-2xl font-semibold",children:s?"New Block Type":`Edit: ${t?.label??n}`}),e.jsxs(de,{children:[e.jsx(me,{children:e.jsx(pe,{children:"Block Type Settings"})}),e.jsx(ue,{children:e.jsxs("form",{onSubmit:A,className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(u,{htmlFor:"name",children:"Name"}),e.jsx(ne,{id:"name",value:n,onChange:g,onBlur:()=>{n&&!S&&y(oe(n))},readOnly:!s,placeholder:"e.g. hero_banner",required:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(u,{htmlFor:"label",children:"Label"}),e.jsx(K,{id:"label",value:j,onChange:r=>{y(r.target.value),L(!0)},required:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(u,{children:"Icon"}),e.jsx(re,{value:f,onChange:P})]}),e.jsx(b,{}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(u,{children:"Block Fields"}),e.jsx(le,{fields:c,onChange:E,existingFieldNames:I})]}),e.jsx(b,{}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(u,{htmlFor:"preview-template",children:"Preview Template (Liquid + Tailwind)"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Optional. Use Liquid syntax to render a preview. Tailwind utility classes are supported."}),e.jsx(ce,{id:"preview-template",value:m,onChange:r=>O(r.target.value),rows:6,placeholder:'<div class="p-4">{{ title }}</div>',className:"font-mono text-sm"}),c.length>0&&e.jsx(ge,{fields:c})]}),(m||c.length>0)&&e.jsxs($,{children:[e.jsxs(D,{className:"flex w-full items-center gap-2 text-sm font-medium",children:[e.jsx(B,{className:"h-4 w-4 transition-transform [[data-state=open]>&]:rotate-90"}),"Preview"]}),e.jsx(F,{className:"mt-2",children:e.jsx(fe,{fields:c,previewTemplate:m,previewData:p,onPreviewDataChange:q,blockTypeName:n,blockTypeLabel:j,blockTypeIcon:f})})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(x,{type:"submit",disabled:l.isPending||d.isPending,children:[(l.isPending||d.isPending)&&e.jsx(Q,{className:"mr-2 h-4 w-4 animate-spin"}),s?"Create":"Save"]}),e.jsx(x,{type:"button",variant:"outline",onClick:()=>i(`/sites/${a}/settings/block-types`),children:"Cancel"})]})]})})]}),!s&&e.jsx("div",{className:"mt-6",children:e.jsxs(X,{open:H,onOpenChange:w,children:[e.jsx(Y,{asChild:!0,children:e.jsxs(x,{variant:"destructive",children:[e.jsx(Z,{className:"mr-2 h-4 w-4"}),"Delete Block Type"]})}),e.jsxs(ee,{children:[e.jsxs(se,{children:[e.jsx(te,{children:"Delete block type?"}),e.jsx(ae,{children:"This will permanently delete this block type."})]}),e.jsxs(ie,{children:[e.jsx(x,{variant:"outline",onClick:()=>w(!1),children:"Cancel"}),e.jsx(x,{variant:"destructive",onClick:M,children:"Delete"})]})]})]})})]})}function ve(a){const s=a.name;switch(a.type){case"media":return`{{ ${s}.url | media_url }} {{ ${s}.alt }} {{ ${s}.width }}`;case"content":return`{{ ${s}.title }} {{ ${s}.id }}`;case"boolean":return`{% if ${s} %}...{% endif %}`;case"array":{const t=a.options?.itemFields;if(t&&t.length>0){const i=t.map(l=>`item.${l.name}`).join(" }} {{ ");return`{% for item in ${s} %}{{ ${i} }}{% endfor %}`}return`{% for item in ${s} %}{{ item }}{% endfor %}`}case"select":return a.options?.multiple?`{% for item in ${s} %}{{ item }}{% endfor %}`:`{{ ${s} }}`;case"container":{const t=a.options?.fields;return t&&t.length>0?t.map(i=>`{{ ${s}.${i.name} }}`).join(" "):`{{ ${s}.fieldName }}`}case"blocks":return`{{ ${s} | blocks_html }} or {{ ${s} | blocks_text }}`;default:return`{{ ${s} }}`}}function ge({fields:a}){return e.jsxs($,{children:[e.jsxs(D,{className:"flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",children:[e.jsx(B,{className:"h-3 w-3 transition-transform [[data-state=open]>&]:rotate-90"}),"Template variables"]}),e.jsx(F,{children:e.jsx("div",{className:"mt-1 rounded-md border bg-muted/50 p-2 font-mono text-xs space-y-0.5",children:a.map(s=>e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("span",{className:"text-muted-foreground shrink-0",children:[s.label,":"]}),e.jsx("code",{children:ve(s)})]},s.name))})})]})}export{Ue as BlockTypeEditPage};
@@ -1 +0,0 @@
1
- import{a as Bs,u as Pn,b as En,j as e}from"./tanstack-Bs3zYPPV.js";import{r as s,u as Ln,f as Tn,m as In,L as Un}from"./react-vendor-C2CvUxFh.js";import{f as Fn,g as St,h as On,i as Ct,j as Bn,k as qn,l as $n,m as Vn,n as _n,o as Mn,p as Hn,q as Jn,r as wt}from"./useContent-Bs7nel7C.js";import{C as Ee,v as V,E as qs,e as ls,u as $s,F as zn,G as Ss,B as P,y as cs,J as Kn,K as Yn,M as Qn,N as Gn,S as fe,O as Rt,Q as Nt,R as ns,V as as,W as Dt,Y as At,Z as Pt,_ as Et,U as Wn,$ as Xn,w as Zn,d as ea,x as sa,L as Ze,I as it,a0 as Lt,X as rt,a1 as ta,a2 as lt,a3 as na,a4 as ct,a5 as aa,j as ia,a as ve,a6 as ot,a7 as dt,a8 as ra,a9 as ut,aa as Cs,ab as la,ac as ca,D as Es,k as Ls,l as Ts,m as Is,n as Us,o as Fs,i as oa,T as da}from"./index-Ce5pmRMj.js";import{A as Tt,a as It,b as Ut,c as Ft,d as Ot,e as Bt,f as qt,g as $t,T as ua}from"./TagInput-57c4DG1w.js";import{a as ts,f as Se}from"./format-C88SDH8g.js";import{u as Vt}from"./useAdminResolver-BJNPz3OG.js";import{u as ha}from"./usePageTitle-C1r1-C00.js";import{s as Oe,T as fa,d as ma}from"./serializeToText-2VrsuRUh.js";import{S as pa,a as ga,b as ba,c as xa,d as ws,e as va,f as ya,g as ja}from"./select-CrRhFGIi.js";import{T as ka}from"./textarea-6fq0R6VV.js";import{C as Ue,c as Fe,a as ht,b as ft}from"./card-C9hfyHXf.js";import{C as _t,a as Mt,b as Ht}from"./collapsible-D3d29uJp.js";import{u as Sa}from"./useTags-B-HgMVwo.js";import{M as Ca}from"./MediaField-CxccCFGQ.js";import{m as wa}from"./media-url-DdCoIedP.js";import{R as Ra}from"./RelationshipPicker-B3Ftmqxp.js";import{A as Na,a as Da,i as Aa,F as Pa,b as es,C as Ea}from"./FieldRenderer-DiOKvkWV.js";import{g as La,a as Ta,b as Ia}from"./contentStatus-CkPi9Dh6.js";import{O as Ua,f as Fa,g as is,e as Jt,w as Rs,a as Oa,t as Ba,r as Ns,b as qa,c as $a,d as Va,h as _a,i as mt,j as Ma,D as Ha}from"./yjs-tXBm_srz.js";import"./radix-C5ZmWuuL.js";import"./useMedia-ae3s_ajC.js";import"./core.esm-DdQHdRkd.js";import"./sortable.esm-qVEMoaTg.js";import"./ContentField-pilCbdnA.js";import"./popover-CzaQYEEP.js";import"./command-Bfmj0MEL.js";import"./useContentSearch-B3aTjuCu.js";import"./checkbox-DVJcwUt1.js";const Ja=3e3,za="__HEADROOM_API_URL__".replace(/\/+$/,"");function Ka(r,t,i,a,l,c=Ja,f,h={}){const m=Fn(r,t),u=s.useRef(null),v=s.useRef(i?JSON.stringify(i):""),x=s.useRef(void 0),[S,w]=s.useState(null),[j,L]=s.useState(null),C=s.useRef(!1),R=s.useRef(!1),y=s.useRef(!1),k=s.useRef(!1),N=s.useRef(!1),[$,M]=s.useState(!1),_=s.useRef(!1),E=s.useCallback(O=>{_.current!==O&&(_.current=O,M(O))},[]),D=s.useRef(f);s.useEffect(()=>{D.current=f},[f]);const T=s.useRef(h.onBeforeFirstSave);s.useEffect(()=>{T.current=h.onBeforeFirstSave},[h.onBeforeFirstSave]);const X=s.useRef(h.onStaleBaseConflict);s.useEffect(()=>{X.current=h.onStaleBaseConflict},[h.onStaleBaseConflict]);const K=s.useRef(h.getCurrentParams);s.useEffect(()=>{K.current=h.getCurrentParams},[h.getCurrentParams]);const se=s.useCallback(O=>{N.current||JSON.stringify(O)===v.current||(u.current=O,E(!0),clearTimeout(x.current),x.current=window.setTimeout(async()=>{if(!u.current)return;if(!k.current&&T.current)try{if(!(await T.current()).ok)return;k.current=!0}catch{return}if(!u.current||R.current)return;const I=u.current,H=JSON.stringify(I);y.current=!0,m.mutate(I,{onSuccess:A=>{if(y.current=!1,C.current){C.current=!1;return}u.current===I&&(u.current=null,E(!1)),v.current=H,w(Date.now()),A?.blockId&&L(A.blockId),D.current?.(A)},onError:A=>{if(y.current=!1,A instanceof Ee&&A.code==="SLUG_TAKEN")a?.();else if(A instanceof Ee&&A.code==="LOCK_HELD")k.current=!1,l?.(A);else if(A instanceof Ee&&A.code==="STALE_BASE"){const J=A.body;X.current?.(J?.currentUpdatedAt??0,J?.currentBlockId??"")}else A instanceof Ee&&A.status===400?V.error("Auto-save failed",{description:A.message}):A instanceof Ee&&A.status>=500&&V.error("Auto-save failed",{description:"The server returned an error. Reload to continue editing safely."})}})},c))},[m,a,l,c,E]),re=s.useCallback(async O=>{clearTimeout(x.current),R.current=!0;try{let B=null;if(u.current?B={...u.current}:O?.createVersion&&K.current&&(B=K.current()),!B)return;if(O?.createVersion&&(B.createVersion=!0),!k.current&&T.current)try{if(!(await T.current()).ok)return;k.current=!0}catch{return}const I=JSON.stringify(B);u.current=null,E(!1);const H=await m.mutateAsync(B);v.current=I,w(Date.now()),H?.blockId&&L(H.blockId)}finally{R.current=!1}},[m,E]),Z=s.useCallback(()=>{clearTimeout(x.current),u.current=null,E(!1)},[E]),Q=s.useCallback(()=>{k.current=!1},[]),F=s.useCallback(O=>{v.current=JSON.stringify(O),k.current=!1},[]),le=s.useCallback(()=>{clearTimeout(x.current),u.current=null,E(!1),C.current=!0,L(null),k.current=!1},[E]),o=s.useCallback(()=>{N.current=!0,clearTimeout(x.current)},[]),d=s.useCallback(()=>{N.current=!1},[]);return s.useEffect(()=>()=>{if(clearTimeout(x.current),u.current){const{sessionId:O,...B}=u.current,I=JSON.stringify(B),H=qs(),A=`${za}/v1/admin/sites/${r}/content/${t}/draft`;fetch(A,{method:"PUT",body:I,headers:{"Content-Type":"application/json",...H?{Authorization:`Bearer ${H}`}:{}},keepalive:!0}).catch(()=>{}),u.current=null}},[r,t]),{schedule:se,flush:re,cancel:Z,resetBaseline:F,discard:le,pause:o,resume:d,markLockReleased:Q,isDirty:$,isSaving:m.isPending,lastSavedAt:S,lastSavedBlockId:j,getIsSavingSync:()=>y.current,getHasPending:()=>u.current!==null}}const pt="headroom:idleHintShown",Ya="__HEADROOM_API_URL__".replace(/\/+$/,""),Qa=5e3,Ga=3600*1e3,Wa=6e4,Ds=2e3;function Xa(r){const t=`headroom:editSession:${r}`;let i=sessionStorage.getItem(t);return i||(i=zn(),sessionStorage.setItem(t,i)),i}const As=new Map;function Za(r,t,i={}){const a=ls(),{user:l}=$s(),c=Bs(),[f,h]=s.useState("viewing"),[m,u]=s.useState(null),[v,x]=s.useState(null),[S,w]=s.useState([]),[j,L]=s.useState(!1),[C,R]=s.useState(!1),y=t?Xa(t):"",k=s.useRef(0),N=s.useRef(!1),$=s.useRef(!1),M=s.useRef(!1),_=s.useRef(null),E=s.useRef(null),D=s.useRef(0),T=s.useRef(null),X=s.useRef(i.getIsDirty),K=s.useRef(i.getIsSaving),se=s.useRef(i.getIsSavingSync),re=s.useRef(i.onIdleRelease);s.useEffect(()=>{X.current=i.getIsDirty,K.current=i.getIsSaving,se.current=i.getIsSavingSync,re.current=i.onIdleRelease});const Z=s.useCallback(async(b=!1)=>{if(!r||!t||!y)return null;const q=`${r}:${t}:${b?"force":"edit"}`,U=As.get(q);if(U)return U;const ee=a.apiFetch(`/v1/admin/sites/${r}/content/${t}/edit-lock`,{method:"POST",body:JSON.stringify({sessionId:y,force:b,email:l?.email,name:l?.name})}).finally(()=>{As.delete(q)});return As.set(q,ee),ee},[a,r,t,y,l?.email,l?.name]),Q=s.useCallback(async()=>{if(!(!r||!t||!y)&&!$.current&&!M.current){$.current=!0,M.current=!0;try{await a.apiFetch(`/v1/admin/sites/${r}/content/${t}/edit-lock`,{method:"DELETE",body:JSON.stringify({sessionId:y})})}catch{}finally{M.current=!1}}},[a,r,t,y]),F=s.useCallback(()=>{_.current&&(clearTimeout(_.current),_.current=null),E.current&&(clearTimeout(E.current),E.current=null)},[]),le=s.useRef(()=>{}),o=s.useCallback(()=>{const b=X.current?X.current():!1,q=K.current?K.current():!1,U=se.current?se.current():!1;if(b||q||U){E.current=setTimeout(()=>le.current(),1e3);return}if(N.current){N.current=!1,Q(),re.current?.(),h("idle-released"),u(null),x(null),w([]),R(!1);try{typeof window<"u"&&window.sessionStorage&&(window.sessionStorage.getItem(pt)||(V("Released editing — others can edit now."),window.sessionStorage.setItem(pt,"1")))}catch{}}},[Q]);s.useEffect(()=>{le.current=o},[o]);const d=s.useCallback(()=>{F(),_.current=setTimeout(o,Wa)},[F,o]),O=s.useCallback(()=>{if(C){F();return}N.current&&d()},[C,F,d]),B=s.useRef(C);s.useEffect(()=>{const b=B.current;B.current=C,b!==C&&(C?F():N.current&&d())},[C,F,d]);const I=s.useCallback(async()=>{if(!r||!t||!y||!l)return{ok:!1,holder:null};if(Date.now()<D.current)return{ok:!1,holder:T.current};try{const b=await Z(!1);if(!b||!b.acquired){const q=b?.lockHolder??null;return D.current=Date.now()+Ds,T.current=q,h("blocked-edit"),u(q),R(b?.collaborationEnabled??!1),k.current||(k.current=Date.now()),{ok:!1,holder:q}}return N.current=!0,$.current=!1,D.current=0,T.current=null,h("editing"),u(b.lockHolder??null),x(b.takeoverReason),R(b.collaborationEnabled),d(),{ok:!0}}catch(b){const q=b;if(q.status===409){const U=q.body?.lockHolder??null,ee=q.body?.collaborationEnabled??!1;if(U&&U.sub===l.sub&&U.sessionId!==y)try{const G=await Z(!1);if(G?.acquired)return N.current=!0,$.current=!1,D.current=0,T.current=null,h("editing"),u(G.lockHolder??null),x(G.takeoverReason),R(G.collaborationEnabled),d(),{ok:!0}}catch{}return D.current=Date.now()+Ds,T.current=U,h("blocked-edit"),u(U),R(ee),k.current||(k.current=Date.now()),{ok:!1,holder:U}}return h("error"),{ok:!1,holder:null}}},[r,t,y,l,Z,d]);s.useEffect(()=>{if(!r||!t||!y)return;const b=()=>{if(!N.current||$.current||M.current)return;$.current=!0;const q=qs(),U=`${Ya}/v1/admin/sites/${r}/content/${t}/edit-lock`;fetch(U,{method:"DELETE",body:JSON.stringify({sessionId:y}),headers:{"Content-Type":"application/json",...q?{Authorization:`Bearer ${q}`}:{}},keepalive:!0}).catch(()=>{})};return window.addEventListener("beforeunload",b),()=>window.removeEventListener("beforeunload",b)},[r,t,y]);const H=s.useRef(Q),A=s.useRef(F);s.useEffect(()=>{H.current=Q,A.current=F},[Q,F]),s.useEffect(()=>()=>{A.current(),N.current&&(N.current=!1,H.current())},[r,t,y]);const J=f==="blocked-edit"&&!j,ye=s.useCallback(b=>{if(k.current&&Date.now()-k.current>Ga){L(!0),h("poll-ceiling");return}const q=b.lock;if(!q)D.current=0,T.current=null,u(null),R(!1),w([]),h("idle-released"),k.current=0;else{u(q.heldBy),R(q.collaborationEnabled);const U=(q.accessRequests??[]).filter(ee=>ee.sub!==l?.sub);w(U)}},[l?.sub]);Pn({queryKey:["sites",r,"edit-lock",t],queryFn:async()=>{try{const b=await a.apiFetch(`/v1/admin/sites/${r}/content/${t}/edit-lock`);return ye(b),b}catch{return{lock:m?{heldBy:m,expiresAt:0,collaborationEnabled:C,accessRequests:[]}:null}}},enabled:J,refetchInterval:J?Qa:!1,refetchIntervalInBackground:!1,retry:!1});const ne=En({mutationFn:()=>a.apiFetch(`/v1/admin/sites/${r}/content/${t}/edit-lock/access-requests`,{method:"POST",body:JSON.stringify({sessionId:y,email:l?.email,name:l?.name})})}),g=s.useCallback(async()=>{const b=await Z(!0);return b?.acquired&&(N.current=!0,$.current=!1,D.current=0,T.current=null,h("editing"),u(b.lockHolder??null),x(b.takeoverReason),R(b.collaborationEnabled),d(),c.invalidateQueries({queryKey:["sites",r,"edit-lock",t]})),b},[Z,c,r,t,d]),Be=s.useCallback(async()=>I(),[I]),Y=s.useCallback(b=>{N.current=!1,F(),D.current=Date.now()+Ds,T.current=b.lockHolder??null,h("blocked-edit"),u(b.lockHolder??null),x(b.takeoverReason??null),k.current||(k.current=Date.now())},[F]),os=s.useCallback(()=>{F(),N.current&&(N.current=!1,Q()),D.current=0,T.current=null,h("viewing"),u(null),x(null),R(!1),w([]),k.current=0},[F,Q]),ds=s.useCallback(()=>{F(),h("stale-reload-pending")},[F]),de=s.useCallback(()=>{h("editing"),N.current&&d()},[d]),me=s.useCallback(()=>{F(),D.current=0,T.current=null,h("read-only-explicit")},[F]),je=s.useCallback(()=>{h("viewing")},[]);return{status:f,lockHolder:m,takeoverReason:v,accessRequests:S,sessionId:y,pollCeiling:j,collaborationEnabled:C,acquireLock:Z,releaseLock:Q,tryAcquireForEdit:I,bumpIdleTimer:O,requestCollaboration:ne,forceTakeover:g,takeEditing:Be,endEditing:os,setStaleReloadPending:ds,resumeEditingAfterStale:de,setReadOnlyExplicit:me,exitReadOnly:je,onAutosaveConflict:Y,setAccessRequests:w,setCollaborationEnabled:R}}function ei({host:r,contentId:t,isDirty:i,serverBlockId:a,serverUpdatedAt:l,onSilentReload:c,onStaleWithDirty:f,onTabHidden:h,onTabVisibleResume:m,minHiddenMs:u=3e4}){const v=Bs(),x=s.useRef(null),S=s.useRef(i),w=s.useRef(a),j=s.useRef(l),L=s.useRef(c),C=s.useRef(f),R=s.useRef(h),y=s.useRef(m),k=s.useRef(u);s.useEffect(()=>{S.current=i,w.current=a,j.current=l,L.current=c,C.current=f,R.current=h,y.current=m,k.current=u},[i,a,l,c,f,h,m,u]),s.useEffect(()=>{if(typeof document>"u"||!r||!t)return;const N=["sites",r,"content-detail",t];let $=!1;const M=async()=>{if(typeof document>"u")return;if(document.visibilityState==="hidden"){x.current=Date.now(),R.current&&R.current();return}if(document.visibilityState!=="visible")return;const _=x.current;if(x.current=null,_==null)return;if(Date.now()-_<k.current){y.current&&y.current();return}if(await v.refetchQueries({queryKey:[...N],exact:!0}),$)return;const D=v.getQueryData([...N]);if(!D){y.current&&y.current();return}const T=D.draft?.updatedAt,X=D.draft?.blockId,K=j.current??0,se=w.current??null;if(!(typeof T=="number"&&T>K||X!=null&&X!==se)){y.current&&y.current();return}$||(S.current?C.current(D):(y.current&&y.current(),L.current(D)))};return document.addEventListener("visibilitychange",M),()=>{$=!0,document.removeEventListener("visibilitychange",M)}},[r,t,v])}function Vs(){return"__HEADROOM_COLLAB_ENABLED__"!=="false"}function gt({variant:r="read-only-explicit",lockHolder:t,onRequestCollaboration:i,onForceTakeover:a,onDiscardPending:l,onViewReadOnly:c,onResumeEditing:f,isRequesting:h,requestSent:m}){if(r==="poll-ceiling")return e.jsx("div",{className:"bg-amber-50 border border-amber-200 rounded-lg p-4 mb-4","data-testid":"edit-lock-banner","data-variant":"poll-ceiling",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Ss,{className:"h-5 w-5 text-amber-600 mt-0.5 shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"font-medium text-amber-900",children:"Lock check paused"}),e.jsx("p",{className:"text-sm text-amber-700 mt-1",children:"Refresh the page to retry."})]})]})});const u=Vs(),v=t?.name||t?.email||"another user";return r==="blocked-edit"?e.jsx("div",{className:"bg-amber-50 border border-amber-200 rounded-lg p-4 mb-4","data-testid":"edit-lock-banner","data-variant":"blocked-edit",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Ss,{className:"h-5 w-5 text-amber-600 mt-0.5 shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("p",{className:"font-medium text-amber-900",children:[v," is editing this content"]}),e.jsxs("p",{className:"text-sm text-amber-700 mt-1",children:["Your changes are pending and will be saved when ",v," finishes."]}),e.jsxs("div",{className:"flex flex-wrap gap-2 mt-3 items-center",children:[u&&i&&e.jsx(P,{size:"sm",variant:"outline",onClick:i,disabled:h||m,"data-testid":"request-collaboration-btn",children:m?"Request sent":"Request collaboration"}),l&&e.jsx(P,{size:"sm",variant:"ghost",onClick:l,"data-testid":"discard-pending-btn",children:"Discard pending changes"}),c&&e.jsx(P,{size:"sm",variant:"ghost",onClick:c,"data-testid":"view-read-only-btn",children:"View read-only"}),a&&e.jsx(P,{size:"sm",variant:"destructive",onClick:a,"data-testid":"force-takeover-btn",children:"Take over"})]})]})]})}):e.jsx("div",{className:"bg-amber-50 border border-amber-200 rounded-lg p-4 mb-4","data-testid":"edit-lock-banner","data-variant":"read-only-explicit",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Ss,{className:"h-5 w-5 text-amber-600 mt-0.5 shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("p",{className:"font-medium text-amber-900",children:["Editing: ",v]}),e.jsx("p",{className:"text-sm text-amber-700 mt-1",children:u?"This content is being edited. You can view it read-only or ask to collaborate.":"This content is being edited. You can view it read-only until the editor is finished."}),e.jsxs("div",{className:"flex gap-2 mt-3",children:[u&&i&&e.jsx(P,{size:"sm",variant:"outline",onClick:i,disabled:h||m,"data-testid":"request-collaboration-btn",children:m?"Request sent":"Request collaboration"}),f&&e.jsx(P,{size:"sm",variant:"ghost",onClick:f,"data-testid":"resume-editing-btn",children:"Resume editing"})]})]})]})})}function si({open:r,trigger:t,updatedBy:i,updatedAt:a,onReload:l,onCancel:c}){const f=a>0?ts(a):"just now";return e.jsx(Tt,{open:r,children:e.jsxs(It,{"data-testid":"stale-reload-modal","data-trigger":t,onEscapeKeyDown:h=>h.preventDefault(),children:[e.jsxs(Ut,{children:[e.jsx(Ft,{children:"This content was updated"}),e.jsx(Ot,{children:t==="save-conflict"?e.jsxs(e.Fragment,{children:["Your save couldn't go through —"," ",e.jsx("strong",{"data-testid":"stale-reload-updated-by",children:i})," ",e.jsxs("span",{className:"text-muted-foreground","data-testid":"stale-reload-updated-at",children:["(",f,")"]})," ","updated this content since you started editing. Reload to see the latest version (your unsaved changes will be lost), or cancel to keep editing — your next save will hit the same conflict."]}):e.jsxs(e.Fragment,{children:["This content was updated by"," ",e.jsx("strong",{"data-testid":"stale-reload-updated-by",children:i})," ",e.jsxs("span",{className:"text-muted-foreground","data-testid":"stale-reload-updated-at",children:["(",f,")"]})," ","while this tab was inactive. Reload to see the latest version (your unsaved changes will be lost), or cancel to keep editing your version — the next save will be rejected if it conflicts."]})})]}),e.jsxs(Bt,{children:[e.jsx(qt,{onClick:c,"data-testid":"stale-reload-cancel-btn",children:"Cancel"}),e.jsx($t,{onClick:l,"data-testid":"stale-reload-reload-btn",children:"Reload"})]})]})})}function ti({lines:r}){return e.jsx("div",{className:"font-mono text-sm leading-relaxed",children:r.map((t,i)=>e.jsx("div",{style:{paddingLeft:`${t.indent*1.5}rem`},className:cs("min-h-[1.5em]",t.type==="label"&&"text-muted-foreground font-semibold mt-1",t.type==="heading"&&"font-bold",t.type==="empty"&&"h-2"),children:t.text},i))})}function Os(r){switch(r.kind){case"draft":return"Draft";case"published":return"Published";case"history":return Se(r.createdAt)}}function rs(r){switch(r.kind){case"draft":return"draft";case"published":return"published";case"history":return`history:${r.blockId}`}}function bt({value:r,onChange:t,isPublished:i,versions:a,exclude:l,size:c}){const f=l?rs(l):null;function h(m){if(m==="draft")t({kind:"draft"});else if(m==="published")t({kind:"published"});else if(m.startsWith("history:")){const u=m.slice(8),v=a.find(x=>x.blockId===u);v&&t({kind:"history",blockId:v.blockId,createdAt:v.createdAt,title:v.title})}}return e.jsxs(pa,{value:rs(r),onValueChange:h,children:[e.jsx(ga,{size:c,children:e.jsx(ba,{children:Os(r)})}),e.jsxs(xa,{position:"popper",children:[f!=="draft"&&e.jsx(ws,{value:"draft",children:"Draft"}),i&&f!=="published"&&e.jsx(ws,{value:"published",children:"Published"}),a.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(va,{}),e.jsxs(ya,{children:[e.jsx(ja,{children:"Version History"}),a.map(m=>{const u=`history:${m.blockId}`;return u===f?null:e.jsx(ws,{value:u,children:Se(m.createdAt)},u)})]})]})]})]})}function xt({ref:r,host:t,contentId:i,collectionFields:a,isSingleton:l,draftBody:c,draftMetadata:f,collectionRelationships:h,draftRelationships:m}){const u=r?.kind==="published",v=r?.kind==="history",x=v?r.blockId:null,{data:S,isLoading:w}=St(t,i,u),{data:j,isLoading:L}=On(t,i,v?x:null),C=s.useMemo(()=>(h??[]).map(k=>({name:k.name,label:k.label})),[h]);function R(k){if(C.length!==0)return{defs:C,values:k??{}}}const y=s.useMemo(()=>{if(!r)return[];if(r.kind==="draft")return c?Oe(a,c,l?void 0:f,R(m)):[];if(r.kind==="published"){if(!S)return[];const $=l?void 0:{title:S.title,slug:S.slug,snippet:S.snippet,tags:S.tags},M=S.relationships;return Oe(a,S.fields??{},$,R(M))}if(!j)return[];const k=l?void 0:{title:j.title,slug:j.slug,snippet:j.snippet,tags:j.tags},N=j.relationships;return Oe(a,j.body??{},k,R(N))},[r,c,f,m,S,j,a,l,C]);return r?r.kind==="draft"?{lines:y,isLoading:!1,hasData:!!c}:r.kind==="published"?{lines:y,isLoading:w,hasData:!!S}:{lines:y,isLoading:L,hasData:!!j}:{lines:[],isLoading:!1,hasData:!1}}function ni({open:r,onOpenChange:t,host:i,contentId:a,collectionFields:l,isSingleton:c,isPublished:f,draftBody:h,draftMetadata:m,initialVersion:u,collectionRelationships:v,draftRelationships:x}){const[S,w]=s.useState(u??{kind:"published"}),[j,L]=s.useState({kind:"draft"}),[C,R]=s.useState(r),[y,k]=s.useState(u);if((r!==C||u!==y)&&(R(r),k(u),r)){const T=u??{kind:"published"};w(T),L(T.kind==="draft"?{kind:"published"}:{kind:"draft"})}rs(S)===rs(j)&&(S.kind!=="draft"?L({kind:"draft"}):f&&L({kind:"published"}));const{data:N}=Ct(i,a),$=N?.items??[],M={host:i,contentId:a,collectionFields:l,isSingleton:c,draftBody:h,draftMetadata:m,collectionRelationships:v,draftRelationships:x},_=xt({ref:r?S:null,...M}),E=xt({ref:r?j:null,...M}),D=_.isLoading;return e.jsx(Kn,{open:r,onOpenChange:t,children:e.jsxs(Yn,{className:"w-[calc(100vw-2rem)] sm:max-w-2xl overflow-y-auto pt-[env(safe-area-inset-top,0px)] pr-[env(safe-area-inset-right,0px)]",children:[e.jsx(Qn,{children:e.jsxs(Gn,{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-muted-foreground text-sm font-normal",children:"Viewing"}),e.jsx(bt,{value:S,onChange:w,isPublished:f,versions:$,size:"sm"})]})}),D&&e.jsxs("div",{className:"space-y-4 p-4",children:[e.jsx(fe,{className:"h-6 w-48"}),e.jsx(fe,{className:"h-4 w-full"}),e.jsx(fe,{className:"h-4 w-full"}),e.jsx(fe,{className:"h-4 w-2/3"})]}),!D&&!_.hasData&&e.jsx("p",{className:"p-4 text-sm text-muted-foreground",children:"No data available for this version."}),!D&&_.hasData&&e.jsx("div",{className:"p-4",children:e.jsxs(Rt,{defaultValue:"changes",children:[e.jsxs(Nt,{variant:"line",className:"mb-4",children:[e.jsx(ns,{value:"content",children:"Content"}),e.jsx(ns,{value:"changes",children:"Changes"})]}),e.jsx(as,{value:"content",children:e.jsx(ti,{lines:_.lines})}),e.jsxs(as,{value:"changes",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:"Compare with"}),e.jsx(bt,{value:j,onChange:L,isPublished:f,versions:$,exclude:S,size:"sm"})]}),E.isLoading?e.jsxs("div",{className:"space-y-4",children:[e.jsx(fe,{className:"h-4 w-full"}),e.jsx(fe,{className:"h-4 w-full"}),e.jsx(fe,{className:"h-4 w-2/3"})]}):E.hasData?e.jsx(fa,{left:E.lines,right:_.lines,leftLabel:Os(j),rightLabel:Os(S)}):e.jsx("p",{className:"text-sm text-muted-foreground italic",children:"No data available for comparison."})]})]})})]})})}const Ps=3e4;class ai extends Ua{constructor(t){super(),this.doc=t,this.clientID=t.clientID,this.states=new Map,this.meta=new Map,this._checkInterval=setInterval(()=>{const i=is();this.getLocalState()!==null&&Ps/2<=i-this.meta.get(this.clientID).lastUpdated&&this.setLocalState(this.getLocalState());const a=[];this.meta.forEach((l,c)=>{c!==this.clientID&&Ps<=i-l.lastUpdated&&this.states.has(c)&&a.push(c)}),a.length>0&&ii(this,a,"timeout")},Fa(Ps/10)),t.on("destroy",()=>{this.destroy()}),this.setLocalState({})}destroy(){this.emit("destroy",[this]),this.setLocalState(null),super.destroy(),clearInterval(this._checkInterval)}getLocalState(){return this.states.get(this.clientID)||null}setLocalState(t){const i=this.clientID,a=this.meta.get(i),l=a===void 0?0:a.clock+1,c=this.states.get(i);t===null?this.states.delete(i):this.states.set(i,t),this.meta.set(i,{clock:l,lastUpdated:is()});const f=[],h=[],m=[],u=[];t===null?u.push(i):c==null?t!=null&&f.push(i):(h.push(i),Jt(c,t)||m.push(i)),(f.length>0||m.length>0||u.length>0)&&this.emit("change",[{added:f,updated:m,removed:u},"local"]),this.emit("update",[{added:f,updated:h,removed:u},"local"])}setLocalStateField(t,i){const a=this.getLocalState();a!==null&&this.setLocalState({...a,[t]:i})}getStates(){return this.states}}const ii=(r,t,i)=>{const a=[];for(let l=0;l<t.length;l++){const c=t[l];if(r.states.has(c)){if(r.states.delete(c),c===r.clientID){const f=r.meta.get(c);r.meta.set(c,{clock:f.clock+1,lastUpdated:is()})}a.push(c)}}a.length>0&&(r.emit("change",[{added:[],updated:[],removed:a},i]),r.emit("update",[{added:[],updated:[],removed:a},i]))},vt=(r,t,i=r.states)=>{const a=t.length,l=$a();Rs(l,a);for(let c=0;c<a;c++){const f=t[c],h=i.get(f)||null,m=r.meta.get(f).clock;Rs(l,f),Rs(l,m),Oa(l,JSON.stringify(h))}return Ba(l)},ri=(r,t,i)=>{const a=Va(t),l=is(),c=[],f=[],h=[],m=[],u=Ns(a);for(let v=0;v<u;v++){const x=Ns(a);let S=Ns(a);const w=JSON.parse(qa(a)),j=r.meta.get(x),L=r.states.get(x),C=j===void 0?0:j.clock;(C<S||C===S&&w===null&&r.states.has(x))&&(w===null?x===r.clientID&&r.getLocalState()!=null?S++:r.states.delete(x):r.states.set(x,w),r.meta.set(x,{clock:S,lastUpdated:l}),j===void 0&&w!==null?c.push(x):j!==void 0&&w===null?m.push(x):w!==null&&(Jt(w,L)||h.push(x),f.push(x)))}(c.length>0||h.length>0||m.length>0)&&r.emit("change",[{added:c,updated:h,removed:m},i]),(c.length>0||f.length>0||m.length>0)&&r.emit("update",[{added:c,updated:f,removed:m},i])},yt=[1e3,2e3,4e3,8e3,16e3];class _s{awareness;ws=null;doc;room;wsUrl;ticket;getTicket;reconnectAttempt=0;reconnectTimer=null;connected=!1;destroyed=!1;pendingUpdates=[];pendingFieldUpdates=[];static MAX_PENDING_FIELD_UPDATES=100;statusListeners=new Set;constructor(t){this.doc=t.doc,this.room=t.room,this.wsUrl=t.wsUrl,this.ticket=t.ticket,this.getTicket=t.getTicket,this.awareness=new ai(this.doc),this.awareness.setLocalStateField("user",t.user),this.doc.on("update",this.handleDocUpdate),this.awareness.on("update",this.handleAwarenessUpdate),this.connect()}onStatus(t){return this.statusListeners.add(t),()=>{this.statusListeners.delete(t)}}connect(){if(this.destroyed)return;this.statusListeners.forEach(i=>i("connecting"));const t=`${this.wsUrl}?ticket=${encodeURIComponent(this.ticket)}&room=${encodeURIComponent(this.room)}`;this.ws=new WebSocket(t),this.ws.onopen=()=>{this.connected=!0,this.reconnectAttempt=0,this.statusListeners.forEach(l=>l("connected"));const i=_a(this.doc);this.ws.send(JSON.stringify({action:"yjs",type:"sync-step-1",data:Ie(i)}));const a=vt(this.awareness,[this.doc.clientID]);this.ws.send(JSON.stringify({action:"awareness",data:Ie(a)}))},this.ws.onmessage=i=>{const a=JSON.parse(i.data);switch(a.action){case"yjs":this.handleYjsMessage(a);break;case"field":this.fieldListeners.forEach(l=>l(a));break;case"awareness":this.handleAwarenessMessage(a);break;case"presence":this.presenceListeners.forEach(l=>l(a));break;case"leader-change":this.leaderChangeListeners.forEach(l=>l(a));break;case"collaboration-disabled":this.collabDisabledListeners.forEach(l=>l());break;case"publish-requested":this.publishRequestedListeners.forEach(l=>l(a));break;case"save-version-requested":this.saveVersionRequestedListeners.forEach(l=>l(a));break;case"publish-in-progress":this.publishInProgressListeners.forEach(l=>l());break;case"published":this.publishedListeners.forEach(l=>l(a));break}},this.ws.onclose=()=>{this.connected=!1,this.statusListeners.forEach(i=>i("disconnected")),this.scheduleReconnect()},this.ws.onerror=()=>{this.ws?.close()}}handleDocUpdate=(t,i)=>{i!=="remote"&&(this.connected?this.sendYjsUpdate(t):this.pendingUpdates.push(t))};sendYjsUpdate(t){this.ws?.send(JSON.stringify({action:"yjs",type:"update",data:Ie(t)}))}flushPendingUpdates(){for(const t of this.pendingUpdates)this.sendYjsUpdate(t);this.pendingUpdates=[]}handleYjsMessage(t){const i=jt(t.data);switch(t.type){case"sync-step-1":{const a=Ma(this.doc,i);this.ws.send(JSON.stringify({action:"yjs",type:"sync-step-2",data:Ie(a)}));break}case"sync-step-2":mt(this.doc,i,"remote"),this.flushPendingUpdates(),this.flushPendingFieldUpdates();break;case"update":mt(this.doc,i,"remote");break}}fieldListeners=new Set;onFieldUpdate(t){return this.fieldListeners.add(t),()=>{this.fieldListeners.delete(t)}}sendFieldUpdate(t,i){if(!this.connected){const a=this.pendingFieldUpdates.findIndex(l=>l.field===t);a>=0?this.pendingFieldUpdates[a]={field:t,value:i}:(this.pendingFieldUpdates.length>=_s.MAX_PENDING_FIELD_UPDATES&&this.pendingFieldUpdates.shift(),this.pendingFieldUpdates.push({field:t,value:i}));return}this.ws?.send(JSON.stringify({action:"field",field:t,value:i}))}flushPendingFieldUpdates(){for(const{field:t,value:i}of this.pendingFieldUpdates)this.ws?.send(JSON.stringify({action:"field",field:t,value:i}));this.pendingFieldUpdates=[]}presenceListeners=new Set;onPresence(t){return this.presenceListeners.add(t),()=>{this.presenceListeners.delete(t)}}leaderChangeListeners=new Set;onLeaderChange(t){return this.leaderChangeListeners.add(t),()=>{this.leaderChangeListeners.delete(t)}}collabDisabledListeners=new Set;onCollabDisabled(t){return this.collabDisabledListeners.add(t),()=>{this.collabDisabledListeners.delete(t)}}sendDisableCollab(){this.connected&&this.ws?.send(JSON.stringify({action:"disable-collab"}))}publishRequestedListeners=new Set;onPublishRequested(t){return this.publishRequestedListeners.add(t),()=>{this.publishRequestedListeners.delete(t)}}saveVersionRequestedListeners=new Set;onSaveVersionRequested(t){return this.saveVersionRequestedListeners.add(t),()=>{this.saveVersionRequestedListeners.delete(t)}}publishInProgressListeners=new Set;onPublishInProgress(t){return this.publishInProgressListeners.add(t),()=>{this.publishInProgressListeners.delete(t)}}publishedListeners=new Set;onPublished(t){return this.publishedListeners.add(t),()=>{this.publishedListeners.delete(t)}}sendRequestPublish(){this.connected&&this.ws?.send(JSON.stringify({action:"request-publish"}))}sendRequestSaveVersion(){this.connected&&this.ws?.send(JSON.stringify({action:"request-save-version"}))}sendPublishInProgress(){this.connected&&this.ws?.send(JSON.stringify({action:"publish-in-progress"}))}sendPublished(t){this.connected&&this.ws?.send(JSON.stringify({action:"published",...t?.contentId?{contentId:t.contentId}:{},...t?.version!==void 0?{version:t.version}:{}}))}handleAwarenessUpdate=({added:t,updated:i,removed:a})=>{if(!this.connected)return;const l=vt(this.awareness,[...t,...i,...a]);this.ws?.send(JSON.stringify({action:"awareness",data:Ie(l)}))};handleAwarenessMessage(t){const i=jt(t.data);ri(this.awareness,i,"remote")}scheduleReconnect(){if(this.destroyed)return;const t=yt[Math.min(this.reconnectAttempt,yt.length-1)];this.reconnectAttempt++,this.reconnectTimer=window.setTimeout(async()=>{try{this.ticket=await this.getTicket()}catch{this.statusListeners.forEach(i=>i("disconnected"));return}this.connect()},t)}destroy(){this.destroyed=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.doc.off("update",this.handleDocUpdate),this.awareness.off("update",this.handleAwarenessUpdate),this.awareness.destroy(),this.ws?.close()}}function Ie(r){let t="";for(let a=0;a<r.length;a+=8192)t+=String.fromCharCode(...r.subarray(a,a+8192));return btoa(t)}function jt(r){const t=atob(r),i=new Uint8Array(t.length);for(let a=0;a<t.length;a++)i[a]=t.charCodeAt(a);return i}const ss=["#3b82f6","#ef4444","#10b981","#f59e0b","#8b5cf6","#ec4899","#14b8a6","#f97316"];function li(r,t,i,a){const{user:l}=$s(),[c,f]=s.useState(null),[h,m]=s.useState("disconnected"),[u,v]=s.useState([]),[x,S]=s.useState({}),w=s.useRef(null),j=s.useRef(a?.onCollabDisabled),L=s.useRef(a?.onPublishRequested),C=s.useRef(a?.onSaveVersionRequested),R=s.useRef(a?.onPublishInProgress),y=s.useRef(a?.onPublished);s.useEffect(()=>{j.current=a?.onCollabDisabled,L.current=a?.onPublishRequested,C.current=a?.onSaveVersionRequested,R.current=a?.onPublishInProgress,y.current=a?.onPublished},[a?.onCollabDisabled,a?.onPublishRequested,a?.onSaveVersionRequested,a?.onPublishInProgress,a?.onPublished]);const k="__HEADROOM_COLLAB_WS_URL__",N=Vs(),$=N&&!!c&&h==="connected";s.useEffect(()=>{if(!N||!k||!l||!i)return;const o=new Ha;w.current=o;const d=`${r}/${t}`,O=async()=>{const H=qs();if(!H)throw new Error("No access token");const A="__HEADROOM_API_URL__".replace(/\/+$/,""),J=await fetch(`${A}/v1/admin/sites/${r}/content/${t}/collab/ticket`,{method:"POST",headers:{Authorization:`Bearer ${H}`,"Content-Type":"application/json"},body:JSON.stringify({room:d})});if(!J.ok)throw new Error(`Ticket request failed: ${J.status}`);return(await J.json()).ticket};let B=!1,I=null;return O().then(H=>{if(B)return;const A=kt(l.sub)%ss.length;I=new _s({wsUrl:k,room:d,ticket:H,getTicket:O,doc:o,user:{sub:l.sub,name:l.name||l.email,color:ss[A]}}),I.onStatus(m),I.onPresence(J=>{v(J.connections.filter(ne=>ne.connectionId!==J.youAre).map(ne=>({sub:ne.adminSub,name:ne.adminName,color:ne.color})));const ye=J.connections.find(ne=>ne.connectionId===J.youAre);le(ye?.isLeader??!1)}),I.onCollabDisabled(()=>{j.current?.()}),I.onPublishRequested(()=>L.current?.()),I.onSaveVersionRequested(()=>C.current?.()),I.onPublishInProgress(()=>R.current?.()),I.onPublished(J=>y.current?.({contentId:J.contentId,version:J.version})),f(I)}).catch(()=>{B||m("disconnected")}),()=>{B=!0,I?.destroy(),o.destroy(),f(null),m("disconnected")}},[r,t,l?.sub,i,k]);const M=s.useCallback(o=>{if(!c||!l||!w.current)return;const d=w.current.getXmlFragment(`document-store-${o}`),O=kt(l.sub)%ss.length;return{provider:c,fragment:d,user:{name:l.email,color:ss[O]}}},[c,l]);s.useEffect(()=>{if(!c){S({});return}const o=()=>{const d={};c.awareness.getStates().forEach(B=>{const I=B?.user?.sub;if(!I)return;const H=B.activeField??null;d[I]=H}),S(d)};return o(),c.awareness.on("change",o),()=>{c.awareness.off("change",o)}},[c]);const _=s.useMemo(()=>u.map(o=>({...o,activeField:x[o.sub]??null})),[u,x]),E=s.useCallback(o=>{c&&c.awareness.setLocalStateField("activeField",o)},[c]),D=s.useRef(new Set),T=s.useCallback(o=>(D.current.add(o),()=>{D.current.delete(o)}),[]);s.useEffect(()=>{if(c)return c.onFieldUpdate(o=>{D.current.forEach(d=>d(o.field,o.value))})},[c]);const X=s.useCallback((o,d)=>{c?.sendFieldUpdate(o,d)},[c]),K=s.useCallback(()=>{c?.sendDisableCollab()},[c]),se=s.useCallback(()=>{c?.sendRequestPublish()},[c]),re=s.useCallback(()=>{c?.sendRequestSaveVersion()},[c]),Z=s.useCallback(()=>{c?.sendPublishInProgress()},[c]),Q=s.useCallback(o=>{c?.sendPublished(o)},[c]),[F,le]=s.useState(!1);return s.useEffect(()=>{if(c)return c.onLeaderChange(o=>{le(o.leaderSub===l?.sub)})},[c,l]),{active:$,status:h,editors:_,isLeader:F,getBlockNoteCollab:M,updateField:X,onRemoteFieldChange:T,setActiveField:E,sendDisableCollab:K,sendRequestPublish:se,sendRequestSaveVersion:re,sendPublishInProgress:Z,sendPublished:Q}}function kt(r){let t=0;for(let i=0;i<r.length;i++)t=(t<<5)-t+r.charCodeAt(i)|0;return Math.abs(t)}function ci({status:r,editors:t}){return t.length===0&&r==="connected"?null:e.jsxs("div",{className:"flex items-center gap-2 px-3 py-1.5 bg-muted/50 rounded-md text-sm","data-testid":"collaboration-bar",children:[e.jsxs("div",{className:"flex items-center gap-1.5","aria-label":r,children:[e.jsx("span",{"data-testid":"collaboration-bar-status-dot","data-status":r,className:cs("h-2 w-2 rounded-full",r==="connected"&&"bg-green-500",r==="connecting"&&"bg-yellow-500 animate-pulse",r==="disconnected"&&"bg-red-500")}),e.jsx("span",{className:"text-muted-foreground text-xs",children:r==="connected"?"Live":r==="connecting"?"Connecting...":"Offline"})]}),t.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(Dt,{orientation:"vertical",className:"h-4"}),e.jsx("div",{className:"flex -space-x-1.5",children:t.map(i=>e.jsxs(At,{children:[e.jsx(Pt,{asChild:!0,children:e.jsx(Na,{className:"h-6 w-6 border-2",style:{borderColor:i.color},"aria-label":i.name,children:e.jsx(Da,{className:"text-[10px]",style:{backgroundColor:i.color+"20"},children:Aa(i.name)})})}),e.jsx(Et,{children:i.name})]},i.sub))}),e.jsxs("span",{className:"text-muted-foreground text-xs",children:[t.length," other ",t.length===1?"editor":"editors"]})]})]})}function oi({host:r,contentId:t,collaborationEnabled:i,hasConnectedPeers:a,isLockHolder:l,sessionId:c,onChange:f,onBeforeDisable:h}){const[m,u]=s.useState(!1),v=ls();if(!Vs()||!l)return null;const x=async()=>{const C=!i;u(!0);try{if(!C)try{h?.()}catch{}await v.apiFetch(`/v1/admin/sites/${r}/content/${t}/edit-lock/collaboration`,{method:"POST",body:JSON.stringify({collaborationEnabled:C,sessionId:c})}),f(C)}catch{V.error("Failed to update collaboration setting")}finally{u(!1)}},S=i&&a,w=m||S,j=S?"Cannot stop sharing while other editors are connected":null,L=e.jsxs(P,{variant:i?"default":"outline",size:"sm",disabled:w,onClick:x,"aria-pressed":i,children:[i?e.jsx(Wn,{className:"h-4 w-4"}):e.jsx(Xn,{className:"h-4 w-4"}),i?"Collaborating":"Collaborate"]});return j?e.jsxs(At,{children:[e.jsx(Pt,{asChild:!0,children:L}),e.jsx(Et,{children:j})]}):L}function di(r,t,i,a,l){const c=s.useRef(new Set),f=ls();s.useEffect(()=>{const h=new Set(a.map(m=>m.sub));for(const m of Array.from(c.current))h.has(m)||c.current.delete(m)},[a]),s.useEffect(()=>{for(const h of a){if(c.current.has(h.sub))continue;c.current.add(h.sub);const m=h.name||h.email||"Someone";V(`${m} wants to collaborate`,{action:{label:"Allow",onClick:()=>{f.apiFetch(`/v1/admin/sites/${r}/content/${t}/edit-lock/collaboration`,{method:"POST",body:JSON.stringify({collaborationEnabled:!0,sessionId:i})}).then(()=>l()).catch(()=>V.error("Failed to enable collaboration"))}},cancel:{label:"Decline",onClick:()=>{f.apiFetch(`/v1/admin/sites/${r}/content/${t}/edit-lock/access-requests/${h.sub}?sessionId=${i}`,{method:"DELETE"}).catch(()=>V.error("Failed to decline request"))}},duration:1/0})}},[a,r,t,i,l,f])}function Hi(){const{host:r,collection:t,id:i}=Ln(),{data:a,isLoading:l}=Bn(r,i);return l?e.jsxs("div",{className:"space-y-4",children:[e.jsx(fe,{className:"h-8 w-64"}),e.jsx(fe,{className:"h-64 w-full"})]}):a?.content?e.jsx(ui,{host:r,collection:t,contentId:i,content:a.content,draft:a.draft,publishedBlockId:a.publishedBlockId}):e.jsx("p",{className:"text-muted-foreground",children:"Content not found."})}function ui({host:r,collection:t,contentId:i,content:a,draft:l,publishedBlockId:c}){const f=Tn(),h=ls(),m=Bs(),{collections:u}=Zn(),v=qn(r,i),x=$n(r,i),S=Vn(r,i),w=_n(r,i),j=Mn(r,i),L=Hn(r,i),C=l?{title:l.title??a.title,slug:l.slug??a.slug??"",snippet:l.snippet??a.snippet??"",tags:l.tags??a.tags??[],cover:l.cover??a.cover??null,body:l.body??{},relationships:l.relationships??{}}:void 0,{user:R}=$s(),{data:y}=ea(),k=R?(y?.superAdminIds??[]).includes(R.sub):!1,N=s.useRef(null),$=s.useCallback(async()=>{const n=N.current;return n?n():{ok:!0}},[]),M=typeof l?.updatedAt=="number"?l.updatedAt:0,[_,E]=s.useState(M),D=s.useRef(M);s.useEffect(()=>{D.current=_},[_]);const T=s.useRef(()=>{}),X=s.useRef(()=>{}),[K,se]=s.useState(!1),re=s.useRef(!1),Z=s.useRef(!1),Q=s.useRef(()=>!1),F=s.useRef(()=>!1),le=s.useRef(null),o=Za(r,i,{getIsDirty:()=>Q.current()||re.current,getIsSaving:()=>Z.current,getIsSavingSync:()=>F.current(),onIdleRelease:()=>le.current?.()}),d=li(r,i,o.collaborationEnabled,{onCollabDisabled:()=>o.setCollaborationEnabled(!1),onPublishRequested:()=>T.current(),onSaveVersionRequested:()=>X.current(),onPublishInProgress:()=>se(!0),onPublished:()=>{se(!1),V.success("Content published")}}),[O,B]=s.useState(null),I=d.active?1e4:void 0,H=s.useCallback(n=>{const p=n,W=(p?.accessRequests??[]).filter(Te=>Te.sub!==R?.sub);o.setAccessRequests(W),typeof p?.updatedAt=="number"&&(E(p.updatedAt),xs(!1))},[o,R?.sub]),A=s.useRef(null),J=s.useCallback(()=>{A.current?.()},[]),ye=s.useRef(null),ne=s.useCallback(()=>ye.current?.()??{},[]),g=Ka(r,i,C,()=>{B("This slug is already in use by another item in this collection")},n=>{o.onAutosaveConflict({lockHolder:n.body?.lockHolder??void 0,takeoverReason:n.body?.takeoverReason??"expired"})},I,H,{onBeforeFirstSave:$,onStaleBaseConflict:J,getCurrentParams:ne});N.current=o.tryAcquireForEdit,re.current=g.isDirty,Z.current=g.isSaving,Q.current=g.getHasPending,F.current=g.getIsSavingSync,le.current=g.markLockReleased;const Be=o.bumpIdleTimer;s.useEffect(()=>{g.lastSavedAt!=null&&Be()},[g.lastSavedAt,Be]);const Y=(o.status==="blocked-edit"||o.status==="read-only-explicit"||o.status==="stale-reload-pending"||o.status==="poll-ceiling")&&!o.collaborationEnabled;di(r,i,o.sessionId,o.accessRequests,()=>o.setCollaborationEnabled(!0));const{data:os}=Sa(r),ds=os?.map(n=>n.tag),de=u.find(n=>n.name===t),me=s.useMemo(()=>de?.fields??[],[de?.fields]),je=s.useMemo(()=>de?.relationships??[],[de?.relationships]),b=de?.singleton??!1,q=sa(),[U,ee]=s.useState(l?.title??a.title),[G,Ce]=s.useState(l?.slug??a.slug??""),[ce,we]=s.useState(l?.snippet??a.snippet??""),Ms=l?.autoSnippet??"",[pe,Re]=s.useState(l?.tags??a.tags??[]),[ae,Ne]=s.useState(l?.cover??a.cover??null),[ge,De]=s.useState(l?.body??{}),[be,Ae]=s.useState(l?.relationships??{}),[zt,us]=s.useState(0),[Kt,Yt]=s.useState(!1),[Qt,qe]=s.useState(!1),[Gt,Le]=s.useState(!1),[Wt,$e]=s.useState(null),[hs,Ve]=s.useState(!1),[Xt,_e]=s.useState(!1),[Zt,Me]=s.useState(!1),[He,Hs]=s.useState(""),[en,fs]=s.useState(!1),[ms,Js]=s.useState(""),zs=Jn(r,i),te=s.useCallback(()=>({title:U,slug:G,snippet:ce,tags:pe,cover:ae,body:ge,relationships:be,...o.sessionId?{sessionId:o.sessionId}:{},...D.current?{baseUpdatedAt:D.current}:{}}),[U,G,ce,pe,ae,ge,be,o.sessionId]);s.useEffect(()=>{ye.current=te},[te]);const sn=d.active?n=>{ee(n),d.updateField("title",n)}:n=>{ee(n),g.schedule({...te(),title:n})},tn=d.active?n=>{Ce(n),B(null),d.updateField("slug",n)}:n=>{Ce(n),B(null),g.schedule({...te(),slug:n})},nn=d.active?n=>{we(n),d.updateField("snippet",n)}:n=>{we(n),g.schedule({...te(),snippet:n})},an=d.active?n=>{Re(n),d.updateField("tags",n)}:n=>{Re(n),g.schedule({...te(),tags:n})},Ks=d.active?n=>{Ne(n),d.updateField("cover",n)}:n=>{Ne(n),g.schedule({...te(),cover:n})},rn=d.active?n=>{De(n),d.updateField("body",n)}:n=>{De(n),g.schedule({...te(),body:n})},ln=d.active?n=>{Ae(n),d.updateField("relationships",n)}:n=>{Ae(n),g.schedule({...te(),relationships:n})},Je=d.active,ze=d.setActiveField,ps=s.useCallback(n=>{Je&&ze(n)},[Je,ze]),gs=s.useCallback(()=>{Je&&ze(null)},[Je,ze]);s.useEffect(()=>{if(d.active)return d.onRemoteFieldChange((n,p)=>{switch(n){case"title":ee(p);break;case"slug":Ce(p);break;case"snippet":we(p);break;case"tags":Re(p);break;case"cover":Ne(p);break;case"body":De(p);break;case"relationships":Ae(p);break}d.isLeader&&g.schedule(te())})},[d.active,d.onRemoteFieldChange,d.isLeader]);const Ys=d.active?d.isLeader:!0;s.useEffect(()=>{if(!d.active||!Ys)return;g.schedule(te());const n=window.setInterval(()=>{g.schedule(te())},1e4);return()=>window.clearInterval(n)},[Ys,d.active]);const Qs=g.lastSavedBlockId??l?.blockId,ke=s.useCallback(n=>{const p=n.draft,z=n.content;if(!p&&!z)return;const W={title:p?.title??z?.title??"",slug:p?.slug??z?.slug??"",snippet:p?.snippet??z?.snippet??"",tags:p?.tags??z?.tags??[],cover:p?.cover??z?.cover??null,body:p?.body??{},relationships:p?.relationships??{}};ee(W.title),Ce(W.slug),we(W.snippet),Re(W.tags),Ne(W.cover),De(W.body),Ae(W.relationships);const Te=p?.updatedAt??0;E(Te),g.resetBaseline(W),us(js=>js+1)},[g]),[oe,bs]=s.useState(null),cn=s.useMemo(()=>oe?.updatedBy?[oe.updatedBy]:[],[oe?.updatedBy]),{resolve:Gs}=Vt(cn),on=s.useMemo(()=>{const n=oe?.updatedBy??"";if(!n)return"another admin";const p=Gs(n);return!p||p===n?"another admin":p},[oe?.updatedBy,Gs]),[dn,xs]=s.useState(!1),Ke=s.useRef(null),Ws=o.setStaleReloadPending,Ye=s.useCallback((n,p)=>{g.pause(),Ke.current={title:U,slug:G,snippet:ce,tags:pe,cover:ae,body:ge,relationships:be};const z=n.draft?.updatedAt??0,W=n.draft?.updatedBy??"";bs({trigger:p,updatedBy:W,updatedAt:z,latest:n}),Ws()},[g,Ws,U,G,ce,pe,ae,ge,be]),Qe=o.endEditing,un=s.useCallback(()=>{const n=oe;n&&ke(n.latest),Ke.current=null,bs(null),xs(!1),g.resume(),Qe()},[oe,ke,g,Qe]),Xs=o.resumeEditingAfterStale,hn=s.useCallback(()=>{const n=Ke.current;n&&(ee(n.title),Ce(n.slug),we(n.snippet),Re(n.tags),Ne(n.cover),De(n.body),Ae(n.relationships),us(p=>p+1),g.resetBaseline(n),Ke.current=null),bs(null),xs(!0),g.resume(),Xs()},[g,Xs]),Pe=s.useCallback(async()=>(await m.invalidateQueries({queryKey:["sites",r,"content-detail",i]}),m.getQueryData(["sites",r,"content-detail",i])??null),[m,r,i]),fn=s.useCallback(async()=>{g.cancel();const n=await Pe();n&&ke(n),Qe()},[g,Pe,ke,Qe]),Zs=o.setReadOnlyExplicit,mn=s.useCallback(async()=>{g.cancel();const n=await Pe();n&&ke(n),Zs()},[g,Pe,ke,Zs]),et=s.useCallback(async()=>{const n=await Pe();n&&Ye(n,"save-conflict")},[Pe,Ye]);s.useEffect(()=>{A.current=()=>void et()},[et]);const pn=s.useCallback(()=>{g.pause()},[g]),gn=s.useCallback(()=>{g.resume()},[g]),bn=s.useCallback(n=>{Ye(n,"tab-refocus")},[Ye]);ei({host:r,contentId:i,isDirty:g.isDirty,serverBlockId:Qs,serverUpdatedAt:_,onSilentReload:ke,onStaleWithDirty:bn,onTabHidden:pn,onTabVisibleResume:gn});const ue=La(a.publishedAt,a.lastPublishedAt,c,Qs,a.scheduledAt,a.scheduledFailed),Ge=Ta(ue),We=Ia(ue),{data:xe}=St(r,i,!!a.publishedAt),he=s.useMemo(()=>{if(!hs||!xe)return null;const n=b?void 0:{title:xe.title,slug:xe.slug,snippet:xe.snippet,tags:xe.tags},p=je.map(ie=>({name:ie.name,label:ie.label})),z=xe.relationships,W=p.length>0?{defs:p,values:z??{}}:void 0,Te=Oe(me,xe.fields??{},n,W),js=b?void 0:{title:U,slug:G,snippet:ce,tags:pe},Nn=p.length>0?{defs:p,values:be}:void 0,Dn=Oe(me,ge,js,Nn),An=ma(Te,Dn,{comparator:(ie,ks)=>ie.text===ks.text&&ie.indent===ks.indent&&ie.type===ks.type});let nt=0,at=0;for(const ie of An)ie.added?nt+=ie.count??0:ie.removed&&(at+=ie.count??0);return{added:nt,removed:at}},[hs,xe,me,je,b,U,G,ce,pe,ge,be]),[xn]=In(),vn=xn.get("from")==="recent"?`/sites/${r}/content`:`/sites/${r}/content/${t}`;ha({title:b?de?.label??t:U||"Untitled",showBack:!b,backTo:b?void 0:vn,badge:{label:Ge.label,variant:Ge.variant}});function Xe(){if(d.active&&!d.isLeader){d.sendRequestPublish();return}if(a.publishedAt&&a.slug&&G!==a.slug){_e(!0);return}ue==="published-changes"?Ve(!0):vs()}async function vs(){d.active&&d.isLeader&&d.sendPublishInProgress();try{await g.flush({createVersion:!0});const p=(await v.mutateAsync(void 0))?.updatedAt;typeof p=="number"&&p>0&&E(p),g.discard(),o.endEditing(),V.success("Content published"),d.active&&d.isLeader&&d.sendPublished({contentId:i})}catch(n){if(n instanceof Ee&&n.code==="SLUG_TAKEN"){B("This slug is already in use by another item in this collection"),V.error("Slug already in use",{description:"Please choose a different slug before publishing."});return}V.error("Failed to publish",{description:n instanceof Error?n.message:void 0})}finally{}}function yn(){if(d.active&&!d.isLeader){d.sendRequestSaveVersion();return}g.flush({createVersion:!0})}s.useEffect(()=>{T.current=Xe,X.current=()=>{g.flush({createVersion:!0})}});async function jn(){try{const p=(await x.mutateAsync())?.updatedAt;typeof p=="number"&&p>0&&E(p),Le(!1),o.endEditing(),V.success("Content unpublished")}catch(n){V.error("Failed to unpublish",{description:n instanceof Error?n.message:void 0})}}async function kn(){try{g.discard();const n=await h.apiFetch(`/v1/admin/sites/${r}/content/${i}/published`);await zs.mutateAsync();const p={title:n.title??"",slug:n.slug??"",snippet:n.snippet??"",tags:n.tags??[],cover:n.cover??null,body:n.fields??{},relationships:n.relationships??{}};ee(p.title),Ce(p.slug),we(p.snippet),Re(p.tags),Ne(p.cover),De(p.body),Ae(p.relationships),us(z=>z+1),g.resetBaseline(p),V.success("Changes discarded")}catch(n){V.error("Failed to discard changes",{description:n instanceof Error?n.message:void 0})}}async function Sn(){try{await S.mutateAsync(),o.endEditing(),V.success("Content deleted"),f(`/sites/${r}/content/${t}`)}catch(n){V.error("Failed to delete",{description:n instanceof Error?n.message:void 0})}}async function Cn(){if(He)try{await g.flush({createVersion:!0});const n=new Date(He).getTime(),z=(await j.mutateAsync(n))?.updatedAt;typeof z=="number"&&z>0&&E(z),Me(!1),Hs(""),o.endEditing(),V.success("Content scheduled for publishing")}catch(n){V.error("Failed to schedule",{description:n instanceof Error?n.message:void 0})}}async function wn(){try{const p=(await L.mutateAsync())?.updatedAt;typeof p=="number"&&p>0&&E(p),o.endEditing(),V.success("Schedule cancelled")}catch(n){V.error("Failed to cancel schedule",{description:n instanceof Error?n.message:void 0})}}async function Rn(){if(ms)try{const n=new Date(ms).getTime();await w.mutateAsync(n),fs(!1),V.success("Publish date updated")}catch(n){V.error("Failed to update publish date",{description:n instanceof Error?n.message:void 0})}}function ys(n){const p=new Date(n),z=p.getTimezoneOffset();return new Date(p.getTime()-z*6e4).toISOString().slice(0,16)}const st=e.jsx("div",{className:`space-y-6 ${Y?"pointer-events-none opacity-60 select-none":""}`,"aria-readonly":Y||void 0,children:me.length>0?e.jsx(Pa,{fields:me,values:ge,onChange:rn},zt):e.jsx(Ue,{children:e.jsx(Fe,{className:"py-8 text-center",children:e.jsxs("p",{className:"text-sm text-muted-foreground",children:["No fields defined for this collection."," ",e.jsx(Un,{to:`/sites/${r}/settings/collections/${t}`,className:"underline",children:"Configure fields"})]})})})}),tt=e.jsxs("div",{className:`space-y-6 ${Y?"pointer-events-none opacity-60 select-none":""}`,"aria-readonly":Y||void 0,children:[!b&&e.jsx(Ue,{children:e.jsxs(Fe,{className:"space-y-4 pt-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(Ze,{htmlFor:"title",className:"flex items-center",children:["Title",e.jsx(es,{field:"title",editors:d.editors})]}),e.jsx(it,{id:"title",value:U,onChange:n=>sn(n.target.value),onFocus:()=>ps("title"),onBlur:gs})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(Ze,{htmlFor:"slug",className:"flex items-center",children:["Slug",e.jsx(es,{field:"slug",editors:d.editors})]}),e.jsx(it,{id:"slug",value:G,onChange:n=>tn(n.target.value),onFocus:()=>ps("slug"),onBlur:gs,className:O?"border-destructive":""}),O&&e.jsx("p",{className:"text-sm text-destructive",children:O})]}),e.jsxs(_t,{defaultOpen:!!ce,children:[e.jsxs(Mt,{className:"flex w-full items-center gap-2 text-sm font-medium",children:[e.jsx(Lt,{className:"h-4 w-4 transition-transform [[data-state=open]>&]:rotate-90"}),"Snippet",e.jsx("span",{className:"text-xs text-muted-foreground",children:"(auto-generated if empty)"}),e.jsx(es,{field:"snippet",editors:d.editors})]}),e.jsxs(Ht,{className:"mt-2 space-y-2",children:[e.jsx(ka,{id:"snippet",value:ce,onChange:n=>nn(n.target.value),onFocus:()=>ps("snippet"),onBlur:gs,rows:3,placeholder:"Brief summary of this content..."}),!ce&&Ms&&e.jsxs("p",{className:"text-xs italic text-muted-foreground",children:["Auto-generated: ",Ms]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(Ze,{children:"Cover Image"}),ae?e.jsxs("div",{className:"flex items-center gap-3 rounded-md border p-2 cursor-pointer hover:bg-muted/50 transition-colors",onClick:()=>qe(!0),children:[e.jsx("img",{src:wa(ae.url),alt:ae.alt??ae.filename??"",className:"h-10 w-10 rounded object-cover bg-muted"}),e.jsx("span",{className:"flex-1 truncate text-sm",children:ae.filename??ae.alt??ae.id}),e.jsx(P,{type:"button",variant:"ghost",size:"sm",onClick:n=>{n.stopPropagation(),Ks(null)},children:e.jsx(rt,{className:"h-3 w-3"})})]}):e.jsxs(P,{type:"button",variant:"outline",className:"w-full",onClick:()=>qe(!0),children:[e.jsx(ta,{className:"mr-2 h-4 w-4"}),"Select Image"]}),e.jsx(Ca,{open:Qt,onClose:()=>qe(!1),onSelect:n=>{Ks({id:n.mediaId,url:n.url,width:n.width??0,height:n.height??0,alt:n.alt,caption:n.caption,filename:n.filename}),qe(!1)},allowedTypes:["image/*"]})]})]})}),!b&&e.jsxs(Ue,{children:[e.jsx(ht,{children:e.jsxs(ft,{className:"flex items-center",children:["Tags",e.jsx(es,{field:"tags",editors:d.editors})]})}),e.jsx(Fe,{children:e.jsx(ua,{tags:pe,onChange:an,suggestions:ds})})]}),je.length>0&&e.jsx(Ra,{relationships:je,values:be,onChange:ln,host:r}),e.jsxs(Ue,{children:[e.jsx(ht,{children:e.jsx(ft,{children:"Info"})}),e.jsxs(Fe,{className:"space-y-2 text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Collection"}),e.jsx("span",{children:a.collection})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"ID"}),e.jsx("span",{className:"font-mono text-xs",children:a.contentId})]}),a.publishedAt?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsx("span",{className:"text-muted-foreground",children:"Published"}),en?e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("input",{type:"datetime-local",value:ms,onChange:n=>Js(n.target.value),className:"text-xs border rounded px-1 py-0.5",max:ys(Date.now())}),e.jsx(P,{variant:"ghost",size:"sm",className:"h-6 w-6 p-0",onClick:Rn,disabled:w.isPending,children:e.jsx(lt,{className:"h-3 w-3"})}),e.jsx(P,{variant:"ghost",size:"sm",className:"h-6 w-6 p-0",onClick:()=>fs(!1),children:e.jsx(rt,{className:"h-3 w-3"})})]}):e.jsxs("span",{className:"cursor-pointer hover:underline",title:Se(a.publishedAt),onClick:()=>{Js(ys(a.publishedAt)),fs(!0)},children:[ts(a.publishedAt),e.jsx(na,{className:"inline ml-1 h-3 w-3 text-muted-foreground"})]})]}),a.lastPublishedAt&&a.lastPublishedAt!==a.publishedAt&&e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Last published"}),e.jsx("span",{title:Se(a.lastPublishedAt),children:ts(a.lastPublishedAt)})]})]}):a.lastPublishedAt?e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Last published"}),e.jsx("span",{title:Se(a.lastPublishedAt),children:ts(a.lastPublishedAt)})]}):null,ue==="scheduled"&&a.scheduledAt&&e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsx("span",{className:"text-muted-foreground",children:"Scheduled for"}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(ct,{className:"h-3 w-3"}),Se(a.scheduledAt)]})]}),ue==="schedule-failed"&&e.jsx("div",{className:"text-destructive text-xs",children:"Scheduled publishing failed after multiple attempts."}),a.publishedAt&&e.jsxs(P,{variant:"outline",size:"sm",className:"w-full mt-2",onClick:()=>{$e({kind:"published"}),Le(!0)},children:[e.jsx(aa,{className:"mr-2 h-4 w-4"}),"View published"]})]})]}),e.jsx(mi,{host:r,contentId:i,onViewVersion:n=>{$e({kind:"history",blockId:n.blockId,createdAt:n.createdAt,title:n.title}),Le(!0)}}),!b&&e.jsx(fi,{deleteOpen:Kt,setDeleteOpen:Yt,onDelete:Sn,host:r,contentId:i})]});return e.jsx(Ea.Provider,{value:d.active?d:null,children:e.jsxs("div",{className:"mx-auto max-w-6xl",children:[o.collaborationEnabled&&e.jsx("div",{className:"mb-3",children:e.jsx(ci,{status:d.status,editors:d.editors})}),o.status==="poll-ceiling"&&e.jsx(gt,{variant:"poll-ceiling"}),(o.status==="blocked-edit"||o.status==="read-only-explicit")&&o.lockHolder&&e.jsx(gt,{variant:o.status,lockHolder:o.lockHolder,onRequestCollaboration:()=>o.requestCollaboration.mutate(),isRequesting:o.requestCollaboration.isPending,requestSent:o.requestCollaboration.isSuccess,onDiscardPending:o.status==="blocked-edit"?()=>void fn():void 0,onViewReadOnly:o.status==="blocked-edit"?()=>void mn():void 0,onResumeEditing:o.status==="read-only-explicit"?()=>o.exitReadOnly():void 0,onForceTakeover:o.status==="blocked-edit"&&k?()=>void o.forceTakeover():void 0}),o.status==="read-only-explicit"&&!o.lockHolder&&e.jsxs("div",{className:"bg-emerald-50 border border-emerald-200 rounded-lg p-4 mb-4 flex items-center justify-between gap-3","data-testid":"lock-available-banner",children:[e.jsx("p",{className:"text-sm text-emerald-900",children:"Lock available — you can take over editing now."}),e.jsx(P,{size:"sm",onClick:()=>void o.takeEditing(),"data-testid":"take-editing-btn",children:"Take editing"})]}),!q&&e.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2 md:mb-6 md:flex-nowrap md:gap-3 md:justify-between",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-2 md:gap-3",children:[e.jsx("h1",{className:"truncate text-xl font-semibold md:text-2xl",children:b?de?.label??t:U||"Untitled"}),e.jsx(ia,{variant:Ge.variant,children:Ge.label}),g.isSaving&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx(ve,{className:"h-3 w-3 animate-spin"}),"Saving..."]}),!g.isSaving&&g.lastSavedAt&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx(lt,{className:"h-3 w-3"}),"Saved"]}),dn&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-amber-700",title:"Your edits are based on an older version. The next save may be rejected.","data-testid":"stale-base-indicator",children:[e.jsx("span",{className:"inline-block h-2 w-2 rounded-full bg-amber-500"}),"Older version"]})]}),e.jsxs("div",{className:"flex gap-2 ml-auto",children:[e.jsx(oi,{host:r,contentId:i,collaborationEnabled:o.collaborationEnabled,hasConnectedPeers:d.editors.length>0,isLockHolder:o.status==="editing",sessionId:o.sessionId,onChange:n=>o.setCollaborationEnabled(n),onBeforeDisable:d.sendDisableCollab}),e.jsxs(P,{variant:"outline",size:"sm",onClick:yn,disabled:g.isSaving||Y,className:"px-3",children:[g.isSaving&&e.jsx(ve,{className:"mr-2 h-4 w-4 animate-spin"}),"Save Draft"]}),ue==="scheduled"&&e.jsxs(e.Fragment,{children:[e.jsxs(P,{variant:"outline",size:"sm",onClick:wn,disabled:L.isPending||Y,className:"px-3",children:[L.isPending&&e.jsx(ve,{className:"mr-2 h-4 w-4 animate-spin"}),"Cancel Schedule"]}),e.jsxs(P,{size:"sm",onClick:Xe,disabled:v.isPending||K||Y,className:"px-3",children:[(v.isPending||K)&&e.jsx(ve,{className:"mr-2 h-4 w-4 animate-spin"}),"Publish Now"]})]}),ue!=="scheduled"&&We&&e.jsxs("div",{className:"flex",children:[e.jsxs(P,{size:"sm",onClick:Xe,disabled:v.isPending||K||Y,className:cs("px-3",!a.publishedAt&&"rounded-r-none"),children:[(v.isPending||K)&&e.jsx(ve,{className:"mr-2 h-4 w-4 animate-spin"}),We]}),!a.publishedAt&&e.jsxs(ot,{children:[e.jsx(dt,{asChild:!0,children:e.jsx(P,{size:"sm",className:"rounded-l-none border-l px-2",disabled:v.isPending||K||Y,children:e.jsx(ra,{className:"h-4 w-4"})})}),e.jsx(ut,{align:"end",children:e.jsxs(Cs,{onClick:()=>Me(!0),disabled:Y,children:[e.jsx(ct,{className:"mr-2 h-4 w-4"}),"Schedule for later"]})})]})]}),a.publishedAt&&e.jsxs(ot,{children:[e.jsx(dt,{asChild:!0,children:e.jsx(P,{variant:"outline",size:"sm",className:"size-8 p-0",disabled:Y,children:e.jsx(la,{className:"h-4 w-4"})})}),e.jsxs(ut,{align:"end",children:[ue==="published-changes"&&e.jsxs(Cs,{onClick:kn,disabled:zs.isPending||Y,children:[e.jsx(ca,{className:"mr-2 h-4 w-4"}),"Discard Changes"]}),e.jsx(Cs,{onClick:jn,className:"text-destructive focus:text-destructive",disabled:Y,children:"Unpublish"})]})]})]})]}),q?e.jsxs(Rt,{defaultValue:"content",children:[e.jsxs("div",{className:"mb-2 flex items-center",children:[e.jsxs(Nt,{variant:"line",children:[e.jsx(ns,{value:"content",children:"Content"}),e.jsx(ns,{value:"info",children:"Info"})]}),e.jsxs("div",{className:"ml-auto flex gap-2",children:[e.jsxs(P,{variant:"outline",size:"sm",onClick:()=>g.flush({createVersion:!0}),disabled:g.isSaving||Y,children:[g.isSaving&&e.jsx(ve,{className:"mr-1 h-3 w-3 animate-spin"}),"Save"]}),ue!=="scheduled"&&We&&e.jsxs(P,{size:"sm",onClick:Xe,disabled:v.isPending||Y,children:[v.isPending&&e.jsx(ve,{className:"mr-1 h-3 w-3 animate-spin"}),We]})]})]}),e.jsx(as,{value:"content",className:"mt-0",children:st}),e.jsx(as,{value:"info",className:"mt-0",children:tt})]}):e.jsxs("div",{className:"grid gap-6 lg:grid-cols-3",children:[e.jsx("div",{className:"lg:col-span-2",children:st}),e.jsx("div",{children:tt})]}),e.jsx(ni,{open:Gt,onOpenChange:n=>{Le(n),n||$e(null)},host:r,contentId:i,collectionFields:me,isSingleton:b,isPublished:!!a.publishedAt,draftBody:ge,draftMetadata:b?void 0:{title:U,slug:G,snippet:ce,tags:pe},initialVersion:Wt,collectionRelationships:je,draftRelationships:be}),e.jsx(si,{open:!!oe,trigger:oe?.trigger??"tab-refocus",updatedBy:on,updatedAt:oe?.updatedAt??0,onReload:un,onCancel:hn}),e.jsx(Tt,{open:hs,onOpenChange:Ve,children:e.jsxs(It,{children:[e.jsxs(Ut,{children:[e.jsx(Ft,{children:"Publish changes?"}),e.jsx(Ot,{children:he?e.jsxs(e.Fragment,{children:[he.added>0&&e.jsxs("span",{className:"text-green-600",children:["+",he.added," added"]}),he.added>0&&he.removed>0&&", ",he.removed>0&&e.jsxs("span",{className:"text-red-600",children:["-",he.removed," removed"]}),he.added===0&&he.removed===0&&e.jsx("span",{children:"No visible changes detected."})]}):"This will update the published version with your current changes."})]}),e.jsx("div",{className:"mb-2",children:e.jsx(P,{variant:"link",className:"p-0 h-auto text-sm",onClick:()=>{Ve(!1),$e({kind:"draft"}),Le(!0)},children:"View full diff"})}),e.jsxs(Bt,{children:[e.jsx(qt,{children:"Cancel"}),e.jsx($t,{onClick:()=>{Ve(!1),vs()},children:"Publish Update"})]})]})}),e.jsx(Es,{open:Xt,onOpenChange:_e,children:e.jsxs(Ls,{children:[e.jsxs(Ts,{children:[e.jsx(Is,{children:"Slug change detected"}),e.jsxs(Us,{children:["You are changing the slug from “",a.slug,"” to “",G,"”. This may break external bookmarks and SEO links."]})]}),e.jsx(hi,{host:r,contentId:i}),e.jsxs(Fs,{children:[e.jsx(P,{variant:"outline",onClick:()=>_e(!1),children:"Cancel"}),e.jsx(P,{onClick:()=>{_e(!1),vs()},children:"Publish Anyway"})]})]})}),e.jsx(Es,{open:Zt,onOpenChange:Me,children:e.jsxs(Ls,{children:[e.jsxs(Ts,{children:[e.jsx(Is,{children:"Schedule publishing"}),e.jsx(Us,{children:"Choose a date and time to automatically publish this content. Times are rounded to the nearest 15-minute interval."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(Ze,{htmlFor:"schedule-date",children:"Publish at"}),e.jsx("input",{id:"schedule-date",type:"datetime-local",value:He,onChange:n=>Hs(n.target.value),min:ys(Date.now()+1200*1e3),className:"w-full rounded-md border px-3 py-2 text-sm",step:"900"})]}),e.jsxs(Fs,{children:[e.jsx(P,{variant:"outline",onClick:()=>Me(!1),children:"Cancel"}),e.jsxs(P,{onClick:Cn,disabled:!He||j.isPending,children:[j.isPending&&e.jsx(ve,{className:"mr-2 h-4 w-4 animate-spin"}),"Schedule"]})]})]})})]})})}function hi({host:r,contentId:t}){const{data:i}=wt(r,t,!0);return!i||i.count===0?null:e.jsxs("div",{className:"rounded-md border border-yellow-500/50 bg-yellow-50 p-3 text-sm dark:bg-yellow-950/30",children:[e.jsxs("p",{className:"font-medium text-yellow-800 dark:text-yellow-200",children:["This content is referenced by ",i.count," other"," ",i.count===1?"item":"items",":"]}),e.jsxs("ul",{className:"mt-1 list-disc pl-5 text-yellow-700 dark:text-yellow-300",children:[i.items.slice(0,5).map(a=>e.jsxs("li",{children:[a.title," (",a.collection,")"]},`${a.contentId}-${a.fieldName}`)),i.items.length>5&&e.jsxs("li",{children:["and ",i.items.length-5," more..."]})]})]})}function fi({deleteOpen:r,setDeleteOpen:t,onDelete:i,host:a,contentId:l}){const{data:c}=wt(a,l,r);return e.jsxs(e.Fragment,{children:[e.jsx(Dt,{}),e.jsxs(Es,{open:r,onOpenChange:t,children:[e.jsx(oa,{asChild:!0,children:e.jsxs(P,{variant:"destructive",className:"w-full",children:[e.jsx(da,{className:"mr-2 h-4 w-4"}),"Delete"]})}),e.jsxs(Ls,{children:[e.jsxs(Ts,{children:[e.jsx(Is,{children:"Delete content?"}),e.jsx(Us,{children:"This action cannot be undone. The content will be permanently deleted."})]}),c&&c.count>0&&e.jsxs("div",{className:"rounded-md border border-yellow-500/50 bg-yellow-50 p-3 text-sm dark:bg-yellow-950/30",children:[e.jsxs("p",{className:"font-medium text-yellow-800 dark:text-yellow-200",children:["This content is referenced by ",c.count," other"," ",c.count===1?"item":"items",":"]}),e.jsxs("ul",{className:"mt-1 list-disc pl-5 text-yellow-700 dark:text-yellow-300",children:[c.items.slice(0,5).map(f=>e.jsxs("li",{children:[f.title," (",f.collection,")"]},`${f.contentId}-${f.fieldName}`)),c.items.length>5&&e.jsxs("li",{children:["and ",c.items.length-5," more..."]})]})]}),e.jsxs(Fs,{children:[e.jsx(P,{variant:"outline",onClick:()=>t(!1),children:"Cancel"}),e.jsx(P,{variant:"destructive",onClick:i,children:"Delete"})]})]})]})]})}function mi({host:r,contentId:t,onViewVersion:i}){const{data:a}=Ct(r,t),[l,c]=s.useState(!1),f=a?.items??[],h=f.map(u=>u.createdBy).filter(Boolean),{resolve:m}=Vt(h);return f.length===0?null:e.jsx(Ue,{children:e.jsx(Fe,{className:"pt-4",children:e.jsxs(_t,{open:l,onOpenChange:c,children:[e.jsxs(Mt,{className:"flex w-full items-center gap-2 text-sm font-medium",children:[e.jsx(Lt,{className:cs("h-4 w-4 transition",l&&"rotate-90")}),"Version History (",f.length,")"]}),e.jsx(Ht,{className:"mt-2",children:e.jsx("div",{className:"space-y-1",children:f.map((u,v)=>e.jsxs("button",{className:"py-1 text-sm hover:bg-muted rounded px-1 -mx-1 transition-colors w-full text-left",onClick:()=>i(u),children:[e.jsx("span",{children:Se(u.createdAt)}),u.createdBy&&e.jsx("span",{className:"ml-2 text-muted-foreground",children:m(u.createdBy)}),u.title&&e.jsx("span",{className:"ml-2 text-muted-foreground",children:u.title})]},`${u.createdAt}-${v}`))})})]})})})}export{Hi as ContentEditPage};
@@ -1 +0,0 @@
1
- import{j as s}from"./tanstack-Bs3zYPPV.js";import{u as Ce,f as ke,r as S}from"./react-vendor-C2CvUxFh.js";import{w as ye,x as Ae,B as R,P as ie,v as w,z as de,I as oe,X as B,A as Pe,L as z,j as T,S as Te,a as _e,y as Ie}from"./index-Ce5pmRMj.js";import{d as $e,e as Fe,a as Ve,b as Be,c as De}from"./useContent-Bs7nel7C.js";import{u as Le}from"./useTags-B-HgMVwo.js";import{u as Ue}from"./useContentSearch-B3aTjuCu.js";import{u as qe}from"./usePageTitle-C1r1-C00.js";import{u as Me}from"./useFilterParams-DYdEuWPE.js";import{m as ue}from"./media-url-DdCoIedP.js";import{u as Re,F as ze}from"./FilterBar-BZoa63zh.js";import{C as Oe,c as Ee}from"./card-C9hfyHXf.js";import{C as Z}from"./checkbox-DVJcwUt1.js";import{P as He,a as We,b as Xe}from"./popover-CzaQYEEP.js";import{S as C,a as k,b as y,c as A,d as o}from"./select-CrRhFGIi.js";import{T as Ze,a as Ge,b as he,c as D,d as Qe,e as L}from"./table-_3bMY0_z.js";import{a as I,f as xe}from"./format-C88SDH8g.js";import{g as me,a as ge}from"./contentStatus-CkPi9Dh6.js";import{B as Je}from"./BulkActionBar-BxdfUSrN.js";import{P as Ke}from"./Pagination-Df9nQ7Z0.js";import"./radix-C5ZmWuuL.js";import"./command-Bfmj0MEL.js";const O=3,fe=[{value:"updated_desc",label:"Last updated"},{value:"updated_asc",label:"Oldest updated"},{value:"title_asc",label:"Title A–Z",requiresCollection:!0},{value:"title_desc",label:"Title Z–A",requiresCollection:!0},{value:"created_desc",label:"Newest created"},{value:"created_asc",label:"Oldest created"}],G=[{value:"all",label:"All statuses"},{value:"draft",label:"Draft"},{value:"published",label:"Published"},{value:"changed",label:"Changed"},{value:"unpublished",label:"Unpublished"},{value:"scheduled",label:"Scheduled"}];function bs(){const{host:c,collection:r}=Ce(),_=ke(),{collections:pe}=ye(),[i,a]=Me([{key:"q",defaultValue:""},{key:"search",defaultValue:"prefix"},{key:"tag",defaultValue:""},{key:"status",defaultValue:""},{key:"sort",defaultValue:"updated_desc"},{key:"relatedTo",defaultValue:""},{key:"relField",defaultValue:""},{key:"page",defaultValue:"1"},{key:"perPage",defaultValue:"20"},{key:"after",defaultValue:""}]),$=i.search,x=i.tag||void 0,m=i.status||void 0,g=i.sort,j=i.relatedTo,v=i.relField,b=Number(i.page)||1,E=Number(i.perPage)||20,Q=S.useMemo(()=>{const e=i.after;return e?e.split(","):[]},[i.after]),[F,V]=S.useState(i.q),[u,t]=S.useState(new Set),H=Ae(),f=pe.find(e=>e.name===r),U=f?.relationships??[],{data:J}=Re(c,j||void 0),K=S.useMemo(()=>{if(!j||!v)return null;const e=U.find(n=>n.name===v);return{type:"relationship",relName:v,relLabel:e?.label??v,contentId:j,contentTitle:J??"Loading..."}},[j,v,U,J]);qe({title:f?.label??r??"",actions:f?.singleton?void 0:s.jsx(R,{size:"sm",onClick:()=>_(`/sites/${c}/content/${r}/new`),children:s.jsx(ie,{className:"h-4 w-4"})})});const h=Ue(F,300);S.useEffect(()=>{h!==i.q&&a({q:h})},[h,i.q,a]);const N=S.useCallback(()=>{a({page:"1",after:""}),t(new Set)},[a]),je=S.useMemo(()=>{const e={};return h&&(e.q=h,e.search=$),x&&(e.tag=x),m&&(e.status=m),g!=="updated_desc"&&(e.sort=g),j&&(e.relatedTo=j),v&&(e.relField=v),e.limit=E,e},[h,$,x,m,g,j,v,E]),ve=b>1?Q[b-2]:void 0,{data:P,isLoading:be}=$e(c,r,je,ve),W=Fe(c),Y=Ve(c),ee=Be(c),se=De(c),{data:ae}=Le(c),q=S.useMemo(()=>ae?.map(e=>e.tag)??[],[ae]);if(f?.singleton&&P?.items.length===1)return _(`/sites/${c}/content/${r}/${P.items[0].contentId}`,{replace:!0}),null;const M=P?.items,X=M?.map(e=>e.contentId)??[],te=X.length>0&&X.every(e=>u.has(e));function le(e){t(n=>{const l=new Set(n);return l.has(e)?l.delete(e):l.add(e),l})}function Ne(){t(te?new Set:new Set(X))}const ne=!!(h||x||m||j),re=!!h,ce=[$!=="prefix"?1:0,x?1:0,m?1:0,g!=="updated_desc"?1:0].reduce((e,n)=>e+n,0),Se=Y.isPending||ee.isPending||se.isPending;async function we(){try{const e=await W.mutateAsync({collection:r,title:f?.label??r});w.success("Singleton content recreated"),_(`/sites/${c}/content/${r}/${e.contentId}`)}catch(e){w.error("Failed to recreate singleton",{description:e instanceof Error?e.message:void 0})}}return s.jsxs("div",{children:[!H&&s.jsxs("div",{className:"mb-6 flex items-center justify-between",children:[s.jsx("h1",{className:"text-2xl font-semibold",children:f?.label??r}),!f?.singleton&&s.jsxs(R,{onClick:()=>_(`/sites/${c}/content/${r}/new`),children:[s.jsx(ie,{className:"mr-2 h-4 w-4"}),"New"]})]}),u.size>0?s.jsx(Je,{selectedCount:u.size,onPublish:async()=>{const e=[...u],l=(await Y.mutateAsync(e)).filter(d=>d.status==="rejected").length;l?w.error(`${l} of ${e.length} failed to publish`):w.success(`${e.length} item(s) published`),N()},onUnpublish:async()=>{const e=[...u],l=(await ee.mutateAsync(e)).filter(d=>d.status==="rejected").length;l?w.error(`${l} of ${e.length} failed to unpublish`):w.success(`${e.length} item(s) unpublished`),N()},onDelete:async()=>{const e=[...u],l=(await se.mutateAsync(e)).filter(d=>d.status==="rejected").length;l?w.error(`${l} of ${e.length} failed to delete`):w.success(`${e.length} item(s) deleted`),N()},onClear:()=>t(new Set),isPending:Se}):H?s.jsxs("div",{className:"mb-4 flex items-center gap-2",children:[s.jsxs("div",{className:"relative flex-1",children:[s.jsx(de,{className:"absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground"}),s.jsx(oe,{placeholder:"Search...",value:F,onChange:e=>{V(e.target.value),N()},className:"pl-8 pr-8"}),F&&s.jsx("button",{onClick:()=>{V(""),N()},className:"absolute right-2 top-2.5 text-muted-foreground hover:text-foreground",children:s.jsx(B,{className:"h-4 w-4"})})]}),s.jsxs(He,{children:[s.jsx(We,{asChild:!0,children:s.jsxs(R,{variant:"outline",size:"icon",className:"relative shrink-0","aria-label":"Filters",children:[s.jsx(Pe,{className:"h-4 w-4"}),ce>0&&s.jsx("span",{className:"absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-primary text-[10px] text-primary-foreground",children:ce})]})}),s.jsxs(Xe,{className:"w-64 space-y-3",align:"end",children:[s.jsxs("div",{className:"space-y-2",children:[s.jsx(z,{className:"text-xs font-medium",children:"Search Mode"}),s.jsxs(C,{value:$,onValueChange:e=>{a({search:e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{children:s.jsx(y,{})}),s.jsxs(A,{children:[s.jsx(o,{value:"prefix",children:"Starts with"}),s.jsx(o,{value:"full",children:"Contains"})]})]})]}),q.length>0&&s.jsxs("div",{className:"space-y-2",children:[s.jsx(z,{className:"text-xs font-medium",children:"Tag"}),s.jsxs(C,{value:x??"__all__",onValueChange:e=>{a({tag:e==="__all__"?"":e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{children:s.jsx(y,{})}),s.jsxs(A,{children:[s.jsx(o,{value:"__all__",children:"All tags"}),q.map(e=>s.jsx(o,{value:e,children:e},e))]})]})]}),s.jsxs("div",{className:"space-y-2",children:[s.jsx(z,{className:"text-xs font-medium",children:"Status"}),s.jsxs(C,{value:m??"all",onValueChange:e=>{a({status:e==="all"?"":e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{children:s.jsx(y,{})}),s.jsx(A,{children:G.map(e=>s.jsx(o,{value:e.value??"all",children:e.label},e.value??"all"))})]})]}),s.jsxs("div",{className:"space-y-2",children:[s.jsx(z,{className:"text-xs font-medium",children:"Sort"}),s.jsxs(C,{value:g,onValueChange:e=>{a({sort:e,page:"1",after:""}),t(new Set)},disabled:re,children:[s.jsx(k,{children:s.jsx(y,{})}),s.jsx(A,{children:fe.map(e=>s.jsx(o,{value:e.value,disabled:e.requiresCollection&&!r,children:e.label},e.value))})]})]})]})]})]}):s.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2",children:[s.jsxs("div",{className:"relative flex items-center",children:[s.jsx(de,{className:"absolute left-2.5 h-4 w-4 text-muted-foreground"}),s.jsx(oe,{placeholder:"Search titles...",value:F,onChange:e=>{V(e.target.value),N()},className:"w-56 pl-8 pr-8"}),F&&s.jsx("button",{onClick:()=>{V(""),N()},className:"absolute right-2 text-muted-foreground hover:text-foreground",children:s.jsx(B,{className:"h-4 w-4"})})]}),s.jsxs(C,{value:$,onValueChange:e=>{a({search:e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{className:"w-[130px]",children:s.jsx(y,{})}),s.jsxs(A,{children:[s.jsx(o,{value:"prefix",children:"Starts with"}),s.jsx(o,{value:"full",children:"Contains"})]})]}),q.length>0&&s.jsxs(C,{value:x??"__all__",onValueChange:e=>{a({tag:e==="__all__"?"":e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{className:"w-[140px]",children:s.jsx(y,{placeholder:"Tag"})}),s.jsxs(A,{children:[s.jsx(o,{value:"__all__",children:"All tags"}),q.map(e=>s.jsx(o,{value:e,children:e},e))]})]}),s.jsxs(C,{value:m??"all",onValueChange:e=>{a({status:e==="all"?"":e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{className:"w-[150px]",children:s.jsx(y,{})}),s.jsx(A,{children:G.map(e=>s.jsx(o,{value:e.value??"all",children:e.label},e.value??"all"))})]}),s.jsx("div",{className:"ml-auto",children:s.jsxs(C,{value:g,onValueChange:e=>{a({sort:e,page:"1",after:""}),t(new Set)},disabled:re,children:[s.jsx(k,{className:"w-[170px]",children:s.jsx(y,{})}),s.jsx(A,{children:fe.map(e=>s.jsx(o,{value:e.value,disabled:e.requiresCollection&&!r,children:e.label},e.value))})]})})]}),U.length>0&&s.jsx("div",{className:"mb-3",children:s.jsx(ze,{relationships:U,activeFilters:K?[K]:[],onFilterAdd:e=>{a({relatedTo:e.contentId,relField:e.relName,page:"1",after:""}),t(new Set)},onFilterRemove:()=>{a({relatedTo:"",relField:"",page:"1",after:""}),t(new Set)}})}),ne&&u.size===0&&s.jsxs("div",{className:"mb-3 flex flex-wrap items-center gap-1.5",children:[h&&s.jsxs(T,{variant:"secondary",className:"gap-1",children:["Search: ",h,s.jsx("button",{onClick:()=>{V(""),N()},children:s.jsx(B,{className:"h-3 w-3"})})]}),x&&s.jsxs(T,{variant:"secondary",className:"gap-1",children:["Tag: ",x,s.jsx("button",{onClick:()=>{a({tag:"",page:"1",after:""}),t(new Set)},children:s.jsx(B,{className:"h-3 w-3"})})]}),m&&s.jsxs(T,{variant:"secondary",className:"gap-1",children:["Status: ",G.find(e=>e.value===m)?.label,s.jsx("button",{onClick:()=>{a({status:"",page:"1",after:""}),t(new Set)},children:s.jsx(B,{className:"h-3 w-3"})})]})]}),be?s.jsx("div",{className:"space-y-2",children:Array.from({length:5}).map((e,n)=>s.jsx(Te,{className:"h-12 w-full"},n))}):M?.length?s.jsxs(s.Fragment,{children:[H?s.jsx("div",{className:"grid gap-3 sm:grid-cols-2","data-testid":"content-card-view",children:M.map(e=>{const n=me(e.publishedAt,e.lastPublishedAt,e.publishedBlockId,e.lastDraftBlockId,e.scheduledAt,e.scheduledFailed),l=ge(n),d=e.tags??[];return s.jsx(Oe,{className:Ie("cursor-pointer gap-0 overflow-hidden py-0 transition-shadow hover:shadow-md",u.has(e.contentId)&&"ring-2 ring-primary"),onClick:()=>_(`/sites/${c}/content/${r}/${e.contentId}`),children:s.jsxs(Ee,{className:"p-3",children:[s.jsxs("div",{className:"flex items-start gap-3 min-w-0",children:[e.cover?.url&&s.jsx("img",{src:ue(e.cover.url),alt:e.cover.alt??"",className:"h-12 w-12 rounded object-cover flex-shrink-0"}),s.jsxs("div",{className:"min-w-0 flex-1",children:[s.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[s.jsx("span",{className:"font-medium truncate",children:e.draftTitle||e.title||"Untitled"}),s.jsx(T,{variant:l.variant,className:"shrink-0",children:l.label})]}),(e.draftSlug||e.slug)&&s.jsxs("p",{className:"text-xs text-muted-foreground truncate mt-0.5",children:["/",e.draftSlug||e.slug]}),s.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:g.startsWith("created")?e.createdAt?I(e.createdAt):"—":e.lastDraftAt?I(e.lastDraftAt):"—"})]}),s.jsx(Z,{checked:u.has(e.contentId),onCheckedChange:()=>le(e.contentId),onClick:p=>p.stopPropagation(),className:"mt-1"})]}),d.length>0&&s.jsx("div",{className:"mt-2 flex flex-wrap gap-1",children:d.slice(0,O).map(p=>s.jsx(T,{variant:"outline",className:"text-[10px] px-1.5 py-0",children:p},p))})]})},e.contentId)})}):s.jsxs(Ze,{children:[s.jsx(Ge,{children:s.jsxs(he,{children:[s.jsx(D,{className:"w-10",children:s.jsx(Z,{checked:te,onCheckedChange:Ne,"aria-label":"Select all"})}),s.jsx(D,{children:"Title"}),s.jsx(D,{children:"Slug"}),s.jsx(D,{children:"Status"}),s.jsx(D,{children:g.startsWith("created")?"Created":"Updated"})]})}),s.jsx(Qe,{children:M.map(e=>{const n=me(e.publishedAt,e.lastPublishedAt,e.publishedBlockId,e.lastDraftBlockId),l=ge(n),d=e.tags??[];return s.jsxs(he,{className:"cursor-pointer",onClick:()=>_(`/sites/${c}/content/${r}/${e.contentId}`),children:[s.jsx(L,{onClick:p=>p.stopPropagation(),children:s.jsx(Z,{checked:u.has(e.contentId),onCheckedChange:()=>le(e.contentId),"aria-label":`Select ${e.draftTitle||e.title||"Untitled"}`})}),s.jsx(L,{className:"font-medium",children:s.jsxs("div",{className:"flex items-center gap-3",children:[e.cover?.url&&s.jsx("img",{src:ue(e.cover.url),alt:e.cover.alt??"",className:"h-8 w-8 rounded object-cover flex-shrink-0"}),s.jsxs("div",{className:"min-w-0",children:[s.jsx("span",{children:e.draftTitle||e.title||"Untitled"}),d.length>0&&s.jsxs("div",{className:"mt-0.5 flex flex-wrap gap-1",children:[d.slice(0,O).map(p=>s.jsx(T,{variant:"outline",className:"text-[10px] px-1.5 py-0 font-normal text-muted-foreground",children:p},p)),d.length>O&&s.jsxs("span",{className:"text-[10px] text-muted-foreground",children:["+",d.length-O," more"]})]})]})]})}),s.jsx(L,{className:"text-muted-foreground text-sm",children:e.draftSlug||e.slug||"—"}),s.jsx(L,{children:s.jsx(T,{variant:l.variant,children:l.label})}),s.jsx(L,{className:"text-muted-foreground",children:g.startsWith("created")?e.createdAt?I(e.createdAt):"—":e.scheduledAt&&!e.publishedAt?s.jsxs("span",{title:xe(e.scheduledAt),children:["Scheduled ",I(e.scheduledAt)]}):e.publishedAt?s.jsx("span",{title:xe(e.publishedAt),children:I(e.publishedAt)}):e.lastDraftAt?I(e.lastDraftAt):"—"})]},e.contentId)})})]}),s.jsx(Ke,{page:b,hasNext:!!P?.hasMore,hasPrevious:b>1,onNext:()=>{if(P?.items.length){const e=P.items[P.items.length-1].contentId,n=[...Q.slice(0,b-1),e];a({page:String(b+1),after:n.join(",")})}else a({page:String(b+1)});t(new Set)},onPrevious:()=>{const e=b-1;a(e<=1?{page:"1",after:""}:{page:String(e)}),t(new Set)},perPage:E,onPerPageChange:e=>{a({perPage:String(e),page:"1",after:""}),t(new Set)}})]}):f?.singleton?s.jsxs("div",{className:"space-y-4",children:[s.jsx("p",{className:"text-muted-foreground",children:"Singleton content is missing. Click below to recreate it."}),s.jsxs(R,{onClick:we,disabled:W.isPending,children:[W.isPending&&s.jsx(_e,{className:"mr-2 h-4 w-4 animate-spin"}),"Recreate ",f.label]})]}):s.jsx("p",{className:"text-muted-foreground",children:ne?"No content matches the current filters.":"No content yet."})]})}export{bs as ContentListPage};
@@ -1,2 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/BlockEditor-3wnisTOZ.js","assets/tanstack-Bs3zYPPV.js","assets/react-vendor-C2CvUxFh.js","assets/index-Ce5pmRMj.js","assets/radix-C5ZmWuuL.js","assets/index-BB9Syqw2.css","assets/yjs-tXBm_srz.js","assets/command-Bfmj0MEL.js","assets/MediaField-CxccCFGQ.js","assets/useMedia-ae3s_ajC.js","assets/select-CrRhFGIi.js","assets/card-C9hfyHXf.js","assets/media-url-DdCoIedP.js","assets/CustomBlockPreview-DNnTFM0z.js","assets/ContentField-pilCbdnA.js","assets/core.esm-DdQHdRkd.js","assets/sortable.esm-qVEMoaTg.js","assets/popover-CzaQYEEP.js","assets/useContentSearch-B3aTjuCu.js","assets/BlockEditor-CQpF8tYb.css"])))=>i.map(i=>d[i]);
2
- import{j as t}from"./tanstack-Bs3zYPPV.js";import{I as h,B as g,P as A,ai as I,T as D,aJ as B,x as _,S as $,aK as z,y as N,Y as E,Z as L,_ as M,L as P}from"./index-Ce5pmRMj.js";import{T as q}from"./textarea-6fq0R6VV.js";import{C as w}from"./checkbox-DVJcwUt1.js";import{S as O,a as R,b as V,c as U,d as K}from"./select-CrRhFGIi.js";import{a as H}from"./MediaField-CxccCFGQ.js";import{b as Y,c as G,P as J,D as X,e as Z,C as Q}from"./core.esm-DdQHdRkd.js";import{S as W,v as ee,a as te,u as se}from"./sortable.esm-qVEMoaTg.js";import{C as y,c as C}from"./card-C9hfyHXf.js";import{r as x}from"./react-vendor-C2CvUxFh.js";import{C as re}from"./ContentField-pilCbdnA.js";import{K as ne,M as ae}from"./radix-C5ZmWuuL.js";function j({field:e,value:s,onChange:r}){const n=e.options;return t.jsx(h,{value:s??"",onChange:a=>r(a.target.value),placeholder:n?.placeholder,maxLength:n?.maxLength,required:!!n?.required,type:e.type==="url"?"url":e.type==="email"?"email":"text"})}function oe({field:e,value:s,onChange:r}){const n=e.options;return t.jsx(q,{value:s??"",onChange:a=>r(a.target.value),placeholder:n?.placeholder,maxLength:n?.maxLength,required:!!n?.required,rows:4})}function ie({field:e,value:s,onChange:r}){const n=e.options;return t.jsx(h,{type:"number",value:s??"",onChange:a=>r(a.target.value===""?void 0:Number(a.target.value)),min:n?.min,max:n?.max,step:n?.step,required:!!n?.required})}function ce({field:e,value:s,onChange:r}){return t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(w,{id:`field-${e.name}`,checked:!!s,onCheckedChange:n=>r(!!n)}),t.jsx("label",{htmlFor:`field-${e.name}`,className:"text-sm text-muted-foreground",children:e.label})]})}function le({field:e,value:s,onChange:r}){const a=e.options?.choices??[];return t.jsxs(O,{value:s??"",onValueChange:i=>r(i),children:[t.jsx(R,{children:t.jsx(V,{placeholder:"Select..."})}),t.jsx(U,{children:a.map(i=>t.jsx(K,{value:i,children:i},i))})]})}function de({field:e,value:s,onChange:r}){const n=Y(G(J)),a=Array.isArray(s)?s:[],l=e.options?.itemFields??[],o=a.map((m,c)=>`item-${c}`);function d(){r([...a,{}])}function p(m){r(a.filter((c,u)=>u!==m))}function f(m,c){const u=[...a];u[m]=c,r(u)}function v(m){const{active:c,over:u}=m;if(u&&c.id!==u.id){const T=o.indexOf(String(c.id)),k=o.indexOf(String(u.id));r(te(a,T,k))}}return t.jsx(X,{sensors:n,collisionDetection:Z,onDragEnd:v,children:t.jsx(W,{items:o,strategy:ee,children:t.jsxs("div",{className:"space-y-3",children:[a.map((m,c)=>t.jsx(ue,{id:`item-${c}`,itemFields:l,item:m,onUpdate:u=>f(c,u),onRemove:()=>p(c)},`item-${c}`)),t.jsxs(g,{type:"button",variant:"outline",size:"sm",onClick:d,children:[t.jsx(A,{className:"mr-2 h-3 w-3"})," Add Item"]})]})})})}function ue({id:e,itemFields:s,item:r,onUpdate:n,onRemove:a}){const{attributes:i,listeners:l,setNodeRef:o,transform:d,transition:p}=se({id:e}),f={transform:Q.Transform.toString(d),transition:p};return t.jsx(y,{ref:o,style:f,children:t.jsxs(C,{className:"flex gap-2 p-3",children:[t.jsx("button",{type:"button",className:"cursor-grab touch-none text-muted-foreground hover:text-foreground",...i,...l,children:t.jsx(I,{className:"h-4 w-4"})}),t.jsx("div",{className:"flex-1",children:t.jsx(F,{fields:s,values:r,onChange:n})}),t.jsx(g,{type:"button",variant:"ghost",size:"sm",onClick:a,className:"text-destructive",children:t.jsx(D,{className:"h-3 w-3"})})]})})}const me=x.createContext(null);function S(){return x.useContext(me)}const xe=x.lazy(()=>z(()=>import("./BlockEditor-3wnisTOZ.js").then(e=>e.a),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]))),pe=2,b=x.createContext(0);function fe({field:e,value:s,onChange:r,compact:n=!0}){const a=x.useContext(b),l=B()?.blockTypes??[],o=_(),p=S()?.getBlockNoteCollab(e.name);return a>=pe?t.jsx("div",{className:"rounded-md border border-muted p-4 text-sm text-muted-foreground",children:"Maximum nesting depth reached. Cannot embed another block editor here."}):t.jsx(b.Provider,{value:a+1,children:t.jsx("div",{className:o?"":"rounded-md border",children:t.jsx(x.Suspense,{fallback:t.jsx($,{className:"h-48"}),children:t.jsx(xe,{initialBlocks:Array.isArray(s)?s:[],onChange:r,blockTypes:l,compact:n,collaboration:p})})})})}function he({field:e,value:s,onChange:r}){const a=e.options?.fields??[],i=s&&typeof s=="object"&&!Array.isArray(s)?s:{};return t.jsx(y,{children:t.jsx(C,{className:"p-3",children:t.jsx(F,{fields:a,values:i,onChange:l=>r(l)})})})}function je({field:e,value:s,onChange:r}){const n=e.options,a=e.type==="datetime",i=be(s,a);function l(o){if(!o){r(void 0);return}const d=a?new Date(o).getTime():Date.UTC(Number(o.slice(0,4)),Number(o.slice(5,7))-1,Number(o.slice(8,10)));if(Number.isNaN(d)){r(void 0);return}r(d)}return t.jsx(h,{type:a?"datetime-local":"date",value:i,onChange:o=>l(o.target.value),required:!!n?.required})}function be(e,s){if(e==null||e==="")return"";let r;if(typeof e=="number")r=e;else if(typeof e=="string"){const a=/^-?\d+$/.test(e)?Number(e):Date.parse(e);if(Number.isNaN(a))return"";r=a}else return"";const n=new Date(r);if(Number.isNaN(n.getTime()))return"";if(s){const a=i=>String(i).padStart(2,"0");return`${n.getFullYear()}-${a(n.getMonth()+1)}-${a(n.getDate())}T${a(n.getHours())}:${a(n.getMinutes())}`}return n.toISOString().slice(0,10)}function ge({className:e,size:s="default",...r}){return t.jsx(ne,{"data-slot":"avatar","data-size":s,className:N("group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",e),...r})}function Ne({className:e,...s}){return t.jsx(ae,{"data-slot":"avatar-fallback",className:N("bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs",e),...s})}function ye(e){const s=e.trim().split(/\s+/).filter(Boolean);return s.length>=2?(s[0][0]+s[1][0]).toUpperCase():(s[0]?.[0]??"?").toUpperCase()}function Ce({field:e,editors:s}){const r=s.filter(n=>n.activeField===e);return r.length===0?null:t.jsx("span",{className:"inline-flex items-center -space-x-1 ml-2 align-middle","data-testid":"field-presence-indicator",children:r.map(n=>t.jsxs(E,{children:[t.jsx(L,{asChild:!0,children:t.jsx(ge,{className:"h-4 w-4 border-2 ring-1 ring-background",style:{borderColor:n.color},"aria-label":`${n.name} is editing`,children:t.jsx(Ne,{className:"text-[8px] font-medium",style:{backgroundColor:n.color+"20",color:n.color},children:ye(n.name)})})}),t.jsxs(M,{children:[n.name," is editing"]})]},n.sub))})}function F({fields:e,values:s,onChange:r}){const n=S();function a(o,d){r({...s,[o]:d})}function i(o){n?.setActiveField(o)}function l(o){o.currentTarget.contains(o.relatedTarget)||n?.setActiveField(null)}return t.jsx("div",{className:"space-y-4",children:e.map(o=>t.jsxs("div",{className:"space-y-2",onFocusCapture:()=>i(o.name),onBlurCapture:l,children:[o.type!=="boolean"&&t.jsxs(P,{className:"flex items-center",children:[o.label,n&&t.jsx(Ce,{field:o.name,editors:n.editors})]}),Se(o,s[o.name],d=>a(o.name,d))]},o.name))})}function Se(e,s,r){switch(e.type){case"text":case"url":case"email":return t.jsx(j,{field:e,value:s,onChange:r});case"textarea":return t.jsx(oe,{field:e,value:s,onChange:r});case"number":return t.jsx(ie,{field:e,value:s,onChange:r});case"boolean":return t.jsx(ce,{field:e,value:s,onChange:r});case"select":return t.jsx(le,{field:e,value:s,onChange:r});case"media":return t.jsx(H,{field:e,value:s,onChange:r});case"content":return t.jsx(re,{field:e,value:s,onChange:r});case"blocks":return t.jsx(fe,{field:e,value:s,onChange:r});case"array":return t.jsx(de,{field:e,value:s,onChange:r});case"container":return t.jsx(he,{field:e,value:s,onChange:r});case"date":case"datetime":return t.jsx(je,{field:e,value:s,onChange:r});default:return t.jsx(j,{field:e,value:s,onChange:r})}}export{ge as A,me as C,F,Ne as a,Ce as b,ye as i};
@@ -1 +0,0 @@
1
- import{u as N,j as e}from"./tanstack-Bs3zYPPV.js";import{u as v,r as h}from"./react-vendor-C2CvUxFh.js";import{e as w,j as x,X as y,a6 as S,a7 as F,B as p,ba as j,a9 as R,aa as I,ad as P}from"./index-Ce5pmRMj.js";import{P as T,a as L,b as D}from"./popover-CzaQYEEP.js";import{C as B,a as M,b as $,c as k,d as q,e as E}from"./command-Bfmj0MEL.js";import{u as Q,a as z}from"./useContentSearch-B3aTjuCu.js";function H({relationships:s,activeFilters:a,onFilterAdd:o,onFilterRemove:i}){const{host:u}=v(),[l,c]=h.useState(null),[d,r]=h.useState(""),n=Q(d,300);if(s.length===0)return null;const g=new Set(a.map(t=>t.relName)),m=s.filter(t=>!g.has(t.name));function C(t){c(t),r("")}function f(t){l&&(o({type:"relationship",relName:l.name,relLabel:l.label,contentId:t.contentId,contentTitle:t.title}),c(null),r(""))}function b(){c(null),r("")}return e.jsxs("div",{className:"flex flex-wrap items-center gap-2","data-testid":"filter-bar",children:[a.map(t=>e.jsxs(x,{variant:"secondary",className:"gap-1 pl-2",children:[t.relLabel,": ",t.contentTitle,e.jsx("button",{onClick:()=>i(t.relName),className:"ml-0.5 hover:text-foreground","aria-label":`Remove ${t.relLabel} filter`,children:e.jsx(y,{className:"h-3 w-3"})})]},t.relName)),m.length>0&&(l?e.jsx(A,{host:u,rel:l,query:d,debouncedQuery:n,onQueryChange:r,onSelect:f,onClose:b}):e.jsxs(S,{children:[e.jsx(F,{asChild:!0,children:e.jsxs(p,{variant:"outline",size:"sm","data-testid":"add-filter-button",children:[e.jsx(j,{className:"mr-1.5 h-3.5 w-3.5"}),"Add filter"]})}),e.jsx(R,{align:"start",children:m.map(t=>e.jsx(I,{onSelect:()=>C(t),children:t.label},t.name))})]}))]})}function A({host:s,rel:a,query:o,debouncedQuery:i,onQueryChange:u,onSelect:l,onClose:c}){const{data:d,isLoading:r}=z(s,i,[a.targetCollection],"published");return e.jsxs(T,{open:!0,onOpenChange:n=>{n||c()},children:[e.jsx(L,{asChild:!0,children:e.jsxs(p,{variant:"outline",size:"sm",children:[e.jsx(j,{className:"mr-1.5 h-3.5 w-3.5"}),a.label,"..."]})}),e.jsx(D,{className:"w-80 p-0",align:"start",children:e.jsxs(B,{shouldFilter:!1,children:[e.jsx(M,{placeholder:`Search ${a.label.toLowerCase()}...`,value:o,onValueChange:u,autoFocus:!0}),e.jsx($,{children:r?e.jsx("p",{className:"py-6 text-center text-sm text-muted-foreground",children:"Searching..."}):e.jsxs(e.Fragment,{children:[e.jsx(k,{children:"No published content found."}),e.jsx(q,{heading:i.length===0?"Recent":void 0,children:d?.items.map(n=>e.jsxs(E,{value:n.contentId,onSelect:()=>l({contentId:n.contentId,collection:n.collection,slug:n.slug??"",title:n.title}),children:[e.jsx(P,{className:"h-4 w-4"}),e.jsx("span",{className:"flex-1 truncate",children:n.title}),e.jsx(x,{variant:"outline",className:"text-xs",children:n.collection})]},n.contentId))})]})})]})})]})}function J(s,a){const o=w();return N({queryKey:["sites",s,"content-detail",a,"filter-title"],queryFn:async()=>(await o.apiFetch(`/v1/admin/sites/${s}/content/${a}`)).content?.title||"Untitled",enabled:!!s&&!!a,staleTime:6e4})}export{H as F,J as u};
@@ -1 +0,0 @@
1
- import{t as c,N as m,v as s,z as d,B as f,G as u,X as b,K as g,w as h,M as x,P as v,U as C,o as j,s as y,f as O,W as P}from"./BlockEditor-3wnisTOZ.js";import{r as I}from"./react-vendor-C2CvUxFh.js";import{j as r}from"./tanstack-Bs3zYPPV.js";import"./index-Ce5pmRMj.js";import"./radix-C5ZmWuuL.js";import"./yjs-tXBm_srz.js";import"./command-Bfmj0MEL.js";import"./MediaField-CxccCFGQ.js";import"./useMedia-ae3s_ajC.js";import"./select-CrRhFGIi.js";import"./card-C9hfyHXf.js";import"./media-url-DdCoIedP.js";import"./FieldRenderer-DiOKvkWV.js";import"./textarea-6fq0R6VV.js";import"./checkbox-DVJcwUt1.js";import"./core.esm-DdQHdRkd.js";import"./sortable.esm-qVEMoaTg.js";import"./ContentField-pilCbdnA.js";import"./popover-CzaQYEEP.js";import"./useContentSearch-B3aTjuCu.js";import"./CustomBlockPreview-DNnTFM0z.js";function S(){let o=m(s),t=d(),n=f(),e=u({trailingBlock:!1,dictionary:{...n,placeholders:{emptyDocument:n.placeholders.new_comment}},schema:o.commentEditorSchema||b});return r.jsx(t.Comments.Card,{className:"bn-thread",children:r.jsx(g,{autoFocus:!0,editable:!0,editor:e,actions:({isEmpty:a})=>r.jsx(t.Generic.Toolbar.Root,{className:h("bn-action-toolbar","bn-comment-actions"),variant:"action-toolbar",children:r.jsx(t.Generic.Toolbar.Button,{className:"bn-button",mainTooltip:"Save",variant:"compact",isDisabled:a,onClick:async()=>{await o.createThread({initialComment:{body:e.document}}),o.stopPendingComment()},children:"Save"})})})})}var L=c({default:()=>U});function U(o){let t=x(),n=m(s),e=v(s,{editor:t,selector:i=>i.pendingComment}),a=C({editor:t,selector:({editor:i})=>e?{from:i.prosemirrorState.selection.from,to:i.prosemirrorState.selection.to}:void 0}),p=I.useMemo(()=>({...o.floatingUIOptions,useFloatingOptions:{open:!!e,onOpenChange:i=>{i||(n.stopPendingComment(),t.focus())},placement:"bottom",middleware:[j(10),y(),O()],...o.floatingUIOptions?.useFloatingOptions},focusManagerProps:{disabled:!1},elementProps:{style:{zIndex:60},...o.floatingUIOptions?.elementProps}}),[n,t,e,o.floatingUIOptions]),l=o.floatingComposer||S;return r.jsx(P,{position:a,...p,children:r.jsx(l,{})})}export{L as n,S as r,U as t};