@underverse-ui/underverse 1.0.4 → 1.0.6

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
@@ -733,6 +733,8 @@ var defaultTranslations = {
733
733
  month: "Month",
734
734
  week: "Week",
735
735
  day: "Day",
736
+ sprint: "Sprint",
737
+ sprints: "{n} sprints",
736
738
  resourcesHeader: "Resources",
737
739
  expandGroup: "Expand group",
738
740
  collapseGroup: "Collapse group",
@@ -809,6 +811,8 @@ var defaultTranslations = {
809
811
  month: "Th\xE1ng",
810
812
  week: "Tu\u1EA7n",
811
813
  day: "Ng\xE0y",
814
+ sprint: "Sprint",
815
+ sprints: "{n} sprint",
812
816
  resourcesHeader: "T\xE0i nguy\xEAn",
813
817
  expandGroup: "M\u1EDF nh\xF3m",
814
818
  collapseGroup: "Thu g\u1ECDn nh\xF3m",
@@ -885,6 +889,8 @@ var defaultTranslations = {
885
889
  month: "\uC6D4",
886
890
  week: "\uC8FC",
887
891
  day: "\uC77C",
892
+ sprint: "\uC2A4\uD504\uB9B0\uD2B8",
893
+ sprints: "{n} \uC2A4\uD504\uB9B0\uD2B8",
888
894
  resourcesHeader: "\uB9AC\uC18C\uC2A4",
889
895
  expandGroup: "\uADF8\uB8F9 \uD3BC\uCE58\uAE30",
890
896
  collapseGroup: "\uADF8\uB8F9 \uC811\uAE30",
@@ -961,6 +967,8 @@ var defaultTranslations = {
961
967
  month: "\u6708",
962
968
  week: "\u9031",
963
969
  day: "\u65E5",
970
+ sprint: "\u30B9\u30D7\u30EA\u30F3\u30C8",
971
+ sprints: "{n} \u30B9\u30D7\u30EA\u30F3\u30C8",
964
972
  resourcesHeader: "\u30EA\u30BD\u30FC\u30B9",
965
973
  expandGroup: "\u30B0\u30EB\u30FC\u30D7\u3092\u5C55\u958B",
966
974
  collapseGroup: "\u30B0\u30EB\u30FC\u30D7\u3092\u6298\u308A\u305F\u305F\u3080",
@@ -8571,6 +8579,10 @@ function startOfZonedMonth(date, timeZone) {
8571
8579
  const p = getZonedParts(date, timeZone);
8572
8580
  return new Date(zonedTimeToUtcMs({ year: p.year, month: p.month, day: 1, hour: 0, minute: 0, second: 0 }, timeZone));
8573
8581
  }
8582
+ function startOfZonedYear(date, timeZone) {
8583
+ const p = getZonedParts(date, timeZone);
8584
+ return new Date(zonedTimeToUtcMs({ year: p.year, month: 1, day: 1, hour: 0, minute: 0, second: 0 }, timeZone));
8585
+ }
8574
8586
  function addZonedDays(date, days, timeZone) {
8575
8587
  const p = getZonedParts(date, timeZone);
8576
8588
  return new Date(zonedTimeToUtcMs({ ...p, day: p.day + days }, timeZone));
@@ -8583,6 +8595,9 @@ function addZonedMonths(date, months, timeZone) {
8583
8595
  const clampedDay = Math.min(p.day, daysInTargetMonth);
8584
8596
  return new Date(zonedTimeToUtcMs({ year: next.year, month: next.month, day: clampedDay, hour: p.hour, minute: p.minute, second: p.second }, timeZone));
8585
8597
  }
8598
+ function addZonedYears(date, years, timeZone) {
8599
+ return addZonedMonths(date, years * 12, timeZone);
8600
+ }
8586
8601
  function startOfZonedWeek(date, weekStartsOn, timeZone) {
8587
8602
  const p = getZonedParts(date, timeZone);
8588
8603
  const weekday = new Date(Date.UTC(p.year, p.month - 1, p.day)).getUTCDay();
@@ -8821,6 +8836,13 @@ function defaultSlotHeader(slotStart, view, locale, timeZone) {
8821
8836
  if (view === "day") {
8822
8837
  return getDtf(locale, timeZone, { hour: "2-digit", minute: "2-digit", hourCycle: "h23" }).format(slotStart);
8823
8838
  }
8839
+ if (view === "sprint") {
8840
+ const { week } = getIsoWeekInfo(slotStart, timeZone);
8841
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "inline-flex flex-col items-center leading-tight", children: [
8842
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70", children: "S" }),
8843
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-sm font-semibold text-foreground", children: String(week).padStart(2, "0") })
8844
+ ] });
8845
+ }
8824
8846
  const weekday = getDtf(locale, timeZone, { weekday: "short" }).format(slotStart);
8825
8847
  const day = getDtf(locale, timeZone, { day: "numeric" }).format(slotStart);
8826
8848
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "inline-flex flex-col items-center leading-tight", children: [
@@ -8881,7 +8903,10 @@ function getGroupResourceCounts(resources) {
8881
8903
  function computeSlotStarts(args) {
8882
8904
  const { view, date, timeZone, weekStartsOn, dayTimeStepMinutes, dayRangeMode, workHours } = args;
8883
8905
  const baseDayStart = startOfZonedDay(date, timeZone);
8884
- const start = view === "month" ? startOfZonedMonth(date, timeZone) : view === "week" ? startOfZonedWeek(date, weekStartsOn, timeZone) : baseDayStart;
8906
+ const start = view === "month" ? startOfZonedMonth(date, timeZone) : view === "week" ? startOfZonedWeek(date, weekStartsOn, timeZone) : view === "sprint" ? (() => {
8907
+ const yearStart = startOfZonedYear(date, timeZone);
8908
+ return startOfZonedWeek(yearStart, weekStartsOn, timeZone);
8909
+ })() : baseDayStart;
8885
8910
  if (view === "day") {
8886
8911
  const step = Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes)));
8887
8912
  const stepMs = step * 6e4;
@@ -8898,6 +8923,21 @@ function computeSlotStarts(args) {
8898
8923
  }
8899
8924
  return { start: start2, end: end3, slotStarts: slotStarts2 };
8900
8925
  }
8926
+ if (view === "sprint") {
8927
+ const yearStart = startOfZonedYear(date, timeZone);
8928
+ const nextYearStart = startOfZonedYear(addZonedMonths(yearStart, 12, timeZone), timeZone);
8929
+ const lastDayOfYear = addZonedDays(nextYearStart, -1, timeZone);
8930
+ const lastSlotStart = startOfZonedWeek(lastDayOfYear, weekStartsOn, timeZone);
8931
+ const end2 = addZonedDays(lastSlotStart, 7, timeZone);
8932
+ const slotStarts2 = [];
8933
+ let cur2 = start;
8934
+ let guard2 = 0;
8935
+ while (cur2.getTime() < end2.getTime() && guard2++ < 60) {
8936
+ slotStarts2.push(cur2);
8937
+ cur2 = addZonedDays(cur2, 7, timeZone);
8938
+ }
8939
+ return { start, end: end2, slotStarts: slotStarts2 };
8940
+ }
8901
8941
  const end = view === "month" ? startOfZonedMonth(addZonedMonths(start, 1, timeZone), timeZone) : addZonedDays(start, 7, timeZone);
8902
8942
  const slotStarts = [];
8903
8943
  let cur = start;
@@ -8946,7 +8986,8 @@ var import_jsx_runtime34 = require("react/jsx-runtime");
8946
8986
  var VIEW_ICONS = {
8947
8987
  month: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.CalendarRange, { className: "h-4 w-4" }),
8948
8988
  week: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.CalendarDays, { className: "h-4 w-4" }),
8949
- day: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Calendar, { className: "h-4 w-4" })
8989
+ day: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Calendar, { className: "h-4 w-4" }),
8990
+ sprint: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.CalendarDays, { className: "h-4 w-4" })
8950
8991
  };
8951
8992
  function CalendarTimelineHeader(props) {
8952
8993
  const {
@@ -8971,7 +9012,7 @@ function CalendarTimelineHeader(props) {
8971
9012
  slotHeaderNodes
8972
9013
  } = props;
8973
9014
  const resolvedAvailableViews = React28.useMemo(
8974
- () => availableViews?.length ? availableViews : ["month", "week", "day"],
9015
+ () => availableViews?.length ? availableViews : ["month", "week", "day", "sprint"],
8975
9016
  [availableViews]
8976
9017
  );
8977
9018
  const showViewSwitcher = resolvedAvailableViews.length > 1;
@@ -9034,7 +9075,7 @@ function CalendarTimelineHeader(props) {
9034
9075
  onApplyDateTime(tempDate);
9035
9076
  setTodayOpen(false);
9036
9077
  }, [onApplyDateTime, tempDate]);
9037
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "sticky top-0 z-30 bg-linear-to-b from-background via-background to-background/95 border-b border-border/40 backdrop-blur-xl", children: [
9078
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "sticky top-0 z-30 bg-linear-to-b from-card via-card to-card/95 border-b border-border/40 backdrop-blur-xl", children: [
9038
9079
  /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cn("flex items-center justify-between gap-4", sizeConfig.headerPaddingClass), children: [
9039
9080
  /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-1.5 min-w-0", children: [
9040
9081
  /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center bg-muted/40 rounded-full p-1 gap-0.5", children: [
@@ -9045,7 +9086,7 @@ function CalendarTimelineHeader(props) {
9045
9086
  size: "icon",
9046
9087
  onClick: () => navigate(-1),
9047
9088
  "aria-label": labels.prev,
9048
- className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-background/80 transition-all duration-200"),
9089
+ className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-card/80 transition-all duration-200"),
9049
9090
  children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.ChevronLeft, { className: "h-4 w-4" })
9050
9091
  }
9051
9092
  ),
@@ -9060,7 +9101,7 @@ function CalendarTimelineHeader(props) {
9060
9101
  {
9061
9102
  variant: "ghost",
9062
9103
  size: "sm",
9063
- className: cn(sizeConfig.controlButtonTextClass, "rounded-full hover:bg-background/80 font-medium transition-all duration-200"),
9104
+ className: cn(sizeConfig.controlButtonTextClass, "rounded-full hover:bg-card/80 font-medium transition-all duration-200"),
9064
9105
  children: labels.today
9065
9106
  }
9066
9107
  ),
@@ -9140,7 +9181,7 @@ function CalendarTimelineHeader(props) {
9140
9181
  size: "icon",
9141
9182
  onClick: () => navigate(1),
9142
9183
  "aria-label": labels.next,
9143
- className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-background/80 transition-all duration-200"),
9184
+ className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-card/80 transition-all duration-200"),
9144
9185
  children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.ChevronRight, { className: "h-4 w-4" })
9145
9186
  }
9146
9187
  )
@@ -9169,7 +9210,7 @@ function CalendarTimelineHeader(props) {
9169
9210
  className: cn(
9170
9211
  sizeConfig.controlButtonTextClass,
9171
9212
  "rounded-full font-medium transition-all duration-200 gap-1.5",
9172
- activeView === v ? "bg-primary text-primary-foreground shadow-sm shadow-primary/25" : "hover:bg-background/80 text-muted-foreground hover:text-foreground"
9213
+ activeView === v ? "bg-primary text-primary-foreground shadow-sm shadow-primary/25" : "hover:bg-card/80 text-muted-foreground hover:text-foreground"
9173
9214
  ),
9174
9215
  children: [
9175
9216
  VIEW_ICONS[v],
@@ -9184,7 +9225,7 @@ function CalendarTimelineHeader(props) {
9184
9225
  showLeftColumn ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
9185
9226
  "div",
9186
9227
  {
9187
- className: "shrink-0 border-r border-border/30 bg-muted/20 flex items-center justify-center relative group/uv-ct-top-left",
9228
+ className: "shrink-0 border-r border-border/30 bg-card/60 flex items-center justify-center relative group/uv-ct-top-left",
9188
9229
  style: { width: effectiveResourceColumnWidth, minWidth: effectiveResourceColumnWidth },
9189
9230
  children: [
9190
9231
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-xs font-medium text-muted-foreground/70 uppercase tracking-wider", children: resourcesHeaderLabel }),
@@ -9239,7 +9280,7 @@ function DefaultGroupRow(props) {
9239
9280
  "span",
9240
9281
  {
9241
9282
  className: cn(
9242
- "inline-flex items-center justify-center w-5 h-5 rounded-md bg-background/60 transition-transform duration-200",
9283
+ "inline-flex items-center justify-center w-5 h-5 rounded-md bg-card/60 transition-transform duration-200",
9243
9284
  collapsed ? "" : "rotate-180"
9244
9285
  ),
9245
9286
  children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react19.ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
@@ -9260,7 +9301,7 @@ function ResourceRowCell(props) {
9260
9301
  "div",
9261
9302
  {
9262
9303
  className: cn(
9263
- "h-full w-full flex items-center border-b border-border/30 bg-linear-to-r from-background to-background/95 relative",
9304
+ "h-full w-full flex items-center border-b border-border/30 bg-linear-to-r from-card to-card/95 relative",
9264
9305
  sizeConfig.resourceRowClass,
9265
9306
  "hover:from-muted/30 hover:to-muted/10 transition-all duration-200 group/uv-ct-row-header"
9266
9307
  ),
@@ -9320,7 +9361,7 @@ var CalendarTimelineGridOverlay = React29.memo(function CalendarTimelineGridOver
9320
9361
  if (showToday && idx === todaySlotIdx) return null;
9321
9362
  const left = slotLefts[idx] ?? 0;
9322
9363
  const width = slotWidths[idx] ?? 0;
9323
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "absolute top-0 h-full bg-destructive/5", style: { left, width }, "aria-hidden": true }, `we_${idx}`);
9364
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "absolute top-0 h-full bg-muted/20", style: { left, width }, "aria-hidden": true }, `we_${idx}`);
9324
9365
  }) : null,
9325
9366
  showToday ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9326
9367
  "div",
@@ -9383,7 +9424,8 @@ function useTimelineSlots(args) {
9383
9424
  dayRangeMode,
9384
9425
  workHours,
9385
9426
  resolvedNow,
9386
- formatters
9427
+ formatters,
9428
+ dueDateSprint
9387
9429
  } = args;
9388
9430
  const { slots, range } = React31.useMemo(() => {
9389
9431
  const { start, end, slotStarts: slotStarts2 } = computeSlotStarts({
@@ -9396,17 +9438,89 @@ function useTimelineSlots(args) {
9396
9438
  workHours
9397
9439
  });
9398
9440
  const todayStart = startOfZonedDay(resolvedNow, resolvedTimeZone).getTime();
9399
- const slotItems = slotStarts2.map((s) => ({
9441
+ const nowMs = resolvedNow.getTime();
9442
+ const sprintDefs = (() => {
9443
+ if (activeView !== "sprint") return [];
9444
+ if (!dueDateSprint) return [];
9445
+ const out = [];
9446
+ for (const v of Object.values(dueDateSprint)) {
9447
+ const startInput = v.range_date?.start;
9448
+ const endInput = v.range_date?.end;
9449
+ if (startInput == null || endInput == null) continue;
9450
+ const startRaw = toDate2(startInput);
9451
+ const endRaw = toDate2(endInput);
9452
+ if (Number.isNaN(startRaw.getTime()) || Number.isNaN(endRaw.getTime())) continue;
9453
+ const startMs = startOfZonedDay(startRaw, resolvedTimeZone).getTime();
9454
+ const endMs = startOfZonedDay(endRaw, resolvedTimeZone).getTime();
9455
+ if (!Number.isFinite(startMs) || !Number.isFinite(endMs)) continue;
9456
+ if (endMs <= startMs) continue;
9457
+ out.push({ startMs, endMs, title: v.title });
9458
+ }
9459
+ out.sort((a, b) => a.startMs - b.startMs);
9460
+ return out;
9461
+ })();
9462
+ const sprintRangeText = (() => {
9463
+ if (activeView !== "sprint") return null;
9464
+ const df = getDtf(resolvedLocale, resolvedTimeZone, { month: "short", day: "numeric" });
9465
+ return (startMs, endMs) => {
9466
+ const a = df.format(new Date(startMs));
9467
+ const b = df.format(new Date(endMs - 1));
9468
+ return a === b ? a : `${a}\u2013${b}`;
9469
+ };
9470
+ })();
9471
+ const matchSprintDef = (slotStart, idx) => {
9472
+ if (activeView !== "sprint") return null;
9473
+ if (sprintDefs.length === 0) return null;
9474
+ const sMs = startOfZonedDay(slotStart, resolvedTimeZone).getTime();
9475
+ const byRange = sprintDefs.find((d) => sMs >= d.startMs && sMs < d.endMs) ?? null;
9476
+ return byRange ?? sprintDefs[idx] ?? null;
9477
+ };
9478
+ const slotItems = slotStarts2.map((s, idx) => ({
9400
9479
  start: s,
9401
- label: formatters?.slotHeader?.(s, { view: activeView, locale: resolvedLocale, timeZone: resolvedTimeZone }) ?? defaultSlotHeader(s, activeView, resolvedLocale, resolvedTimeZone),
9402
- isToday: startOfZonedDay(s, resolvedTimeZone).getTime() === todayStart,
9403
- isWeekend: activeView === "day" ? false : (() => {
9480
+ label: formatters?.slotHeader?.(s, { view: activeView, locale: resolvedLocale, timeZone: resolvedTimeZone }) ?? (() => {
9481
+ if (activeView !== "sprint") return defaultSlotHeader(s, activeView, resolvedLocale, resolvedTimeZone);
9482
+ const match = matchSprintDef(s, idx);
9483
+ if (match && sprintRangeText) {
9484
+ const rangeText = sprintRangeText(match.startMs, match.endMs);
9485
+ return React31.createElement(
9486
+ "span",
9487
+ { className: "inline-flex flex-col items-center leading-tight" },
9488
+ React31.createElement("span", { className: "text-[11px] font-semibold text-foreground truncate max-w-[8rem]" }, match.title),
9489
+ React31.createElement("span", { className: "text-[10px] font-medium text-muted-foreground/70" }, rangeText)
9490
+ );
9491
+ }
9492
+ return React31.createElement(
9493
+ "span",
9494
+ { className: "inline-flex flex-col items-center leading-tight" },
9495
+ React31.createElement("span", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70" }, "S"),
9496
+ React31.createElement("span", { className: "text-sm font-semibold text-foreground" }, String(idx + 1).padStart(2, "0"))
9497
+ );
9498
+ })(),
9499
+ isToday: (() => {
9500
+ if (activeView !== "sprint") return startOfZonedDay(s, resolvedTimeZone).getTime() === todayStart;
9501
+ const match = matchSprintDef(s, idx);
9502
+ const sprintEndMs = match ? match.endMs : addZonedDays(s, 7, resolvedTimeZone).getTime();
9503
+ return nowMs >= s.getTime() && nowMs < sprintEndMs;
9504
+ })(),
9505
+ isWeekend: activeView === "day" || activeView === "sprint" ? false : (() => {
9404
9506
  const wd = getZonedWeekday(s, resolvedTimeZone);
9405
9507
  return wd === 0 || wd === 6;
9406
9508
  })()
9407
9509
  }));
9408
9510
  return { slots: slotItems, range: { start, end } };
9409
- }, [activeView, activeDate, dayRangeMode, dayTimeStepMinutes, formatters, resolvedLocale, resolvedNow, resolvedTimeZone, weekStartsOn, workHours]);
9511
+ }, [
9512
+ activeView,
9513
+ activeDate,
9514
+ dayRangeMode,
9515
+ dayTimeStepMinutes,
9516
+ dueDateSprint,
9517
+ formatters,
9518
+ resolvedLocale,
9519
+ resolvedNow,
9520
+ resolvedTimeZone,
9521
+ weekStartsOn,
9522
+ workHours
9523
+ ]);
9410
9524
  const slotStarts = React31.useMemo(() => slots.map((s) => s.start), [slots]);
9411
9525
  const todaySlotIdx = React31.useMemo(() => slots.findIndex((s) => s.isToday), [slots]);
9412
9526
  const weekendSlotIdxs = React31.useMemo(() => {
@@ -9697,6 +9811,7 @@ function CalendarTimeline({
9697
9811
  view,
9698
9812
  defaultView = "month",
9699
9813
  onViewChange,
9814
+ dueDateSprint,
9700
9815
  date,
9701
9816
  defaultDate,
9702
9817
  onDateChange,
@@ -9729,6 +9844,8 @@ function CalendarTimeline({
9729
9844
  adaptiveSlotWidths,
9730
9845
  dayEventStyle = "span",
9731
9846
  dayEventMaxWidth,
9847
+ monthEventStyle = "span",
9848
+ monthEventMaxWidth,
9732
9849
  dayTimeStepMinutes = 60,
9733
9850
  enableEventTooltips = true,
9734
9851
  dayHeaderMode = "full",
@@ -9823,18 +9940,29 @@ function CalendarTimeline({
9823
9940
  setInternalRowHeight(defaultRowHeight);
9824
9941
  }, [defaultRowHeight, isControlledRowHeight]);
9825
9942
  const effectiveRowHeight = isControlledRowHeight ? rowHeight : internalRowHeight;
9826
- const effectiveSlotMinWidth = slotMinWidth ?? sizeConfig.slotMinWidth;
9943
+ const baseSlotMinWidth = slotMinWidth ?? sizeConfig.slotMinWidth;
9827
9944
  const colMin = minResourceColumnWidth ?? 160;
9828
9945
  const colMax = maxResourceColumnWidth ?? 520;
9829
9946
  const rowMin = minRowHeight ?? 36;
9830
9947
  const rowMax = maxRowHeight ?? 120;
9831
9948
  const availableViews = React32.useMemo(
9832
- () => onlyView ? [onlyView] : ["month", "week", "day"],
9949
+ () => onlyView ? [onlyView] : ["month", "week", "day", "sprint"],
9833
9950
  [onlyView]
9834
9951
  );
9835
9952
  const isControlledView = view !== void 0;
9836
9953
  const [internalView, setInternalView] = React32.useState(() => onlyView ?? defaultView);
9837
9954
  const activeView = onlyView ? onlyView : isControlledView ? view : internalView;
9955
+ const effectiveSlotMinWidth = React32.useMemo(() => {
9956
+ if (slotMinWidth == null) {
9957
+ if (activeView === "month" && monthEventStyle === "compact") {
9958
+ return clamp4(Math.round(sizeConfig.slotMinWidth * 0.55), 32, sizeConfig.slotMinWidth);
9959
+ }
9960
+ if (activeView === "sprint") {
9961
+ return clamp4(Math.round(sizeConfig.slotMinWidth * 0.4), 18, 48);
9962
+ }
9963
+ }
9964
+ return baseSlotMinWidth;
9965
+ }, [activeView, baseSlotMinWidth, monthEventStyle, sizeConfig.slotMinWidth, slotMinWidth]);
9838
9966
  const isControlledDate = date !== void 0;
9839
9967
  const [internalDate, setInternalDate] = React32.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
9840
9968
  const activeDate = isControlledDate ? date : internalDate;
@@ -9847,6 +9975,7 @@ function CalendarTimeline({
9847
9975
  month: labels?.month ?? t("month"),
9848
9976
  week: labels?.week ?? t("week"),
9849
9977
  day: labels?.day ?? t("day"),
9978
+ sprint: labels?.sprint ?? t("sprint"),
9850
9979
  newEvent: labels?.newEvent ?? t("newEvent"),
9851
9980
  createEventTitle: labels?.createEventTitle ?? t("createEventTitle"),
9852
9981
  create: labels?.create ?? t("create"),
@@ -9887,6 +10016,10 @@ function CalendarTimeline({
9887
10016
  setDate(addZonedDays(base, dir * 7, resolvedTimeZone));
9888
10017
  return;
9889
10018
  }
10019
+ if (activeView === "sprint") {
10020
+ setDate(addZonedYears(base, dir, resolvedTimeZone));
10021
+ return;
10022
+ }
9890
10023
  setDate(addZonedDays(base, dir, resolvedTimeZone));
9891
10024
  },
9892
10025
  [activeDate, activeView, resolvedTimeZone, setDate]
@@ -9912,7 +10045,8 @@ function CalendarTimeline({
9912
10045
  dayRangeMode,
9913
10046
  workHours,
9914
10047
  resolvedNow,
9915
- formatters
10048
+ formatters,
10049
+ dueDateSprint
9916
10050
  });
9917
10051
  React32.useEffect(() => {
9918
10052
  onRangeChange?.(range);
@@ -10158,9 +10292,15 @@ function CalendarTimeline({
10158
10292
  const rangeText = ya === yb ? `${a} \u2013 ${b}, ${ya}` : `${a}, ${ya} \u2013 ${b}, ${yb}`;
10159
10293
  return `${l.week} ${week} \u2022 ${rangeText}`;
10160
10294
  }
10295
+ if (activeView === "sprint") {
10296
+ const fmtYear = getDtf(resolvedLocale, resolvedTimeZone, { year: "numeric" });
10297
+ const yearText = fmtYear.format(activeDate);
10298
+ const count = Math.max(0, slots.length);
10299
+ return `${l.sprint} \u2022 ${yearText} \u2022 ${t("sprints", { n: count })}`;
10300
+ }
10161
10301
  const fmt = getDtf(resolvedLocale, resolvedTimeZone, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
10162
10302
  return fmt.format(range.start);
10163
- }, [activeDate, activeView, formatters, l.week, range.end, range.start, resolvedLocale, resolvedTimeZone]);
10303
+ }, [activeDate, activeView, formatters, l.sprint, l.week, range.end, range.start, resolvedLocale, resolvedTimeZone, slots.length, t]);
10164
10304
  const createMode = interactions?.createMode ?? "drag";
10165
10305
  const canCreate = !isViewOnly && (interactions?.creatable ?? false) && !!onCreateEvent;
10166
10306
  const [createOpen, setCreateOpen] = React32.useState(false);
@@ -10175,11 +10315,54 @@ function CalendarTimeline({
10175
10315
  disabled: r.disabled ?? false
10176
10316
  }));
10177
10317
  }, [resources]);
10178
- const slotPickerLabel = React32.useMemo(() => {
10318
+ const formatCreateBoundaryLabel = React32.useMemo(() => {
10179
10319
  const timeFmt = getDtf(resolvedLocale, resolvedTimeZone, { hour: "2-digit", minute: "2-digit", hourCycle: "h23" });
10180
10320
  const dayFmt = getDtf(resolvedLocale, resolvedTimeZone, { weekday: "short", month: "short", day: "numeric" });
10181
- return (d) => activeView === "day" ? timeFmt.format(d) : dayFmt.format(d);
10182
- }, [activeView, resolvedLocale, resolvedTimeZone]);
10321
+ const yearFmt = getDtf(resolvedLocale, resolvedTimeZone, { year: "numeric" });
10322
+ const sprintDefs = (() => {
10323
+ if (!dueDateSprint) return [];
10324
+ const out = [];
10325
+ for (const v of Object.values(dueDateSprint)) {
10326
+ const startInput = v.range_date?.start;
10327
+ const endInput = v.range_date?.end;
10328
+ if (startInput == null || endInput == null) continue;
10329
+ const startRaw = toDate2(startInput);
10330
+ const endRaw = toDate2(endInput);
10331
+ if (Number.isNaN(startRaw.getTime()) || Number.isNaN(endRaw.getTime())) continue;
10332
+ const startMs = startOfZonedDay(startRaw, resolvedTimeZone).getTime();
10333
+ const endMs = startOfZonedDay(endRaw, resolvedTimeZone).getTime();
10334
+ if (endMs <= startMs) continue;
10335
+ out.push({ startMs, endMs, title: v.title });
10336
+ }
10337
+ out.sort((a, b) => a.startMs - b.startMs);
10338
+ return out;
10339
+ })();
10340
+ const sprintTitleForStart = (slotStart, idx) => {
10341
+ if (activeView !== "sprint") return null;
10342
+ if (sprintDefs.length === 0) return null;
10343
+ const sMs = startOfZonedDay(slotStart, resolvedTimeZone).getTime();
10344
+ const match = sprintDefs.find((d) => sMs >= d.startMs && sMs < d.endMs) ?? sprintDefs[idx] ?? null;
10345
+ if (!match) return null;
10346
+ return typeof match.title === "string" || typeof match.title === "number" ? String(match.title) : null;
10347
+ };
10348
+ return (d, opts) => {
10349
+ if (activeView === "day") return timeFmt.format(d);
10350
+ if (activeView === "sprint") {
10351
+ const y = yearFmt.format(d);
10352
+ const idx = opts?.boundaryIdx;
10353
+ if (typeof idx === "number") {
10354
+ const slotStart = slotStarts[clamp4(idx, 0, Math.max(0, slotStarts.length - 1))] ?? d;
10355
+ const dynamicTitle = sprintTitleForStart(slotStart, idx);
10356
+ if (dynamicTitle) return `${dynamicTitle} \u2022 ${dayFmt.format(d)}, ${y}`;
10357
+ const sprintNumber = opts?.kind === "start" ? idx + 1 : Math.min(idx + 1, Math.max(1, slotStarts.length));
10358
+ const sprintText = `${l.sprint} ${String(sprintNumber).padStart(2, "0")}`;
10359
+ const dateText = dayFmt.format(d);
10360
+ return `${sprintText} \u2022 ${dateText}, ${y}`;
10361
+ }
10362
+ }
10363
+ return dayFmt.format(d);
10364
+ };
10365
+ }, [activeView, dueDateSprint, l.sprint, resolvedLocale, resolvedTimeZone, slotStarts, slotStarts.length]);
10183
10366
  const openCreate = React32.useCallback(() => {
10184
10367
  if (!canCreate) return;
10185
10368
  if (activeEventSheetOpen) setEventSheetOpen(false);
@@ -10216,16 +10399,16 @@ function CalendarTimeline({
10216
10399
  setCreateEndIdx((prev) => Math.min(slots.length, Math.max(prev, createStartIdx + 1)));
10217
10400
  }, [createStartIdx, slots.length]);
10218
10401
  const createStartOptions = React32.useMemo(() => {
10219
- return slotStarts.map((d, idx) => ({ label: slotPickerLabel(d), value: idx }));
10220
- }, [slotStarts, slotPickerLabel]);
10402
+ return slotStarts.map((d, idx) => ({ label: formatCreateBoundaryLabel(d, { kind: "start", boundaryIdx: idx }), value: idx }));
10403
+ }, [formatCreateBoundaryLabel, slotStarts]);
10221
10404
  const createEndOptions = React32.useMemo(() => {
10222
10405
  const out = [];
10223
10406
  for (let idx = createStartIdx + 1; idx <= slotStarts.length; idx++) {
10224
10407
  const boundary = idx >= slotStarts.length ? range.end : slotStarts[idx];
10225
- out.push({ label: slotPickerLabel(boundary), value: idx });
10408
+ out.push({ label: formatCreateBoundaryLabel(boundary, { kind: "end", boundaryIdx: idx }), value: idx });
10226
10409
  }
10227
10410
  return out;
10228
- }, [createStartIdx, range.end, slotPickerLabel, slotStarts]);
10411
+ }, [createStartIdx, formatCreateBoundaryLabel, range.end, slotStarts]);
10229
10412
  const commitCreate = React32.useCallback(() => {
10230
10413
  if (!onCreateEvent) return;
10231
10414
  if (!createResourceId) return;
@@ -10279,6 +10462,9 @@ function CalendarTimeline({
10279
10462
  const stepMs = Math.trunc(Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes))) * 6e4);
10280
10463
  return { start, end: new Date(start.getTime() + stepMs) };
10281
10464
  }
10465
+ if (activeView === "sprint") {
10466
+ return { start, end: addZonedDays(start, 7, resolvedTimeZone) };
10467
+ }
10282
10468
  return { start, end: addZonedDays(start, 1, resolvedTimeZone) };
10283
10469
  },
10284
10470
  [activeView, dayTimeStepMinutes, resolvedTimeZone, slotStarts]
@@ -10561,7 +10747,7 @@ function CalendarTimeline({
10561
10747
  className: cn(
10562
10748
  sizeConfig.slotHeaderClass,
10563
10749
  activeView !== "day" && s.isToday && "bg-primary/8 border-l-primary/40",
10564
- activeView !== "day" && !s.isToday && s.isWeekend && "bg-destructive/8 text-destructive-foreground"
10750
+ activeView !== "day" && !s.isToday && s.isWeekend && "bg-muted/25"
10565
10751
  ),
10566
10752
  dayHeaderMarks
10567
10753
  },
@@ -10592,7 +10778,7 @@ function CalendarTimeline({
10592
10778
  {
10593
10779
  title,
10594
10780
  resourcesHeaderLabel: t("resourcesHeader"),
10595
- labels: { today: l.today, prev: l.prev, next: l.next, month: l.month, week: l.week, day: l.day },
10781
+ labels: { today: l.today, prev: l.prev, next: l.next, month: l.month, week: l.week, day: l.day, sprint: l.sprint },
10596
10782
  newEventLabel: l.newEvent,
10597
10783
  newEventDisabled: isViewOnly || !canCreate || resources.length === 0,
10598
10784
  onNewEventClick: isViewOnly ? void 0 : openCreate,
@@ -10627,8 +10813,9 @@ function CalendarTimeline({
10627
10813
  "div",
10628
10814
  {
10629
10815
  className: cn(
10630
- "border border-border/40 rounded-2xl md:rounded-3xl overflow-hidden bg-background/95 backdrop-blur-sm",
10631
- "shadow-sm hover:shadow-md transition-shadow duration-300",
10816
+ "rounded-2xl md:rounded-3xl overflow-hidden bg-card text-card-foreground backdrop-blur-sm",
10817
+ "border border-border shadow-sm md:hover:shadow-md",
10818
+ "transition-[transform,box-shadow,border-color,background-color] duration-300 ease-soft",
10632
10819
  densityClass,
10633
10820
  className
10634
10821
  ),
@@ -10761,12 +10948,19 @@ function CalendarTimeline({
10761
10948
  })();
10762
10949
  const resource = resourceById.get(ev.resourceId);
10763
10950
  const tooltipTitle = ev.title || ev.id;
10764
- const shouldCompact = activeView === "day" && dayEventStyle === "compact";
10951
+ const shouldCompact = activeView === "day" && dayEventStyle === "compact" || activeView === "month" && monthEventStyle === "compact";
10765
10952
  const eventInsetX = 2;
10766
10953
  const leftInset = left + eventInsetX;
10767
10954
  const widthInset = Math.max(1, width - eventInsetX * 2);
10768
- const defaultMaxVisual = clamp4(Math.round(fixedSlotWidth * 1.2), 160, 360);
10769
- const maxVisual = clamp4(Math.round(dayEventMaxWidth ?? defaultMaxVisual), 80, 1200);
10955
+ const defaultMaxVisual = (() => {
10956
+ if (activeView === "month") return clamp4(Math.round(fixedSlotWidth * 2.5), 72, 360);
10957
+ return clamp4(Math.round(fixedSlotWidth * 1.2), 160, 360);
10958
+ })();
10959
+ const maxVisual = clamp4(
10960
+ Math.round(activeView === "month" ? monthEventMaxWidth ?? defaultMaxVisual : dayEventMaxWidth ?? defaultMaxVisual),
10961
+ 48,
10962
+ 1200
10963
+ );
10770
10964
  const visualWidth = shouldCompact ? Math.min(widthInset, maxVisual) : widthInset;
10771
10965
  const isClipped = shouldCompact && widthInset > visualWidth + 1;
10772
10966
  const block = /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
@@ -10811,7 +11005,7 @@ function CalendarTimeline({
10811
11005
  "transition-all duration-150 ease-out",
10812
11006
  "backdrop-blur-sm",
10813
11007
  ev.className,
10814
- isPreview && "ring-2 ring-primary/50 ring-offset-1 ring-offset-background scale-[1.02]"
11008
+ isPreview && "ring-2 ring-primary/50 ring-offset-1 ring-offset-card scale-[1.02]"
10815
11009
  ),
10816
11010
  style: {
10817
11011
  width: visualWidth,
@@ -10823,7 +11017,7 @@ function CalendarTimeline({
10823
11017
  },
10824
11018
  children: [
10825
11019
  node,
10826
- isClipped ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-10 bg-linear-to-l from-background/50 to-transparent flex items-center justify-end pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-muted-foreground/80", children: "\u2026" }) }) : null
11020
+ isClipped ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-10 bg-linear-to-l from-card/50 to-transparent flex items-center justify-end pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-muted-foreground/80", children: "\u2026" }) }) : null
10827
11021
  ]
10828
11022
  }
10829
11023
  ),
@@ -10879,7 +11073,7 @@ function CalendarTimeline({
10879
11073
  className: cn(
10880
11074
  "pointer-events-none absolute z-20",
10881
11075
  "h-5 w-5 rounded-full",
10882
- "bg-background/80 backdrop-blur-sm",
11076
+ "bg-card/80 backdrop-blur-sm",
10883
11077
  "border border-border/60 shadow-xs",
10884
11078
  "flex items-center justify-center"
10885
11079
  ),
@@ -19411,9 +19605,9 @@ function useSmartLocale() {
19411
19605
  }
19412
19606
 
19413
19607
  // ../../components/ui/UEditor/UEditor.tsx
19414
- var import_react47 = require("react");
19608
+ var import_react50 = require("react");
19415
19609
  var import_next_intl6 = require("next-intl");
19416
- var import_react48 = require("@tiptap/react");
19610
+ var import_react51 = require("@tiptap/react");
19417
19611
 
19418
19612
  // ../../components/ui/UEditor/extensions.ts
19419
19613
  var import_extension_document = __toESM(require("@tiptap/extension-document"), 1);
@@ -19772,12 +19966,924 @@ var ClipboardImages = import_core2.Extension.create({
19772
19966
  }
19773
19967
  });
19774
19968
 
19775
- // ../../components/ui/UEditor/resizable-image.tsx
19776
- var import_react41 = require("react");
19777
- var import_extension_image = __toESM(require("@tiptap/extension-image"), 1);
19969
+ // ../../components/ui/UEditor/emoji-suggestion.tsx
19778
19970
  var import_core3 = require("@tiptap/core");
19779
- var import_react42 = require("@tiptap/react");
19971
+ var import_suggestion2 = __toESM(require("@tiptap/suggestion"), 1);
19972
+ var import_react41 = require("@tiptap/react");
19973
+ var import_state2 = require("@tiptap/pm/state");
19974
+ var import_react42 = require("react");
19975
+ var import_lucide_react39 = require("lucide-react");
19976
+ var import_tippy2 = __toESM(require("tippy.js"), 1);
19977
+
19978
+ // ../../components/ui/UEditor/emojis.ts
19979
+ var EMOJI_LIST = [
19980
+ {
19981
+ id: "smileys_people",
19982
+ name: "Smileys & People",
19983
+ emojis: [
19984
+ { emoji: "\u{1F600}", name: "grinning_face" },
19985
+ { emoji: "\u{1F603}", name: "big_eyes_grin" },
19986
+ { emoji: "\u{1F604}", name: "smiling_eyes_grin" },
19987
+ { emoji: "\u{1F601}", name: "beaming_smile" },
19988
+ { emoji: "\u{1F606}", name: "squinting_laugh" },
19989
+ { emoji: "\u{1F605}", name: "sweat_grin" },
19990
+ { emoji: "\u{1F602}", name: "joy_tears" },
19991
+ { emoji: "\u{1F923}", name: "rofl_laugh" },
19992
+ { emoji: "\u{1F972}", name: "tear_smile" },
19993
+ { emoji: "\u263A\uFE0F", name: "warm_smile" },
19994
+ { emoji: "\u{1F60A}", name: "blush_smile" },
19995
+ { emoji: "\u{1F607}", name: "halo_smile" },
19996
+ { emoji: "\u{1F642}", name: "slight_smile" },
19997
+ { emoji: "\u{1F643}", name: "upside_down" },
19998
+ { emoji: "\u{1F609}", name: "wink_face" },
19999
+ { emoji: "\u{1F60C}", name: "relieved_face" },
20000
+ { emoji: "\u{1F60D}", name: "heart_eyes" },
20001
+ { emoji: "\u{1F970}", name: "hearts_face" },
20002
+ { emoji: "\u{1F618}", name: "blow_kiss" },
20003
+ { emoji: "\u{1F617}", name: "kissing_face" },
20004
+ { emoji: "\u{1F619}", name: "smiling_kiss" },
20005
+ { emoji: "\u{1F61A}", name: "closed_eyes_kiss" },
20006
+ { emoji: "\u{1F60B}", name: "yummy_face" },
20007
+ { emoji: "\u{1F61B}", name: "tongue_out" },
20008
+ { emoji: "\u{1F61D}", name: "squinting_tongue" },
20009
+ { emoji: "\u{1F61C}", name: "wink_tongue" },
20010
+ { emoji: "\u{1F92A}", name: "zany_face" },
20011
+ { emoji: "\u{1F928}", name: "raised_eyebrow" },
20012
+ { emoji: "\u{1F9D0}", name: "monocle_face" },
20013
+ { emoji: "\u{1F913}", name: "nerd_face" },
20014
+ { emoji: "\u{1F60E}", name: "sunglasses_face" },
20015
+ { emoji: "\u{1F978}", name: "disguised_face" },
20016
+ { emoji: "\u{1F929}", name: "star_struck" },
20017
+ { emoji: "\u{1F973}", name: "partying_face" },
20018
+ { emoji: "\u{1F60F}", name: "smirking_face" },
20019
+ { emoji: "\u{1F612}", name: "unamused_face" },
20020
+ { emoji: "\u{1F61E}", name: "disappointed_face" },
20021
+ { emoji: "\u{1F614}", name: "pensive_face" },
20022
+ { emoji: "\u{1F61F}", name: "worried_face" },
20023
+ { emoji: "\u{1F615}", name: "confused_face" },
20024
+ { emoji: "\u{1F641}", name: "slight_frown" },
20025
+ { emoji: "\u2639\uFE0F", name: "frowning_face" },
20026
+ { emoji: "\u{1F623}", name: "persevering_face" },
20027
+ { emoji: "\u{1F616}", name: "confounded_face" },
20028
+ { emoji: "\u{1F62B}", name: "tired_face" },
20029
+ { emoji: "\u{1F629}", name: "weary_face" },
20030
+ { emoji: "\u{1F97A}", name: "pleading_face" },
20031
+ { emoji: "\u{1F622}", name: "crying_face" },
20032
+ { emoji: "\u{1F62D}", name: "loudly_crying" },
20033
+ { emoji: "\u{1F624}", name: "steam_nose" },
20034
+ { emoji: "\u{1F621}", name: "pouting_face" },
20035
+ { emoji: "\u{1F92C}", name: "cursing_face" },
20036
+ { emoji: "\u{1F92F}", name: "exploding_head" },
20037
+ { emoji: "\u{1F633}", name: "flushed_face" },
20038
+ { emoji: "\u{1F975}", name: "hot_face" },
20039
+ { emoji: "\u{1F976}", name: "cold_face" },
20040
+ { emoji: "\u{1F631}", name: "screaming_fear" },
20041
+ { emoji: "\u{1F628}", name: "fearful_face" },
20042
+ { emoji: "\u{1F630}", name: "anxious_sweat" },
20043
+ { emoji: "\u{1F625}", name: "relieved_sad" },
20044
+ { emoji: "\u{1F613}", name: "downcast_sweat" },
20045
+ { emoji: "\u{1F917}", name: "hugging_face" },
20046
+ { emoji: "\u{1F914}", name: "thinking_face" },
20047
+ { emoji: "\u{1F92D}", name: "hand_over_mouth" },
20048
+ { emoji: "\u{1F92B}", name: "shushing_face" },
20049
+ { emoji: "\u{1F925}", name: "lying_face" },
20050
+ { emoji: "\u{1F636}", name: "no_mouth" },
20051
+ { emoji: "\u{1F610}", name: "neutral_face" },
20052
+ { emoji: "\u{1F611}", name: "expressionless_face" },
20053
+ { emoji: "\u{1F62C}", name: "grimacing_face" },
20054
+ { emoji: "\u{1F644}", name: "rolling_eyes" },
20055
+ { emoji: "\u{1F62F}", name: "hushed_face" },
20056
+ { emoji: "\u{1F626}", name: "frowning_open" },
20057
+ { emoji: "\u{1F627}", name: "anguished_face" },
20058
+ { emoji: "\u{1F62E}", name: "open_mouth" },
20059
+ { emoji: "\u{1F632}", name: "astonished_face" },
20060
+ { emoji: "\u{1F971}", name: "yawning_face" },
20061
+ { emoji: "\u{1F634}", name: "sleeping_face" },
20062
+ { emoji: "\u{1F924}", name: "drooling_face" },
20063
+ { emoji: "\u{1F62A}", name: "sleepy_face" },
20064
+ { emoji: "\u{1F635}", name: "dizzy_face" },
20065
+ { emoji: "\u{1F910}", name: "zipper_mouth" },
20066
+ { emoji: "\u{1F974}", name: "woozy_face" },
20067
+ { emoji: "\u{1F922}", name: "nauseated_face" },
20068
+ { emoji: "\u{1F92E}", name: "face_vomiting" },
20069
+ { emoji: "\u{1F927}", name: "sneezing_face" },
20070
+ { emoji: "\u{1F637}", name: "medical_mask" },
20071
+ { emoji: "\u{1F912}", name: "thermometer_face" },
20072
+ { emoji: "\u{1F915}", name: "bandage_head" },
20073
+ { emoji: "\u{1F911}", name: "money_mouth" },
20074
+ { emoji: "\u{1F920}", name: "cowboy_hat" },
20075
+ { emoji: "\u{1F608}", name: "devil_smile" },
20076
+ { emoji: "\u{1F47F}", name: "devil_angry" },
20077
+ { emoji: "\u{1F479}", name: "ogre_mask" },
20078
+ { emoji: "\u{1F47A}", name: "goblin_mask" },
20079
+ { emoji: "\u{1F921}", name: "clown_face" },
20080
+ { emoji: "\u{1F4A9}", name: "poop_pile" },
20081
+ { emoji: "\u{1F47B}", name: "ghost_spooky" },
20082
+ { emoji: "\u{1F480}", name: "skull_head" },
20083
+ { emoji: "\u2620\uFE0F", name: "skull_crossbones" },
20084
+ { emoji: "\u{1F47D}", name: "alien_face" },
20085
+ { emoji: "\u{1F47E}", name: "alien_monster" },
20086
+ { emoji: "\u{1F916}", name: "robot_face" },
20087
+ { emoji: "\u{1F383}", name: "pumpkin_jack" },
20088
+ { emoji: "\u{1F63A}", name: "cat_grin" },
20089
+ { emoji: "\u{1F638}", name: "cat_smile" },
20090
+ { emoji: "\u{1F639}", name: "cat_joy" },
20091
+ { emoji: "\u{1F63B}", name: "cat_heart_eyes" },
20092
+ { emoji: "\u{1F63C}", name: "cat_smirk" },
20093
+ { emoji: "\u{1F63D}", name: "cat_kiss" },
20094
+ { emoji: "\u{1F640}", name: "cat_weary" },
20095
+ { emoji: "\u{1F63F}", name: "cat_crying" },
20096
+ { emoji: "\u{1F63E}", name: "cat_pouting" },
20097
+ { emoji: "\u{1F44B}", name: "waving_hand" },
20098
+ { emoji: "\u{1F91A}", name: "raised_back_hand" },
20099
+ { emoji: "\u{1F590}\uFE0F", name: "splayed_fingers" },
20100
+ { emoji: "\u270B", name: "raised_hand" },
20101
+ { emoji: "\u{1F596}", name: "vulcan_salute" },
20102
+ { emoji: "\u{1F44C}", name: "ok_hand" },
20103
+ { emoji: "\u{1F90C}", name: "pinched_fingers" },
20104
+ { emoji: "\u{1F90F}", name: "pinching_hand" },
20105
+ { emoji: "\u270C\uFE0F", name: "victory_hand" },
20106
+ { emoji: "\u{1F91E}", name: "crossed_fingers" },
20107
+ { emoji: "\u{1F91F}", name: "love_you" },
20108
+ { emoji: "\u{1F918}", name: "rock_on" },
20109
+ { emoji: "\u{1F919}", name: "call_me" },
20110
+ { emoji: "\u{1F448}", name: "point_left" },
20111
+ { emoji: "\u{1F449}", name: "point_right" },
20112
+ { emoji: "\u{1F446}", name: "point_up" },
20113
+ { emoji: "\u{1F595}", name: "middle_finger" },
20114
+ { emoji: "\u{1F447}", name: "point_down" },
20115
+ { emoji: "\u261D\uFE0F", name: "index_up" },
20116
+ { emoji: "\u{1F44D}", name: "thumbs_up" },
20117
+ { emoji: "\u{1F44E}", name: "thumbs_down" },
20118
+ { emoji: "\u270A", name: "raised_fist" },
20119
+ { emoji: "\u{1F44A}", name: "oncoming_fist" },
20120
+ { emoji: "\u{1F91B}", name: "left_fist" },
20121
+ { emoji: "\u{1F91C}", name: "right_fist" },
20122
+ { emoji: "\u{1F44F}", name: "clapping_hands" },
20123
+ { emoji: "\u{1F64C}", name: "raising_hands" },
20124
+ { emoji: "\u{1F450}", name: "open_hands" },
20125
+ { emoji: "\u{1F932}", name: "palms_up" },
20126
+ { emoji: "\u{1F91D}", name: "handshake" },
20127
+ { emoji: "\u{1F64F}", name: "folded_hands" },
20128
+ { emoji: "\u270D\uFE0F", name: "writing_hand" },
20129
+ { emoji: "\u{1F485}", name: "nail_polish" },
20130
+ { emoji: "\u{1F933}", name: "selfie_hand" },
20131
+ { emoji: "\u{1F4AA}", name: "flex_biceps" },
20132
+ { emoji: "\u{1F9BE}", name: "robot_arm" },
20133
+ { emoji: "\u{1F9BF}", name: "robot_leg" },
20134
+ { emoji: "\u{1F9B5}", name: "leg_foot" },
20135
+ { emoji: "\u{1F9B6}", name: "foot_leg" },
20136
+ { emoji: "\u{1F442}", name: "ear_listen" },
20137
+ { emoji: "\u{1F9BB}", name: "ear_hearing_aid" },
20138
+ { emoji: "\u{1F443}", name: "nose_smell" },
20139
+ { emoji: "\u{1F9E0}", name: "brain_mind" },
20140
+ { emoji: "\u{1FAC0}", name: "anatomical_heart" },
20141
+ { emoji: "\u{1FAC1}", name: "lungs_organ" },
20142
+ { emoji: "\u{1F9B7}", name: "tooth_dentist" },
20143
+ { emoji: "\u{1F9B4}", name: "bone_skeleton" },
20144
+ { emoji: "\u{1F440}", name: "eyes_look" },
20145
+ { emoji: "\u{1F441}\uFE0F", name: "eye_look" },
20146
+ { emoji: "\u{1F445}", name: "tongue_lick" },
20147
+ { emoji: "\u{1F444}", name: "mouth_lips" },
20148
+ { emoji: "\u{1F48B}", name: "kiss_mark" },
20149
+ { emoji: "\u{1FA78}", name: "blood_drop" },
20150
+ { emoji: "\u{1F476}", name: "baby_face" },
20151
+ { emoji: "\u{1F9D2}", name: "child_face" },
20152
+ { emoji: "\u{1F466}", name: "boy_face" },
20153
+ { emoji: "\u{1F467}", name: "girl_face" },
20154
+ { emoji: "\u{1F9D1}", name: "person_face" },
20155
+ { emoji: "\u{1F471}", name: "blond_person" },
20156
+ { emoji: "\u{1F468}", name: "man_face" },
20157
+ { emoji: "\u{1F9D4}", name: "beard_person" },
20158
+ { emoji: "\u{1F469}", name: "woman_face" },
20159
+ { emoji: "\u{1F9D3}", name: "older_person" },
20160
+ { emoji: "\u{1F474}", name: "old_man" },
20161
+ { emoji: "\u{1F475}", name: "old_woman" },
20162
+ { emoji: "\u{1F472}", name: "skullcap_person" },
20163
+ { emoji: "\u{1F473}", name: "turban_person" },
20164
+ { emoji: "\u{1F9D5}", name: "headscarf_woman" },
20165
+ { emoji: "\u{1F46E}", name: "police_officer" },
20166
+ { emoji: "\u{1F477}", name: "construction_worker" },
20167
+ { emoji: "\u{1F482}", name: "guard_person" },
20168
+ { emoji: "\u{1F575}\uFE0F", name: "detective_spy" },
20169
+ { emoji: "\u{1F469}\u200D\u2695\uFE0F", name: "woman_doctor" },
20170
+ { emoji: "\u{1F468}\u200D\u2695\uFE0F", name: "man_doctor" },
20171
+ { emoji: "\u{1F469}\u200D\u{1F33E}", name: "woman_farmer" },
20172
+ { emoji: "\u{1F468}\u200D\u{1F33E}", name: "man_farmer" },
20173
+ { emoji: "\u{1F469}\u200D\u{1F373}", name: "woman_cook" },
20174
+ { emoji: "\u{1F468}\u200D\u{1F373}", name: "man_cook" },
20175
+ { emoji: "\u{1F469}\u200D\u{1F393}", name: "woman_student" },
20176
+ { emoji: "\u{1F468}\u200D\u{1F393}", name: "man_student" },
20177
+ { emoji: "\u{1F469}\u200D\u{1F3A4}", name: "woman_singer" },
20178
+ { emoji: "\u{1F468}\u200D\u{1F3A4}", name: "man_singer" },
20179
+ { emoji: "\u{1F469}\u200D\u{1F3EB}", name: "woman_teacher" },
20180
+ { emoji: "\u{1F468}\u200D\u{1F3EB}", name: "man_teacher" },
20181
+ { emoji: "\u{1F469}\u200D", name: "woman_factory" },
20182
+ { emoji: "\u{1F468}\u200D", name: "man_factory" },
20183
+ { emoji: "\u{1F469}\u200D\u{1F4BB}", name: "woman_tech" },
20184
+ { emoji: "\u{1F468}\u200D\u{1F4BB}", name: "man_tech" },
20185
+ { emoji: "\u{1F469}\u200D\u{1F4BC}", name: "woman_office" },
20186
+ { emoji: "\u{1F468}\u200D\u{1F4BC}", name: "man_office" },
20187
+ { emoji: "\u{1F469}\u200D\u{1F527}", name: "woman_mechanic" },
20188
+ { emoji: "\u{1F468}\u200D\u{1F527}", name: "man_mechanic" },
20189
+ { emoji: "\u{1F469}\u200D\u{1F52C}", name: "woman_scientist" },
20190
+ { emoji: "\u{1F468}\u200D\u{1F52C}", name: "man_scientist" },
20191
+ { emoji: "\u{1F469}\u200D\u{1F3A8}", name: "woman_artist" },
20192
+ { emoji: "\u{1F468}\u200D\u{1F3A8}", name: "man_artist" },
20193
+ { emoji: "\u{1F469}\u200D\u{1F692}", name: "woman_firefighter" },
20194
+ { emoji: "\u{1F468}\u200D\u{1F692}", name: "man_firefighter" },
20195
+ { emoji: "\u{1F469}\u200D\u2708\uFE0F", name: "woman_pilot" },
20196
+ { emoji: "\u{1F468}\u200D\u2708\uFE0F", name: "man_pilot" },
20197
+ { emoji: "\u{1F469}\u200D\u{1F680}", name: "woman_astronaut" },
20198
+ { emoji: "\u{1F468}\u200D\u{1F680}", name: "man_astronaut" },
20199
+ { emoji: "\u{1F469}\u200D\u2696\uFE0F", name: "woman_judge" },
20200
+ { emoji: "\u{1F468}\u200D\u2696\uFE0F", name: "man_judge" },
20201
+ { emoji: "\u{1F470}", name: "bride_wedding" },
20202
+ { emoji: "\u{1F935}", name: "groom_tuxedo" },
20203
+ { emoji: "\u{1F478}", name: "princess_crown" },
20204
+ { emoji: "\u{1F934}", name: "prince_crown" },
20205
+ { emoji: "\u{1F9B8}", name: "superhero_person" },
20206
+ { emoji: "\u{1F9B9}", name: "supervillain_person" },
20207
+ { emoji: "\u{1F936}", name: "mrs_claus" },
20208
+ { emoji: "\u{1F385}", name: "santa_claus" },
20209
+ { emoji: "\u{1F9D9}", name: "mage_wizard" },
20210
+ { emoji: "\u{1F9DD}", name: "elf_fantasy" },
20211
+ { emoji: "\u{1F9DB}", name: "vampire_dracula" },
20212
+ { emoji: "\u{1F9DF}", name: "zombie_undead" },
20213
+ { emoji: "\u{1F9DE}", name: "genie_magic" },
20214
+ { emoji: "\u{1F9DC}", name: "mermaid_person" },
20215
+ { emoji: "\u{1F9DA}", name: "fairy_magic" },
20216
+ { emoji: "\u{1F47C}", name: "angel_baby" },
20217
+ { emoji: "\u{1F930}", name: "pregnant_woman" },
20218
+ { emoji: "\u{1F931}", name: "breast_feeding" },
20219
+ { emoji: "\u{1F647}", name: "bowing_person" },
20220
+ { emoji: "\u{1F481}", name: "tipping_hand" },
20221
+ { emoji: "\u{1F645}", name: "gesturing_no" },
20222
+ { emoji: "\u{1F646}", name: "gesturing_ok" },
20223
+ { emoji: "\u{1F64B}", name: "raising_hand" },
20224
+ { emoji: "\u{1F9CF}", name: "deaf_person" },
20225
+ { emoji: "\u{1F926}", name: "face_palm" },
20226
+ { emoji: "\u{1F937}", name: "shrugging_person" },
20227
+ { emoji: "\u{1F64E}", name: "pouting_person" },
20228
+ { emoji: "\u{1F64D}", name: "frowning_person" },
20229
+ { emoji: "\u{1F487}", name: "haircut_person" },
20230
+ { emoji: "\u{1F486}", name: "massage_person" },
20231
+ { emoji: "\u{1F9D6}", name: "sauna_person" },
20232
+ { emoji: "\u{1F483}", name: "woman_dancing" },
20233
+ { emoji: "\u{1F57A}", name: "man_dancing" },
20234
+ { emoji: "\u{1F46F}", name: "bunny_friends" },
20235
+ { emoji: "\u{1F574}\uFE0F", name: "levitating_suit" },
20236
+ { emoji: "\u{1F6B6}", name: "walking_person" },
20237
+ { emoji: "\u{1F3C3}", name: "running_person" },
20238
+ { emoji: "\u{1F9CD}", name: "standing_person" },
20239
+ { emoji: "\u{1F9CE}", name: "kneeling_person" },
20240
+ { emoji: "\u{1F468}\u200D\u{1F9AF}", name: "blind_cane" },
20241
+ { emoji: "\u{1F468}\u200D\u{1F9BC}", name: "motor_wheelchair" },
20242
+ { emoji: "\u{1F468}\u200D\u{1F9BD}", name: "manual_wheelchair" },
20243
+ { emoji: "\u{1F9D7}", name: "climbing_person" },
20244
+ { emoji: "\u{1F93A}", name: "fencing_person" },
20245
+ { emoji: "\u{1F3C7}", name: "horse_racing" },
20246
+ { emoji: "\u26F7\uFE0F", name: "skier_snow" },
20247
+ { emoji: "\u{1F3C2}", name: "snowboarder_snow" },
20248
+ { emoji: "\u{1F3CC}\uFE0F", name: "golfing_person" },
20249
+ { emoji: "\u{1F3C4}", name: "surfing_person" },
20250
+ { emoji: "\u{1F6A3}", name: "rowing_person" },
20251
+ { emoji: "\u{1F3CA}", name: "swimming_person" },
20252
+ { emoji: "\u26F9\uFE0F", name: "basketball_person" },
20253
+ { emoji: "\u{1F3CB}\uFE0F", name: "lifting_weights" },
20254
+ { emoji: "\u{1F6B4}", name: "biking_person" },
20255
+ { emoji: "\u{1F6B5}", name: "mountain_biking" },
20256
+ { emoji: "\u{1F938}", name: "cartwheel_person" },
20257
+ { emoji: "\u{1F93C}", name: "wrestling_people" },
20258
+ { emoji: "\u{1F93D}", name: "water_polo" },
20259
+ { emoji: "\u{1F93E}", name: "handball_person" },
20260
+ { emoji: "\u{1F939}", name: "juggling_person" },
20261
+ { emoji: "\u{1F9D8}", name: "yoga_lotus" },
20262
+ { emoji: "\u{1F6C0}", name: "bath_person" },
20263
+ { emoji: "\u{1F6CC}", name: "bed_person" }
20264
+ ]
20265
+ },
20266
+ {
20267
+ id: "animals_nature",
20268
+ name: "Animals & Nature",
20269
+ emojis: [
20270
+ { emoji: "\u{1F435}", name: "monkey_face" },
20271
+ { emoji: "\u{1F436}", name: "dog_face" },
20272
+ { emoji: "\u{1F43A}", name: "wolf_face" },
20273
+ { emoji: "\u{1F431}", name: "cat_face" },
20274
+ { emoji: "\u{1F981}", name: "lion_face" },
20275
+ { emoji: "\u{1F42F}", name: "tiger_face" },
20276
+ { emoji: "\u{1F434}", name: "horse_face" },
20277
+ { emoji: "\u{1F984}", name: "unicorn_face" },
20278
+ { emoji: "\u{1F42E}", name: "cow_face" },
20279
+ { emoji: "\u{1F437}", name: "pig_face" },
20280
+ { emoji: "\u{1F42D}", name: "mouse_face" },
20281
+ { emoji: "\u{1F430}", name: "rabbit_face" },
20282
+ { emoji: "\u{1F43B}", name: "bear_face" },
20283
+ { emoji: "\u{1F428}", name: "koala_bear" },
20284
+ { emoji: "\u{1F43C}", name: "panda_face" },
20285
+ { emoji: "\u{1F414}", name: "chicken_bird" },
20286
+ { emoji: "\u{1F427}", name: "penguin_bird" },
20287
+ { emoji: "\u{1F426}", name: "bird_fly" },
20288
+ { emoji: "\u{1F986}", name: "duck_bird" },
20289
+ { emoji: "\u{1F985}", name: "eagle_bird" },
20290
+ { emoji: "\u{1F989}", name: "owl_bird" },
20291
+ { emoji: "\u{1F438}", name: "frog_face" },
20292
+ { emoji: "\u{1F422}", name: "turtle_slow" },
20293
+ { emoji: "\u{1F40D}", name: "snake_hiss" },
20294
+ { emoji: "\u{1F433}", name: "whale_sprout" },
20295
+ { emoji: "\u{1F42C}", name: "dolphin_jump" },
20296
+ { emoji: "\u{1F41F}", name: "fish_swim" },
20297
+ { emoji: "\u{1F419}", name: "octopus_legs" },
20298
+ { emoji: "\u{1F98B}", name: "butterfly_fly" },
20299
+ { emoji: "\u{1F490}", name: "flower_bouquet" },
20300
+ { emoji: "\u{1F338}", name: "cherry_blossom" },
20301
+ { emoji: "\u{1F339}", name: "rose_flower" },
20302
+ { emoji: "\u{1F33B}", name: "sunflower_yellow" },
20303
+ { emoji: "\u{1F332}", name: "evergreen_tree" },
20304
+ { emoji: "\u{1F333}", name: "deciduous_tree" },
20305
+ { emoji: "\u{1F334}", name: "palm_tree" },
20306
+ { emoji: "\u{1F335}", name: "cactus_plant" },
20307
+ { emoji: "\u{1F525}", name: "fire_flame" },
20308
+ { emoji: "\u{1F4A7}", name: "water_drop" },
20309
+ { emoji: "\u2B50", name: "star_shine" }
20310
+ ]
20311
+ },
20312
+ {
20313
+ id: "food_drink",
20314
+ name: "Food & Drink",
20315
+ emojis: [
20316
+ { emoji: "\u{1F347}", name: "grapes_fruit" },
20317
+ { emoji: "\u{1F348}", name: "melon_fruit" },
20318
+ { emoji: "\u{1F349}", name: "watermelon_slice" },
20319
+ { emoji: "\u{1F34A}", name: "tangerine_orange" },
20320
+ { emoji: "\u{1F34B}", name: "lemon_sour" },
20321
+ { emoji: "\u{1F34C}", name: "banana_fruit" },
20322
+ { emoji: "\u{1F34D}", name: "pineapple_fruit" },
20323
+ { emoji: "\u{1F34E}", name: "red_apple" },
20324
+ { emoji: "\u{1F34F}", name: "green_apple" },
20325
+ { emoji: "\u{1F350}", name: "pear_fruit" },
20326
+ { emoji: "\u{1F351}", name: "peach_fruit" },
20327
+ { emoji: "\u{1F352}", name: "cherries_red" },
20328
+ { emoji: "\u{1F353}", name: "strawberry_red" },
20329
+ { emoji: "\u{1F95D}", name: "kiwi_fruit" },
20330
+ { emoji: "\u{1F345}", name: "tomato_red" },
20331
+ { emoji: "\u{1F951}", name: "avocado_green" },
20332
+ { emoji: "\u{1F346}", name: "eggplant_purple" },
20333
+ { emoji: "\u{1F954}", name: "potato_spud" },
20334
+ { emoji: "\u{1F955}", name: "carrot_veg" },
20335
+ { emoji: "\u{1F33D}", name: "corn_cob" },
20336
+ { emoji: "\u{1F35E}", name: "bread_loaf" },
20337
+ { emoji: "\u{1F9C0}", name: "cheese_wedge" },
20338
+ { emoji: "\u{1F356}", name: "meat_bone" },
20339
+ { emoji: "\u{1F357}", name: "poultry_leg" },
20340
+ { emoji: "\u{1F969}", name: "meat_cut" },
20341
+ { emoji: "\u{1F953}", name: "bacon_strips" },
20342
+ { emoji: "\u{1F354}", name: "hamburger_fast" },
20343
+ { emoji: "\u{1F35F}", name: "french_fries" },
20344
+ { emoji: "\u{1F355}", name: "pizza_slice" },
20345
+ { emoji: "\u{1F32D}", name: "hot_dog" },
20346
+ { emoji: "\u{1F96A}", name: "sandwich_lunch" },
20347
+ { emoji: "\u{1F32E}", name: "taco_mexican" },
20348
+ { emoji: "\u{1F32F}", name: "burrito_wrap" },
20349
+ { emoji: "\u{1F95A}", name: "egg_white" },
20350
+ { emoji: "\u{1F373}", name: "cooking_egg" },
20351
+ { emoji: "\u{1F37F}", name: "popcorn_box" },
20352
+ { emoji: "\u{1F35A}", name: "rice_bowl" },
20353
+ { emoji: "\u{1F35D}", name: "spaghetti_pasta" },
20354
+ { emoji: "\u{1F363}", name: "sushi_roll" },
20355
+ { emoji: "\u{1F364}", name: "fried_shrimp" },
20356
+ { emoji: "\u{1F366}", name: "ice_cream" },
20357
+ { emoji: "\u{1F369}", name: "doughnut_sweet" },
20358
+ { emoji: "\u{1F36A}", name: "cookie_sweet" },
20359
+ { emoji: "\u{1F382}", name: "birthday_cake" },
20360
+ { emoji: "\u{1F370}", name: "shortcake_slice" },
20361
+ { emoji: "\u{1F36B}", name: "chocolate_bar" },
20362
+ { emoji: "\u{1F36C}", name: "candy_sweet" },
20363
+ { emoji: "\u{1F36D}", name: "lollipop_candy" },
20364
+ { emoji: "\u2615", name: "coffee_hot" },
20365
+ { emoji: "\u{1F37A}", name: "beer_mug" },
20366
+ { emoji: "\u{1F37B}", name: "beer_cheers" },
20367
+ { emoji: "\u{1F942}", name: "champagne_cheers" },
20368
+ { emoji: "\u{1F377}", name: "wine_glass" },
20369
+ { emoji: "\u{1F943}", name: "whiskey_glass" },
20370
+ { emoji: "\u{1F379}", name: "tropical_drink" }
20371
+ ]
20372
+ },
20373
+ {
20374
+ id: "activity",
20375
+ name: "Activity",
20376
+ emojis: [
20377
+ { emoji: "\u26BD", name: "soccer_ball" },
20378
+ { emoji: "\u{1F3C0}", name: "basketball_hoop" },
20379
+ { emoji: "\u{1F3C8}", name: "football_american" },
20380
+ { emoji: "\u26BE", name: "baseball_game" },
20381
+ { emoji: "\u{1F3BE}", name: "tennis_ball" },
20382
+ { emoji: "\u{1F3D0}", name: "volleyball_game" },
20383
+ { emoji: "\u{1F3B1}", name: "pool_8ball" },
20384
+ { emoji: "\u{1F3D3}", name: "ping_pong" },
20385
+ { emoji: "\u{1F3F8}", name: "badminton_game" },
20386
+ { emoji: "\u{1F94A}", name: "boxing_glove" },
20387
+ { emoji: "\u{1F945}", name: "goal_net" },
20388
+ { emoji: "\u{1F3A3}", name: "fishing_pole" },
20389
+ { emoji: "\u{1F3AE}", name: "video_game" },
20390
+ { emoji: "\u{1F3B2}", name: "game_die" },
20391
+ { emoji: "\u{1F3AD}", name: "theater_masks" },
20392
+ { emoji: "\u{1F3A8}", name: "artist_palette" },
20393
+ { emoji: "\u{1F3AC}", name: "clapper_board" },
20394
+ { emoji: "\u{1F3A4}", name: "microphone_sing" },
20395
+ { emoji: "\u{1F3A7}", name: "headphone_music" },
20396
+ { emoji: "\u{1F3B7}", name: "saxophone_jazz" },
20397
+ { emoji: "\u{1F3B8}", name: "guitar_rock" },
20398
+ { emoji: "\u{1F3B9}", name: "piano_keys" },
20399
+ { emoji: "\u{1F3BA}", name: "trumpet_horn" },
20400
+ { emoji: "\u{1F3BB}", name: "violin_music" },
20401
+ { emoji: "\u{1F941}", name: "drum_beat" }
20402
+ ]
20403
+ },
20404
+ {
20405
+ id: "objects",
20406
+ name: "Objects",
20407
+ emojis: [
20408
+ { emoji: "\u{1F4F1}", name: "mobile_phone" },
20409
+ { emoji: "\u{1F4BB}", name: "laptop_computer" },
20410
+ { emoji: "\u{1F5A5}\uFE0F", name: "desktop_computer" },
20411
+ { emoji: "\u231A", name: "watch_wrist" },
20412
+ { emoji: "\u{1F4F7}", name: "camera_photo" },
20413
+ { emoji: "\u{1F4A1}", name: "light_bulb" },
20414
+ { emoji: "\u{1F4DA}", name: "books_pile" },
20415
+ { emoji: "\u{1F4B0}", name: "money_bag" },
20416
+ { emoji: "\u{1F381}", name: "gift_box" },
20417
+ { emoji: "\u{1F388}", name: "balloon_red" },
20418
+ { emoji: "\u{1F389}", name: "party_popper" },
20419
+ { emoji: "\u{1F38A}", name: "confetti_ball" },
20420
+ { emoji: "\u2709\uFE0F", name: "envelope_mail" },
20421
+ { emoji: "\u{1F4E6}", name: "package_box" },
20422
+ { emoji: "\u270F\uFE0F", name: "pencil_write" },
20423
+ { emoji: "\u{1F512}", name: "lock_closed" },
20424
+ { emoji: "\u{1F511}", name: "key_gold" },
20425
+ { emoji: "\u{1F528}", name: "hammer_tool" },
20426
+ { emoji: "\u{1F4A3}", name: "bomb_explode" },
20427
+ { emoji: "\u{1F52B}", name: "pistol_toy" },
20428
+ { emoji: "\u{1F48A}", name: "pill_capsule" },
20429
+ { emoji: "\u{1F6D2}", name: "shopping_cart" }
20430
+ ]
20431
+ },
20432
+ {
20433
+ id: "symbols",
20434
+ name: "Symbols",
20435
+ emojis: [
20436
+ { emoji: "\u2764\uFE0F", name: "red_heart" },
20437
+ { emoji: "\u{1F9E1}", name: "orange_heart" },
20438
+ { emoji: "\u{1F49B}", name: "yellow_heart" },
20439
+ { emoji: "\u{1F49A}", name: "green_heart" },
20440
+ { emoji: "\u{1F499}", name: "blue_heart" },
20441
+ { emoji: "\u{1F49C}", name: "purple_heart" },
20442
+ { emoji: "\u{1F5A4}", name: "black_heart" },
20443
+ { emoji: "\u{1F90D}", name: "white_heart" },
20444
+ { emoji: "\u{1F90E}", name: "brown_heart" },
20445
+ { emoji: "\u{1F494}", name: "broken_heart" },
20446
+ { emoji: "\u2763\uFE0F", name: "heart_exclamation" },
20447
+ { emoji: "\u{1F495}", name: "two_hearts" },
20448
+ { emoji: "\u{1F49E}", name: "revolving_hearts" },
20449
+ { emoji: "\u{1F493}", name: "beating_heart" },
20450
+ { emoji: "\u{1F497}", name: "growing_heart" },
20451
+ { emoji: "\u{1F496}", name: "sparkling_heart" },
20452
+ { emoji: "\u{1F498}", name: "cupid_heart" },
20453
+ { emoji: "\u{1F49D}", name: "gift_heart" },
20454
+ { emoji: "\u{1F4AF}", name: "hundred_points" },
20455
+ { emoji: "\u{1F4A2}", name: "anger_symbol" },
20456
+ { emoji: "\u{1F4A5}", name: "collision_boom" },
20457
+ { emoji: "\u{1F4AB}", name: "dizzy_star" },
20458
+ { emoji: "\u{1F4A6}", name: "sweat_drops" },
20459
+ { emoji: "\u{1F4A8}", name: "dash_away" },
20460
+ { emoji: "\u{1F4A4}", name: "sleeping_zzz" },
20461
+ { emoji: "\u2705", name: "check_mark" },
20462
+ { emoji: "\u274C", name: "cross_mark" },
20463
+ { emoji: "\u26A0\uFE0F", name: "warning_sign" },
20464
+ { emoji: "\u26D4", name: "no_entry" },
20465
+ { emoji: "\u{1F6AB}", name: "prohibited_sign" },
20466
+ { emoji: "\u2B06\uFE0F", name: "arrow_up" },
20467
+ { emoji: "\u2B07\uFE0F", name: "arrow_down" },
20468
+ { emoji: "\u2B05\uFE0F", name: "arrow_left" },
20469
+ { emoji: "\u27A1\uFE0F", name: "arrow_right" },
20470
+ { emoji: "\u267B\uFE0F", name: "recycling_symbol" }
20471
+ ]
20472
+ },
20473
+ {
20474
+ id: "flags",
20475
+ name: "Flags",
20476
+ emojis: [
20477
+ { emoji: "\u{1F3C1}", name: "checkered_flag" },
20478
+ { emoji: "\u{1F3F3}\uFE0F", name: "white_flag" },
20479
+ { emoji: "\u{1F3F3}\uFE0F\u200D\u{1F308}", name: "rainbow_flag" },
20480
+ { emoji: "\u{1F3F3}\uFE0F\u200D\u26A7\uFE0F", name: "transgender_flag" },
20481
+ { emoji: "\u{1F3F4}\u200D\u2620\uFE0F", name: "pirate_flag" },
20482
+ { emoji: "\u{1F1E6}\u{1F1E8}", name: "flag_ascension" },
20483
+ { emoji: "\u{1F1E6}\u{1F1E9}", name: "flag_andorra" },
20484
+ { emoji: "\u{1F1E6}\u{1F1EA}", name: "flag_uae" },
20485
+ { emoji: "\u{1F1E6}\u{1F1EB}", name: "flag_afghanistan" },
20486
+ { emoji: "\u{1F1E6}\u{1F1EC}", name: "flag_antigua" },
20487
+ { emoji: "\u{1F1E6}\u{1F1EE}", name: "flag_anguilla" },
20488
+ { emoji: "\u{1F1E6}\u{1F1F1}", name: "flag_albania" },
20489
+ { emoji: "\u{1F1E6}\u{1F1F2}", name: "flag_armenia" },
20490
+ { emoji: "\u{1F1E6}\u{1F1F4}", name: "flag_angola" },
20491
+ { emoji: "\u{1F1E6}\u{1F1F6}", name: "flag_antarctica" },
20492
+ { emoji: "\u{1F1E6}\u{1F1F7}", name: "flag_argentina" },
20493
+ { emoji: "\u{1F1E6}\u{1F1F8}", name: "flag_samoa" },
20494
+ { emoji: "\u{1F1E6}\u{1F1F9}", name: "flag_austria" },
20495
+ { emoji: "\u{1F1E6}\u{1F1FA}", name: "flag_australia" },
20496
+ { emoji: "\u{1F1E6}\u{1F1FC}", name: "flag_aruba" },
20497
+ { emoji: "\u{1F1E6}\u{1F1FD}", name: "flag_aland" },
20498
+ { emoji: "\u{1F1E6}\u{1F1FF}", name: "flag_azerbaijan" },
20499
+ { emoji: "\u{1F1E7}\u{1F1E6}", name: "flag_bosnia" },
20500
+ { emoji: "\u{1F1E7}\u{1F1E7}", name: "flag_barbados" },
20501
+ { emoji: "\u{1F1E7}\u{1F1E9}", name: "flag_bangladesh" },
20502
+ { emoji: "\u{1F1E7}\u{1F1EA}", name: "flag_belgium" },
20503
+ { emoji: "\u{1F1E7}\u{1F1EB}", name: "flag_burkina" },
20504
+ { emoji: "\u{1F1E7}\u{1F1EC}", name: "flag_bulgaria" },
20505
+ { emoji: "\u{1F1E7}\u{1F1ED}", name: "flag_bahrain" },
20506
+ { emoji: "\u{1F1E7}\u{1F1EE}", name: "flag_burundi" },
20507
+ { emoji: "\u{1F1E7}\u{1F1EF}", name: "flag_benin" },
20508
+ { emoji: "\u{1F1E7}\u{1F1F1}", name: "flag_st_barthelemy" },
20509
+ { emoji: "\u{1F1E7}\u{1F1F2}", name: "flag_bermuda" },
20510
+ { emoji: "\u{1F1E7}\u{1F1F3}", name: "flag_brunei" },
20511
+ { emoji: "\u{1F1E7}\u{1F1F4}", name: "flag_bolivia" },
20512
+ { emoji: "\u{1F1E7}\u{1F1F6}", name: "flag_bonaire" },
20513
+ { emoji: "\u{1F1E7}\u{1F1F7}", name: "flag_brazil" },
20514
+ { emoji: "\u{1F1E7}\u{1F1F8}", name: "flag_bahamas" },
20515
+ { emoji: "\u{1F1E7}\u{1F1F9}", name: "flag_bhutan" },
20516
+ { emoji: "\u{1F1E7}\u{1F1FB}", name: "flag_bouvet" },
20517
+ { emoji: "\u{1F1E7}\u{1F1FC}", name: "flag_botswana" },
20518
+ { emoji: "\u{1F1E7}\u{1F1FE}", name: "flag_belarus" },
20519
+ { emoji: "\u{1F1E7}\u{1F1FF}", name: "flag_belize" },
20520
+ { emoji: "\u{1F1E8}\u{1F1E6}", name: "flag_canada" },
20521
+ { emoji: "\u{1F1E8}\u{1F1E8}", name: "flag_cocos" },
20522
+ { emoji: "\u{1F1E8}\u{1F1E9}", name: "flag_congo_dr" },
20523
+ { emoji: "\u{1F1E8}\u{1F1EB}", name: "flag_central_africa" },
20524
+ { emoji: "\u{1F1E8}\u{1F1EC}", name: "flag_congo" },
20525
+ { emoji: "\u{1F1E8}\u{1F1ED}", name: "flag_switzerland" },
20526
+ { emoji: "\u{1F1E8}\u{1F1EE}", name: "flag_cote_divoire" },
20527
+ { emoji: "\u{1F1E8}\u{1F1F0}", name: "flag_cook_islands" },
20528
+ { emoji: "\u{1F1E8}\u{1F1F1}", name: "flag_chile" },
20529
+ { emoji: "\u{1F1E8}\u{1F1F2}", name: "flag_cameroon" },
20530
+ { emoji: "\u{1F1E8}\u{1F1F3}", name: "flag_china" },
20531
+ { emoji: "\u{1F1E8}\u{1F1F4}", name: "flag_colombia" },
20532
+ { emoji: "\u{1F1E8}\u{1F1F5}", name: "flag_clipperton" },
20533
+ { emoji: "\u{1F1E8}\u{1F1F7}", name: "flag_costa_rica" },
20534
+ { emoji: "\u{1F1E8}\u{1F1FA}", name: "flag_cuba" },
20535
+ { emoji: "\u{1F1E8}\u{1F1FB}", name: "flag_cape_verde" },
20536
+ { emoji: "\u{1F1E8}\u{1F1FC}", name: "flag_curacao" },
20537
+ { emoji: "\u{1F1E8}\u{1F1FD}", name: "flag_christmas_island" },
20538
+ { emoji: "\u{1F1E8}\u{1F1FE}", name: "flag_cyprus" },
20539
+ { emoji: "\u{1F1E8}\u{1F1FF}", name: "flag_czechia" },
20540
+ { emoji: "\u{1F1E9}\u{1F1EA}", name: "flag_germany" },
20541
+ { emoji: "\u{1F1E9}\u{1F1EC}", name: "flag_diego_garcia" },
20542
+ { emoji: "\u{1F1E9}\u{1F1EF}", name: "flag_djibouti" },
20543
+ { emoji: "\u{1F1E9}\u{1F1F0}", name: "flag_denmark" },
20544
+ { emoji: "\u{1F1E9}\u{1F1F2}", name: "flag_dominica" },
20545
+ { emoji: "\u{1F1E9}\u{1F1F4}", name: "flag_dominican_rep" },
20546
+ { emoji: "\u{1F1E9}\u{1F1FF}", name: "flag_algeria" },
20547
+ { emoji: "\u{1F1EA}\u{1F1E8}", name: "flag_ecuador" },
20548
+ { emoji: "\u{1F1EA}\u{1F1EA}", name: "flag_estonia" },
20549
+ { emoji: "\u{1F1EA}\u{1F1EC}", name: "flag_egypt" },
20550
+ { emoji: "\u{1F1EA}\u{1F1ED}", name: "flag_western_sahara" },
20551
+ { emoji: "\u{1F1EA}\u{1F1F7}", name: "flag_eritrea" },
20552
+ { emoji: "\u{1F1EA}\u{1F1F8}", name: "flag_spain" },
20553
+ { emoji: "\u{1F1EA}\u{1F1F9}", name: "flag_ethiopia" },
20554
+ { emoji: "\u{1F1EA}\u{1F1FA}", name: "flag_eu" },
20555
+ { emoji: "\u{1F1EB}\u{1F1EE}", name: "flag_finland" },
20556
+ { emoji: "\u{1F1EB}\u{1F1EF}", name: "flag_fiji" },
20557
+ { emoji: "\u{1F1EB}\u{1F1F0}", name: "flag_falkland" },
20558
+ { emoji: "\u{1F1EB}\u{1F1F2}", name: "flag_micronesia" },
20559
+ { emoji: "\u{1F1EB}\u{1F1F4}", name: "flag_faroe" },
20560
+ { emoji: "\u{1F1EB}\u{1F1F7}", name: "flag_france" },
20561
+ { emoji: "\u{1F1EC}\u{1F1E6}", name: "flag_gabon" },
20562
+ { emoji: "\u{1F1EC}\u{1F1E7}", name: "flag_uk" },
20563
+ { emoji: "\u{1F1EC}\u{1F1E9}", name: "flag_grenada" },
20564
+ { emoji: "\u{1F1EC}\u{1F1EA}", name: "flag_georgia" },
20565
+ { emoji: "\u{1F1EC}\u{1F1EB}", name: "flag_french_guiana" },
20566
+ { emoji: "\u{1F1EC}\u{1F1EC}", name: "flag_guernsey" },
20567
+ { emoji: "\u{1F1EC}\u{1F1ED}", name: "flag_ghana" },
20568
+ { emoji: "\u{1F1EC}\u{1F1EE}", name: "flag_gibraltar" },
20569
+ { emoji: "\u{1F1EC}\u{1F1F1}", name: "flag_greenland" },
20570
+ { emoji: "\u{1F1EC}\u{1F1F2}", name: "flag_gambia" },
20571
+ { emoji: "\u{1F1EC}\u{1F1F3}", name: "flag_guinea" },
20572
+ { emoji: "\u{1F1EC}\u{1F1F5}", name: "flag_guadeloupe" },
20573
+ { emoji: "\u{1F1EC}\u{1F1F6}", name: "flag_equatorial_guinea" },
20574
+ { emoji: "\u{1F1EC}\u{1F1F7}", name: "flag_greece" },
20575
+ { emoji: "\u{1F1EC}\u{1F1F8}", name: "flag_south_georgia" },
20576
+ { emoji: "\u{1F1EC}\u{1F1F9}", name: "flag_guatemala" },
20577
+ { emoji: "\u{1F1EC}\u{1F1FA}", name: "flag_guam" },
20578
+ { emoji: "\u{1F1EC}\u{1F1FC}", name: "flag_guinea_bissau" },
20579
+ { emoji: "\u{1F1EC}\u{1F1FE}", name: "flag_guyana" },
20580
+ { emoji: "\u{1F1ED}\u{1F1F0}", name: "flag_hong_kong" },
20581
+ { emoji: "\u{1F1ED}\u{1F1F2}", name: "flag_heard_island" },
20582
+ { emoji: "\u{1F1ED}\u{1F1F3}", name: "flag_honduras" },
20583
+ { emoji: "\u{1F1ED}\u{1F1F7}", name: "flag_croatia" },
20584
+ { emoji: "\u{1F1ED}\u{1F1F9}", name: "flag_haiti" },
20585
+ { emoji: "\u{1F1ED}\u{1F1FA}", name: "flag_hungary" },
20586
+ { emoji: "\u{1F1EE}\u{1F1E8}", name: "flag_canary_islands" },
20587
+ { emoji: "\u{1F1EE}\u{1F1E9}", name: "flag_indonesia" },
20588
+ { emoji: "\u{1F1EE}\u{1F1EA}", name: "flag_ireland" },
20589
+ { emoji: "\u{1F1EE}\u{1F1F1}", name: "flag_israel" },
20590
+ { emoji: "\u{1F1EE}\u{1F1F2}", name: "flag_isle_of_man" },
20591
+ { emoji: "\u{1F1EE}\u{1F1F3}", name: "flag_india" },
20592
+ { emoji: "\u{1F1EE}\u{1F1F4}", name: "flag_british_indian_ocean" },
20593
+ { emoji: "\u{1F1EE}\u{1F1F6}", name: "flag_iraq" },
20594
+ { emoji: "\u{1F1EE}\u{1F1F7}", name: "flag_iran" },
20595
+ { emoji: "\u{1F1EE}\u{1F1F8}", name: "flag_iceland" },
20596
+ { emoji: "\u{1F1EE}\u{1F1F9}", name: "flag_italy" },
20597
+ { emoji: "\u{1F1EF}\u{1F1EA}", name: "flag_jersey" },
20598
+ { emoji: "\u{1F1EF}\u{1F1F2}", name: "flag_jamaica" },
20599
+ { emoji: "\u{1F1EF}\u{1F1F4}", name: "flag_jordan" },
20600
+ { emoji: "\u{1F1EF}\u{1F1F5}", name: "flag_japan" },
20601
+ { emoji: "\u{1F1F0}\u{1F1EA}", name: "flag_kenya" },
20602
+ { emoji: "\u{1F1F0}\u{1F1EC}", name: "flag_kyrgyzstan" },
20603
+ { emoji: "\u{1F1F0}\u{1F1ED}", name: "flag_cambodia" },
20604
+ { emoji: "\u{1F1F0}\u{1F1EE}", name: "flag_kiribati" },
20605
+ { emoji: "\u{1F1F0}\u{1F1F2}", name: "flag_comoros" },
20606
+ { emoji: "\u{1F1F0}\u{1F1F3}", name: "flag_st_kitts" },
20607
+ { emoji: "\u{1F1F0}\u{1F1F5}", name: "flag_north_korea" },
20608
+ { emoji: "\u{1F1F0}\u{1F1F7}", name: "flag_south_korea" },
20609
+ { emoji: "\u{1F1F0}\u{1F1FC}", name: "flag_kuwait" },
20610
+ { emoji: "\u{1F1F0}\u{1F1FE}", name: "flag_cayman" },
20611
+ { emoji: "\u{1F1F0}\u{1F1FF}", name: "flag_kazakhstan" },
20612
+ { emoji: "\u{1F1F1}\u{1F1E6}", name: "flag_laos" },
20613
+ { emoji: "\u{1F1F1}\u{1F1E7}", name: "flag_lebanon" },
20614
+ { emoji: "\u{1F1F1}\u{1F1E8}", name: "flag_st_lucia" },
20615
+ { emoji: "\u{1F1F1}\u{1F1EE}", name: "flag_liechtenstein" },
20616
+ { emoji: "\u{1F1F1}\u{1F1F0}", name: "flag_sri_lanka" },
20617
+ { emoji: "\u{1F1F1}\u{1F1F7}", name: "flag_liberia" },
20618
+ { emoji: "\u{1F1F1}\u{1F1F8}", name: "flag_lesotho" },
20619
+ { emoji: "\u{1F1F1}\u{1F1F9}", name: "flag_lithuania" },
20620
+ { emoji: "\u{1F1F1}\u{1F1FA}", name: "flag_luxembourg" },
20621
+ { emoji: "\u{1F1F1}\u{1F1FB}", name: "flag_latvia" },
20622
+ { emoji: "\u{1F1F1}\u{1F1FE}", name: "flag_libya" },
20623
+ { emoji: "\u{1F1F2}\u{1F1E6}", name: "flag_morocco" },
20624
+ { emoji: "\u{1F1F2}\u{1F1E8}", name: "flag_monaco" },
20625
+ { emoji: "\u{1F1F2}\u{1F1E9}", name: "flag_moldova" },
20626
+ { emoji: "\u{1F1F2}\u{1F1EA}", name: "flag_montenegro" },
20627
+ { emoji: "\u{1F1F2}\u{1F1EB}", name: "flag_st_martin" },
20628
+ { emoji: "\u{1F1F2}\u{1F1EC}", name: "flag_madagascar" },
20629
+ { emoji: "\u{1F1F2}\u{1F1ED}", name: "flag_marshall_islands" },
20630
+ { emoji: "\u{1F1F2}\u{1F1F0}", name: "flag_north_macedonia" },
20631
+ { emoji: "\u{1F1F2}\u{1F1F1}", name: "flag_mali" },
20632
+ { emoji: "\u{1F1F2}\u{1F1F2}", name: "flag_myanmar" },
20633
+ { emoji: "\u{1F1F2}\u{1F1F3}", name: "flag_mongolia" },
20634
+ { emoji: "\u{1F1F2}\u{1F1F4}", name: "flag_macau" },
20635
+ { emoji: "\u{1F1F2}\u{1F1F5}", name: "flag_northern_mariana" },
20636
+ { emoji: "\u{1F1F2}\u{1F1F6}", name: "flag_martinique" },
20637
+ { emoji: "\u{1F1F2}\u{1F1F7}", name: "flag_mauritania" },
20638
+ { emoji: "\u{1F1F2}\u{1F1F8}", name: "flag_montserrat" },
20639
+ { emoji: "\u{1F1F2}\u{1F1F9}", name: "flag_malta" },
20640
+ { emoji: "\u{1F1F2}\u{1F1FA}", name: "flag_mauritius" },
20641
+ { emoji: "\u{1F1F2}\u{1F1FB}", name: "flag_maldives" },
20642
+ { emoji: "\u{1F1F2}\u{1F1FC}", name: "flag_malawi" },
20643
+ { emoji: "\u{1F1F2}\u{1F1FD}", name: "flag_mexico" },
20644
+ { emoji: "\u{1F1F2}\u{1F1FE}", name: "flag_malaysia" },
20645
+ { emoji: "\u{1F1F2}\u{1F1FF}", name: "flag_mozambique" },
20646
+ { emoji: "\u{1F1F3}\u{1F1E6}", name: "flag_namibia" },
20647
+ { emoji: "\u{1F1F3}\u{1F1E8}", name: "flag_new_caledonia" },
20648
+ { emoji: "\u{1F1F3}\u{1F1EA}", name: "flag_niger" },
20649
+ { emoji: "\u{1F1F3}\u{1F1EB}", name: "flag_norfolk" },
20650
+ { emoji: "\u{1F1F3}\u{1F1EC}", name: "flag_nigeria" },
20651
+ { emoji: "\u{1F1F3}\u{1F1EE}", name: "flag_nicaragua" },
20652
+ { emoji: "\u{1F1F3}\u{1F1F1}", name: "flag_netherlands" },
20653
+ { emoji: "\u{1F1F3}\u{1F1F4}", name: "flag_norway" },
20654
+ { emoji: "\u{1F1F3}\u{1F1F5}", name: "flag_nepal" },
20655
+ { emoji: "\u{1F1F3}\u{1F1F7}", name: "flag_nauru" },
20656
+ { emoji: "\u{1F1F3}\u{1F1FA}", name: "flag_niue" },
20657
+ { emoji: "\u{1F1F3}\u{1F1FF}", name: "flag_new_zealand" },
20658
+ { emoji: "\u{1F1F4}\u{1F1F2}", name: "flag_oman" },
20659
+ { emoji: "\u{1F1F5}\u{1F1E6}", name: "flag_panama" },
20660
+ { emoji: "\u{1F1F5}\u{1F1EA}", name: "flag_peru" },
20661
+ { emoji: "\u{1F1F5}\u{1F1EB}", name: "flag_french_polynesia" },
20662
+ { emoji: "\u{1F1F5}\u{1F1EC}", name: "flag_papua_new_guinea" },
20663
+ { emoji: "\u{1F1F5}\u{1F1ED}", name: "flag_philippines" },
20664
+ { emoji: "\u{1F1F5}\u{1F1F0}", name: "flag_pakistan" },
20665
+ { emoji: "\u{1F1F5}\u{1F1F1}", name: "flag_poland" },
20666
+ { emoji: "\u{1F1F5}\u{1F1F2}", name: "flag_st_pierre" },
20667
+ { emoji: "\u{1F1F5}\u{1F1F3}", name: "flag_pitcairn" },
20668
+ { emoji: "\u{1F1F5}\u{1F1F7}", name: "flag_puerto_rico" },
20669
+ { emoji: "\u{1F1F5}\u{1F1F8}", name: "flag_palestine" },
20670
+ { emoji: "\u{1F1F5}\u{1F1F9}", name: "flag_portugal" },
20671
+ { emoji: "\u{1F1F5}\u{1F1FC}", name: "flag_palau" },
20672
+ { emoji: "\u{1F1F5}\u{1F1FE}", name: "flag_paraguay" },
20673
+ { emoji: "\u{1F1F6}\u{1F1E6}", name: "flag_qatar" },
20674
+ { emoji: "\u{1F1F7}\u{1F1EA}", name: "flag_reunion" },
20675
+ { emoji: "\u{1F1F7}\u{1F1F4}", name: "flag_romania" },
20676
+ { emoji: "\u{1F1F7}\u{1F1F8}", name: "flag_serbia" },
20677
+ { emoji: "\u{1F1F7}\u{1F1FA}", name: "flag_russia" },
20678
+ { emoji: "\u{1F1F7}\u{1F1FC}", name: "flag_rwanda" },
20679
+ { emoji: "\u{1F1F8}\u{1F1E6}", name: "flag_saudi_arabia" },
20680
+ { emoji: "\u{1F1F8}\u{1F1E7}", name: "flag_solomon_islands" },
20681
+ { emoji: "\u{1F1F8}\u{1F1E8}", name: "flag_seychelles" },
20682
+ { emoji: "\u{1F1F8}\u{1F1E9}", name: "flag_sudan" },
20683
+ { emoji: "\u{1F1F8}\u{1F1EA}", name: "flag_sweden" },
20684
+ { emoji: "\u{1F1F8}\u{1F1EC}", name: "flag_singapore" },
20685
+ { emoji: "\u{1F1F8}\u{1F1ED}", name: "flag_st_helena" },
20686
+ { emoji: "\u{1F1F8}\u{1F1EE}", name: "flag_slovenia" },
20687
+ { emoji: "\u{1F1F8}\u{1F1EF}", name: "flag_svalbard" },
20688
+ { emoji: "\u{1F1F8}\u{1F1F0}", name: "flag_slovakia" },
20689
+ { emoji: "\u{1F1F8}\u{1F1F1}", name: "flag_sierra_leone" },
20690
+ { emoji: "\u{1F1F8}\u{1F1F2}", name: "flag_san_marino" },
20691
+ { emoji: "\u{1F1F8}\u{1F1F3}", name: "flag_senegal" },
20692
+ { emoji: "\u{1F1F8}\u{1F1F4}", name: "flag_somalia" },
20693
+ { emoji: "\u{1F1F8}\u{1F1F7}", name: "flag_suriname" },
20694
+ { emoji: "\u{1F1F8}\u{1F1F8}", name: "flag_south_sudan" },
20695
+ { emoji: "\u{1F1F8}\u{1F1F9}", name: "flag_sao_tome" },
20696
+ { emoji: "\u{1F1F8}\u{1F1FB}", name: "flag_el_salvador" },
20697
+ { emoji: "\u{1F1F8}\u{1F1FD}", name: "flag_sint_maarten" },
20698
+ { emoji: "\u{1F1F8}\u{1F1FE}", name: "flag_syria" },
20699
+ { emoji: "\u{1F1F8}\u{1F1FF}", name: "flag_eswatini" },
20700
+ { emoji: "\u{1F1F9}\u{1F1E6}", name: "flag_tristan" },
20701
+ { emoji: "\u{1F1F9}\u{1F1E8}", name: "flag_turks_caicos" },
20702
+ { emoji: "\u{1F1F9}\u{1F1E9}", name: "flag_chad" },
20703
+ { emoji: "\u{1F1F9}\u{1F1EB}", name: "flag_french_southern" },
20704
+ { emoji: "\u{1F1F9}\u{1F1EC}", name: "flag_togo" },
20705
+ { emoji: "\u{1F1F9}\u{1F1ED}", name: "flag_thailand" },
20706
+ { emoji: "\u{1F1F9}\u{1F1EF}", name: "flag_tajikistan" },
20707
+ { emoji: "\u{1F1F9}\u{1F1F0}", name: "flag_tokelau" },
20708
+ { emoji: "\u{1F1F9}\u{1F1F1}", name: "flag_timor_leste" },
20709
+ { emoji: "\u{1F1F9}\u{1F1F2}", name: "flag_turkmenistan" },
20710
+ { emoji: "\u{1F1F9}\u{1F1F3}", name: "flag_tunisia" },
20711
+ { emoji: "\u{1F1F9}\u{1F1F4}", name: "flag_tonga" },
20712
+ { emoji: "\u{1F1F9}\u{1F1F7}", name: "flag_turkey" },
20713
+ { emoji: "\u{1F1F9}\u{1F1F9}", name: "flag_trinidad" },
20714
+ { emoji: "\u{1F1F9}\u{1F1FB}", name: "flag_tuvalu" },
20715
+ { emoji: "\u{1F1F9}\u{1F1FC}", name: "flag_taiwan" },
20716
+ { emoji: "\u{1F1F9}\u{1F1FF}", name: "flag_tanzania" },
20717
+ { emoji: "\u{1F1FA}\u{1F1E6}", name: "flag_ukraine" },
20718
+ { emoji: "\u{1F1FA}\u{1F1EC}", name: "flag_uganda" },
20719
+ { emoji: "\u{1F1FA}\u{1F1F2}", name: "flag_us_outlying" },
20720
+ { emoji: "\u{1F1FA}\u{1F1F3}", name: "flag_un" },
20721
+ { emoji: "\u{1F1FA}\u{1F1F8}", name: "flag_usa" },
20722
+ { emoji: "\u{1F1FA}\u{1F1FE}", name: "flag_uruguay" },
20723
+ { emoji: "\u{1F1FA}\u{1F1FF}", name: "flag_uzbekistan" },
20724
+ { emoji: "\u{1F1FB}\u{1F1E6}", name: "flag_vatican" },
20725
+ { emoji: "\u{1F1FB}\u{1F1E8}", name: "flag_st_vincent" },
20726
+ { emoji: "\u{1F1FB}\u{1F1EA}", name: "flag_venezuela" },
20727
+ { emoji: "\u{1F1FB}\u{1F1EC}", name: "flag_bvi" },
20728
+ { emoji: "\u{1F1FB}\u{1F1EE}", name: "flag_usvi" },
20729
+ { emoji: "\u{1F1FB}\u{1F1F3}", name: "flag_vietnam" },
20730
+ { emoji: "\u{1F1FB}\u{1F1FA}", name: "flag_vanuatu" },
20731
+ { emoji: "\u{1F1FC}\u{1F1EB}", name: "flag_wallis" },
20732
+ { emoji: "\u{1F1FC}\u{1F1F8}", name: "flag_samoa" },
20733
+ { emoji: "\u{1F1FD}\u{1F1F0}", name: "flag_kosovo" },
20734
+ { emoji: "\u{1F1FE}\u{1F1EA}", name: "flag_yemen" },
20735
+ { emoji: "\u{1F1FE}\u{1F1F9}", name: "flag_mayotte" },
20736
+ { emoji: "\u{1F1FF}\u{1F1E6}", name: "flag_south_africa" },
20737
+ { emoji: "\u{1F1FF}\u{1F1F2}", name: "flag_zambia" },
20738
+ { emoji: "\u{1F1FF}\u{1F1FC}", name: "flag_zimbabwe" }
20739
+ ]
20740
+ }
20741
+ ];
20742
+
20743
+ // ../../components/ui/UEditor/emoji-suggestion.tsx
19780
20744
  var import_jsx_runtime76 = require("react/jsx-runtime");
20745
+ var EmojiList = (0, import_react42.forwardRef)((props, ref) => {
20746
+ const [selectedIndex, setSelectedIndex] = (0, import_react42.useState)(0);
20747
+ (0, import_react42.useEffect)(() => {
20748
+ setSelectedIndex(0);
20749
+ }, [props.items]);
20750
+ (0, import_react42.useImperativeHandle)(ref, () => ({
20751
+ onKeyDown: ({ event }) => {
20752
+ if (event.key === "ArrowUp") {
20753
+ setSelectedIndex((prev) => (prev + props.items.length - 1) % props.items.length);
20754
+ return true;
20755
+ }
20756
+ if (event.key === "ArrowDown") {
20757
+ setSelectedIndex((prev) => (prev + 1) % props.items.length);
20758
+ return true;
20759
+ }
20760
+ if (event.key === "ArrowLeft") {
20761
+ setSelectedIndex((prev) => Math.max(0, prev - 8));
20762
+ return true;
20763
+ }
20764
+ if (event.key === "ArrowRight") {
20765
+ setSelectedIndex((prev) => Math.min(props.items.length - 1, prev + 8));
20766
+ return true;
20767
+ }
20768
+ if (event.key === "Enter") {
20769
+ const item = props.items[selectedIndex];
20770
+ if (item) {
20771
+ props.command(item);
20772
+ }
20773
+ return true;
20774
+ }
20775
+ return false;
20776
+ }
20777
+ }));
20778
+ if (props.items.length === 0) {
20779
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "w-80 p-4 text-center text-sm text-muted-foreground bg-card border border-border rounded-2xl shadow-lg", children: "No emoji found" });
20780
+ }
20781
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "w-80 max-h-80 overflow-y-auto bg-card border border-border rounded-2xl shadow-lg", children: [
20782
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "px-3 py-2 border-b bg-muted/30", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "flex items-center gap-2", children: [
20783
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(import_lucide_react39.Smile, { className: "w-4 h-4 text-primary" }),
20784
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Emoji" })
20785
+ ] }) }),
20786
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "p-3", children: [
20787
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "grid grid-cols-8 gap-1", children: props.items.slice(0, 64).map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
20788
+ "button",
20789
+ {
20790
+ type: "button",
20791
+ onClick: () => props.command(item),
20792
+ className: cn(
20793
+ "w-9 h-9 flex items-center justify-center rounded-lg text-xl transition-colors",
20794
+ selectedIndex === index ? "bg-primary/10 ring-2 ring-primary/30" : "hover:bg-accent"
20795
+ ),
20796
+ title: item.name.replace(/_/g, " "),
20797
+ children: item.emoji
20798
+ },
20799
+ item.name
20800
+ )) }),
20801
+ props.items.length > 64 && /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "mt-2 text-xs text-center text-muted-foreground", children: [
20802
+ "Showing first 64 of ",
20803
+ props.items.length,
20804
+ " emojis"
20805
+ ] })
20806
+ ] })
20807
+ ] });
20808
+ });
20809
+ EmojiList.displayName = "EmojiList";
20810
+ var getEmojiSuggestionItems = ({ query }) => {
20811
+ const allEmojis = EMOJI_LIST.flatMap((category) => category.emojis);
20812
+ if (!query.trim()) {
20813
+ return allEmojis.slice(0, 64);
20814
+ }
20815
+ const searchQuery = query.toLowerCase();
20816
+ return allEmojis.filter(
20817
+ (emoji) => emoji.name.toLowerCase().includes(searchQuery) || emoji.emoji.includes(query)
20818
+ );
20819
+ };
20820
+ var EmojiSuggestion = import_core3.Extension.create({
20821
+ name: "emojiSuggestion",
20822
+ addProseMirrorPlugins() {
20823
+ return [
20824
+ (0, import_suggestion2.default)({
20825
+ editor: this.editor,
20826
+ char: ":",
20827
+ pluginKey: new import_state2.PluginKey("emojiSuggestion"),
20828
+ command: ({ editor, range, props }) => {
20829
+ editor.chain().focus().deleteRange(range).insertContent(props.emoji).run();
20830
+ },
20831
+ items: getEmojiSuggestionItems,
20832
+ render: () => {
20833
+ let component;
20834
+ let popup;
20835
+ return {
20836
+ onStart: (props) => {
20837
+ component = new import_react41.ReactRenderer(EmojiList, {
20838
+ props,
20839
+ editor: props.editor
20840
+ });
20841
+ if (!props.clientRect) {
20842
+ return;
20843
+ }
20844
+ popup = (0, import_tippy2.default)("body", {
20845
+ getReferenceClientRect: props.clientRect,
20846
+ appendTo: () => document.body,
20847
+ content: component.element,
20848
+ showOnCreate: true,
20849
+ interactive: true,
20850
+ trigger: "manual",
20851
+ placement: "bottom-start"
20852
+ });
20853
+ },
20854
+ onUpdate(props) {
20855
+ component?.updateProps(props);
20856
+ if (!props.clientRect) {
20857
+ return;
20858
+ }
20859
+ popup?.[0]?.setProps({
20860
+ getReferenceClientRect: props.clientRect
20861
+ });
20862
+ },
20863
+ onKeyDown(props) {
20864
+ if (props.event.key === "Escape") {
20865
+ popup?.[0]?.hide();
20866
+ return true;
20867
+ }
20868
+ return component?.ref?.onKeyDown(props) ?? false;
20869
+ },
20870
+ onExit() {
20871
+ popup?.[0]?.destroy();
20872
+ component?.destroy();
20873
+ }
20874
+ };
20875
+ }
20876
+ })
20877
+ ];
20878
+ }
20879
+ });
20880
+
20881
+ // ../../components/ui/UEditor/resizable-image.tsx
20882
+ var import_react43 = require("react");
20883
+ var import_extension_image = __toESM(require("@tiptap/extension-image"), 1);
20884
+ var import_core4 = require("@tiptap/core");
20885
+ var import_react44 = require("@tiptap/react");
20886
+ var import_jsx_runtime77 = require("react/jsx-runtime");
19781
20887
  var MIN_IMAGE_SIZE_PX = 40;
19782
20888
  var AXIS_LOCK_THRESHOLD_PX = 4;
19783
20889
  function toNullableNumber(value) {
@@ -19793,15 +20899,15 @@ function clamp7(value, min, max) {
19793
20899
  }
19794
20900
  function ResizableImageNodeView(props) {
19795
20901
  const { node, selected, updateAttributes, editor, getPos } = props;
19796
- const wrapperRef = (0, import_react41.useRef)(null);
19797
- const imgRef = (0, import_react41.useRef)(null);
19798
- const [isHovered, setIsHovered] = (0, import_react41.useState)(false);
19799
- const [isResizing, setIsResizing] = (0, import_react41.useState)(false);
20902
+ const wrapperRef = (0, import_react43.useRef)(null);
20903
+ const imgRef = (0, import_react43.useRef)(null);
20904
+ const [isHovered, setIsHovered] = (0, import_react43.useState)(false);
20905
+ const [isResizing, setIsResizing] = (0, import_react43.useState)(false);
19800
20906
  const widthAttr = toNullableNumber(node.attrs["width"]);
19801
20907
  const heightAttr = toNullableNumber(node.attrs["height"]);
19802
20908
  const textAlign = String(node.attrs["textAlign"] ?? "");
19803
- const dragStateRef = (0, import_react41.useRef)(null);
19804
- (0, import_react41.useEffect)(() => {
20909
+ const dragStateRef = (0, import_react43.useRef)(null);
20910
+ (0, import_react43.useEffect)(() => {
19805
20911
  const img = imgRef.current;
19806
20912
  if (!img) return;
19807
20913
  img.style.width = widthAttr ? `${widthAttr}px` : "";
@@ -19895,8 +21001,8 @@ function ResizableImageNodeView(props) {
19895
21001
  const showHandle = selected || isHovered || isResizing;
19896
21002
  const wrapperAlignClass = textAlign === "center" ? "mx-auto" : textAlign === "right" ? "ml-auto" : textAlign === "justify" ? "mx-auto" : "";
19897
21003
  const wrapperWidthClass = "w-fit";
19898
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
19899
- import_react42.NodeViewWrapper,
21004
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
21005
+ import_react44.NodeViewWrapper,
19900
21006
  {
19901
21007
  as: "div",
19902
21008
  ref: wrapperRef,
@@ -19909,7 +21015,7 @@ function ResizableImageNodeView(props) {
19909
21015
  },
19910
21016
  contentEditable: false,
19911
21017
  children: [
19912
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
21018
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
19913
21019
  "img",
19914
21020
  {
19915
21021
  ref: imgRef,
@@ -19928,7 +21034,7 @@ function ResizableImageNodeView(props) {
19928
21034
  }
19929
21035
  }
19930
21036
  ),
19931
- showHandle && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
21037
+ showHandle && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
19932
21038
  "div",
19933
21039
  {
19934
21040
  "aria-hidden": "true",
@@ -19974,10 +21080,10 @@ var ResizableImage = import_extension_image.default.extend({
19974
21080
  };
19975
21081
  },
19976
21082
  renderHTML({ HTMLAttributes: HTMLAttributes2 }) {
19977
- return ["img", (0, import_core3.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes2)];
21083
+ return ["img", (0, import_core4.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes2)];
19978
21084
  },
19979
21085
  addNodeView() {
19980
- return (0, import_react42.ReactNodeViewRenderer)(ResizableImageNodeView);
21086
+ return (0, import_react44.ReactNodeViewRenderer)(ResizableImageNodeView);
19981
21087
  }
19982
21088
  }).configure({
19983
21089
  allowBase64: true,
@@ -20088,23 +21194,24 @@ function buildUEditorExtensions({
20088
21194
  emptyEditorClass: "is-editor-empty",
20089
21195
  emptyNodeClass: "is-empty"
20090
21196
  }),
20091
- SlashCommand
21197
+ SlashCommand,
21198
+ EmojiSuggestion
20092
21199
  ];
20093
21200
  }
20094
21201
 
20095
21202
  // ../../components/ui/UEditor/toolbar.tsx
20096
- var import_react45 = __toESM(require("react"), 1);
21203
+ var import_react48 = __toESM(require("react"), 1);
20097
21204
  var import_next_intl3 = require("next-intl");
20098
- var import_lucide_react41 = require("lucide-react");
21205
+ var import_lucide_react43 = require("lucide-react");
20099
21206
 
20100
21207
  // ../../components/ui/UEditor/colors.tsx
20101
- var import_react43 = require("react");
21208
+ var import_react45 = require("react");
20102
21209
  var import_next_intl = require("next-intl");
20103
- var import_lucide_react39 = require("lucide-react");
20104
- var import_jsx_runtime77 = require("react/jsx-runtime");
21210
+ var import_lucide_react40 = require("lucide-react");
21211
+ var import_jsx_runtime78 = require("react/jsx-runtime");
20105
21212
  var useEditorColors = () => {
20106
21213
  const t = (0, import_next_intl.useTranslations)("UEditor");
20107
- const textColors = (0, import_react43.useMemo)(
21214
+ const textColors = (0, import_react45.useMemo)(
20108
21215
  () => [
20109
21216
  { name: t("colors.default"), color: "inherit", cssClass: "text-foreground" },
20110
21217
  { name: t("colors.muted"), color: "var(--muted-foreground)", cssClass: "text-muted-foreground" },
@@ -20117,7 +21224,7 @@ var useEditorColors = () => {
20117
21224
  ],
20118
21225
  [t]
20119
21226
  );
20120
- const highlightColors = (0, import_react43.useMemo)(
21227
+ const highlightColors = (0, import_react45.useMemo)(
20121
21228
  () => [
20122
21229
  { name: t("colors.default"), color: "", cssClass: "" },
20123
21230
  { name: t("colors.muted"), color: "var(--muted)", cssClass: "bg-muted" },
@@ -20138,9 +21245,9 @@ var EditorColorPalette = ({
20138
21245
  currentColor,
20139
21246
  onSelect,
20140
21247
  label
20141
- }) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "p-2", children: [
20142
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider px-2", children: label }),
20143
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "grid grid-cols-4 gap-1.5 mt-2", children: colors.map((c) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
21248
+ }) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "p-2", children: [
21249
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider px-2", children: label }),
21250
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "grid grid-cols-4 gap-1.5 mt-2", children: colors.map((c) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
20144
21251
  "button",
20145
21252
  {
20146
21253
  type: "button",
@@ -20153,8 +21260,8 @@ var EditorColorPalette = ({
20153
21260
  style: { backgroundColor: c.color || "transparent" },
20154
21261
  title: c.name,
20155
21262
  children: [
20156
- c.color === "" && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(import_lucide_react39.X, { className: "w-4 h-4 text-muted-foreground" }),
20157
- c.color === "inherit" && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "text-xs font-medium", children: "A" })
21263
+ c.color === "" && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react40.X, { className: "w-4 h-4 text-muted-foreground" }),
21264
+ c.color === "inherit" && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-xs font-medium", children: "A" })
20158
21265
  ]
20159
21266
  },
20160
21267
  c.name
@@ -20162,10 +21269,10 @@ var EditorColorPalette = ({
20162
21269
  ] });
20163
21270
 
20164
21271
  // ../../components/ui/UEditor/inputs.tsx
20165
- var import_react44 = require("react");
21272
+ var import_react46 = require("react");
20166
21273
  var import_next_intl2 = require("next-intl");
20167
- var import_lucide_react40 = require("lucide-react");
20168
- var import_jsx_runtime78 = require("react/jsx-runtime");
21274
+ var import_lucide_react41 = require("lucide-react");
21275
+ var import_jsx_runtime79 = require("react/jsx-runtime");
20169
21276
  function normalizeUrl(raw) {
20170
21277
  const url = raw.trim();
20171
21278
  if (!url) return "";
@@ -20179,9 +21286,9 @@ var LinkInput = ({
20179
21286
  initialUrl = ""
20180
21287
  }) => {
20181
21288
  const t = (0, import_next_intl2.useTranslations)("UEditor");
20182
- const [url, setUrl] = (0, import_react44.useState)(initialUrl);
20183
- const inputRef = (0, import_react44.useRef)(null);
20184
- (0, import_react44.useEffect)(() => {
21289
+ const [url, setUrl] = (0, import_react46.useState)(initialUrl);
21290
+ const inputRef = (0, import_react46.useRef)(null);
21291
+ (0, import_react46.useEffect)(() => {
20185
21292
  inputRef.current?.focus();
20186
21293
  inputRef.current?.select();
20187
21294
  }, []);
@@ -20190,8 +21297,8 @@ var LinkInput = ({
20190
21297
  const normalized = normalizeUrl(url);
20191
21298
  if (normalized) onSubmit(normalized);
20192
21299
  };
20193
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("form", { onSubmit: handleSubmit, className: "flex items-center gap-2 p-2", children: [
20194
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
21300
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("form", { onSubmit: handleSubmit, className: "flex items-center gap-2 p-2", children: [
21301
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
20195
21302
  "input",
20196
21303
  {
20197
21304
  ref: inputRef,
@@ -20202,16 +21309,16 @@ var LinkInput = ({
20202
21309
  className: "flex-1 px-3 py-2 text-sm bg-muted/50 border-0 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20"
20203
21310
  }
20204
21311
  ),
20205
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("button", { type: "submit", className: "p-2 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react40.Check, { className: "w-4 h-4" }) }),
20206
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("button", { type: "button", onClick: onCancel, className: "p-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react40.X, { className: "w-4 h-4" }) })
21312
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("button", { type: "submit", className: "p-2 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Check, { className: "w-4 h-4" }) }),
21313
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("button", { type: "button", onClick: onCancel, className: "p-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.X, { className: "w-4 h-4" }) })
20207
21314
  ] });
20208
21315
  };
20209
21316
  var ImageInput = ({ onSubmit, onCancel }) => {
20210
21317
  const t = (0, import_next_intl2.useTranslations)("UEditor");
20211
- const [url, setUrl] = (0, import_react44.useState)("");
20212
- const [alt, setAlt] = (0, import_react44.useState)("");
20213
- const inputRef = (0, import_react44.useRef)(null);
20214
- (0, import_react44.useEffect)(() => {
21318
+ const [url, setUrl] = (0, import_react46.useState)("");
21319
+ const [alt, setAlt] = (0, import_react46.useState)("");
21320
+ const inputRef = (0, import_react46.useRef)(null);
21321
+ (0, import_react46.useEffect)(() => {
20215
21322
  inputRef.current?.focus();
20216
21323
  }, []);
20217
21324
  const handleSubmit = (e) => {
@@ -20220,10 +21327,10 @@ var ImageInput = ({ onSubmit, onCancel }) => {
20220
21327
  onSubmit(url, alt);
20221
21328
  }
20222
21329
  };
20223
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("form", { onSubmit: handleSubmit, className: "p-3 space-y-3", children: [
20224
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { children: [
20225
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.urlLabel") }),
20226
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
21330
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("form", { onSubmit: handleSubmit, className: "p-3 space-y-3", children: [
21331
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { children: [
21332
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.urlLabel") }),
21333
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
20227
21334
  "input",
20228
21335
  {
20229
21336
  ref: inputRef,
@@ -20235,9 +21342,9 @@ var ImageInput = ({ onSubmit, onCancel }) => {
20235
21342
  }
20236
21343
  )
20237
21344
  ] }),
20238
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { children: [
20239
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.altLabel") }),
20240
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
21345
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { children: [
21346
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.altLabel") }),
21347
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
20241
21348
  "input",
20242
21349
  {
20243
21350
  type: "text",
@@ -20248,8 +21355,8 @@ var ImageInput = ({ onSubmit, onCancel }) => {
20248
21355
  }
20249
21356
  )
20250
21357
  ] }),
20251
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex gap-2", children: [
20252
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
21358
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "flex gap-2", children: [
21359
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
20253
21360
  "button",
20254
21361
  {
20255
21362
  type: "submit",
@@ -20258,13 +21365,195 @@ var ImageInput = ({ onSubmit, onCancel }) => {
20258
21365
  children: t("imageInput.addBtn")
20259
21366
  }
20260
21367
  ),
20261
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("button", { type: "button", onClick: onCancel, className: "px-4 py-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: t("imageInput.cancelBtn") })
21368
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("button", { type: "button", onClick: onCancel, className: "px-4 py-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: t("imageInput.cancelBtn") })
20262
21369
  ] })
20263
21370
  ] });
20264
21371
  };
20265
21372
 
21373
+ // ../../components/ui/UEditor/emoji-picker.tsx
21374
+ var import_react47 = require("react");
21375
+ var import_lucide_react42 = require("lucide-react");
21376
+ var import_jsx_runtime80 = require("react/jsx-runtime");
21377
+ var CATEGORY_ICONS = {
21378
+ "smileys_people": import_lucide_react42.Smile,
21379
+ "animals_nature": import_lucide_react42.Leaf,
21380
+ "food_drink": import_lucide_react42.Utensils,
21381
+ "activity": import_lucide_react42.Dumbbell,
21382
+ "objects": import_lucide_react42.Lightbulb,
21383
+ "symbols": import_lucide_react42.Hash,
21384
+ "flags": import_lucide_react42.Flag
21385
+ };
21386
+ var EmojiPicker = ({ onSelect, onClose }) => {
21387
+ const [search, setSearch] = (0, import_react47.useState)("");
21388
+ const [activeCategory, setActiveCategory] = (0, import_react47.useState)(EMOJI_LIST[0]?.id || "");
21389
+ const scrollContainerRef = (0, import_react47.useRef)(null);
21390
+ const categoryRefs = (0, import_react47.useRef)({});
21391
+ const isUserScrolling = (0, import_react47.useRef)(false);
21392
+ const filteredCategories = (0, import_react47.useMemo)(() => {
21393
+ if (!search.trim()) return EMOJI_LIST;
21394
+ const query = search.toLowerCase();
21395
+ return EMOJI_LIST.map((category) => ({
21396
+ ...category,
21397
+ emojis: category.emojis.filter(
21398
+ (emoji) => emoji.name.toLowerCase().includes(query) || emoji.emoji.includes(search)
21399
+ )
21400
+ })).filter((category) => category.emojis.length > 0);
21401
+ }, [search]);
21402
+ const handleEmojiClick = (emoji) => {
21403
+ onSelect(emoji);
21404
+ setSearch("");
21405
+ };
21406
+ (0, import_react47.useEffect)(() => {
21407
+ if (search) return;
21408
+ const container = scrollContainerRef.current;
21409
+ if (!container) return;
21410
+ const handleScroll = () => {
21411
+ if (!isUserScrolling.current) return;
21412
+ const scrollTop = container.scrollTop;
21413
+ const containerHeight = container.clientHeight;
21414
+ let maxVisibility = 0;
21415
+ let mostVisibleCategory = EMOJI_LIST[0]?.id || "";
21416
+ EMOJI_LIST.forEach((category) => {
21417
+ const element = categoryRefs.current[category.id];
21418
+ if (!element) return;
21419
+ const rect = element.getBoundingClientRect();
21420
+ const containerRect = container.getBoundingClientRect();
21421
+ const visibleTop = Math.max(rect.top, containerRect.top);
21422
+ const visibleBottom = Math.min(rect.bottom, containerRect.bottom);
21423
+ const visibleHeight = Math.max(0, visibleBottom - visibleTop);
21424
+ if (visibleHeight > maxVisibility) {
21425
+ maxVisibility = visibleHeight;
21426
+ mostVisibleCategory = category.id;
21427
+ }
21428
+ });
21429
+ if (mostVisibleCategory !== activeCategory) {
21430
+ setActiveCategory(mostVisibleCategory);
21431
+ }
21432
+ };
21433
+ container.addEventListener("scroll", handleScroll);
21434
+ return () => container.removeEventListener("scroll", handleScroll);
21435
+ }, [search, activeCategory]);
21436
+ const handleCategoryClick = (categoryId) => {
21437
+ const element = categoryRefs.current[categoryId];
21438
+ if (!element || !scrollContainerRef.current) return;
21439
+ isUserScrolling.current = false;
21440
+ setActiveCategory(categoryId);
21441
+ element.scrollIntoView({ behavior: "smooth", block: "start" });
21442
+ setTimeout(() => {
21443
+ isUserScrolling.current = true;
21444
+ }, 500);
21445
+ };
21446
+ (0, import_react47.useEffect)(() => {
21447
+ isUserScrolling.current = true;
21448
+ }, []);
21449
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "w-96 bg-card border border-border rounded-2xl shadow-xl overflow-hidden flex flex-col max-h-128", children: [
21450
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "p-3 border-b bg-muted/30 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "relative", children: [
21451
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" }),
21452
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
21453
+ "input",
21454
+ {
21455
+ type: "text",
21456
+ placeholder: "T\xECm ki\u1EBFm bi\u1EC3u t\u01B0\u1EE3ng c\u1EA3m x\xFAc",
21457
+ value: search,
21458
+ onChange: (e) => setSearch(e.target.value),
21459
+ className: cn(
21460
+ "w-full pl-9 pr-9 py-2 rounded-lg",
21461
+ "bg-background border border-border",
21462
+ "text-sm placeholder:text-muted-foreground",
21463
+ "focus:outline-none focus:ring-2 focus:ring-primary/20"
21464
+ )
21465
+ }
21466
+ ),
21467
+ search && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
21468
+ "button",
21469
+ {
21470
+ onClick: () => setSearch(""),
21471
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
21472
+ children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.X, { className: "w-4 h-4" })
21473
+ }
21474
+ )
21475
+ ] }) }),
21476
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
21477
+ "div",
21478
+ {
21479
+ ref: scrollContainerRef,
21480
+ className: "overflow-y-auto px-3 py-2 shrink",
21481
+ style: { height: "20rem" },
21482
+ children: search ? (
21483
+ // Search Results
21484
+ filteredCategories.length > 0 ? filteredCategories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "mb-4", children: [
21485
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2 sticky top-0 bg-card py-1", children: category.name }),
21486
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "grid grid-cols-9 gap-1", children: category.emojis.map((emoji) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
21487
+ "button",
21488
+ {
21489
+ onClick: () => handleEmojiClick(emoji.emoji),
21490
+ className: cn(
21491
+ "w-9 h-9 flex items-center justify-center rounded-lg",
21492
+ "text-2xl hover:bg-accent transition-colors",
21493
+ "focus:outline-none focus:ring-2 focus:ring-primary/20"
21494
+ ),
21495
+ title: emoji.name.replace(/_/g, " "),
21496
+ children: emoji.emoji
21497
+ },
21498
+ emoji.name
21499
+ )) })
21500
+ ] }, category.id)) : /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex flex-col items-center justify-center h-full text-center", children: [
21501
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "text-4xl mb-2", children: "\u{1F50D}" }),
21502
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "text-sm font-medium text-muted-foreground", children: "Kh\xF4ng t\xECm th\u1EA5y emoji" }),
21503
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "text-xs text-muted-foreground mt-1", children: "Th\u1EED t\u1EEB kh\xF3a kh\xE1c" })
21504
+ ] })
21505
+ ) : (
21506
+ // All Categories - Messenger Style
21507
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "space-y-4", children: EMOJI_LIST.map((category) => /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
21508
+ "div",
21509
+ {
21510
+ ref: (el) => {
21511
+ categoryRefs.current[category.id] = el;
21512
+ },
21513
+ children: [
21514
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2 sticky top-0 bg-card py-1 z-10", children: category.name }),
21515
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "grid grid-cols-9 gap-1", children: category.emojis.map((emoji) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
21516
+ "button",
21517
+ {
21518
+ onClick: () => handleEmojiClick(emoji.emoji),
21519
+ className: cn(
21520
+ "w-9 h-9 flex items-center justify-center rounded-lg",
21521
+ "text-2xl hover:bg-accent transition-colors",
21522
+ "focus:outline-none focus:ring-2 focus:ring-primary/20"
21523
+ ),
21524
+ title: emoji.name.replace(/_/g, " "),
21525
+ children: emoji.emoji
21526
+ },
21527
+ emoji.name
21528
+ )) })
21529
+ ]
21530
+ },
21531
+ category.id
21532
+ )) })
21533
+ )
21534
+ }
21535
+ ),
21536
+ !search && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "flex items-center justify-around px-2 py-2 border-t bg-muted/30 shrink-0", children: EMOJI_LIST.map((category) => {
21537
+ const IconComponent = CATEGORY_ICONS[category.id] || import_lucide_react42.Smile;
21538
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
21539
+ "button",
21540
+ {
21541
+ onClick: () => handleCategoryClick(category.id),
21542
+ className: cn(
21543
+ "p-2 rounded-lg transition-colors",
21544
+ activeCategory === category.id ? "text-primary bg-primary/10" : "text-muted-foreground hover:text-foreground hover:bg-accent"
21545
+ ),
21546
+ title: category.name,
21547
+ children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(IconComponent, { className: "w-5 h-5" })
21548
+ },
21549
+ category.id
21550
+ );
21551
+ }) })
21552
+ ] });
21553
+ };
21554
+
20266
21555
  // ../../components/ui/UEditor/toolbar.tsx
20267
- var import_jsx_runtime79 = require("react/jsx-runtime");
21556
+ var import_jsx_runtime81 = require("react/jsx-runtime");
20268
21557
  function fileToDataUrl2(file) {
20269
21558
  return new Promise((resolve, reject) => {
20270
21559
  const reader = new FileReader();
@@ -20273,8 +21562,8 @@ function fileToDataUrl2(file) {
20273
21562
  reader.readAsDataURL(file);
20274
21563
  });
20275
21564
  }
20276
- var ToolbarButton = import_react45.default.forwardRef(({ onClick, onMouseDown, active, disabled, children, title, className }, ref) => {
20277
- const button = /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21565
+ var ToolbarButton = import_react48.default.forwardRef(({ onClick, onMouseDown, active, disabled, children, title, className }, ref) => {
21566
+ const button = /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20278
21567
  "button",
20279
21568
  {
20280
21569
  ref,
@@ -20297,12 +21586,12 @@ var ToolbarButton = import_react45.default.forwardRef(({ onClick, onMouseDown, a
20297
21586
  }
20298
21587
  );
20299
21588
  if (title) {
20300
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Tooltip, { content: title, placement: "top", delay: { open: 200, close: 0 }, children: button });
21589
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(Tooltip, { content: title, placement: "top", delay: { open: 200, close: 0 }, children: button });
20301
21590
  }
20302
21591
  return button;
20303
21592
  });
20304
21593
  ToolbarButton.displayName = "ToolbarButton";
20305
- var ToolbarDivider = () => /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" });
21594
+ var ToolbarDivider = () => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" });
20306
21595
  var EditorToolbar = ({
20307
21596
  editor,
20308
21597
  variant,
@@ -20311,10 +21600,10 @@ var EditorToolbar = ({
20311
21600
  }) => {
20312
21601
  const t = (0, import_next_intl3.useTranslations)("UEditor");
20313
21602
  const { textColors, highlightColors } = useEditorColors();
20314
- const [showImageInput, setShowImageInput] = (0, import_react45.useState)(false);
20315
- const fileInputRef = (0, import_react45.useRef)(null);
20316
- const [isUploadingImage, setIsUploadingImage] = (0, import_react45.useState)(false);
20317
- const [imageUploadError, setImageUploadError] = (0, import_react45.useState)(null);
21603
+ const [showImageInput, setShowImageInput] = (0, import_react48.useState)(false);
21604
+ const fileInputRef = (0, import_react48.useRef)(null);
21605
+ const [isUploadingImage, setIsUploadingImage] = (0, import_react48.useState)(false);
21606
+ const [imageUploadError, setImageUploadError] = (0, import_react48.useState)(null);
20318
21607
  const insertImageFiles = async (files) => {
20319
21608
  if (files.length === 0) return;
20320
21609
  setIsUploadingImage(true);
@@ -20333,63 +21622,63 @@ var EditorToolbar = ({
20333
21622
  setIsUploadingImage(false);
20334
21623
  };
20335
21624
  if (variant === "minimal") {
20336
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "flex items-center gap-1 p-2 border-b bg-muted/30", children: [
20337
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Bold, { className: "w-4 h-4" }) }),
20338
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Italic, { className: "w-4 h-4" }) }),
20339
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21625
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "flex items-center gap-1 p-2 border-b bg-muted/30", children: [
21626
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Bold, { className: "w-4 h-4" }) }),
21627
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Italic, { className: "w-4 h-4" }) }),
21628
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20340
21629
  ToolbarButton,
20341
21630
  {
20342
21631
  onClick: () => editor.chain().focus().toggleBulletList().run(),
20343
21632
  active: editor.isActive("bulletList"),
20344
21633
  title: t("toolbar.bulletList"),
20345
- children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.List, { className: "w-4 h-4" })
21634
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.List, { className: "w-4 h-4" })
20346
21635
  }
20347
21636
  )
20348
21637
  ] });
20349
21638
  }
20350
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "flex flex-wrap items-center gap-1 p-2 border-b bg-linear-to-r from-muted/30 to-transparent", children: [
20351
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
21639
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "flex flex-wrap items-center gap-1 p-2 border-b bg-linear-to-r from-muted/30 to-transparent", children: [
21640
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
20352
21641
  DropdownMenu,
20353
21642
  {
20354
- trigger: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(ToolbarButton, { onClick: () => {
21643
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
20355
21644
  }, title: t("toolbar.textStyle"), className: "px-2 w-auto gap-1", children: [
20356
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Type, { className: "w-4 h-4" }),
20357
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.ChevronDown, { className: "w-3 h-3" })
21645
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Type, { className: "w-4 h-4" }),
21646
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.ChevronDown, { className: "w-3 h-3" })
20358
21647
  ] }),
20359
21648
  children: [
20360
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21649
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20361
21650
  DropdownMenuItem,
20362
21651
  {
20363
- icon: import_lucide_react41.Type,
21652
+ icon: import_lucide_react43.Type,
20364
21653
  label: t("toolbar.normal"),
20365
21654
  onClick: () => editor.chain().focus().setParagraph().run(),
20366
21655
  active: editor.isActive("paragraph")
20367
21656
  }
20368
21657
  ),
20369
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21658
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20370
21659
  DropdownMenuItem,
20371
21660
  {
20372
- icon: import_lucide_react41.Heading1,
21661
+ icon: import_lucide_react43.Heading1,
20373
21662
  label: t("toolbar.heading1"),
20374
21663
  onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),
20375
21664
  active: editor.isActive("heading", { level: 1 }),
20376
21665
  shortcut: "Ctrl+Alt+1"
20377
21666
  }
20378
21667
  ),
20379
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21668
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20380
21669
  DropdownMenuItem,
20381
21670
  {
20382
- icon: import_lucide_react41.Heading2,
21671
+ icon: import_lucide_react43.Heading2,
20383
21672
  label: t("toolbar.heading2"),
20384
21673
  onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
20385
21674
  active: editor.isActive("heading", { level: 2 }),
20386
21675
  shortcut: "Ctrl+Alt+2"
20387
21676
  }
20388
21677
  ),
20389
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21678
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20390
21679
  DropdownMenuItem,
20391
21680
  {
20392
- icon: import_lucide_react41.Heading3,
21681
+ icon: import_lucide_react43.Heading3,
20393
21682
  label: t("toolbar.heading3"),
20394
21683
  onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
20395
21684
  active: editor.isActive("heading", { level: 3 }),
@@ -20399,30 +21688,30 @@ var EditorToolbar = ({
20399
21688
  ]
20400
21689
  }
20401
21690
  ),
20402
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarDivider, {}),
20403
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Bold, { className: "w-4 h-4" }) }),
20404
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Italic, { className: "w-4 h-4" }) }),
20405
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21691
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
21692
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Bold, { className: "w-4 h-4" }) }),
21693
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Italic, { className: "w-4 h-4" }) }),
21694
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20406
21695
  ToolbarButton,
20407
21696
  {
20408
21697
  onClick: () => editor.chain().focus().toggleUnderline().run(),
20409
21698
  active: editor.isActive("underline"),
20410
21699
  title: t("toolbar.underline"),
20411
- children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Underline, { className: "w-4 h-4" })
21700
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Underline, { className: "w-4 h-4" })
20412
21701
  }
20413
21702
  ),
20414
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Strikethrough, { className: "w-4 h-4" }) }),
20415
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Code, { className: "w-4 h-4" }) }),
20416
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarDivider, {}),
20417
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21703
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Strikethrough, { className: "w-4 h-4" }) }),
21704
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Code, { className: "w-4 h-4" }) }),
21705
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
21706
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20418
21707
  DropdownMenu,
20419
21708
  {
20420
- trigger: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(ToolbarButton, { onClick: () => {
21709
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
20421
21710
  }, title: t("colors.textColor"), children: [
20422
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Palette, { className: "w-4 h-4" }),
20423
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.ChevronDown, { className: "w-3 h-3" })
21711
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Palette, { className: "w-4 h-4" }),
21712
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.ChevronDown, { className: "w-3 h-3" })
20424
21713
  ] }),
20425
- children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21714
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20426
21715
  EditorColorPalette,
20427
21716
  {
20428
21717
  colors: textColors,
@@ -20439,15 +21728,15 @@ var EditorToolbar = ({
20439
21728
  )
20440
21729
  }
20441
21730
  ),
20442
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21731
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20443
21732
  DropdownMenu,
20444
21733
  {
20445
- trigger: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(ToolbarButton, { onClick: () => {
21734
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
20446
21735
  }, active: editor.isActive("highlight"), title: t("colors.highlight"), children: [
20447
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Highlighter, { className: "w-4 h-4" }),
20448
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.ChevronDown, { className: "w-3 h-3" })
21736
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Highlighter, { className: "w-4 h-4" }),
21737
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.ChevronDown, { className: "w-3 h-3" })
20449
21738
  ] }),
20450
- children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21739
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20451
21740
  EditorColorPalette,
20452
21741
  {
20453
21742
  colors: highlightColors,
@@ -20464,47 +21753,63 @@ var EditorToolbar = ({
20464
21753
  )
20465
21754
  }
20466
21755
  ),
20467
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarDivider, {}),
20468
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
21756
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
21757
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20469
21758
  DropdownMenu,
20470
21759
  {
20471
- trigger: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(ToolbarButton, { onClick: () => {
21760
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => {
21761
+ }, title: t("toolbar.emoji"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Smile, { className: "w-4 h-4" }) }),
21762
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
21763
+ EmojiPicker,
21764
+ {
21765
+ onSelect: (emoji) => {
21766
+ editor.chain().focus().insertContent(emoji).run();
21767
+ }
21768
+ }
21769
+ )
21770
+ }
21771
+ ),
21772
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
21773
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
21774
+ DropdownMenu,
21775
+ {
21776
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
20472
21777
  }, title: t("toolbar.alignment"), children: [
20473
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.AlignLeft, { className: "w-4 h-4" }),
20474
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.ChevronDown, { className: "w-3 h-3" })
21778
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.AlignLeft, { className: "w-4 h-4" }),
21779
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.ChevronDown, { className: "w-3 h-3" })
20475
21780
  ] }),
20476
21781
  children: [
20477
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21782
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20478
21783
  DropdownMenuItem,
20479
21784
  {
20480
- icon: import_lucide_react41.AlignLeft,
21785
+ icon: import_lucide_react43.AlignLeft,
20481
21786
  label: t("toolbar.alignLeft"),
20482
21787
  onClick: () => editor.chain().focus().setTextAlign("left").run(),
20483
21788
  active: editor.isActive({ textAlign: "left" })
20484
21789
  }
20485
21790
  ),
20486
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21791
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20487
21792
  DropdownMenuItem,
20488
21793
  {
20489
- icon: import_lucide_react41.AlignCenter,
21794
+ icon: import_lucide_react43.AlignCenter,
20490
21795
  label: t("toolbar.alignCenter"),
20491
21796
  onClick: () => editor.chain().focus().setTextAlign("center").run(),
20492
21797
  active: editor.isActive({ textAlign: "center" })
20493
21798
  }
20494
21799
  ),
20495
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21800
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20496
21801
  DropdownMenuItem,
20497
21802
  {
20498
- icon: import_lucide_react41.AlignRight,
21803
+ icon: import_lucide_react43.AlignRight,
20499
21804
  label: t("toolbar.alignRight"),
20500
21805
  onClick: () => editor.chain().focus().setTextAlign("right").run(),
20501
21806
  active: editor.isActive({ textAlign: "right" })
20502
21807
  }
20503
21808
  ),
20504
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21809
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20505
21810
  DropdownMenuItem,
20506
21811
  {
20507
- icon: import_lucide_react41.AlignJustify,
21812
+ icon: import_lucide_react43.AlignJustify,
20508
21813
  label: t("toolbar.justify"),
20509
21814
  onClick: () => editor.chain().focus().setTextAlign("justify").run(),
20510
21815
  active: editor.isActive({ textAlign: "justify" })
@@ -20513,40 +21818,40 @@ var EditorToolbar = ({
20513
21818
  ]
20514
21819
  }
20515
21820
  ),
20516
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarDivider, {}),
20517
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
21821
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
21822
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
20518
21823
  DropdownMenu,
20519
21824
  {
20520
- trigger: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(ToolbarButton, { onClick: () => {
21825
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
20521
21826
  }, title: t("toolbar.bulletList"), children: [
20522
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.List, { className: "w-4 h-4" }),
20523
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.ChevronDown, { className: "w-3 h-3" })
21827
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.List, { className: "w-4 h-4" }),
21828
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.ChevronDown, { className: "w-3 h-3" })
20524
21829
  ] }),
20525
21830
  children: [
20526
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21831
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20527
21832
  DropdownMenuItem,
20528
21833
  {
20529
- icon: import_lucide_react41.List,
21834
+ icon: import_lucide_react43.List,
20530
21835
  label: t("toolbar.bulletList"),
20531
21836
  onClick: () => editor.chain().focus().toggleBulletList().run(),
20532
21837
  active: editor.isActive("bulletList"),
20533
21838
  shortcut: "Ctrl+Shift+8"
20534
21839
  }
20535
21840
  ),
20536
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21841
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20537
21842
  DropdownMenuItem,
20538
21843
  {
20539
- icon: import_lucide_react41.ListOrdered,
21844
+ icon: import_lucide_react43.ListOrdered,
20540
21845
  label: t("toolbar.orderedList"),
20541
21846
  onClick: () => editor.chain().focus().toggleOrderedList().run(),
20542
21847
  active: editor.isActive("orderedList"),
20543
21848
  shortcut: "Ctrl+Shift+7"
20544
21849
  }
20545
21850
  ),
20546
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21851
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20547
21852
  DropdownMenuItem,
20548
21853
  {
20549
- icon: import_lucide_react41.ListTodo,
21854
+ icon: import_lucide_react43.ListTodo,
20550
21855
  label: t("toolbar.taskList"),
20551
21856
  onClick: () => editor.chain().focus().toggleTaskList().run(),
20552
21857
  active: editor.isActive("taskList"),
@@ -20556,29 +21861,29 @@ var EditorToolbar = ({
20556
21861
  ]
20557
21862
  }
20558
21863
  ),
20559
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
21864
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
20560
21865
  DropdownMenu,
20561
21866
  {
20562
- trigger: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(ToolbarButton, { onClick: () => {
21867
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
20563
21868
  }, title: t("toolbar.quote"), children: [
20564
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Quote, { className: "w-4 h-4" }),
20565
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.ChevronDown, { className: "w-3 h-3" })
21869
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Quote, { className: "w-4 h-4" }),
21870
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.ChevronDown, { className: "w-3 h-3" })
20566
21871
  ] }),
20567
21872
  children: [
20568
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21873
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20569
21874
  DropdownMenuItem,
20570
21875
  {
20571
- icon: import_lucide_react41.Quote,
21876
+ icon: import_lucide_react43.Quote,
20572
21877
  label: t("toolbar.quote"),
20573
21878
  onClick: () => editor.chain().focus().toggleBlockquote().run(),
20574
21879
  active: editor.isActive("blockquote"),
20575
21880
  shortcut: "Ctrl+Shift+B"
20576
21881
  }
20577
21882
  ),
20578
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21883
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20579
21884
  DropdownMenuItem,
20580
21885
  {
20581
- icon: import_lucide_react41.FileCode,
21886
+ icon: import_lucide_react43.FileCode,
20582
21887
  label: t("toolbar.codeBlock"),
20583
21888
  onClick: () => editor.chain().focus().toggleCodeBlock().run(),
20584
21889
  active: editor.isActive("codeBlock"),
@@ -20588,15 +21893,15 @@ var EditorToolbar = ({
20588
21893
  ]
20589
21894
  }
20590
21895
  ),
20591
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21896
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20592
21897
  DropdownMenu,
20593
21898
  {
20594
- trigger: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(ToolbarButton, { onClick: () => {
21899
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
20595
21900
  }, title: t("toolbar.image"), children: [
20596
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Image, { className: "w-4 h-4" }),
20597
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.ChevronDown, { className: "w-3 h-3" })
21901
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Image, { className: "w-4 h-4" }),
21902
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.ChevronDown, { className: "w-3 h-3" })
20598
21903
  ] }),
20599
- children: showImageInput ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21904
+ children: showImageInput ? /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20600
21905
  ImageInput,
20601
21906
  {
20602
21907
  onSubmit: (url, alt) => {
@@ -20605,19 +21910,19 @@ var EditorToolbar = ({
20605
21910
  },
20606
21911
  onCancel: () => setShowImageInput(false)
20607
21912
  }
20608
- ) : /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(import_jsx_runtime79.Fragment, { children: [
20609
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(DropdownMenuItem, { icon: import_lucide_react41.Link, label: t("imageInput.addFromUrl"), onClick: () => setShowImageInput(true) }),
20610
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21913
+ ) : /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
21914
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(DropdownMenuItem, { icon: import_lucide_react43.Link, label: t("imageInput.addFromUrl"), onClick: () => setShowImageInput(true) }),
21915
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20611
21916
  DropdownMenuItem,
20612
21917
  {
20613
- icon: import_lucide_react41.Upload,
21918
+ icon: import_lucide_react43.Upload,
20614
21919
  label: isUploadingImage ? t("imageInput.uploading") : t("imageInput.uploadTab"),
20615
21920
  disabled: isUploadingImage,
20616
21921
  onClick: () => fileInputRef.current?.click()
20617
21922
  }
20618
21923
  ),
20619
- imageUploadError && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(DropdownMenuItem, { label: imageUploadError, disabled: true, destructive: true }),
20620
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21924
+ imageUploadError && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(DropdownMenuItem, { label: imageUploadError, disabled: true, destructive: true }),
21925
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20621
21926
  "input",
20622
21927
  {
20623
21928
  ref: fileInputRef,
@@ -20635,83 +21940,83 @@ var EditorToolbar = ({
20635
21940
  ] })
20636
21941
  }
20637
21942
  ),
20638
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
21943
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
20639
21944
  DropdownMenu,
20640
21945
  {
20641
- trigger: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(ToolbarButton, { onClick: () => {
21946
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
20642
21947
  }, title: t("toolbar.table"), children: [
20643
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Table, { className: "w-4 h-4" }),
20644
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.ChevronDown, { className: "w-3 h-3" })
21948
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Table, { className: "w-4 h-4" }),
21949
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.ChevronDown, { className: "w-3 h-3" })
20645
21950
  ] }),
20646
21951
  children: [
20647
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21952
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20648
21953
  DropdownMenuItem,
20649
21954
  {
20650
- icon: import_lucide_react41.Table,
21955
+ icon: import_lucide_react43.Table,
20651
21956
  label: t("tableMenu.insert3x3"),
20652
21957
  onClick: () => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
20653
21958
  }
20654
21959
  ),
20655
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "my-1 border-t" }),
20656
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21960
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "my-1 border-t" }),
21961
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20657
21962
  DropdownMenuItem,
20658
21963
  {
20659
- icon: import_lucide_react41.ArrowDown,
21964
+ icon: import_lucide_react43.ArrowDown,
20660
21965
  label: t("tableMenu.addColumnBefore"),
20661
21966
  onClick: () => editor.chain().focus().addColumnBefore().run(),
20662
21967
  disabled: !editor.can().addColumnBefore()
20663
21968
  }
20664
21969
  ),
20665
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21970
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20666
21971
  DropdownMenuItem,
20667
21972
  {
20668
- icon: import_lucide_react41.ArrowDown,
21973
+ icon: import_lucide_react43.ArrowDown,
20669
21974
  label: t("tableMenu.addColumnAfter"),
20670
21975
  onClick: () => editor.chain().focus().addColumnAfter().run(),
20671
21976
  disabled: !editor.can().addColumnAfter()
20672
21977
  }
20673
21978
  ),
20674
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21979
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20675
21980
  DropdownMenuItem,
20676
21981
  {
20677
- icon: import_lucide_react41.ArrowRight,
21982
+ icon: import_lucide_react43.ArrowRight,
20678
21983
  label: t("tableMenu.addRowBefore"),
20679
21984
  onClick: () => editor.chain().focus().addRowBefore().run(),
20680
21985
  disabled: !editor.can().addRowBefore()
20681
21986
  }
20682
21987
  ),
20683
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21988
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20684
21989
  DropdownMenuItem,
20685
21990
  {
20686
- icon: import_lucide_react41.ArrowRight,
21991
+ icon: import_lucide_react43.ArrowRight,
20687
21992
  label: t("tableMenu.addRowAfter"),
20688
21993
  onClick: () => editor.chain().focus().addRowAfter().run(),
20689
21994
  disabled: !editor.can().addRowAfter()
20690
21995
  }
20691
21996
  ),
20692
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "my-1 border-t" }),
20693
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
21997
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "my-1 border-t" }),
21998
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20694
21999
  DropdownMenuItem,
20695
22000
  {
20696
- icon: import_lucide_react41.Trash2,
22001
+ icon: import_lucide_react43.Trash2,
20697
22002
  label: t("tableMenu.deleteColumn"),
20698
22003
  onClick: () => editor.chain().focus().deleteColumn().run(),
20699
22004
  disabled: !editor.can().deleteColumn()
20700
22005
  }
20701
22006
  ),
20702
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
22007
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20703
22008
  DropdownMenuItem,
20704
22009
  {
20705
- icon: import_lucide_react41.Trash2,
22010
+ icon: import_lucide_react43.Trash2,
20706
22011
  label: t("tableMenu.deleteRow"),
20707
22012
  onClick: () => editor.chain().focus().deleteRow().run(),
20708
22013
  disabled: !editor.can().deleteRow()
20709
22014
  }
20710
22015
  ),
20711
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
22016
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20712
22017
  DropdownMenuItem,
20713
22018
  {
20714
- icon: import_lucide_react41.Trash2,
22019
+ icon: import_lucide_react43.Trash2,
20715
22020
  label: t("tableMenu.deleteTable"),
20716
22021
  onClick: () => editor.chain().focus().deleteTable().run(),
20717
22022
  disabled: !editor.can().deleteTable()
@@ -20720,105 +22025,105 @@ var EditorToolbar = ({
20720
22025
  ]
20721
22026
  }
20722
22027
  ),
20723
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarDivider, {}),
20724
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
22028
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
22029
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20725
22030
  ToolbarButton,
20726
22031
  {
20727
22032
  onClick: () => editor.chain().focus().toggleSubscript().run(),
20728
22033
  active: editor.isActive("subscript"),
20729
22034
  title: t("toolbar.subscript"),
20730
- children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Subscript, { className: "w-4 h-4" })
22035
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Subscript, { className: "w-4 h-4" })
20731
22036
  }
20732
22037
  ),
20733
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
22038
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
20734
22039
  ToolbarButton,
20735
22040
  {
20736
22041
  onClick: () => editor.chain().focus().toggleSuperscript().run(),
20737
22042
  active: editor.isActive("superscript"),
20738
22043
  title: t("toolbar.superscript"),
20739
- children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Superscript, { className: "w-4 h-4" })
22044
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Superscript, { className: "w-4 h-4" })
20740
22045
  }
20741
22046
  ),
20742
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarDivider, {}),
20743
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().undo().run(), disabled: !editor.can().undo(), title: t("toolbar.undo"), children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Undo, { className: "w-4 h-4" }) }),
20744
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().redo().run(), disabled: !editor.can().redo(), title: t("toolbar.redo"), children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(import_lucide_react41.Redo, { className: "w-4 h-4" }) })
22047
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
22048
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().undo().run(), disabled: !editor.can().undo(), title: t("toolbar.undo"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Undo, { className: "w-4 h-4" }) }),
22049
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().redo().run(), disabled: !editor.can().redo(), title: t("toolbar.redo"), children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Redo, { className: "w-4 h-4" }) })
20745
22050
  ] });
20746
22051
  };
20747
22052
 
20748
22053
  // ../../components/ui/UEditor/menus.tsx
20749
- var import_react46 = require("react");
22054
+ var import_react49 = require("react");
20750
22055
  var import_react_dom9 = require("react-dom");
20751
22056
  var import_next_intl4 = require("next-intl");
20752
- var import_lucide_react42 = require("lucide-react");
20753
- var import_jsx_runtime80 = require("react/jsx-runtime");
22057
+ var import_lucide_react44 = require("lucide-react");
22058
+ var import_jsx_runtime82 = require("react/jsx-runtime");
20754
22059
  var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
20755
22060
  const t = (0, import_next_intl4.useTranslations)("UEditor");
20756
- const [selectedIndex, setSelectedIndex] = (0, import_react46.useState)(0);
20757
- const menuRef = (0, import_react46.useRef)(null);
20758
- const allCommands = (0, import_react46.useMemo)(
22061
+ const [selectedIndex, setSelectedIndex] = (0, import_react49.useState)(0);
22062
+ const menuRef = (0, import_react49.useRef)(null);
22063
+ const allCommands = (0, import_react49.useMemo)(
20759
22064
  () => [
20760
22065
  {
20761
- icon: import_lucide_react42.Type,
22066
+ icon: import_lucide_react44.Type,
20762
22067
  label: t("slashCommand.text"),
20763
22068
  description: t("slashCommand.textDesc"),
20764
22069
  action: () => editor.chain().focus().setParagraph().run()
20765
22070
  },
20766
22071
  {
20767
- icon: import_lucide_react42.Heading1,
22072
+ icon: import_lucide_react44.Heading1,
20768
22073
  label: t("slashCommand.heading1"),
20769
22074
  description: t("slashCommand.heading1Desc"),
20770
22075
  action: () => editor.chain().focus().toggleHeading({ level: 1 }).run()
20771
22076
  },
20772
22077
  {
20773
- icon: import_lucide_react42.Heading2,
22078
+ icon: import_lucide_react44.Heading2,
20774
22079
  label: t("slashCommand.heading2"),
20775
22080
  description: t("slashCommand.heading2Desc"),
20776
22081
  action: () => editor.chain().focus().toggleHeading({ level: 2 }).run()
20777
22082
  },
20778
22083
  {
20779
- icon: import_lucide_react42.Heading3,
22084
+ icon: import_lucide_react44.Heading3,
20780
22085
  label: t("slashCommand.heading3"),
20781
22086
  description: t("slashCommand.heading3Desc"),
20782
22087
  action: () => editor.chain().focus().toggleHeading({ level: 3 }).run()
20783
22088
  },
20784
22089
  {
20785
- icon: import_lucide_react42.List,
22090
+ icon: import_lucide_react44.List,
20786
22091
  label: t("slashCommand.bulletList"),
20787
22092
  description: t("slashCommand.bulletListDesc"),
20788
22093
  action: () => editor.chain().focus().toggleBulletList().run()
20789
22094
  },
20790
22095
  {
20791
- icon: import_lucide_react42.ListOrdered,
22096
+ icon: import_lucide_react44.ListOrdered,
20792
22097
  label: t("slashCommand.orderedList"),
20793
22098
  description: t("slashCommand.orderedListDesc"),
20794
22099
  action: () => editor.chain().focus().toggleOrderedList().run()
20795
22100
  },
20796
22101
  {
20797
- icon: import_lucide_react42.ListTodo,
22102
+ icon: import_lucide_react44.ListTodo,
20798
22103
  label: t("slashCommand.todoList"),
20799
22104
  description: t("slashCommand.todoListDesc"),
20800
22105
  action: () => editor.chain().focus().toggleTaskList().run()
20801
22106
  },
20802
22107
  {
20803
- icon: import_lucide_react42.Quote,
22108
+ icon: import_lucide_react44.Quote,
20804
22109
  label: t("slashCommand.quote"),
20805
22110
  description: t("slashCommand.quoteDesc"),
20806
22111
  action: () => editor.chain().focus().toggleBlockquote().run()
20807
22112
  },
20808
22113
  {
20809
- icon: import_lucide_react42.FileCode,
22114
+ icon: import_lucide_react44.FileCode,
20810
22115
  label: t("slashCommand.codeBlock"),
20811
22116
  description: t("slashCommand.codeBlockDesc"),
20812
22117
  action: () => editor.chain().focus().toggleCodeBlock().run()
20813
22118
  },
20814
22119
  {
20815
- icon: import_lucide_react42.Minus,
22120
+ icon: import_lucide_react44.Minus,
20816
22121
  label: t("slashCommand.divider"),
20817
22122
  description: t("slashCommand.dividerDesc"),
20818
22123
  action: () => editor.chain().focus().setHorizontalRule().run()
20819
22124
  },
20820
22125
  {
20821
- icon: import_lucide_react42.Table,
22126
+ icon: import_lucide_react44.Table,
20822
22127
  label: t("slashCommand.table"),
20823
22128
  description: t("slashCommand.tableDesc"),
20824
22129
  action: () => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
@@ -20826,19 +22131,19 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
20826
22131
  ],
20827
22132
  [editor, t]
20828
22133
  );
20829
- const commands = (0, import_react46.useMemo)(() => {
22134
+ const commands = (0, import_react49.useMemo)(() => {
20830
22135
  if (!filterText) return allCommands;
20831
22136
  const lowerFilter = filterText.toLowerCase();
20832
22137
  return allCommands.filter((cmd) => cmd.label.toLowerCase().includes(lowerFilter) || cmd.description.toLowerCase().includes(lowerFilter));
20833
22138
  }, [allCommands, filterText]);
20834
- (0, import_react46.useEffect)(() => {
22139
+ (0, import_react49.useEffect)(() => {
20835
22140
  setSelectedIndex(0);
20836
22141
  }, [filterText]);
20837
- (0, import_react46.useEffect)(() => {
22142
+ (0, import_react49.useEffect)(() => {
20838
22143
  const selectedElement = menuRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
20839
22144
  selectedElement?.scrollIntoView({ block: "nearest" });
20840
22145
  }, [selectedIndex]);
20841
- const selectCommand = (0, import_react46.useCallback)(
22146
+ const selectCommand = (0, import_react49.useCallback)(
20842
22147
  (index) => {
20843
22148
  const command = commands[index];
20844
22149
  if (command) {
@@ -20848,7 +22153,7 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
20848
22153
  },
20849
22154
  [commands, onClose]
20850
22155
  );
20851
- (0, import_react46.useEffect)(() => {
22156
+ (0, import_react49.useEffect)(() => {
20852
22157
  const handleKeyDown = (e) => {
20853
22158
  if (commands.length === 0) return;
20854
22159
  if (e.key === "ArrowDown") {
@@ -20869,11 +22174,11 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
20869
22174
  return () => document.removeEventListener("keydown", handleKeyDown);
20870
22175
  }, [commands, selectedIndex, selectCommand, onClose]);
20871
22176
  if (commands.length === 0) {
20872
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "w-72 p-4 text-center text-muted-foreground text-sm", children: t("slashCommand.noResults") });
22177
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "w-72 p-4 text-center text-muted-foreground text-sm", children: t("slashCommand.noResults") });
20873
22178
  }
20874
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { ref: menuRef, className: "w-72 max-h-80 overflow-y-auto", children: [
20875
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("slashCommand.basicBlocks") }) }),
20876
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "p-1", children: commands.map((cmd, index) => /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
22179
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { ref: menuRef, className: "w-72 max-h-80 overflow-y-auto", children: [
22180
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("slashCommand.basicBlocks") }) }),
22181
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "p-1", children: commands.map((cmd, index) => /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
20877
22182
  "button",
20878
22183
  {
20879
22184
  type: "button",
@@ -20886,19 +22191,19 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
20886
22191
  selectedIndex === index ? "bg-accent" : "hover:bg-accent/50"
20887
22192
  ),
20888
22193
  children: [
20889
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22194
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
20890
22195
  "div",
20891
22196
  {
20892
22197
  className: cn(
20893
22198
  "flex items-center justify-center w-10 h-10 rounded-lg mr-3 transition-colors",
20894
22199
  selectedIndex === index ? "bg-primary/10" : "bg-muted/50 group-hover:bg-muted"
20895
22200
  ),
20896
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(cmd.icon, { className: cn("w-5 h-5", selectedIndex === index ? "text-primary" : "text-muted-foreground") })
22201
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(cmd.icon, { className: cn("w-5 h-5", selectedIndex === index ? "text-primary" : "text-muted-foreground") })
20897
22202
  }
20898
22203
  ),
20899
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "text-left", children: [
20900
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: cn("text-sm font-medium", selectedIndex === index && "text-primary"), children: cmd.label }),
20901
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "text-xs text-muted-foreground", children: cmd.description })
22204
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "text-left", children: [
22205
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: cn("text-sm font-medium", selectedIndex === index && "text-primary"), children: cmd.label }),
22206
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "text-xs text-muted-foreground", children: cmd.description })
20902
22207
  ] })
20903
22208
  ]
20904
22209
  },
@@ -20908,19 +22213,19 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
20908
22213
  };
20909
22214
  var FloatingMenuContent = ({ editor }) => {
20910
22215
  const t = (0, import_next_intl4.useTranslations)("UEditor");
20911
- const [showCommands, setShowCommands] = (0, import_react46.useState)(false);
22216
+ const [showCommands, setShowCommands] = (0, import_react49.useState)(false);
20912
22217
  if (showCommands) {
20913
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(SlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
22218
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(SlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
20914
22219
  }
20915
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
22220
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
20916
22221
  "button",
20917
22222
  {
20918
22223
  type: "button",
20919
22224
  onClick: () => setShowCommands(true),
20920
22225
  className: "flex items-center gap-1 px-2 py-1.5 rounded-lg hover:bg-accent transition-all group",
20921
22226
  children: [
20922
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Plus, { className: "w-4 h-4 text-muted-foreground group-hover:text-foreground" }),
20923
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "text-sm text-muted-foreground group-hover:text-foreground", children: t("floatingMenu.addBlock") })
22227
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Plus, { className: "w-4 h-4 text-muted-foreground group-hover:text-foreground" }),
22228
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "text-sm text-muted-foreground group-hover:text-foreground", children: t("floatingMenu.addBlock") })
20924
22229
  ]
20925
22230
  }
20926
22231
  );
@@ -20931,12 +22236,12 @@ var BubbleMenuContent = ({
20931
22236
  }) => {
20932
22237
  const t = (0, import_next_intl4.useTranslations)("UEditor");
20933
22238
  const { textColors, highlightColors } = useEditorColors();
20934
- const [showLinkInput, setShowLinkInput] = (0, import_react46.useState)(false);
20935
- const [showEditorColorPalette, setShowEditorColorPalette] = (0, import_react46.useState)(false);
20936
- (0, import_react46.useEffect)(() => {
22239
+ const [showLinkInput, setShowLinkInput] = (0, import_react49.useState)(false);
22240
+ const [showEditorColorPalette, setShowEditorColorPalette] = (0, import_react49.useState)(false);
22241
+ (0, import_react49.useEffect)(() => {
20937
22242
  onKeepOpenChange?.(showLinkInput);
20938
22243
  }, [onKeepOpenChange, showLinkInput]);
20939
- (0, import_react46.useEffect)(() => {
22244
+ (0, import_react49.useEffect)(() => {
20940
22245
  if (!showLinkInput) return;
20941
22246
  const close = () => setShowLinkInput(false);
20942
22247
  editor.on("selectionUpdate", close);
@@ -20947,7 +22252,7 @@ var BubbleMenuContent = ({
20947
22252
  };
20948
22253
  }, [editor, showLinkInput]);
20949
22254
  if (showLinkInput) {
20950
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22255
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
20951
22256
  LinkInput,
20952
22257
  {
20953
22258
  initialUrl: editor.getAttributes("link").href || "",
@@ -20964,8 +22269,8 @@ var BubbleMenuContent = ({
20964
22269
  );
20965
22270
  }
20966
22271
  if (showEditorColorPalette) {
20967
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "w-48", children: [
20968
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22272
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "w-48", children: [
22273
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
20969
22274
  EditorColorPalette,
20970
22275
  {
20971
22276
  colors: textColors,
@@ -20980,8 +22285,8 @@ var BubbleMenuContent = ({
20980
22285
  label: t("colors.textColor")
20981
22286
  }
20982
22287
  ),
20983
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "border-t my-1" }),
20984
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22288
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "border-t my-1" }),
22289
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
20985
22290
  EditorColorPalette,
20986
22291
  {
20987
22292
  colors: highlightColors,
@@ -20996,7 +22301,7 @@ var BubbleMenuContent = ({
20996
22301
  label: t("colors.highlight")
20997
22302
  }
20998
22303
  ),
20999
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "p-2 border-t", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22304
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "p-2 border-t", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21000
22305
  "button",
21001
22306
  {
21002
22307
  type: "button",
@@ -21007,22 +22312,22 @@ var BubbleMenuContent = ({
21007
22312
  ) })
21008
22313
  ] });
21009
22314
  }
21010
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex items-center gap-0.5 p-1", children: [
21011
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Bold, { className: "w-4 h-4" }) }),
21012
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Italic, { className: "w-4 h-4" }) }),
21013
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22315
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex items-center gap-0.5 p-1", children: [
22316
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Bold, { className: "w-4 h-4" }) }),
22317
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Italic, { className: "w-4 h-4" }) }),
22318
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21014
22319
  ToolbarButton,
21015
22320
  {
21016
22321
  onClick: () => editor.chain().focus().toggleUnderline().run(),
21017
22322
  active: editor.isActive("underline"),
21018
22323
  title: t("toolbar.underline"),
21019
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Underline, { className: "w-4 h-4" })
22324
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Underline, { className: "w-4 h-4" })
21020
22325
  }
21021
22326
  ),
21022
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Strikethrough, { className: "w-4 h-4" }) }),
21023
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Code, { className: "w-4 h-4" }) }),
21024
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" }),
21025
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22327
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Strikethrough, { className: "w-4 h-4" }) }),
22328
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Code, { className: "w-4 h-4" }) }),
22329
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" }),
22330
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21026
22331
  ToolbarButton,
21027
22332
  {
21028
22333
  onMouseDown: () => {
@@ -21033,41 +22338,41 @@ var BubbleMenuContent = ({
21033
22338
  },
21034
22339
  active: editor.isActive("link"),
21035
22340
  title: t("toolbar.link"),
21036
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Link, { className: "w-4 h-4" })
22341
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Link, { className: "w-4 h-4" })
21037
22342
  }
21038
22343
  ),
21039
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(ToolbarButton, { onClick: () => setShowEditorColorPalette(true), title: t("colors.textColor"), children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Palette, { className: "w-4 h-4" }) }),
21040
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" }),
21041
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22344
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(ToolbarButton, { onClick: () => setShowEditorColorPalette(true), title: t("colors.textColor"), children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Palette, { className: "w-4 h-4" }) }),
22345
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" }),
22346
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21042
22347
  ToolbarButton,
21043
22348
  {
21044
22349
  onClick: () => editor.chain().focus().toggleSubscript().run(),
21045
22350
  active: editor.isActive("subscript"),
21046
22351
  title: t("toolbar.subscript"),
21047
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Subscript, { className: "w-4 h-4" })
22352
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Subscript, { className: "w-4 h-4" })
21048
22353
  }
21049
22354
  ),
21050
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22355
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21051
22356
  ToolbarButton,
21052
22357
  {
21053
22358
  onClick: () => editor.chain().focus().toggleSuperscript().run(),
21054
22359
  active: editor.isActive("superscript"),
21055
22360
  title: t("toolbar.superscript"),
21056
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react42.Superscript, { className: "w-4 h-4" })
22361
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Superscript, { className: "w-4 h-4" })
21057
22362
  }
21058
22363
  )
21059
22364
  ] });
21060
22365
  };
21061
22366
  var CustomBubbleMenu = ({ editor }) => {
21062
- const [isVisible, setIsVisible] = (0, import_react46.useState)(false);
21063
- const [position, setPosition] = (0, import_react46.useState)({ top: 0, left: 0 });
21064
- const menuRef = (0, import_react46.useRef)(null);
21065
- const keepOpenRef = (0, import_react46.useRef)(false);
21066
- const setKeepOpen = (0, import_react46.useCallback)((next) => {
22367
+ const [isVisible, setIsVisible] = (0, import_react49.useState)(false);
22368
+ const [position, setPosition] = (0, import_react49.useState)({ top: 0, left: 0 });
22369
+ const menuRef = (0, import_react49.useRef)(null);
22370
+ const keepOpenRef = (0, import_react49.useRef)(false);
22371
+ const setKeepOpen = (0, import_react49.useCallback)((next) => {
21067
22372
  keepOpenRef.current = next;
21068
22373
  if (next) setIsVisible(true);
21069
22374
  }, []);
21070
- (0, import_react46.useEffect)(() => {
22375
+ (0, import_react49.useEffect)(() => {
21071
22376
  const updatePosition = () => {
21072
22377
  const { state, view } = editor;
21073
22378
  const { from, to, empty } = state.selection;
@@ -21096,7 +22401,7 @@ var CustomBubbleMenu = ({ editor }) => {
21096
22401
  }, [editor]);
21097
22402
  if (!isVisible) return null;
21098
22403
  return (0, import_react_dom9.createPortal)(
21099
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22404
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21100
22405
  "div",
21101
22406
  {
21102
22407
  ref: menuRef,
@@ -21107,7 +22412,7 @@ var CustomBubbleMenu = ({ editor }) => {
21107
22412
  transform: "translate(-50%, -100%)"
21108
22413
  },
21109
22414
  onMouseDown: (e) => e.preventDefault(),
21110
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22415
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21111
22416
  BubbleMenuContent,
21112
22417
  {
21113
22418
  editor,
@@ -21120,9 +22425,9 @@ var CustomBubbleMenu = ({ editor }) => {
21120
22425
  );
21121
22426
  };
21122
22427
  var CustomFloatingMenu = ({ editor }) => {
21123
- const [isVisible, setIsVisible] = (0, import_react46.useState)(false);
21124
- const [position, setPosition] = (0, import_react46.useState)({ top: 0, left: 0 });
21125
- (0, import_react46.useEffect)(() => {
22428
+ const [isVisible, setIsVisible] = (0, import_react49.useState)(false);
22429
+ const [position, setPosition] = (0, import_react49.useState)({ top: 0, left: 0 });
22430
+ (0, import_react49.useEffect)(() => {
21126
22431
  const updatePosition = () => {
21127
22432
  const { state, view } = editor;
21128
22433
  const { $from, empty } = state.selection;
@@ -21149,7 +22454,7 @@ var CustomFloatingMenu = ({ editor }) => {
21149
22454
  }, [editor]);
21150
22455
  if (!isVisible) return null;
21151
22456
  return (0, import_react_dom9.createPortal)(
21152
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
22457
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21153
22458
  "div",
21154
22459
  {
21155
22460
  className: "fixed z-50 rounded-2xl border border-border bg-card text-card-foreground shadow-lg backdrop-blur-sm overflow-hidden animate-in fade-in-0 slide-in-from-bottom-2",
@@ -21159,7 +22464,7 @@ var CustomFloatingMenu = ({ editor }) => {
21159
22464
  transform: "translate(-50%, -100%)"
21160
22465
  },
21161
22466
  onMouseDown: (e) => e.preventDefault(),
21162
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(FloatingMenuContent, { editor })
22467
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(FloatingMenuContent, { editor })
21163
22468
  }
21164
22469
  ),
21165
22470
  document.body
@@ -21168,25 +22473,25 @@ var CustomFloatingMenu = ({ editor }) => {
21168
22473
 
21169
22474
  // ../../components/ui/UEditor/CharacterCount.tsx
21170
22475
  var import_next_intl5 = require("next-intl");
21171
- var import_jsx_runtime81 = require("react/jsx-runtime");
22476
+ var import_jsx_runtime83 = require("react/jsx-runtime");
21172
22477
  var CharacterCountDisplay = ({ editor, maxCharacters }) => {
21173
22478
  const t = (0, import_next_intl5.useTranslations)("UEditor");
21174
22479
  const storage = editor.storage;
21175
22480
  const characterCount = storage.characterCount?.characters?.() ?? 0;
21176
22481
  const wordCount = storage.characterCount?.words?.() ?? 0;
21177
22482
  const percentage = maxCharacters ? Math.round(characterCount / maxCharacters * 100) : 0;
21178
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "flex items-center gap-3 px-3 py-2 text-xs text-muted-foreground border-t bg-muted/20", children: [
21179
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
22483
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex items-center gap-3 px-3 py-2 text-xs text-muted-foreground border-t bg-muted/20", children: [
22484
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { children: [
21180
22485
  wordCount,
21181
22486
  " ",
21182
22487
  t("words")
21183
22488
  ] }),
21184
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
22489
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { children: [
21185
22490
  characterCount,
21186
22491
  " ",
21187
22492
  t("characters")
21188
22493
  ] }),
21189
- maxCharacters && /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: cn(percentage > 90 && "text-destructive", percentage > 100 && "font-bold"), children: [
22494
+ maxCharacters && /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: cn(percentage > 90 && "text-destructive", percentage > 100 && "font-bold"), children: [
21190
22495
  characterCount,
21191
22496
  "/",
21192
22497
  maxCharacters
@@ -21195,7 +22500,7 @@ var CharacterCountDisplay = ({ editor, maxCharacters }) => {
21195
22500
  };
21196
22501
 
21197
22502
  // ../../components/ui/UEditor/UEditor.tsx
21198
- var import_jsx_runtime82 = require("react/jsx-runtime");
22503
+ var import_jsx_runtime84 = require("react/jsx-runtime");
21199
22504
  var UEditor = ({
21200
22505
  content = "",
21201
22506
  onChange,
@@ -21218,11 +22523,11 @@ var UEditor = ({
21218
22523
  }) => {
21219
22524
  const t = (0, import_next_intl6.useTranslations)("UEditor");
21220
22525
  const effectivePlaceholder = placeholder ?? t("placeholder");
21221
- const extensions = (0, import_react47.useMemo)(
22526
+ const extensions = (0, import_react50.useMemo)(
21222
22527
  () => buildUEditorExtensions({ placeholder: effectivePlaceholder, maxCharacters, uploadImage, imageInsertMode, editable }),
21223
22528
  [effectivePlaceholder, maxCharacters, uploadImage, imageInsertMode, editable]
21224
22529
  );
21225
- const editor = (0, import_react48.useEditor)({
22530
+ const editor = (0, import_react51.useEditor)({
21226
22531
  immediatelyRender: false,
21227
22532
  extensions,
21228
22533
  content,
@@ -21327,7 +22632,7 @@ var UEditor = ({
21327
22632
  onJsonChange?.(editor2.getJSON());
21328
22633
  }
21329
22634
  });
21330
- (0, import_react47.useEffect)(() => {
22635
+ (0, import_react50.useEffect)(() => {
21331
22636
  if (editor && content !== editor.getHTML()) {
21332
22637
  if (editor.isEmpty && content) {
21333
22638
  editor.commands.setContent(content);
@@ -21335,7 +22640,7 @@ var UEditor = ({
21335
22640
  }
21336
22641
  }, [content, editor]);
21337
22642
  if (!editor) {
21338
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
22643
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
21339
22644
  "div",
21340
22645
  {
21341
22646
  className: cn("w-full rounded-lg border bg-background flex items-center justify-center text-muted-foreground", className),
@@ -21344,7 +22649,7 @@ var UEditor = ({
21344
22649
  }
21345
22650
  );
21346
22651
  }
21347
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
22652
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
21348
22653
  "div",
21349
22654
  {
21350
22655
  className: cn(
@@ -21356,11 +22661,11 @@ var UEditor = ({
21356
22661
  className
21357
22662
  ),
21358
22663
  children: [
21359
- editable && showToolbar && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(EditorToolbar, { editor, variant, uploadImage, imageInsertMode }),
21360
- editable && showBubbleMenu && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(CustomBubbleMenu, { editor }),
21361
- editable && showFloatingMenu && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(CustomFloatingMenu, { editor }),
21362
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
21363
- import_react48.EditorContent,
22664
+ editable && showToolbar && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(EditorToolbar, { editor, variant, uploadImage, imageInsertMode }),
22665
+ editable && showBubbleMenu && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(CustomBubbleMenu, { editor }),
22666
+ editable && showFloatingMenu && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(CustomFloatingMenu, { editor }),
22667
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
22668
+ import_react51.EditorContent,
21364
22669
  {
21365
22670
  editor,
21366
22671
  className: "flex-1 overflow-y-auto",
@@ -21370,7 +22675,7 @@ var UEditor = ({
21370
22675
  }
21371
22676
  }
21372
22677
  ),
21373
- showCharacterCount && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(CharacterCountDisplay, { editor, maxCharacters })
22678
+ showCharacterCount && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(CharacterCountDisplay, { editor, maxCharacters })
21374
22679
  ]
21375
22680
  }
21376
22681
  );