@burdenoff/microfe-vibecontrols 2026.531.11 → 2026.531.13

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.
@@ -1,140 +1,146 @@
1
1
  import { useCreateVibeDeckShareLinkMutation as e, useListVibeDeckShareLinksQuery as t, useRevokeVibeDeckShareLinkMutation as n } from "../../generated/wspace-operations.js";
2
- import { useTr as r } from "../../shared/hooks/useTr.js";
3
- import { useCallback as i, useState as a } from "react";
4
- import { Check as o, Code as s, Copy as c, Eye as l, Globe as u, Link2 as d, Loader2 as f, Lock as p, Play as m, Shield as h, Trash2 as g, Users as _, X as v } from "lucide-react";
5
- import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
2
+ import { useTr as ee } from "../../shared/hooks/useTr.js";
3
+ import { buildEmbedUrl as r, copyTextToClipboard as i, escapeHtmlAttribute as a, normalizeShareUrl as o } from "../../utils/shareUrl.js";
4
+ import { useCallback as s, useState as c } from "react";
5
+ import { Check as l, Code as u, Copy as d, Eye as f, Globe as p, Link2 as m, Loader2 as h, Lock as g, Play as _, Shield as v, Trash2 as te, Users as ne, X as y } from "lucide-react";
6
+ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
6
7
  //#region src/components/vibedeck/VibeDeckShareDialog.tsx
7
- var S = [
8
+ var C = [
8
9
  {
9
10
  value: "SIGNED_LINK",
10
11
  label: "Anyone with the link",
11
12
  description: "Anyone who has the link can access, no login required",
12
- icon: d
13
+ icon: m
13
14
  },
14
15
  {
15
16
  value: "PUBLIC",
16
17
  label: "Public",
17
18
  description: "Anyone can discover and access this deck",
18
- icon: u
19
+ icon: p
19
20
  },
20
21
  {
21
22
  value: "RESTRICTED",
22
23
  label: "Restricted",
23
24
  description: "Only people with permission can access (requires login)",
24
- icon: p
25
+ icon: g
25
26
  }
26
- ], C = [{
27
+ ], w = [{
27
28
  value: "VIEW",
28
29
  label: "Viewer",
29
30
  description: "Can view the deck",
30
- icon: l
31
+ icon: f
31
32
  }, {
32
33
  value: "EXECUTE",
33
34
  label: "Can execute",
34
35
  description: "Can view and execute buttons",
35
- icon: m
36
- }], w = ({ vibeDeckId: w, vibeDeckName: T, onClose: E }) => {
37
- let D = r(), [O, k] = a(null), [A, j] = a(null), [M, N] = a("SIGNED_LINK"), [P, F] = a("EXECUTE"), [I, L] = a(""), [R, z] = a(""), [B, V] = a(!1), [H, U] = a(""), { data: W, loading: G, refetch: ee } = t({ variables: { vibeDeckId: w } }), [K, { loading: q }] = e({ refetchQueries: ["ListVibeDeckShareLinks"] }), [J] = n({ refetchQueries: ["ListVibeDeckShareLinks"] }), Y = W?.vibeDeckShareLinks || [], X = i(async () => {
36
+ icon: _
37
+ }], T = ({ vibeDeckId: T, vibeDeckName: E, onClose: D }) => {
38
+ let O = ee(), [k, A] = c(null), [re, j] = c(null), [M, N] = c(null), [P, F] = c(null), [I, L] = c("SIGNED_LINK"), [R, z] = c("EXECUTE"), [B, V] = c(""), [H, U] = c(""), [W, G] = c(!1), [K, q] = c(""), { data: J, loading: Y, refetch: ie } = t({ variables: { vibeDeckId: T } }), [X, { loading: Z }] = e({ refetchQueries: ["ListVibeDeckShareLinks"] }), [Q] = n({ refetchQueries: ["ListVibeDeckShareLinks"] }), $ = J?.vibeDeckShareLinks || [], ae = s(async () => {
38
39
  try {
39
- await K({ variables: { input: {
40
- vibeDeckId: w,
41
- name: H || null,
42
- visibility: M,
43
- permission: P,
44
- expiresInHours: I ? parseInt(I, 10) : null,
45
- password: R || null,
46
- allowIframe: B
47
- } } }), U(""), z(""), L(""), V(!1);
40
+ await X({ variables: { input: {
41
+ vibeDeckId: T,
42
+ name: K || null,
43
+ visibility: I,
44
+ permission: R,
45
+ expiresInHours: B ? parseInt(B, 10) : null,
46
+ password: H || null,
47
+ allowIframe: W
48
+ } } }), q(""), U(""), V(""), G(!1);
48
49
  } catch {}
49
50
  }, [
51
+ X,
52
+ T,
50
53
  K,
51
- w,
52
- H,
53
- M,
54
- P,
55
54
  I,
56
55
  R,
57
- B
58
- ]), Z = i(async (e) => {
56
+ B,
57
+ H,
58
+ W
59
+ ]), oe = s(async (e) => {
59
60
  try {
60
- await J({ variables: { id: e } });
61
+ await Q({ variables: { id: e } });
61
62
  } catch {}
62
- }, [J]), Q = i((e, t) => {
63
- navigator.clipboard.writeText(t), k(e), setTimeout(() => k(null), 2e3);
64
- }, []), $ = i((e, t) => {
65
- let n = `<iframe src="${t}?embed=true" width="100%" height="600" frameborder="0" allow="clipboard-write" style="border-radius: 8px; border: 1px solid var(--color-border-subtle);"></iframe>`;
66
- navigator.clipboard.writeText(n), j(e), setTimeout(() => j(null), 2e3);
67
- }, []), te = (e) => {
63
+ }, [Q]), se = s(async (e, t) => {
64
+ let n = await i(o(t)).then(() => !0, (e) => (console.warn("Failed to copy VibeDeck share link:", e), !1));
65
+ A(n ? e : null), N(n ? null : e), setTimeout(() => {
66
+ A(null), N(null);
67
+ }, 2e3);
68
+ }, []), ce = s(async (e, t) => {
69
+ let n = await i(`<iframe src="${a(r(t))}" width="100%" height="600" frameborder="0" allow="clipboard-write" style="border-radius: 8px; border: 1px solid var(--color-border-subtle);"></iframe>`).then(() => !0, (e) => (console.warn("Failed to copy VibeDeck embed code:", e), !1));
70
+ j(n ? e : null), F(n ? null : e), setTimeout(() => {
71
+ j(null), F(null);
72
+ }, 2e3);
73
+ }, []), le = (e) => {
68
74
  switch (e) {
69
- case "PUBLIC": return /* @__PURE__ */ b(u, {
75
+ case "PUBLIC": return /* @__PURE__ */ x(p, {
70
76
  size: 14,
71
77
  className: "text-status-success-text"
72
78
  });
73
- case "RESTRICTED": return /* @__PURE__ */ b(p, {
79
+ case "RESTRICTED": return /* @__PURE__ */ x(g, {
74
80
  size: 14,
75
81
  className: "text-status-warning-text"
76
82
  });
77
- default: return /* @__PURE__ */ b(d, {
83
+ default: return /* @__PURE__ */ x(m, {
78
84
  size: 14,
79
85
  className: "text-status-info-text"
80
86
  });
81
87
  }
82
88
  };
83
- return /* @__PURE__ */ b("div", {
89
+ return /* @__PURE__ */ x("div", {
84
90
  className: "fixed inset-0 z-50 flex items-center justify-center bg-bg-elevated/60 backdrop-blur-sm",
85
- children: /* @__PURE__ */ x("div", {
91
+ children: /* @__PURE__ */ S("div", {
86
92
  className: "bg-bg-surface border border-border-default rounded-xl shadow-2xl w-full max-w-lg mx-4 max-h-[85vh] flex flex-col",
87
- children: [/* @__PURE__ */ x("div", {
93
+ children: [/* @__PURE__ */ S("div", {
88
94
  className: "flex items-center justify-between px-6 py-4 border-b border-border-default",
89
- children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ x("h2", {
95
+ children: [/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ S("h2", {
90
96
  className: "text-lg font-semibold text-text-primary",
91
97
  children: [
92
98
  "Share \"",
93
- T,
99
+ E,
94
100
  "\""
95
101
  ]
96
- }), /* @__PURE__ */ b("p", {
102
+ }), /* @__PURE__ */ x("p", {
97
103
  className: "text-sm text-text-secondary mt-0.5",
98
- children: D("vibecontrols.vibedeck.share.manageAccess", "Manage access to this VibeDeck")
99
- })] }), /* @__PURE__ */ b("button", {
104
+ children: O("vibecontrols.vibedeck.share.manageAccess", "Manage access to this VibeDeck")
105
+ })] }), /* @__PURE__ */ x("button", {
100
106
  type: "button",
101
- onClick: E,
107
+ onClick: D,
102
108
  className: "p-1.5 rounded-lg hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors",
103
- children: /* @__PURE__ */ b(v, { size: 18 })
109
+ children: /* @__PURE__ */ x(y, { size: 18 })
104
110
  })]
105
- }), /* @__PURE__ */ x("div", {
111
+ }), /* @__PURE__ */ S("div", {
106
112
  className: "overflow-y-auto flex-1 px-6 py-4 space-y-6",
107
- children: [/* @__PURE__ */ x("div", {
113
+ children: [/* @__PURE__ */ S("div", {
108
114
  className: "space-y-4",
109
115
  children: [
110
- /* @__PURE__ */ x("h3", {
116
+ /* @__PURE__ */ S("h3", {
111
117
  className: "text-sm font-medium text-text-primary flex items-center gap-2",
112
- children: [/* @__PURE__ */ b(d, { size: 14 }), D("vibecontrols.vibedeck.share.createShareLink", "Create share link")]
118
+ children: [/* @__PURE__ */ x(m, { size: 14 }), O("vibecontrols.vibedeck.share.createShareLink", "Create share link")]
113
119
  }),
114
- /* @__PURE__ */ b("input", {
120
+ /* @__PURE__ */ x("input", {
115
121
  "aria-label": "Link name (optional)",
116
122
  type: "text",
117
- value: H,
118
- onChange: (e) => U(e.target.value),
123
+ value: K,
124
+ onChange: (e) => q(e.target.value),
119
125
  placeholder: "Link name (optional)",
120
126
  className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
121
127
  }),
122
- /* @__PURE__ */ x("div", {
128
+ /* @__PURE__ */ S("div", {
123
129
  className: "space-y-2",
124
- children: [/* @__PURE__ */ b("label", {
130
+ children: [/* @__PURE__ */ x("label", {
125
131
  htmlFor: "vibedecksharedialog-37",
126
132
  className: "text-xs font-medium text-text-secondary uppercase tracking-wider",
127
133
  children: "Access"
128
- }), /* @__PURE__ */ b("div", {
134
+ }), /* @__PURE__ */ x("div", {
129
135
  className: "grid grid-cols-3 gap-2",
130
- children: S.map((e) => {
136
+ children: C.map((e) => {
131
137
  let t = e.icon;
132
- return /* @__PURE__ */ x("button", {
138
+ return /* @__PURE__ */ S("button", {
133
139
  type: "button",
134
- onClick: () => N(e.value),
135
- className: `flex flex-col items-center gap-1.5 p-3 rounded-lg border-2 text-xs font-medium transition-all ${M === e.value ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-default text-text-secondary hover:border-border-default hover:bg-bg-secondary"}`,
140
+ onClick: () => L(e.value),
141
+ className: `flex flex-col items-center gap-1.5 p-3 rounded-lg border-2 text-xs font-medium transition-all ${I === e.value ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-default text-text-secondary hover:border-border-default hover:bg-bg-secondary"}`,
136
142
  title: e.description,
137
- children: [/* @__PURE__ */ b(t, { size: 16 }), /* @__PURE__ */ b("span", {
143
+ children: [/* @__PURE__ */ x(t, { size: 16 }), /* @__PURE__ */ x("span", {
138
144
  className: "text-center leading-tight",
139
145
  children: e.label
140
146
  })]
@@ -142,180 +148,186 @@ var S = [
142
148
  })
143
149
  })]
144
150
  }),
145
- /* @__PURE__ */ x("div", {
151
+ /* @__PURE__ */ S("div", {
146
152
  className: "space-y-2",
147
- children: [/* @__PURE__ */ b("label", {
153
+ children: [/* @__PURE__ */ x("label", {
148
154
  htmlFor: "vibedecksharedialog-37",
149
155
  className: "text-xs font-medium text-text-secondary uppercase tracking-wider",
150
156
  children: "Permission"
151
- }), /* @__PURE__ */ b("div", {
157
+ }), /* @__PURE__ */ x("div", {
152
158
  className: "grid grid-cols-2 gap-2",
153
- children: C.map((e) => {
159
+ children: w.map((e) => {
154
160
  let t = e.icon;
155
- return /* @__PURE__ */ x("button", {
161
+ return /* @__PURE__ */ S("button", {
156
162
  type: "button",
157
- onClick: () => F(e.value),
158
- className: `flex items-center gap-2 p-3 rounded-lg border-2 text-sm font-medium transition-all ${P === e.value ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-default text-text-secondary hover:border-border-default hover:bg-bg-secondary"}`,
159
- children: [/* @__PURE__ */ b(t, { size: 14 }), e.label]
163
+ onClick: () => z(e.value),
164
+ className: `flex items-center gap-2 p-3 rounded-lg border-2 text-sm font-medium transition-all ${R === e.value ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-default text-text-secondary hover:border-border-default hover:bg-bg-secondary"}`,
165
+ children: [/* @__PURE__ */ x(t, { size: 14 }), e.label]
160
166
  }, e.value);
161
167
  })
162
168
  })]
163
169
  }),
164
- /* @__PURE__ */ x("div", {
170
+ /* @__PURE__ */ S("div", {
165
171
  className: "grid grid-cols-2 gap-3",
166
- children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
172
+ children: [/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("label", {
167
173
  htmlFor: "vibedecksharedialog-37",
168
174
  className: "text-xs font-medium text-text-secondary",
169
175
  children: "Expires in (hours)"
170
- }), /* @__PURE__ */ b("input", {
176
+ }), /* @__PURE__ */ x("input", {
171
177
  id: "vibedecksharedialog-37",
172
178
  "aria-label": "Never",
173
179
  type: "number",
174
180
  min: "1",
175
- value: I,
176
- onChange: (e) => L(e.target.value),
181
+ value: B,
182
+ onChange: (e) => V(e.target.value),
177
183
  placeholder: "Never",
178
184
  className: "w-full mt-1 px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
179
- })] }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
185
+ })] }), /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("label", {
180
186
  htmlFor: "vibedecksharedialog-36",
181
187
  className: "text-xs font-medium text-text-secondary",
182
188
  children: "Password (optional)"
183
- }), /* @__PURE__ */ b("input", {
189
+ }), /* @__PURE__ */ x("input", {
184
190
  id: "vibedecksharedialog-36",
185
191
  "aria-label": "No password",
186
192
  type: "password",
187
- value: R,
188
- onChange: (e) => z(e.target.value),
193
+ value: H,
194
+ onChange: (e) => U(e.target.value),
189
195
  placeholder: "No password",
190
196
  className: "w-full mt-1 px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
191
197
  })] })]
192
198
  }),
193
- /* @__PURE__ */ x("label", {
199
+ /* @__PURE__ */ S("label", {
194
200
  className: "flex items-center gap-3 cursor-pointer",
195
- children: [/* @__PURE__ */ b("input", {
201
+ children: [/* @__PURE__ */ x("input", {
196
202
  "aria-label": "control",
197
203
  type: "checkbox",
198
- checked: B,
199
- onChange: (e) => V(e.target.checked),
204
+ checked: W,
205
+ onChange: (e) => G(e.target.checked),
200
206
  className: "size-4 rounded border-border-default text-action-primary-bg focus:ring-action-primary-bg"
201
- }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("span", {
207
+ }), /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("span", {
202
208
  className: "text-sm text-text-primary",
203
209
  children: "Allow iframe embedding"
204
- }), /* @__PURE__ */ b("p", {
210
+ }), /* @__PURE__ */ x("p", {
205
211
  className: "text-xs text-text-tertiary",
206
212
  children: "Enable embedding this deck in other websites"
207
213
  })] })]
208
214
  }),
209
- /* @__PURE__ */ x("button", {
215
+ /* @__PURE__ */ S("button", {
210
216
  type: "button",
211
- onClick: X,
212
- disabled: q,
217
+ onClick: ae,
218
+ disabled: Z,
213
219
  className: "w-full px-4 py-2.5 rounded-lg bg-action-primary-bg text-action-primary-text text-sm font-medium hover:bg-action-primary-bg-hover disabled:opacity-50 transition-colors flex items-center justify-center gap-2",
214
- children: [q ? /* @__PURE__ */ b(f, {
220
+ children: [Z ? /* @__PURE__ */ x(h, {
215
221
  size: 14,
216
222
  className: "animate-spin"
217
- }) : /* @__PURE__ */ b(d, { size: 14 }), D("vibecontrols.vibedeck.share.createLink", "Create Link")]
223
+ }) : /* @__PURE__ */ x(m, { size: 14 }), O("vibecontrols.vibedeck.share.createLink", "Create Link")]
218
224
  })
219
225
  ]
220
- }), G ? /* @__PURE__ */ b("div", {
226
+ }), Y ? /* @__PURE__ */ x("div", {
221
227
  className: "flex items-center justify-center py-6",
222
- children: /* @__PURE__ */ b(f, {
228
+ children: /* @__PURE__ */ x(h, {
223
229
  size: 20,
224
230
  className: "animate-spin text-text-tertiary"
225
231
  })
226
- }) : Y.length > 0 ? /* @__PURE__ */ x("div", {
232
+ }) : $.length > 0 ? /* @__PURE__ */ S("div", {
227
233
  className: "space-y-3",
228
- children: [/* @__PURE__ */ x("h3", {
234
+ children: [/* @__PURE__ */ S("h3", {
229
235
  className: "text-sm font-medium text-text-primary flex items-center gap-2",
230
236
  children: [
231
- /* @__PURE__ */ b(h, { size: 14 }),
237
+ /* @__PURE__ */ x(v, { size: 14 }),
232
238
  "Active links (",
233
- Y.length,
239
+ $.length,
234
240
  ")"
235
241
  ]
236
- }), Y.map((e) => /* @__PURE__ */ x("div", {
242
+ }), $.map((e) => /* @__PURE__ */ S("div", {
237
243
  className: `rounded-lg border p-3 space-y-2 ${e.status === "ACTIVE" ? "border-border-default bg-bg-secondary" : "border-border-default/50 bg-bg-secondary/50 opacity-60"}`,
238
- children: [/* @__PURE__ */ x("div", {
244
+ children: [/* @__PURE__ */ S("div", {
239
245
  className: "flex items-center justify-between",
240
- children: [/* @__PURE__ */ x("div", {
246
+ children: [/* @__PURE__ */ S("div", {
241
247
  className: "flex items-center gap-2",
242
248
  children: [
243
- te(e.visibility),
244
- /* @__PURE__ */ b("span", {
249
+ le(e.visibility),
250
+ /* @__PURE__ */ x("span", {
245
251
  className: "text-sm font-medium text-text-primary",
246
252
  children: e.name || "Unnamed link"
247
253
  }),
248
- /* @__PURE__ */ b("span", {
254
+ /* @__PURE__ */ x("span", {
249
255
  className: `text-[10px] font-bold uppercase px-1.5 py-0.5 rounded ${e.status === "ACTIVE" ? "bg-status-success-bg/20 text-status-success-text" : e.status === "REVOKED" ? "bg-status-error-bg/20 text-status-error-text" : "bg-status-warning-bg/20 text-status-warning-text"}`,
250
256
  children: e.status
251
257
  })
252
258
  ]
253
- }), /* @__PURE__ */ b("div", {
259
+ }), /* @__PURE__ */ x("div", {
254
260
  className: "flex items-center gap-1",
255
- children: e.status === "ACTIVE" && /* @__PURE__ */ x(y, { children: [
256
- /* @__PURE__ */ b("button", {
261
+ children: e.status === "ACTIVE" && /* @__PURE__ */ S(b, { children: [
262
+ /* @__PURE__ */ x("button", {
257
263
  type: "button",
258
- onClick: () => Q(e.id, e.shareUrl),
264
+ onClick: () => se(e.id, e.shareUrl),
259
265
  className: "p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors",
260
266
  title: "Copy link",
261
- children: O === e.id ? /* @__PURE__ */ b(o, {
267
+ children: k === e.id ? /* @__PURE__ */ x(l, {
262
268
  size: 14,
263
269
  className: "text-status-success-text"
264
- }) : /* @__PURE__ */ b(c, { size: 14 })
270
+ }) : M === e.id ? /* @__PURE__ */ x(y, {
271
+ size: 14,
272
+ className: "text-status-error-text"
273
+ }) : /* @__PURE__ */ x(d, { size: 14 })
265
274
  }),
266
- e.allowIframe && /* @__PURE__ */ b("button", {
275
+ e.allowIframe && /* @__PURE__ */ x("button", {
267
276
  type: "button",
268
- onClick: () => $(e.id, e.shareUrl),
277
+ onClick: () => ce(e.id, e.shareUrl),
269
278
  className: "p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors",
270
279
  title: "Copy embed code",
271
- children: A === e.id ? /* @__PURE__ */ b(o, {
280
+ children: re === e.id ? /* @__PURE__ */ x(l, {
272
281
  size: 14,
273
282
  className: "text-status-success-text"
274
- }) : /* @__PURE__ */ b(s, { size: 14 })
283
+ }) : P === e.id ? /* @__PURE__ */ x(y, {
284
+ size: 14,
285
+ className: "text-status-error-text"
286
+ }) : /* @__PURE__ */ x(u, { size: 14 })
275
287
  }),
276
- /* @__PURE__ */ b("button", {
288
+ /* @__PURE__ */ x("button", {
277
289
  type: "button",
278
- onClick: () => Z(e.id),
290
+ onClick: () => oe(e.id),
279
291
  className: "p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-status-error-text transition-colors",
280
292
  title: "Revoke link",
281
- children: /* @__PURE__ */ b(g, { size: 14 })
293
+ children: /* @__PURE__ */ x(te, { size: 14 })
282
294
  })
283
295
  ] })
284
296
  })]
285
- }), /* @__PURE__ */ x("div", {
297
+ }), /* @__PURE__ */ S("div", {
286
298
  className: "flex items-center gap-3 text-xs text-text-tertiary",
287
299
  children: [
288
- /* @__PURE__ */ x("span", {
300
+ /* @__PURE__ */ S("span", {
289
301
  className: "flex items-center gap-1",
290
- children: [e.permission === "EXECUTE" ? /* @__PURE__ */ b(m, { size: 10 }) : /* @__PURE__ */ b(l, { size: 10 }), e.permission === "EXECUTE" ? "Can execute" : "View only"]
302
+ children: [e.permission === "EXECUTE" ? /* @__PURE__ */ x(_, { size: 10 }) : /* @__PURE__ */ x(f, { size: 10 }), e.permission === "EXECUTE" ? "Can execute" : "View only"]
291
303
  }),
292
- e.hasPassword && /* @__PURE__ */ x("span", {
304
+ e.hasPassword && /* @__PURE__ */ S("span", {
293
305
  className: "flex items-center gap-1",
294
- children: [/* @__PURE__ */ b(p, { size: 10 }), "Password"]
306
+ children: [/* @__PURE__ */ x(g, { size: 10 }), "Password"]
295
307
  }),
296
- e.allowIframe && /* @__PURE__ */ x("span", {
308
+ e.allowIframe && /* @__PURE__ */ S("span", {
297
309
  className: "flex items-center gap-1",
298
- children: [/* @__PURE__ */ b(s, { size: 10 }), "Embeddable"]
310
+ children: [/* @__PURE__ */ x(u, { size: 10 }), "Embeddable"]
299
311
  }),
300
- /* @__PURE__ */ x("span", { children: [e.useCount, " uses"] }),
301
- e.expiresAt && /* @__PURE__ */ x("span", { children: ["Expires ", new Date(e.expiresAt).toLocaleDateString()] })
312
+ /* @__PURE__ */ S("span", { children: [e.useCount, " uses"] }),
313
+ e.expiresAt && /* @__PURE__ */ S("span", { children: ["Expires ", new Date(e.expiresAt).toLocaleDateString()] })
302
314
  ]
303
315
  })]
304
316
  }, e.id))]
305
- }) : /* @__PURE__ */ x("div", {
317
+ }) : /* @__PURE__ */ S("div", {
306
318
  className: "text-center py-6",
307
319
  children: [
308
- /* @__PURE__ */ b(_, {
320
+ /* @__PURE__ */ x(ne, {
309
321
  size: 24,
310
322
  className: "mx-auto text-text-tertiary mb-2"
311
323
  }),
312
- /* @__PURE__ */ b("p", {
324
+ /* @__PURE__ */ x("p", {
313
325
  className: "text-sm text-text-secondary",
314
- children: D("vibecontrols.vibedeck.share.noLinks", "No share links yet")
326
+ children: O("vibecontrols.vibedeck.share.noLinks", "No share links yet")
315
327
  }),
316
- /* @__PURE__ */ b("p", {
328
+ /* @__PURE__ */ x("p", {
317
329
  className: "text-xs text-text-tertiary mt-1",
318
- children: D("vibecontrols.vibedeck.share.createLinkHint", "Create a link above to share this VibeDeck")
330
+ children: O("vibecontrols.vibedeck.share.createLinkHint", "Create a link above to share this VibeDeck")
319
331
  })
320
332
  ]
321
333
  })]
@@ -324,6 +336,6 @@ var S = [
324
336
  });
325
337
  };
326
338
  //#endregion
327
- export { w as VibeDeckShareDialog };
339
+ export { T as VibeDeckShareDialog };
328
340
 
329
341
  //# sourceMappingURL=VibeDeckShareDialog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VibeDeckShareDialog.js","names":[],"sources":["../../../src/components/vibedeck/VibeDeckShareDialog.tsx"],"sourcesContent":["import { type FC, useState, useCallback } from 'react';\nimport {\n X,\n Link2,\n Copy,\n Check,\n Trash2,\n Globe,\n Lock,\n Users,\n Code,\n Eye,\n Play,\n Shield,\n Loader2,\n} from 'lucide-react';\nimport { type VibeDeckShareLink } from '@/generated/wspace-types';\nimport {\n useListVibeDeckShareLinksQuery,\n useCreateVibeDeckShareLinkMutation,\n useRevokeVibeDeckShareLinkMutation,\n} from '@/generated/wspace-operations';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface VibeDeckShareDialogProps {\n vibeDeckId: string;\n vibeDeckName: string;\n onClose: () => void;\n}\n\nconst VISIBILITY_OPTIONS = [\n {\n value: 'SIGNED_LINK' as const,\n label: 'Anyone with the link',\n description: 'Anyone who has the link can access, no login required',\n icon: Link2,\n },\n {\n value: 'PUBLIC' as const,\n label: 'Public',\n description: 'Anyone can discover and access this deck',\n icon: Globe,\n },\n {\n value: 'RESTRICTED' as const,\n label: 'Restricted',\n description: 'Only people with permission can access (requires login)',\n icon: Lock,\n },\n];\n\nconst PERMISSION_OPTIONS = [\n {\n value: 'VIEW' as const,\n label: 'Viewer',\n description: 'Can view the deck',\n icon: Eye,\n },\n {\n value: 'EXECUTE' as const,\n label: 'Can execute',\n description: 'Can view and execute buttons',\n icon: Play,\n },\n];\n\nexport const VibeDeckShareDialog: FC<VibeDeckShareDialogProps> = ({\n vibeDeckId,\n vibeDeckName,\n onClose,\n}) => {\n const tr = useTr();\n const [copiedId, setCopiedId] = useState<string | null>(null);\n const [copiedEmbed, setCopiedEmbed] = useState<string | null>(null);\n\n // New link form state\n const [visibility, setVisibility] = useState<'SIGNED_LINK' | 'PUBLIC' | 'RESTRICTED'>(\n 'SIGNED_LINK'\n );\n const [permission, setPermission] = useState<'VIEW' | 'EXECUTE'>('EXECUTE');\n const [expiresInHours, setExpiresInHours] = useState<string>('');\n const [password, setPassword] = useState('');\n const [allowIframe, setAllowIframe] = useState(false);\n const [linkName, setLinkName] = useState('');\n\n const { data, loading, refetch } = useListVibeDeckShareLinksQuery({\n variables: { vibeDeckId },\n });\n\n const [createShareLink, { loading: creating }] = useCreateVibeDeckShareLinkMutation({\n refetchQueries: ['ListVibeDeckShareLinks'],\n });\n\n const [revokeShareLink] = useRevokeVibeDeckShareLinkMutation({\n refetchQueries: ['ListVibeDeckShareLinks'],\n });\n\n const shareLinks = data?.vibeDeckShareLinks || [];\n\n const handleCreate = useCallback(async () => {\n try {\n await createShareLink({\n variables: {\n input: {\n vibeDeckId,\n name: linkName || null,\n visibility,\n permission,\n expiresInHours: expiresInHours ? parseInt(expiresInHours, 10) : null,\n password: password || null,\n allowIframe,\n },\n },\n });\n // Reset form\n setLinkName('');\n setPassword('');\n setExpiresInHours('');\n setAllowIframe(false);\n } catch {\n // Error handled by Apollo\n }\n }, [\n createShareLink,\n vibeDeckId,\n linkName,\n visibility,\n permission,\n expiresInHours,\n password,\n allowIframe,\n ]);\n\n const handleRevoke = useCallback(\n async (id: string) => {\n try {\n await revokeShareLink({ variables: { id } });\n } catch {\n // Error handled by Apollo\n }\n },\n [revokeShareLink]\n );\n\n const handleCopyUrl = useCallback((id: string, url: string) => {\n navigator.clipboard.writeText(url);\n setCopiedId(id);\n setTimeout(() => setCopiedId(null), 2000);\n }, []);\n\n const handleCopyEmbed = useCallback((id: string, url: string) => {\n const embedCode = `<iframe src=\"${url}?embed=true\" width=\"100%\" height=\"600\" frameborder=\"0\" allow=\"clipboard-write\" style=\"border-radius: 8px; border: 1px solid var(--color-border-subtle);\"></iframe>`;\n navigator.clipboard.writeText(embedCode);\n setCopiedEmbed(id);\n setTimeout(() => setCopiedEmbed(null), 2000);\n }, []);\n\n const visibilityIcon = (v: string) => {\n switch (v) {\n case 'PUBLIC':\n return <Globe size={14} className=\"text-status-success-text\" />;\n case 'RESTRICTED':\n return <Lock size={14} className=\"text-status-warning-text\" />;\n default:\n return <Link2 size={14} className=\"text-status-info-text\" />;\n }\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-elevated/60 backdrop-blur-sm\">\n <div className=\"bg-bg-surface border border-border-default rounded-xl shadow-2xl w-full max-w-lg mx-4 max-h-[85vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Share \"{vibeDeckName}\"</h2>\n <p className=\"text-sm text-text-secondary mt-0.5\">\n {tr('vibecontrols.vibedeck.share.manageAccess', 'Manage access to this VibeDeck')}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1.5 rounded-lg hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors\"\n >\n <X size={18} />\n </button>\n </div>\n\n <div className=\"overflow-y-auto flex-1 px-6 py-4 space-y-6\">\n {/* Create new link section */}\n <div className=\"space-y-4\">\n <h3 className=\"text-sm font-medium text-text-primary flex items-center gap-2\">\n <Link2 size={14} />\n {tr('vibecontrols.vibedeck.share.createShareLink', 'Create share link')}\n </h3>\n\n {/* Link name (optional) */}\n <input\n aria-label=\"Link name (optional)\"\n type=\"text\"\n value={linkName}\n onChange={(e) => setLinkName(e.target.value)}\n placeholder=\"Link name (optional)\"\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n\n {/* Visibility selector */}\n <div className=\"space-y-2\">\n <label\n htmlFor=\"vibedecksharedialog-37\"\n className=\"text-xs font-medium text-text-secondary uppercase tracking-wider\"\n >\n Access\n </label>\n <div className=\"grid grid-cols-3 gap-2\">\n {VISIBILITY_OPTIONS.map((opt) => {\n const Icon = opt.icon;\n const isSelected = visibility === opt.value;\n return (\n <button\n type=\"button\"\n key={opt.value}\n onClick={() => setVisibility(opt.value)}\n className={`flex flex-col items-center gap-1.5 p-3 rounded-lg border-2 text-xs font-medium transition-all ${\n isSelected\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-default text-text-secondary hover:border-border-default hover:bg-bg-secondary'\n }`}\n title={opt.description}\n >\n <Icon size={16} />\n <span className=\"text-center leading-tight\">{opt.label}</span>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Permission selector */}\n <div className=\"space-y-2\">\n <label\n htmlFor=\"vibedecksharedialog-37\"\n className=\"text-xs font-medium text-text-secondary uppercase tracking-wider\"\n >\n Permission\n </label>\n <div className=\"grid grid-cols-2 gap-2\">\n {PERMISSION_OPTIONS.map((opt) => {\n const Icon = opt.icon;\n const isSelected = permission === opt.value;\n return (\n <button\n type=\"button\"\n key={opt.value}\n onClick={() => setPermission(opt.value)}\n className={`flex items-center gap-2 p-3 rounded-lg border-2 text-sm font-medium transition-all ${\n isSelected\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-default text-text-secondary hover:border-border-default hover:bg-bg-secondary'\n }`}\n >\n <Icon size={14} />\n {opt.label}\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Options row */}\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label\n htmlFor=\"vibedecksharedialog-37\"\n className=\"text-xs font-medium text-text-secondary\"\n >\n Expires in (hours)\n </label>\n <input\n id=\"vibedecksharedialog-37\"\n aria-label=\"Never\"\n type=\"number\"\n min=\"1\"\n value={expiresInHours}\n onChange={(e) => setExpiresInHours(e.target.value)}\n placeholder=\"Never\"\n className=\"w-full mt-1 px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n <div>\n <label\n htmlFor=\"vibedecksharedialog-36\"\n className=\"text-xs font-medium text-text-secondary\"\n >\n Password (optional)\n </label>\n <input\n id=\"vibedecksharedialog-36\"\n aria-label=\"No password\"\n type=\"password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder=\"No password\"\n className=\"w-full mt-1 px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n </div>\n\n {/* Allow iframe toggle */}\n <label className=\"flex items-center gap-3 cursor-pointer\">\n <input\n aria-label=\"control\"\n type=\"checkbox\"\n checked={allowIframe}\n onChange={(e) => setAllowIframe(e.target.checked)}\n className=\"size-4 rounded border-border-default text-action-primary-bg focus:ring-action-primary-bg\"\n />\n <div>\n <span className=\"text-sm text-text-primary\">Allow iframe embedding</span>\n <p className=\"text-xs text-text-tertiary\">\n Enable embedding this deck in other websites\n </p>\n </div>\n </label>\n\n {/* Create button */}\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={creating}\n className=\"w-full px-4 py-2.5 rounded-lg bg-action-primary-bg text-action-primary-text text-sm font-medium hover:bg-action-primary-bg-hover disabled:opacity-50 transition-colors flex items-center justify-center gap-2\"\n >\n {creating ? <Loader2 size={14} className=\"animate-spin\" /> : <Link2 size={14} />}\n {tr('vibecontrols.vibedeck.share.createLink', 'Create Link')}\n </button>\n </div>\n\n {/* Existing links */}\n {loading ? (\n <div className=\"flex items-center justify-center py-6\">\n <Loader2 size={20} className=\"animate-spin text-text-tertiary\" />\n </div>\n ) : shareLinks.length > 0 ? (\n <div className=\"space-y-3\">\n <h3 className=\"text-sm font-medium text-text-primary flex items-center gap-2\">\n <Shield size={14} />\n Active links ({shareLinks.length})\n </h3>\n {shareLinks.map((link: VibeDeckShareLink) => (\n <div\n key={link.id}\n className={`rounded-lg border p-3 space-y-2 ${\n link.status === 'ACTIVE'\n ? 'border-border-default bg-bg-secondary'\n : 'border-border-default/50 bg-bg-secondary/50 opacity-60'\n }`}\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n {visibilityIcon(link.visibility)}\n <span className=\"text-sm font-medium text-text-primary\">\n {link.name || 'Unnamed link'}\n </span>\n <span\n className={`text-[10px] font-bold uppercase px-1.5 py-0.5 rounded ${\n link.status === 'ACTIVE'\n ? 'bg-status-success-bg/20 text-status-success-text'\n : link.status === 'REVOKED'\n ? 'bg-status-error-bg/20 text-status-error-text'\n : 'bg-status-warning-bg/20 text-status-warning-text'\n }`}\n >\n {link.status}\n </span>\n </div>\n <div className=\"flex items-center gap-1\">\n {link.status === 'ACTIVE' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleCopyUrl(link.id, link.shareUrl)}\n className=\"p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors\"\n title=\"Copy link\"\n >\n {copiedId === link.id ? (\n <Check size={14} className=\"text-status-success-text\" />\n ) : (\n <Copy size={14} />\n )}\n </button>\n {link.allowIframe && (\n <button\n type=\"button\"\n onClick={() => handleCopyEmbed(link.id, link.shareUrl)}\n className=\"p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors\"\n title=\"Copy embed code\"\n >\n {copiedEmbed === link.id ? (\n <Check size={14} className=\"text-status-success-text\" />\n ) : (\n <Code size={14} />\n )}\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => handleRevoke(link.id)}\n className=\"p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-status-error-text transition-colors\"\n title=\"Revoke link\"\n >\n <Trash2 size={14} />\n </button>\n </>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-3 text-xs text-text-tertiary\">\n <span className=\"flex items-center gap-1\">\n {link.permission === 'EXECUTE' ? <Play size={10} /> : <Eye size={10} />}\n {link.permission === 'EXECUTE' ? 'Can execute' : 'View only'}\n </span>\n {link.hasPassword && (\n <span className=\"flex items-center gap-1\">\n <Lock size={10} />\n Password\n </span>\n )}\n {link.allowIframe && (\n <span className=\"flex items-center gap-1\">\n <Code size={10} />\n Embeddable\n </span>\n )}\n <span>{link.useCount} uses</span>\n {link.expiresAt && (\n <span>Expires {new Date(link.expiresAt).toLocaleDateString()}</span>\n )}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"text-center py-6\">\n <Users size={24} className=\"mx-auto text-text-tertiary mb-2\" />\n <p className=\"text-sm text-text-secondary\">\n {tr('vibecontrols.vibedeck.share.noLinks', 'No share links yet')}\n </p>\n <p className=\"text-xs text-text-tertiary mt-1\">\n {tr(\n 'vibecontrols.vibedeck.share.createLinkHint',\n 'Create a link above to share this VibeDeck'\n )}\n </p>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"VibeDeckShareDialog.js","names":[],"sources":["../../../src/components/vibedeck/VibeDeckShareDialog.tsx"],"sourcesContent":["import { type FC, useState, useCallback } from 'react';\nimport {\n X,\n Link2,\n Copy,\n Check,\n Trash2,\n Globe,\n Lock,\n Users,\n Code,\n Eye,\n Play,\n Shield,\n Loader2,\n} from 'lucide-react';\nimport { type VibeDeckShareLink } from '@/generated/wspace-types';\nimport {\n useListVibeDeckShareLinksQuery,\n useCreateVibeDeckShareLinkMutation,\n useRevokeVibeDeckShareLinkMutation,\n} from '@/generated/wspace-operations';\nimport { useTr } from '../../shared/hooks/useTr';\nimport {\n buildEmbedUrl,\n copyTextToClipboard,\n escapeHtmlAttribute,\n normalizeShareUrl,\n} from '../../utils/shareUrl';\n\ninterface VibeDeckShareDialogProps {\n vibeDeckId: string;\n vibeDeckName: string;\n onClose: () => void;\n}\n\nconst VISIBILITY_OPTIONS = [\n {\n value: 'SIGNED_LINK' as const,\n label: 'Anyone with the link',\n description: 'Anyone who has the link can access, no login required',\n icon: Link2,\n },\n {\n value: 'PUBLIC' as const,\n label: 'Public',\n description: 'Anyone can discover and access this deck',\n icon: Globe,\n },\n {\n value: 'RESTRICTED' as const,\n label: 'Restricted',\n description: 'Only people with permission can access (requires login)',\n icon: Lock,\n },\n];\n\nconst PERMISSION_OPTIONS = [\n {\n value: 'VIEW' as const,\n label: 'Viewer',\n description: 'Can view the deck',\n icon: Eye,\n },\n {\n value: 'EXECUTE' as const,\n label: 'Can execute',\n description: 'Can view and execute buttons',\n icon: Play,\n },\n];\n\nexport const VibeDeckShareDialog: FC<VibeDeckShareDialogProps> = ({\n vibeDeckId,\n vibeDeckName,\n onClose,\n}) => {\n const tr = useTr();\n const [copiedId, setCopiedId] = useState<string | null>(null);\n const [copiedEmbed, setCopiedEmbed] = useState<string | null>(null);\n const [copyFailedId, setCopyFailedId] = useState<string | null>(null);\n const [copyFailedEmbed, setCopyFailedEmbed] = useState<string | null>(null);\n\n // New link form state\n const [visibility, setVisibility] = useState<'SIGNED_LINK' | 'PUBLIC' | 'RESTRICTED'>(\n 'SIGNED_LINK'\n );\n const [permission, setPermission] = useState<'VIEW' | 'EXECUTE'>('EXECUTE');\n const [expiresInHours, setExpiresInHours] = useState<string>('');\n const [password, setPassword] = useState('');\n const [allowIframe, setAllowIframe] = useState(false);\n const [linkName, setLinkName] = useState('');\n\n const { data, loading, refetch } = useListVibeDeckShareLinksQuery({\n variables: { vibeDeckId },\n });\n\n const [createShareLink, { loading: creating }] = useCreateVibeDeckShareLinkMutation({\n refetchQueries: ['ListVibeDeckShareLinks'],\n });\n\n const [revokeShareLink] = useRevokeVibeDeckShareLinkMutation({\n refetchQueries: ['ListVibeDeckShareLinks'],\n });\n\n const shareLinks = data?.vibeDeckShareLinks || [];\n\n const handleCreate = useCallback(async () => {\n try {\n await createShareLink({\n variables: {\n input: {\n vibeDeckId,\n name: linkName || null,\n visibility,\n permission,\n expiresInHours: expiresInHours ? parseInt(expiresInHours, 10) : null,\n password: password || null,\n allowIframe,\n },\n },\n });\n // Reset form\n setLinkName('');\n setPassword('');\n setExpiresInHours('');\n setAllowIframe(false);\n } catch {\n // Error handled by Apollo\n }\n }, [\n createShareLink,\n vibeDeckId,\n linkName,\n visibility,\n permission,\n expiresInHours,\n password,\n allowIframe,\n ]);\n\n const handleRevoke = useCallback(\n async (id: string) => {\n try {\n await revokeShareLink({ variables: { id } });\n } catch {\n // Error handled by Apollo\n }\n },\n [revokeShareLink]\n );\n\n const handleCopyUrl = useCallback(async (id: string, url: string) => {\n const ok = await copyTextToClipboard(normalizeShareUrl(url)).then(\n () => true,\n (error) => {\n console.warn('Failed to copy VibeDeck share link:', error);\n return false;\n }\n );\n setCopiedId(ok ? id : null);\n setCopyFailedId(ok ? null : id);\n setTimeout(() => {\n setCopiedId(null);\n setCopyFailedId(null);\n }, 2000);\n }, []);\n\n const handleCopyEmbed = useCallback(async (id: string, url: string) => {\n const embedCode = `<iframe src=\"${escapeHtmlAttribute(buildEmbedUrl(url))}\" width=\"100%\" height=\"600\" frameborder=\"0\" allow=\"clipboard-write\" style=\"border-radius: 8px; border: 1px solid var(--color-border-subtle);\"></iframe>`;\n const ok = await copyTextToClipboard(embedCode).then(\n () => true,\n (error) => {\n console.warn('Failed to copy VibeDeck embed code:', error);\n return false;\n }\n );\n setCopiedEmbed(ok ? id : null);\n setCopyFailedEmbed(ok ? null : id);\n setTimeout(() => {\n setCopiedEmbed(null);\n setCopyFailedEmbed(null);\n }, 2000);\n }, []);\n\n const visibilityIcon = (v: string) => {\n switch (v) {\n case 'PUBLIC':\n return <Globe size={14} className=\"text-status-success-text\" />;\n case 'RESTRICTED':\n return <Lock size={14} className=\"text-status-warning-text\" />;\n default:\n return <Link2 size={14} className=\"text-status-info-text\" />;\n }\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-elevated/60 backdrop-blur-sm\">\n <div className=\"bg-bg-surface border border-border-default rounded-xl shadow-2xl w-full max-w-lg mx-4 max-h-[85vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Share \"{vibeDeckName}\"</h2>\n <p className=\"text-sm text-text-secondary mt-0.5\">\n {tr('vibecontrols.vibedeck.share.manageAccess', 'Manage access to this VibeDeck')}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1.5 rounded-lg hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors\"\n >\n <X size={18} />\n </button>\n </div>\n\n <div className=\"overflow-y-auto flex-1 px-6 py-4 space-y-6\">\n {/* Create new link section */}\n <div className=\"space-y-4\">\n <h3 className=\"text-sm font-medium text-text-primary flex items-center gap-2\">\n <Link2 size={14} />\n {tr('vibecontrols.vibedeck.share.createShareLink', 'Create share link')}\n </h3>\n\n {/* Link name (optional) */}\n <input\n aria-label=\"Link name (optional)\"\n type=\"text\"\n value={linkName}\n onChange={(e) => setLinkName(e.target.value)}\n placeholder=\"Link name (optional)\"\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n\n {/* Visibility selector */}\n <div className=\"space-y-2\">\n <label\n htmlFor=\"vibedecksharedialog-37\"\n className=\"text-xs font-medium text-text-secondary uppercase tracking-wider\"\n >\n Access\n </label>\n <div className=\"grid grid-cols-3 gap-2\">\n {VISIBILITY_OPTIONS.map((opt) => {\n const Icon = opt.icon;\n const isSelected = visibility === opt.value;\n return (\n <button\n type=\"button\"\n key={opt.value}\n onClick={() => setVisibility(opt.value)}\n className={`flex flex-col items-center gap-1.5 p-3 rounded-lg border-2 text-xs font-medium transition-all ${\n isSelected\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-default text-text-secondary hover:border-border-default hover:bg-bg-secondary'\n }`}\n title={opt.description}\n >\n <Icon size={16} />\n <span className=\"text-center leading-tight\">{opt.label}</span>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Permission selector */}\n <div className=\"space-y-2\">\n <label\n htmlFor=\"vibedecksharedialog-37\"\n className=\"text-xs font-medium text-text-secondary uppercase tracking-wider\"\n >\n Permission\n </label>\n <div className=\"grid grid-cols-2 gap-2\">\n {PERMISSION_OPTIONS.map((opt) => {\n const Icon = opt.icon;\n const isSelected = permission === opt.value;\n return (\n <button\n type=\"button\"\n key={opt.value}\n onClick={() => setPermission(opt.value)}\n className={`flex items-center gap-2 p-3 rounded-lg border-2 text-sm font-medium transition-all ${\n isSelected\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-default text-text-secondary hover:border-border-default hover:bg-bg-secondary'\n }`}\n >\n <Icon size={14} />\n {opt.label}\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Options row */}\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label\n htmlFor=\"vibedecksharedialog-37\"\n className=\"text-xs font-medium text-text-secondary\"\n >\n Expires in (hours)\n </label>\n <input\n id=\"vibedecksharedialog-37\"\n aria-label=\"Never\"\n type=\"number\"\n min=\"1\"\n value={expiresInHours}\n onChange={(e) => setExpiresInHours(e.target.value)}\n placeholder=\"Never\"\n className=\"w-full mt-1 px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n <div>\n <label\n htmlFor=\"vibedecksharedialog-36\"\n className=\"text-xs font-medium text-text-secondary\"\n >\n Password (optional)\n </label>\n <input\n id=\"vibedecksharedialog-36\"\n aria-label=\"No password\"\n type=\"password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder=\"No password\"\n className=\"w-full mt-1 px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-lg text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n </div>\n\n {/* Allow iframe toggle */}\n <label className=\"flex items-center gap-3 cursor-pointer\">\n <input\n aria-label=\"control\"\n type=\"checkbox\"\n checked={allowIframe}\n onChange={(e) => setAllowIframe(e.target.checked)}\n className=\"size-4 rounded border-border-default text-action-primary-bg focus:ring-action-primary-bg\"\n />\n <div>\n <span className=\"text-sm text-text-primary\">Allow iframe embedding</span>\n <p className=\"text-xs text-text-tertiary\">\n Enable embedding this deck in other websites\n </p>\n </div>\n </label>\n\n {/* Create button */}\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={creating}\n className=\"w-full px-4 py-2.5 rounded-lg bg-action-primary-bg text-action-primary-text text-sm font-medium hover:bg-action-primary-bg-hover disabled:opacity-50 transition-colors flex items-center justify-center gap-2\"\n >\n {creating ? <Loader2 size={14} className=\"animate-spin\" /> : <Link2 size={14} />}\n {tr('vibecontrols.vibedeck.share.createLink', 'Create Link')}\n </button>\n </div>\n\n {/* Existing links */}\n {loading ? (\n <div className=\"flex items-center justify-center py-6\">\n <Loader2 size={20} className=\"animate-spin text-text-tertiary\" />\n </div>\n ) : shareLinks.length > 0 ? (\n <div className=\"space-y-3\">\n <h3 className=\"text-sm font-medium text-text-primary flex items-center gap-2\">\n <Shield size={14} />\n Active links ({shareLinks.length})\n </h3>\n {shareLinks.map((link: VibeDeckShareLink) => (\n <div\n key={link.id}\n className={`rounded-lg border p-3 space-y-2 ${\n link.status === 'ACTIVE'\n ? 'border-border-default bg-bg-secondary'\n : 'border-border-default/50 bg-bg-secondary/50 opacity-60'\n }`}\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n {visibilityIcon(link.visibility)}\n <span className=\"text-sm font-medium text-text-primary\">\n {link.name || 'Unnamed link'}\n </span>\n <span\n className={`text-[10px] font-bold uppercase px-1.5 py-0.5 rounded ${\n link.status === 'ACTIVE'\n ? 'bg-status-success-bg/20 text-status-success-text'\n : link.status === 'REVOKED'\n ? 'bg-status-error-bg/20 text-status-error-text'\n : 'bg-status-warning-bg/20 text-status-warning-text'\n }`}\n >\n {link.status}\n </span>\n </div>\n <div className=\"flex items-center gap-1\">\n {link.status === 'ACTIVE' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleCopyUrl(link.id, link.shareUrl)}\n className=\"p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors\"\n title=\"Copy link\"\n >\n {copiedId === link.id ? (\n <Check size={14} className=\"text-status-success-text\" />\n ) : copyFailedId === link.id ? (\n <X size={14} className=\"text-status-error-text\" />\n ) : (\n <Copy size={14} />\n )}\n </button>\n {link.allowIframe && (\n <button\n type=\"button\"\n onClick={() => handleCopyEmbed(link.id, link.shareUrl)}\n className=\"p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-text-primary transition-colors\"\n title=\"Copy embed code\"\n >\n {copiedEmbed === link.id ? (\n <Check size={14} className=\"text-status-success-text\" />\n ) : copyFailedEmbed === link.id ? (\n <X size={14} className=\"text-status-error-text\" />\n ) : (\n <Code size={14} />\n )}\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => handleRevoke(link.id)}\n className=\"p-1.5 rounded hover:bg-bg-tertiary text-text-tertiary hover:text-status-error-text transition-colors\"\n title=\"Revoke link\"\n >\n <Trash2 size={14} />\n </button>\n </>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-3 text-xs text-text-tertiary\">\n <span className=\"flex items-center gap-1\">\n {link.permission === 'EXECUTE' ? <Play size={10} /> : <Eye size={10} />}\n {link.permission === 'EXECUTE' ? 'Can execute' : 'View only'}\n </span>\n {link.hasPassword && (\n <span className=\"flex items-center gap-1\">\n <Lock size={10} />\n Password\n </span>\n )}\n {link.allowIframe && (\n <span className=\"flex items-center gap-1\">\n <Code size={10} />\n Embeddable\n </span>\n )}\n <span>{link.useCount} uses</span>\n {link.expiresAt && (\n <span>Expires {new Date(link.expiresAt).toLocaleDateString()}</span>\n )}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"text-center py-6\">\n <Users size={24} className=\"mx-auto text-text-tertiary mb-2\" />\n <p className=\"text-sm text-text-secondary\">\n {tr('vibecontrols.vibedeck.share.noLinks', 'No share links yet')}\n </p>\n <p className=\"text-xs text-text-tertiary mt-1\">\n {tr(\n 'vibecontrols.vibedeck.share.createLinkHint',\n 'Create a link above to share this VibeDeck'\n )}\n </p>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -2087,7 +2087,7 @@ var e = {
2087
2087
  namePlaceholder: "My Project",
2088
2088
  nameRequired: "Name is required",
2089
2089
  openEditorPathMissing: "No path available to open in editor",
2090
- pathLabel: "Path *",
2090
+ pathLabel: "Path",
2091
2091
  pathPlaceholder: "/path/to/project",
2092
2092
  pathRequired: "Path is required",
2093
2093
  refreshTitle: "Refresh vibes",