@saasquatch/mint-components 2.1.8-21 → 2.1.8-22

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 (42) hide show
  1. package/dist/cjs/sqm-share-link.cjs.entry.js +271 -0
  2. package/dist/cjs/sqm-stencilbook.cjs.entry.js +1144 -588
  3. package/dist/cjs/useShareLink-1282123e.js +422 -0
  4. package/dist/cjs/useShareLink-3c22b1b9.js +448 -0
  5. package/dist/cjs/useShareLink-54e24928.js +448 -0
  6. package/dist/cjs/useShareLink-b664fbc7.js +450 -0
  7. package/dist/cjs/useShareLink-bf04b25c.js +450 -0
  8. package/dist/cjs/useShareLink-e8e2ae6d.js +448 -0
  9. package/dist/collection/components/sqm-share-link/sqm-share-link-view.js +2 -28
  10. package/dist/esm/sqm-share-link.entry.js +267 -0
  11. package/dist/esm/sqm-stencilbook.entry.js +3327 -2771
  12. package/dist/esm/useShareLink-023284f3.js +445 -0
  13. package/dist/esm/useShareLink-436e9cad.js +445 -0
  14. package/dist/esm/useShareLink-4ba01373.js +447 -0
  15. package/dist/esm/useShareLink-79056582.js +445 -0
  16. package/dist/esm/useShareLink-a3329e33.js +419 -0
  17. package/dist/esm/useShareLink-bc20ec4c.js +447 -0
  18. package/dist/esm-es5/sqm-share-link.entry.js +1 -0
  19. package/dist/esm-es5/sqm-stencilbook.entry.js +1 -1
  20. package/dist/esm-es5/useShareLink-023284f3.js +1 -0
  21. package/dist/esm-es5/useShareLink-436e9cad.js +1 -0
  22. package/dist/esm-es5/useShareLink-4ba01373.js +1 -0
  23. package/dist/esm-es5/useShareLink-79056582.js +1 -0
  24. package/dist/esm-es5/useShareLink-a3329e33.js +1 -0
  25. package/dist/esm-es5/useShareLink-bc20ec4c.js +1 -0
  26. package/dist/mint-components/sqm-share-link.entry.js +267 -0
  27. package/dist/mint-components/sqm-share-link.system.entry.js +1 -0
  28. package/dist/mint-components/sqm-stencilbook.entry.js +22106 -0
  29. package/dist/mint-components/sqm-stencilbook.system.entry.js +1 -0
  30. package/dist/mint-components/useShareLink-023284f3.js +445 -0
  31. package/dist/mint-components/useShareLink-1d7c9fd8.system.js +1 -0
  32. package/dist/mint-components/useShareLink-211e061c.system.js +1 -0
  33. package/dist/mint-components/useShareLink-2de7ffce.system.js +1 -0
  34. package/dist/mint-components/useShareLink-436e9cad.js +445 -0
  35. package/dist/mint-components/useShareLink-454939f5.system.js +1 -0
  36. package/dist/mint-components/useShareLink-4ba01373.js +447 -0
  37. package/dist/mint-components/useShareLink-79056582.js +445 -0
  38. package/dist/mint-components/useShareLink-a3329e33.js +419 -0
  39. package/dist/mint-components/useShareLink-bc20ec4c.js +447 -0
  40. package/dist/mint-components/useShareLink-c05fe151.system.js +1 -0
  41. package/dist/mint-components/useShareLink-cb5abd96.system.js +1 -0
  42. package/package.json +1 -1
@@ -0,0 +1,419 @@
1
+ import { h } from './index-d9876cd5.js';
2
+ import { i as intl } from './global-e1c1ff72.js';
3
+ import { i as useState, k as useRef } from './dom-context-hooks.module-8411297a.js';
4
+ import { d as dist, H, J, B, F as Fn, w as wn, $ as $e, X as Xe, h as Qe } from './index.module-60e4da3a.js';
5
+ import { c as createStyleSheet } from './JSS-8c381d8b.js';
6
+ import { R as REFERRAL_CODES_NAMESPACE, S as SET_CODE_COPIED } from './useReferralCodes-cff9a9dc.js';
7
+ import { C as CopyTextView } from './copy-text-view-c508f2e1.js';
8
+
9
+ const vanillaStyle = `
10
+ :host {
11
+ display: block;
12
+ width: 100%;
13
+ }
14
+ `;
15
+ function ShareLinkView(props) {
16
+ const { copyTextViewProps, customizeUrl, customizeLinkLabel, saveLabelText, cancelLabelText, isEditing, editValue, domainPrefix, editsRemaining, maxEdits, limitReached, validationError, isValidating, isSaving, characterLimit, minCharacters, charactersRemaining, editLimitText, editLimitReachedText, supportLinkText, customizeDisabled, customizeDisabledTooltip, onCustomizeClick, onEditValueChange, onSave, onCancel, } = props;
17
+ const style = {
18
+ Container: {
19
+ display: "flex",
20
+ flexDirection: "column",
21
+ gap: "var(--sl-spacing-xx-small)",
22
+ width: "100%",
23
+ },
24
+ CustomizeLinkText: {
25
+ margin: "0",
26
+ fontSize: "var(--sl-font-size-small)",
27
+ fontWeight: "600",
28
+ cursor: "pointer",
29
+ color: "var(--sl-color-neutral-900)",
30
+ textAlign: "left",
31
+ padding: "var(--sl-spacing-small)",
32
+ "&:hover": {
33
+ textDecoration: "underline",
34
+ },
35
+ },
36
+ CustomizeLinkDisabled: {
37
+ margin: "0",
38
+ fontSize: "var(--sl-font-size-small)",
39
+ fontWeight: "600",
40
+ color: "var(--sl-color-neutral-400)",
41
+ cursor: "default",
42
+ textAlign: "left",
43
+ padding: "var(--sl-spacing-small)",
44
+ },
45
+ EditContainer: {
46
+ display: "flex",
47
+ flexDirection: "column",
48
+ gap: "var(--sl-spacing-x-small)",
49
+ width: "100%",
50
+ },
51
+ EditInputWrapper: {
52
+ display: "flex",
53
+ alignItems: "center",
54
+ width: "100%",
55
+ border: "var(--sqm-border-thickness, 1px) solid var(--sqm-input-border-color, #d1d5db)",
56
+ borderRadius: "var(--sqm-border-radius-normal, 4px)",
57
+ background: "var(--sqm-input-background, #fff)",
58
+ overflow: "hidden",
59
+ "&:focus-within": {
60
+ borderColor: "#999999",
61
+ boxShadow: "0 0 0 var(--sl-focus-ring-width) var(--sl-input-focus-ring-color)",
62
+ },
63
+ },
64
+ DomainPrefix: {
65
+ padding: "0 0 0 var(--sl-spacing-medium)",
66
+ fontSize: "var(--sl-font-size-medium)",
67
+ color: "var(--sl-color-neutral-500)",
68
+ whiteSpace: "nowrap",
69
+ userSelect: "none",
70
+ lineHeight: "var(--sl-input-height-medium)",
71
+ },
72
+ EditInput: {
73
+ flex: "1",
74
+ border: "none",
75
+ outline: "none",
76
+ padding: "0 var(--sl-spacing-medium) 0 0",
77
+ fontSize: "var(--sl-font-size-medium)",
78
+ fontFamily: "var(--sl-font-sans)",
79
+ color: "var(--sl-input-color)",
80
+ background: "transparent",
81
+ lineHeight: "var(--sl-input-height-medium)",
82
+ minWidth: "0",
83
+ },
84
+ EditLabel: {
85
+ margin: "0",
86
+ fontSize: "var(--sl-font-size-small)",
87
+ color: "var(--sl-color-neutral-500)",
88
+ },
89
+ HelperText: {
90
+ margin: "0",
91
+ fontSize: "var(--sl-font-size-small)",
92
+ color: "var(--sl-color-neutral-500)",
93
+ },
94
+ ErrorText: {
95
+ margin: "0",
96
+ fontSize: "var(--sl-font-size-small)",
97
+ color: "var(--sqm-danger-color-text, #dc2626)",
98
+ },
99
+ ActionRow: {
100
+ display: "flex",
101
+ gap: "var(--sl-spacing-medium)",
102
+ alignItems: "center",
103
+ },
104
+ LimitReachedContainer: {
105
+ display: "flex",
106
+ alignItems: "center",
107
+ gap: "var(--sl-spacing-x-small)",
108
+ },
109
+ };
110
+ const sheet = createStyleSheet(style);
111
+ const styleString = sheet.toString();
112
+ const errorMessageType = (validationError === null || validationError === void 0 ? void 0 : validationError.code) === "EXISTING_CODE_CONFLICT" ? "info" : "warning";
113
+ const showCharactersRemaining = charactersRemaining <= 14;
114
+ console.log(customizeUrl, limitReached, customizeDisabled, validationError, "customize URL state");
115
+ // Editing state
116
+ if (isEditing) {
117
+ return (h("div", { class: sheet.classes.Container },
118
+ h("style", { type: "text/css" },
119
+ styleString,
120
+ vanillaStyle),
121
+ h("p", { class: sheet.classes.EditLabel }, "Enter your link"),
122
+ h("div", { class: sheet.classes.EditInputWrapper },
123
+ h("span", { class: sheet.classes.DomainPrefix }, domainPrefix),
124
+ h("input", { class: sheet.classes.EditInput, type: "text", value: editValue, onInput: (e) => onEditValueChange(e.target.value), onKeyDown: (e) => {
125
+ if (e.key === "/" || e.key === "@")
126
+ e.preventDefault();
127
+ }, disabled: isSaving, maxLength: characterLimit })),
128
+ h("p", { class: sheet.classes.HelperText },
129
+ editLimitText,
130
+ showCharactersRemaining &&
131
+ ` Characters remaining: ${charactersRemaining}`),
132
+ validationError && (h("sqm-form-message", { type: errorMessageType, style: { paddingBottom: "var(--sl-spacing-xx-small)" } },
133
+ h("p", { part: "alert-title" }, validationError.title),
134
+ validationError.description)),
135
+ isValidating && h("p", { class: sheet.classes.HelperText }, "Validating..."),
136
+ h("div", { class: sheet.classes.ActionRow },
137
+ h("sl-button", { type: "primary", onClick: onSave, disabled: isSaving ||
138
+ isValidating ||
139
+ !!validationError ||
140
+ !editValue ||
141
+ editValue.length < minCharacters }, isSaving ? "Saving..." : saveLabelText),
142
+ h("sl-button", { type: "secondary", onClick: onCancel, disabled: isSaving }, cancelLabelText))));
143
+ }
144
+ // Default / Customized / Limit reached states
145
+ return (h("div", { class: sheet.classes.Container },
146
+ h("style", { type: "text/css" },
147
+ styleString,
148
+ vanillaStyle),
149
+ h(CopyTextView, Object.assign({}, copyTextViewProps)),
150
+ customizeUrl &&
151
+ (customizeDisabled ? (h("sl-tooltip", { content: customizeDisabledTooltip, placement: "top", style: { display: "inline-block", width: "fit-content" } },
152
+ h("p", { class: sheet.classes.CustomizeLinkDisabled }, customizeLinkLabel))) : (h("div", { class: sheet.classes.LimitReachedContainer },
153
+ h("p", { class: limitReached
154
+ ? sheet.classes.CustomizeLinkDisabled
155
+ : sheet.classes.CustomizeLinkText, onClick: limitReached ? undefined : onCustomizeClick }, customizeLinkLabel),
156
+ customizeUrl && limitReached && (h("p", { class: sheet.classes.HelperText }, intl.formatMessage({
157
+ id: "editLimitReached",
158
+ defaultMessage: editLimitReachedText,
159
+ }, {
160
+ supportLink: (h("a", { target: "_blank", href: "https://help.impact.com/other/readme/get-help-and-support" }, supportLinkText)),
161
+ }))))))));
162
+ }
163
+
164
+ const MAX_EDITS = 5;
165
+ const CHARACTER_LIMIT = 15;
166
+ const MIN_CHARACTERS = 3;
167
+ const MessageLinkQuery = dist.gql `
168
+ query ($programId: ID) {
169
+ user: viewer {
170
+ ... on User {
171
+ shareLink(programId: $programId)
172
+ }
173
+ }
174
+ }
175
+ `;
176
+ const WIDGET_ENGAGEMENT_EVENT = dist.gql `
177
+ mutation loadEvent($eventMeta: UserAnalyticsEvent!) {
178
+ createUserAnalyticsEvent(eventMeta: $eventMeta)
179
+ }
180
+ `;
181
+ const ADD_SHARE_LINK_CODE = dist.gql `
182
+ mutation ($addShareLinkCodeInput: AddShareLinkCodeInput!) {
183
+ addShareLinkCode(addShareLinkCodeInput: $addShareLinkCodeInput) {
184
+ linkCode {
185
+ linkCode
186
+ shortUrl
187
+ referralCode {
188
+ code
189
+ }
190
+ }
191
+ }
192
+ }
193
+ `;
194
+ const VALIDATE_LINK_CODE = dist.gql `
195
+ query validateLinkCode($linkCode: String!) {
196
+ validateLinkCode(linkCode: $linkCode) {
197
+ valid
198
+ invalidReason
199
+ }
200
+ }
201
+ `;
202
+ const GET_LINK_DOMAIN = dist.gql `
203
+ query getLinkDomain {
204
+ tenantSettings {
205
+ primaryLinkDomain {
206
+ host
207
+ }
208
+ }
209
+ }
210
+ `;
211
+ const SHARE_LINK_EDIT_COUNT = dist.gql `
212
+ query shareLinkEditCount {
213
+ viewer {
214
+ ... on User {
215
+ shareLinkCodes {
216
+ totalCount
217
+ data {
218
+ isVanity
219
+ }
220
+ }
221
+ }
222
+ }
223
+ }
224
+ `;
225
+ function parseShareUrl(url) {
226
+ try {
227
+ const parsed = new URL(url);
228
+ return {
229
+ url: parsed.origin + parsed.pathname,
230
+ domain: parsed.origin + "/",
231
+ path: parsed.pathname.slice(1),
232
+ };
233
+ }
234
+ catch {
235
+ return { url, domain: url, path: "" };
236
+ }
237
+ }
238
+ function useShareLink(props) {
239
+ var _a, _b, _c, _d, _e, _f, _g;
240
+ const { programId = H() } = props;
241
+ const user = J();
242
+ const engagementMedium = B();
243
+ const contextData = Fn(REFERRAL_CODES_NAMESPACE);
244
+ const { data, refetch } = wn(MessageLinkQuery, { programId }, !(user === null || user === void 0 ? void 0 : user.jwt) || !!props.linkOverride || (contextData === null || contextData === void 0 ? void 0 : contextData.shareLink) !== undefined);
245
+ const [sendLoadEvent] = $e(WIDGET_ENGAGEMENT_EVENT);
246
+ const [setCopied] = $e(SET_CODE_COPIED);
247
+ const [addShareLinkCode, { loading: isSaving }] = $e(ADD_SHARE_LINK_CODE);
248
+ const [validateLinkCode] = Xe(VALIDATE_LINK_CODE);
249
+ const { refresh } = Qe();
250
+ const { data: linkDomainData } = wn(GET_LINK_DOMAIN, {}, !(user === null || user === void 0 ? void 0 : user.jwt) || !props.customizeUrl);
251
+ const { data: editCountData, refetch: refetchEditCount } = wn(SHARE_LINK_EDIT_COUNT, {}, !(user === null || user === void 0 ? void 0 : user.jwt) || !props.customizeUrl);
252
+ const { url: copyString, domain: domainPrefix, path: pathSuffix, } = parseShareUrl((_b = ((contextData === null || contextData === void 0 ? void 0 : contextData.shareLink) || ((_a = data === null || data === void 0 ? void 0 : data.user) === null || _a === void 0 ? void 0 : _a.shareLink))) !== null && _b !== void 0 ? _b :
253
+ // Shown during loading
254
+ "...");
255
+ const [open, setOpen] = useState(false);
256
+ const [isEditing, setIsEditing] = useState(false);
257
+ const [editValue, setEditValue] = useState("");
258
+ const [validationError, setValidationError] = useState(null);
259
+ const [isValidating, setIsValidating] = useState(false);
260
+ const debounceTimerRef = useRef(undefined);
261
+ const hasPrimaryLinkDomain = ((_c = linkDomainData === null || linkDomainData === void 0 ? void 0 : linkDomainData.tenantSettings) === null || _c === void 0 ? void 0 : _c.primaryLinkDomain) != null;
262
+ const customizeDisabled = !hasPrimaryLinkDomain;
263
+ const vanityCount = (_g = (_f = (_e = (_d = editCountData === null || editCountData === void 0 ? void 0 : editCountData.viewer) === null || _d === void 0 ? void 0 : _d.shareLinkCodes) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.filter((code) => code.isVanity).length) !== null && _g !== void 0 ? _g : 0;
264
+ const editCount = vanityCount;
265
+ const editsRemaining = Math.max(0, MAX_EDITS - editCount);
266
+ const limitReached = editsRemaining <= 0;
267
+ function mapErrorCodeToInfo(errorCode) {
268
+ if (!errorCode)
269
+ return null;
270
+ const errorMap = {
271
+ EXISTING_CODE_CONFLICT: {
272
+ code: "EXISTING_CODE_CONFLICT",
273
+ title: props.existingCodeConflictErrorTitle,
274
+ description: props.existingCodeConflictErrorDescription,
275
+ },
276
+ INVALID_CHARACTER: {
277
+ code: "INVALID_CHARACTER",
278
+ title: props.invalidCharactersErrorTitle,
279
+ description: props.invalidCharactersErrorDescription,
280
+ },
281
+ BLOCKED_WORD: {
282
+ code: "BLOCKED_WORD",
283
+ title: props.profanityErrorTitle,
284
+ description: props.profanityErrorDescription,
285
+ },
286
+ };
287
+ return errorMap[errorCode];
288
+ }
289
+ async function onClick() {
290
+ if (contextData) {
291
+ await setCopied({ referralCode: contextData.referralCode });
292
+ contextData.refresh();
293
+ }
294
+ // Should well supported: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard#browser_compatibility
295
+ // Only if called from a user-initiated event
296
+ navigator.clipboard.writeText(copyString);
297
+ setOpen(true);
298
+ setTimeout(() => setOpen(false), props.tooltiplifespan);
299
+ sendLoadEvent({
300
+ eventMeta: {
301
+ programId,
302
+ id: user === null || user === void 0 ? void 0 : user.id,
303
+ accountId: user === null || user === void 0 ? void 0 : user.accountId,
304
+ type: "USER_REFERRAL_PROGRAM_ENGAGEMENT_EVENT",
305
+ meta: {
306
+ engagementMedium,
307
+ shareMedium: "DIRECT",
308
+ },
309
+ },
310
+ });
311
+ }
312
+ function onCustomizeClick() {
313
+ if (limitReached || customizeDisabled)
314
+ return;
315
+ setIsEditing(true);
316
+ setEditValue(editCount === 0 ? "" : pathSuffix);
317
+ setValidationError(null);
318
+ }
319
+ function onEditValueChange(value) {
320
+ const trimmed = value.slice(0, CHARACTER_LIMIT);
321
+ setEditValue(trimmed);
322
+ setValidationError(null);
323
+ if (debounceTimerRef.current)
324
+ clearTimeout(debounceTimerRef.current);
325
+ if (!trimmed || trimmed.length < MIN_CHARACTERS) {
326
+ setIsValidating(false);
327
+ return;
328
+ }
329
+ setIsValidating(true);
330
+ debounceTimerRef.current = setTimeout(async () => {
331
+ var _a, _b;
332
+ try {
333
+ const result = await validateLinkCode({ linkCode: trimmed });
334
+ if (!((_a = result === null || result === void 0 ? void 0 : result.validateLinkCode) === null || _a === void 0 ? void 0 : _a.valid)) {
335
+ const reason = (_b = result === null || result === void 0 ? void 0 : result.validateLinkCode) === null || _b === void 0 ? void 0 : _b.invalidReason;
336
+ console.log(reason, "validation error reason from validateLinkCode query");
337
+ setValidationError(mapErrorCodeToInfo(reason));
338
+ }
339
+ }
340
+ catch {
341
+ // Validation query failed — don't block the user
342
+ }
343
+ setIsValidating(false);
344
+ }, 2000);
345
+ }
346
+ async function onSave() {
347
+ var _a, _b;
348
+ if (!editValue ||
349
+ editValue.length < MIN_CHARACTERS ||
350
+ validationError ||
351
+ isValidating)
352
+ return;
353
+ try {
354
+ await addShareLinkCode({
355
+ addShareLinkCodeInput: {
356
+ userId: user === null || user === void 0 ? void 0 : user.id,
357
+ accountId: user === null || user === void 0 ? void 0 : user.accountId,
358
+ programId,
359
+ linkCode: editValue,
360
+ makeShareLinkCodePrimaryForReferralCode: true,
361
+ },
362
+ });
363
+ setIsEditing(false);
364
+ await Promise.all([refetch(), refetchEditCount()]);
365
+ refresh();
366
+ }
367
+ catch (e) {
368
+ const errorCode = (_a = e === null || e === void 0 ? void 0 : e.extensions) === null || _a === void 0 ? void 0 : _a.code;
369
+ console.log(errorCode, "errorCode from addSharelInkCodeMutation");
370
+ setValidationError((_b = mapErrorCodeToInfo(errorCode)) !== null && _b !== void 0 ? _b : {
371
+ code: null,
372
+ title: "Error",
373
+ description: (e === null || e === void 0 ? void 0 : e.message) || "Failed to save custom link. Please try again.",
374
+ });
375
+ }
376
+ }
377
+ function onCancel() {
378
+ setIsEditing(false);
379
+ setEditValue("");
380
+ setValidationError(null);
381
+ setIsValidating(false);
382
+ }
383
+ console.log(validationError, "validation error state"); // TEMP --- IGNORE ---
384
+ return {
385
+ copyTextViewProps: {
386
+ ...props,
387
+ onClick,
388
+ open,
389
+ copyString,
390
+ },
391
+ customizeUrl: props.customizeUrl,
392
+ customizeLinkLabel: props.customizeLinkLabel,
393
+ saveLabelText: props.saveLabelText,
394
+ cancelLabelText: props.cancelLabelText,
395
+ isEditing,
396
+ editValue,
397
+ domainPrefix,
398
+ editsRemaining,
399
+ maxEdits: MAX_EDITS,
400
+ limitReached,
401
+ validationError,
402
+ isValidating,
403
+ isSaving,
404
+ characterLimit: CHARACTER_LIMIT,
405
+ minCharacters: MIN_CHARACTERS,
406
+ charactersRemaining: CHARACTER_LIMIT - editValue.length,
407
+ editLimitText: props.editLimitText,
408
+ editLimitReachedText: props.editLimitReachedText,
409
+ supportLinkText: props.supportLinkText,
410
+ customizeDisabled,
411
+ customizeDisabledTooltip: props.customizeDisabledTooltip,
412
+ onCustomizeClick,
413
+ onEditValueChange,
414
+ onSave,
415
+ onCancel,
416
+ };
417
+ }
418
+
419
+ export { ShareLinkView as S, useShareLink as u };