droplinked-editor-configs 1.9.10 → 1.9.12

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.
@@ -12,10 +12,7 @@ export interface IAppStore {
12
12
  states: {
13
13
  cart: Icart;
14
14
  user: {
15
- [shopName: string]: {
16
- token: string;
17
- user: IUser;
18
- };
15
+ [shopName: string]: IUser;
19
16
  } | null;
20
17
  shop: IShop;
21
18
  };
@@ -34,10 +31,7 @@ declare const useAppStore: import('zustand').UseBoundStore<Omit<Omit<import('zus
34
31
  states: {
35
32
  cart: Icart;
36
33
  user: {
37
- [shopName: string]: {
38
- token: string;
39
- user: IUser;
40
- };
34
+ [shopName: string]: IUser;
41
35
  } | null;
42
36
  shop: IShop;
43
37
  };
@@ -51,10 +45,7 @@ declare const useAppStore: import('zustand').UseBoundStore<Omit<Omit<import('zus
51
45
  states: {
52
46
  cart: Icart;
53
47
  user: {
54
- [shopName: string]: {
55
- token: string;
56
- user: IUser;
57
- };
48
+ [shopName: string]: IUser;
58
49
  } | null;
59
50
  shop: IShop;
60
51
  };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Checks if a given string is likely an external URL (domain or http/https).
3
+ * It returns true for "google.com", "www.test.com", "http://site.com".
4
+ * It returns false for "home", "/about", "contact-us".
5
+ */
6
+ export declare const isExternalUrl: (url: string) => boolean;
7
+ /**
8
+ * Normalizes a URL string.
9
+ * If it's detected as an external URL but missing protocol, prepends https://.
10
+ */
11
+ export declare const normalizeUrl: (url: string) => string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "droplinked-editor-configs",
3
3
  "private": false,
4
- "version": "1.9.10",
4
+ "version": "1.9.12",
5
5
  "type": "module",
6
6
  "main": "dist/droplinked-editor.umd.js",
7
7
  "module": "dist/droplinked-editor.es.js",
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { socialMediaLinks } from './socialLinks';
3
3
  import CustomIcon from 'components/customIcon/CustomIcon';
4
4
  import useThemeInfo from 'hooks/useThemeInfo';
5
+ import { isExternalUrl, normalizeUrl } from 'lib/utils/urlUtils';
5
6
 
6
7
  // Accept socialChannels as prop
7
8
  interface SocialChannel {
@@ -25,12 +26,11 @@ interface SocialMediaBarProps {
25
26
  const SocialMediaBar: React.FC<SocialMediaBarProps> = React.memo(({ socialChannels }) => {
26
27
  const { shopDesign: { foreground } } = useThemeInfo()
27
28
 
28
- // Map channel name to icon from socialMediaLinks
29
- const getIconByChannel = (channel: string) => {
30
- const found = socialMediaLinks.find(
29
+ // Map channel name to social link item
30
+ const getSocialLinkItem = (channel: string) => {
31
+ return socialMediaLinks.find(
31
32
  (item) => item.key.replace('URL', '').toLowerCase() === channel.toLowerCase()
32
33
  );
33
- return found ? found.icon : undefined;
34
34
  };
35
35
 
36
36
  return (
@@ -39,12 +39,22 @@ const SocialMediaBar: React.FC<SocialMediaBarProps> = React.memo(({ socialChanne
39
39
  .filter((item) => !!item.links?.url && !!item.links?.channel)
40
40
  .map((item, idx) => {
41
41
  const { channel, url } = item.links!;
42
- const Icon = getIconByChannel(channel!);
43
- if (!Icon) return null;
42
+ const socialItem = getSocialLinkItem(channel!);
43
+ if (!socialItem) return null;
44
+
45
+ const Icon = socialItem.icon;
46
+ let href = url!;
47
+
48
+ if (isExternalUrl(href)) {
49
+ href = normalizeUrl(href);
50
+ } else {
51
+ href = `${socialItem.link}${href.replace(/^\//, '')}`;
52
+ }
53
+
44
54
  return (
45
55
  <a
46
56
  key={channel + idx}
47
- href={url}
57
+ href={href}
48
58
  target="_blank"
49
59
  rel="noopener noreferrer"
50
60
  className="inline-block rounded-md p-[10px] transition-colors duration-100 ease-out"
@@ -58,31 +68,4 @@ const SocialMediaBar: React.FC<SocialMediaBarProps> = React.memo(({ socialChanne
58
68
  );
59
69
  });
60
70
 
61
- export default SocialMediaBar;
62
-
63
- /**
64
- * Utility function to darken a hexadecimal color by a percentage
65
- *
66
- * @param color - Hexadecimal color string (e.g., "#FFFFFF")
67
- * @param percent - Percentage to darken the color (-100 to 100)
68
- * @returns Darkened hexadecimal color string
69
- */
70
- const darkenColor = (color: string, percent: number): string => {
71
- let num = parseInt(color.slice(1), 16);
72
- let amt = Math.round(2.55 * percent);
73
- let R = (num >> 16) + amt;
74
- let G = ((num >> 8) & 0x00ff) + amt;
75
- let B = (num & 0x0000ff) + amt;
76
-
77
- return (
78
- '#' +
79
- (
80
- 0x1000000 +
81
- (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +
82
- (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +
83
- (B < 255 ? (B < 1 ? 0 : B) : 255)
84
- )
85
- .toString(16)
86
- .slice(1)
87
- );
88
- };
71
+ export default SocialMediaBar;
@@ -1,6 +1,7 @@
1
1
  import { ArrowrightSm } from "assets/icon/Navigation/ArrowRight/ArrowrightSm";
2
2
  import Text from "components/ui/Text";
3
3
  import useThemeInfo from "hooks/useThemeInfo";
4
+ import { isExternalUrl, normalizeUrl } from "lib/utils/urlUtils";
4
5
  import React from "react";
5
6
 
6
7
  interface LinkItem {
@@ -49,14 +50,14 @@ export default function FooterNavigation({ linkManagement }: FooterNavigationPro
49
50
  const firstColumnLinks: LinkItem[] =
50
51
  linkManagement?.firstColumn?.links?.map(link => ({
51
52
  caption: link.list?.label ?? "",
52
- link: link.list?.url ?? "#"
53
+ link: link.list?.url ? normalizeUrl(link.list.url) : "#"
53
54
  })) ?? [];
54
55
 
55
56
  const secondColumnName = linkManagement?.secondColumn?.name ?? "Second Column";
56
57
  const secondColumnLinks: LinkItem[] =
57
58
  linkManagement?.secondColumn?.links?.map(link => ({
58
59
  caption: link.list?.label ?? "",
59
- link: link.list?.url ?? "#"
60
+ link: link.list?.url ? normalizeUrl(link.list.url) : "#"
60
61
  })) ?? [];
61
62
 
62
63
  return (
@@ -85,7 +86,7 @@ const CommonLinks: React.FC<CommonLinksProps> = ({ links, linkTextClass, isDynam
85
86
  {links.map(({ caption, link }, index) => (
86
87
  <li key={index}>
87
88
  {isDynamic ? (
88
- <a href={link} target="_self" rel="noopener noreferrer" className="flex">
89
+ <a href={link} target={isExternalUrl(link) ? "_blank" : "_self"} rel="noopener noreferrer" className="flex">
89
90
  <span className="group flex">
90
91
  <Text className={`relative flex items-center text-sm ${linkTextClass}`}>
91
92
  {caption}
@@ -18,7 +18,7 @@ interface Props {
18
18
  function Sidebar({ iconColor, linkManagement, ProfileDropdownWrapper }: Props) {
19
19
  const { isOpen, onOpen, onClose } = useDisclosure()
20
20
  const { states: { user, shop: { url } } } = useAppStore()
21
- const { id } = user?.[url]?.user || {}
21
+ const { id } = user?.[url] || {}
22
22
  const { shopDesign: { backgroundBody } } = useThemeInfo()
23
23
  const [isLargerThan768] = useMediaQuery('(min-width: 768px)')
24
24
  const { defineMultiStyleConfig } = createMultiStyleConfigHelpers(parts.keys)
@@ -16,7 +16,7 @@ interface Icart {
16
16
  export interface IAppStore {
17
17
  states: {
18
18
  cart: Icart;
19
- user: { [shopName: string]: { token: string; user: IUser } } | null;
19
+ user: { [shopName: string]: IUser } | null;
20
20
  shop: IShop;
21
21
  };
22
22
  methods: {
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Checks if a given string is likely an external URL (domain or http/https).
3
+ * It returns true for "google.com", "www.test.com", "http://site.com".
4
+ * It returns false for "home", "/about", "contact-us".
5
+ */
6
+ export const isExternalUrl = (url: string): boolean => {
7
+ if (!url) return false;
8
+
9
+ // Already has protocol
10
+ if (/^https?:\/\//i.test(url)) {
11
+ return true;
12
+ }
13
+
14
+ // Check for domain-like pattern (e.g., "example.com", "sub.domain.net/path")
15
+ // Pattern: starts with alphanumeric, contains dots, ends with TLD (2+ chars)
16
+ // We exclude strings that start with '/' (absolute paths)
17
+ if (url.startsWith('/')) {
18
+ return false;
19
+ }
20
+
21
+ // Regex to match domain at the start of the string
22
+ // [domain part].[tld] followed by optional path/query
23
+ const domainRegex = /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(\/.*)?$/;
24
+
25
+ return domainRegex.test(url);
26
+ };
27
+
28
+ /**
29
+ * Normalizes a URL string.
30
+ * If it's detected as an external URL but missing protocol, prepends https://.
31
+ */
32
+ export const normalizeUrl = (url: string): string => {
33
+ if (!url) return url;
34
+
35
+ if (isExternalUrl(url) && !/^https?:\/\//i.test(url)) {
36
+ return `https://${url}`;
37
+ }
38
+
39
+ return url;
40
+ };