@agentiffai/design 1.5.0 → 1.5.2

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.cjs CHANGED
@@ -9944,13 +9944,17 @@ var PostPreviewCard = ({
9944
9944
  isEditing = false,
9945
9945
  editContent,
9946
9946
  onContentChange,
9947
+ editHashtags,
9948
+ onHashtagsChange,
9947
9949
  isLoading = false,
9948
9950
  onImageChange
9949
9951
  }) => {
9950
9952
  const platformConfig = PLATFORM_CONFIGS[post.platform] || PLATFORM_CONFIGS.x;
9951
9953
  const [imageError, setImageError] = React4.useState(false);
9954
+ const [newHashtag, setNewHashtag] = React4.useState("");
9952
9955
  const showSkeleton = isLoading && !post.content;
9953
9956
  const displayContent = isEditing && editContent !== void 0 ? editContent : post.editedContent || post.content;
9957
+ const displayHashtags = editHashtags !== void 0 ? editHashtags : post.hashtags;
9954
9958
  const currentCharCount = displayContent.length;
9955
9959
  const charPercentage = React4.useMemo(
9956
9960
  () => getCharacterLimitPercentage(post.platform, currentCharCount),
@@ -9964,6 +9968,32 @@ var PostPreviewCard = ({
9964
9968
  const handleContentChange = (e) => {
9965
9969
  onContentChange?.(e.target.value);
9966
9970
  };
9971
+ const normalizeHashtag = (value) => value.trim().replace(/^#+/, "").replace(/[^\p{L}\p{N}_]/gu, "");
9972
+ const handleRemoveHashtag = (hashtagToRemove) => {
9973
+ const normalizedToRemove = normalizeHashtag(hashtagToRemove).toLowerCase();
9974
+ onHashtagsChange?.(
9975
+ displayHashtags.filter(
9976
+ (hashtag) => normalizeHashtag(hashtag).toLowerCase() !== normalizedToRemove
9977
+ )
9978
+ );
9979
+ };
9980
+ const handleAddHashtag = () => {
9981
+ const normalized = normalizeHashtag(newHashtag);
9982
+ if (!normalized) return;
9983
+ const exists = displayHashtags.some(
9984
+ (hashtag) => normalizeHashtag(hashtag).toLowerCase() === normalized.toLowerCase()
9985
+ );
9986
+ if (!exists) {
9987
+ onHashtagsChange?.([...displayHashtags, normalized]);
9988
+ }
9989
+ setNewHashtag("");
9990
+ };
9991
+ const handleNewHashtagKeyDown = (e) => {
9992
+ if (e.key === "Enter") {
9993
+ e.preventDefault();
9994
+ handleAddHashtag();
9995
+ }
9996
+ };
9967
9997
  return /* @__PURE__ */ jsxRuntime.jsxs(
9968
9998
  CardContainer,
9969
9999
  {
@@ -9993,10 +10023,45 @@ var PostPreviewCard = ({
9993
10023
  autoFocus: true
9994
10024
  }
9995
10025
  ) : /* @__PURE__ */ jsxRuntime.jsx(PostContent, { children: displayContent }),
9996
- !showSkeleton && post.hashtags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HashtagsContainer, { children: post.hashtags.map((hashtag) => /* @__PURE__ */ jsxRuntime.jsxs(HashtagPill, { $platformColor: platformConfig.color, children: [
9997
- "#",
9998
- hashtag.replace(/^#/, "")
9999
- ] }, hashtag)) })
10026
+ !showSkeleton && (displayHashtags.length > 0 || onHashtagsChange) && /* @__PURE__ */ jsxRuntime.jsxs(HashtagsContainer, { children: [
10027
+ displayHashtags.map((hashtag) => /* @__PURE__ */ jsxRuntime.jsxs(HashtagPill, { $platformColor: platformConfig.color, children: [
10028
+ "#",
10029
+ hashtag.replace(/^#/, ""),
10030
+ onHashtagsChange && /* @__PURE__ */ jsxRuntime.jsx(
10031
+ RemoveHashtagButton,
10032
+ {
10033
+ type: "button",
10034
+ onClick: () => handleRemoveHashtag(hashtag),
10035
+ "aria-label": `Remove #${hashtag.replace(/^#/, "")}`,
10036
+ children: "\xD7"
10037
+ }
10038
+ )
10039
+ ] }, hashtag)),
10040
+ onHashtagsChange && /* @__PURE__ */ jsxRuntime.jsxs(HashtagEditor, { children: [
10041
+ /* @__PURE__ */ jsxRuntime.jsxs(HashtagInputWrapper, { children: [
10042
+ /* @__PURE__ */ jsxRuntime.jsx(HashPrefix, { children: "#" }),
10043
+ /* @__PURE__ */ jsxRuntime.jsx(
10044
+ HashtagInput,
10045
+ {
10046
+ value: newHashtag,
10047
+ onChange: (e) => setNewHashtag(e.target.value),
10048
+ onKeyDown: handleNewHashtagKeyDown,
10049
+ placeholder: "Add hashtag",
10050
+ "aria-label": "Add hashtag"
10051
+ }
10052
+ )
10053
+ ] }),
10054
+ /* @__PURE__ */ jsxRuntime.jsx(
10055
+ AddHashtagButton,
10056
+ {
10057
+ type: "button",
10058
+ onClick: handleAddHashtag,
10059
+ disabled: !normalizeHashtag(newHashtag),
10060
+ children: "Add"
10061
+ }
10062
+ )
10063
+ ] })
10064
+ ] })
10000
10065
  ] }),
10001
10066
  post.imageUrl && !imageError ? onImageChange ? /* @__PURE__ */ jsxRuntime.jsx(ImageChangeButton, { type: "button", onClick: onImageChange, "aria-label": "Change image", children: /* @__PURE__ */ jsxRuntime.jsxs(ImagePreviewContainer, { children: [
10002
10067
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -10211,7 +10276,9 @@ var HashtagsContainer = styled58__default.default.div`
10211
10276
  gap: 6px;
10212
10277
  `;
10213
10278
  var HashtagPill = styled58__default.default.span`
10214
- display: inline-block;
10279
+ display: inline-flex;
10280
+ align-items: center;
10281
+ gap: 6px;
10215
10282
  padding: ${tokens.spacing.xs} 10px;
10216
10283
  border-radius: ${tokens.borderRadius.full};
10217
10284
  font-size: ${tokens.typography.fontSize.xs};
@@ -10227,6 +10294,99 @@ var HashtagPill = styled58__default.default.span`
10227
10294
  color: ${tokens.colors.primary};
10228
10295
  }
10229
10296
  `;
10297
+ var RemoveHashtagButton = styled58__default.default.button`
10298
+ width: 16px;
10299
+ height: 16px;
10300
+ display: inline-flex;
10301
+ align-items: center;
10302
+ justify-content: center;
10303
+ padding: 0;
10304
+ border: none;
10305
+ border-radius: ${tokens.borderRadius.full};
10306
+ background: ${tokens.colors.background.light};
10307
+ color: ${tokens.colors.text.secondary};
10308
+ cursor: pointer;
10309
+ font-size: 12px;
10310
+ line-height: 1;
10311
+ transition: all ${tokens.transitions.fast};
10312
+
10313
+ &:hover,
10314
+ &:focus-visible {
10315
+ background: ${tokens.colors.error};
10316
+ color: ${tokens.colors.text.primary};
10317
+ outline: none;
10318
+ }
10319
+ `;
10320
+ var HashtagEditor = styled58__default.default.div`
10321
+ display: inline-flex;
10322
+ align-items: center;
10323
+ gap: ${tokens.spacing.xs};
10324
+ min-width: min(100%, 190px);
10325
+ `;
10326
+ var HashtagInputWrapper = styled58__default.default.div`
10327
+ display: inline-flex;
10328
+ align-items: center;
10329
+ flex: 1;
10330
+ min-width: 0;
10331
+ padding: 0 ${tokens.spacing.sm};
10332
+ border: 1px solid ${tokens.colors.border.default};
10333
+ border-radius: ${tokens.borderRadius.full};
10334
+ background: ${tokens.colors.background.darker};
10335
+ transition: border-color ${tokens.transitions.fast}, box-shadow ${tokens.transitions.fast};
10336
+
10337
+ &:focus-within {
10338
+ border-color: ${tokens.colors.border.focus};
10339
+ box-shadow: 0 0 0 2px ${tokens.colors.primary}20;
10340
+ }
10341
+ `;
10342
+ var HashPrefix = styled58__default.default.span`
10343
+ color: ${tokens.colors.text.tertiary};
10344
+ font-size: ${tokens.typography.fontSize.xs};
10345
+ `;
10346
+ var HashtagInput = styled58__default.default.input`
10347
+ width: 100%;
10348
+ min-width: 0;
10349
+ height: 28px;
10350
+ padding: 0;
10351
+ border: none;
10352
+ background: transparent;
10353
+ color: ${tokens.colors.text.primary};
10354
+ font-size: ${tokens.typography.fontSize.xs};
10355
+ font-family: ${tokens.typography.fontFamily.primary};
10356
+
10357
+ &:focus {
10358
+ outline: none;
10359
+ }
10360
+
10361
+ &::placeholder {
10362
+ color: ${tokens.colors.text.tertiary};
10363
+ }
10364
+ `;
10365
+ var AddHashtagButton = styled58__default.default.button`
10366
+ height: 28px;
10367
+ padding: 0 ${tokens.spacing.sm};
10368
+ border: 1px solid ${tokens.colors.border.default};
10369
+ border-radius: ${tokens.borderRadius.full};
10370
+ background: ${tokens.colors.background.light};
10371
+ color: ${tokens.colors.text.primary};
10372
+ cursor: pointer;
10373
+ font-size: ${tokens.typography.fontSize.xs};
10374
+ font-weight: ${tokens.typography.fontWeight.semibold};
10375
+ transition: all ${tokens.transitions.fast};
10376
+
10377
+ &:hover:not(:disabled),
10378
+ &:focus-visible:not(:disabled) {
10379
+ background: ${tokens.colors.primary};
10380
+ border-color: ${tokens.colors.primary};
10381
+ color: ${tokens.colors.background.dark};
10382
+ outline: none;
10383
+ }
10384
+
10385
+ &:disabled {
10386
+ opacity: 0.45;
10387
+ cursor: not-allowed;
10388
+ }
10389
+ `;
10230
10390
  var ProgressBarContainer2 = styled58__default.default.div`
10231
10391
  margin-top: ${tokens.spacing.sm};
10232
10392
  `;
@@ -10372,6 +10532,8 @@ var PlatformCarousel = ({
10372
10532
  editingIndex,
10373
10533
  editContent,
10374
10534
  onEditContentChange,
10535
+ editHashtags,
10536
+ onEditHashtagsChange,
10375
10537
  isLoading = false,
10376
10538
  onImageChangeRequest
10377
10539
  }) => {
@@ -10425,14 +10587,18 @@ var PlatformCarousel = ({
10425
10587
  }) }),
10426
10588
  /* @__PURE__ */ jsxRuntime.jsx(ContentContainer2, { children: posts.map((post, index) => {
10427
10589
  const isEditing = editingIndex === index;
10428
- return /* @__PURE__ */ jsxRuntime.jsx(Slide, { $isActive: index === activeIndex, children: /* @__PURE__ */ jsxRuntime.jsx(
10590
+ const isActive = index === activeIndex;
10591
+ const canEditHashtags = isActive && !!onEditHashtagsChange;
10592
+ return /* @__PURE__ */ jsxRuntime.jsx(Slide, { $isActive: isActive, children: /* @__PURE__ */ jsxRuntime.jsx(
10429
10593
  PostPreviewCard,
10430
10594
  {
10431
10595
  post,
10432
- isActive: index === activeIndex,
10596
+ isActive,
10433
10597
  isEditing,
10434
10598
  editContent: isEditing ? editContent : void 0,
10435
10599
  onContentChange: isEditing ? onEditContentChange : void 0,
10600
+ editHashtags: canEditHashtags ? editHashtags : void 0,
10601
+ onHashtagsChange: canEditHashtags ? onEditHashtagsChange : void 0,
10436
10602
  isLoading,
10437
10603
  onImageChange: onImageChangeRequest ? () => onImageChangeRequest(index) : void 0
10438
10604
  }
@@ -10563,6 +10729,8 @@ var PlatformGrid = ({
10563
10729
  editingIndex,
10564
10730
  editContent,
10565
10731
  onEditContentChange,
10732
+ editHashtags,
10733
+ onEditHashtagsChange,
10566
10734
  isLoading = false,
10567
10735
  activeIndex = 0,
10568
10736
  onActiveChange,
@@ -10578,6 +10746,7 @@ var PlatformGrid = ({
10578
10746
  return /* @__PURE__ */ jsxRuntime.jsx(Grid, { "data-testid": "platform-grid", children: posts.map((post, index) => {
10579
10747
  const isEditing = editingIndex === index;
10580
10748
  const isActive = activeIndex === index;
10749
+ const canEditHashtags = isActive && !!onEditHashtagsChange;
10581
10750
  return /* @__PURE__ */ jsxRuntime.jsx(
10582
10751
  GridCell,
10583
10752
  {
@@ -10603,6 +10772,8 @@ var PlatformGrid = ({
10603
10772
  isEditing,
10604
10773
  editContent: isEditing ? editContent : void 0,
10605
10774
  onContentChange: isEditing ? onEditContentChange : void 0,
10775
+ editHashtags: canEditHashtags ? editHashtags : void 0,
10776
+ onHashtagsChange: canEditHashtags ? onEditHashtagsChange : void 0,
10606
10777
  isLoading,
10607
10778
  onImageChange: onImageChangeRequest ? () => onImageChangeRequest(index) : void 0
10608
10779
  }
@@ -10797,6 +10968,8 @@ var SocialMediaCanvas = ({
10797
10968
  editingIndex,
10798
10969
  editContent,
10799
10970
  onEditContentChange,
10971
+ editHashtags,
10972
+ onEditHashtagsChange,
10800
10973
  isLoading = false,
10801
10974
  activeIndex = 0,
10802
10975
  onImageChangeRequest
@@ -10856,6 +11029,8 @@ var SocialMediaCanvas = ({
10856
11029
  editingIndex,
10857
11030
  editContent,
10858
11031
  onEditContentChange,
11032
+ editHashtags,
11033
+ onEditHashtagsChange,
10859
11034
  isLoading,
10860
11035
  onImageChangeRequest
10861
11036
  }
@@ -10866,6 +11041,8 @@ var SocialMediaCanvas = ({
10866
11041
  editingIndex,
10867
11042
  editContent,
10868
11043
  onEditContentChange,
11044
+ editHashtags,
11045
+ onEditHashtagsChange,
10869
11046
  isLoading,
10870
11047
  activeIndex,
10871
11048
  onActiveChange: handleActiveChange,