helldots 0.10.0 → 0.11.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.
package/dist/index.d.ts CHANGED
@@ -125,6 +125,37 @@ export interface CommentContext {
125
125
  */
126
126
  export type CommentId = string | number;
127
127
 
128
+ /**
129
+ * The actions `can` is consulted about — editing and deleting, at both
130
+ * levels, and nothing else. Classification and reactions are triage: they
131
+ * are reversible and shared by design, so they are never gated.
132
+ */
133
+ export type PermissionAction =
134
+ "edit:comment" | "delete:comment" | "edit:reply" | "delete:reply";
135
+
136
+ /**
137
+ * What `can` is told about the record an action would affect. Identity only:
138
+ * enough to decide, and deliberately not a live reference into widget state
139
+ * or a copy of the screenshots hanging off it.
140
+ */
141
+ export interface PermissionTarget {
142
+ /** Id of the comment or of the reply, matching the action. */
143
+ id: CommentId;
144
+ /** Display name the record was written under. */
145
+ author: string;
146
+ /**
147
+ * Identity the record was written under; null when the host had declared
148
+ * no `user.id` at the time. This is the field to compare against your own
149
+ * session — `author` is a label and two people can share it.
150
+ */
151
+ authorId: string | null;
152
+ /**
153
+ * The parent comment's id. Present only on `edit:reply` and
154
+ * `delete:reply`: a reply's id is unique only inside its thread.
155
+ */
156
+ commentId?: CommentId;
157
+ }
158
+
128
159
  export interface SerializedComment {
129
160
  /**
130
161
  * Version of this serialized shape. Stamped as 1 by serializeComments;
@@ -398,6 +429,32 @@ export interface CommentOverlayOptions {
398
429
  * at face value and recorded as-is.
399
430
  */
400
431
  user?: { name: string; id?: string };
432
+ /**
433
+ * Decides whether the current `user` may edit or delete a given comment or
434
+ * reply. Return literal `true` to allow; anything else — including the
435
+ * `undefined` of a branch with no return — denies, and a predicate that
436
+ * throws denies too.
437
+ *
438
+ * Omit it and the default rule applies: you may edit and delete what
439
+ * carries your identity, nobody else's. A host that never sets `user` is
440
+ * unaffected, since every record is then written by the same anonymous
441
+ * actor.
442
+ *
443
+ * Only the four destructive actions are asked about. Status, type,
444
+ * priority, reactions and replying stay open to everyone.
445
+ *
446
+ * This gates the widget's own menus and refuses the action when it comes
447
+ * from a click inside the widget. It does NOT gate your calls: the host's
448
+ * own `deleteComment()` always goes through, so a moderation flow your
449
+ * backend has already authorized is not blocked by a client-side rule.
450
+ * Nor is it security — the page can always reach the API directly. Check
451
+ * `authorId` against your session on the server.
452
+ *
453
+ * @example
454
+ * can: (action, target) =>
455
+ * isAdmin || target.authorId === session.userId,
456
+ */
457
+ can?: (action: PermissionAction, target: PermissionTarget) => boolean;
401
458
  /**
402
459
  * Query parameter carrying a comment id in "Copy link" URLs, and read back
403
460
  * on startup to open that comment. Default: "helldotsComment". Override it
@@ -761,6 +818,15 @@ export declare class CommentOverlay {
761
818
  * an object with a non-blank `name`.
762
819
  */
763
820
  setUser(user: { name: string; id?: string } | null): boolean;
821
+ /**
822
+ * Whether the current actor may perform `action` on `target`, under the
823
+ * host's `can` or — without one — the default ownership rule.
824
+ *
825
+ * The same verdict the widget's own menus render from, exposed so a host
826
+ * putting a delete button in its own chrome asks the one rule rather than
827
+ * keeping a second copy of it in step.
828
+ */
829
+ can(action: PermissionAction, target: PermissionTarget): boolean;
764
830
  setCommentStatus(id: CommentId, status: CommentStatus): boolean;
765
831
  setCommentType(id: CommentId, type: CommentType | null): boolean;
766
832
  setCommentPriority(id: CommentId, priority: CommentPriority | null): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helldots",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Drop-in comment overlay for web apps — click anywhere to leave a comment anchored to that element, with an automatic screenshot and environment capture",
5
5
  "keywords": [
6
6
  "comments",