@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 +1609 -304
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -2
- package/dist/index.d.ts +24 -2
- package/dist/index.js +1555 -249
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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) :
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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 }) ??
|
|
9402
|
-
|
|
9403
|
-
|
|
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
|
-
}, [
|
|
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
|
|
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
|
|
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
|
-
|
|
10182
|
-
|
|
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:
|
|
10220
|
-
}, [
|
|
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:
|
|
10408
|
+
out.push({ label: formatCreateBoundaryLabel(boundary, { kind: "end", boundaryIdx: idx }), value: idx });
|
|
10226
10409
|
}
|
|
10227
10410
|
return out;
|
|
10228
|
-
}, [createStartIdx, range.end,
|
|
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-
|
|
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
|
-
"
|
|
10631
|
-
"shadow-sm hover:shadow-md
|
|
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 =
|
|
10769
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
19608
|
+
var import_react50 = require("react");
|
|
19415
19609
|
var import_next_intl6 = require("next-intl");
|
|
19416
|
-
var
|
|
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/
|
|
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
|
|
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,
|
|
19797
|
-
const imgRef = (0,
|
|
19798
|
-
const [isHovered, setIsHovered] = (0,
|
|
19799
|
-
const [isResizing, setIsResizing] = (0,
|
|
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,
|
|
19804
|
-
(0,
|
|
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,
|
|
19899
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
21083
|
+
return ["img", (0, import_core4.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes2)];
|
|
19978
21084
|
},
|
|
19979
21085
|
addNodeView() {
|
|
19980
|
-
return (0,
|
|
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
|
|
21203
|
+
var import_react48 = __toESM(require("react"), 1);
|
|
20097
21204
|
var import_next_intl3 = require("next-intl");
|
|
20098
|
-
var
|
|
21205
|
+
var import_lucide_react43 = require("lucide-react");
|
|
20099
21206
|
|
|
20100
21207
|
// ../../components/ui/UEditor/colors.tsx
|
|
20101
|
-
var
|
|
21208
|
+
var import_react45 = require("react");
|
|
20102
21209
|
var import_next_intl = require("next-intl");
|
|
20103
|
-
var
|
|
20104
|
-
var
|
|
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,
|
|
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,
|
|
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,
|
|
20142
|
-
/* @__PURE__ */ (0,
|
|
20143
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
20157
|
-
c.color === "inherit" && /* @__PURE__ */ (0,
|
|
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
|
|
21272
|
+
var import_react46 = require("react");
|
|
20166
21273
|
var import_next_intl2 = require("next-intl");
|
|
20167
|
-
var
|
|
20168
|
-
var
|
|
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,
|
|
20183
|
-
const inputRef = (0,
|
|
20184
|
-
(0,
|
|
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,
|
|
20194
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
20206
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
20212
|
-
const [alt, setAlt] = (0,
|
|
20213
|
-
const inputRef = (0,
|
|
20214
|
-
(0,
|
|
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,
|
|
20224
|
-
/* @__PURE__ */ (0,
|
|
20225
|
-
/* @__PURE__ */ (0,
|
|
20226
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
20239
|
-
/* @__PURE__ */ (0,
|
|
20240
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
20252
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
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 =
|
|
20277
|
-
const button = /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
20315
|
-
const fileInputRef = (0,
|
|
20316
|
-
const [isUploadingImage, setIsUploadingImage] = (0,
|
|
20317
|
-
const [imageUploadError, setImageUploadError] = (0,
|
|
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,
|
|
20337
|
-
/* @__PURE__ */ (0,
|
|
20338
|
-
/* @__PURE__ */ (0,
|
|
20339
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
20351
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
20357
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
21649
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20361
21650
|
DropdownMenuItem,
|
|
20362
21651
|
{
|
|
20363
|
-
icon:
|
|
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,
|
|
21658
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20370
21659
|
DropdownMenuItem,
|
|
20371
21660
|
{
|
|
20372
|
-
icon:
|
|
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,
|
|
21668
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20380
21669
|
DropdownMenuItem,
|
|
20381
21670
|
{
|
|
20382
|
-
icon:
|
|
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,
|
|
21678
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20390
21679
|
DropdownMenuItem,
|
|
20391
21680
|
{
|
|
20392
|
-
icon:
|
|
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,
|
|
20403
|
-
/* @__PURE__ */ (0,
|
|
20404
|
-
/* @__PURE__ */ (0,
|
|
20405
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
21700
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Underline, { className: "w-4 h-4" })
|
|
20412
21701
|
}
|
|
20413
21702
|
),
|
|
20414
|
-
/* @__PURE__ */ (0,
|
|
20415
|
-
/* @__PURE__ */ (0,
|
|
20416
|
-
/* @__PURE__ */ (0,
|
|
20417
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
21709
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
|
|
20421
21710
|
}, title: t("colors.textColor"), children: [
|
|
20422
|
-
/* @__PURE__ */ (0,
|
|
20423
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
21731
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20443
21732
|
DropdownMenu,
|
|
20444
21733
|
{
|
|
20445
|
-
trigger: /* @__PURE__ */ (0,
|
|
21734
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
|
|
20446
21735
|
}, active: editor.isActive("highlight"), title: t("colors.highlight"), children: [
|
|
20447
|
-
/* @__PURE__ */ (0,
|
|
20448
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
20468
|
-
/* @__PURE__ */ (0,
|
|
21756
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
|
|
21757
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20469
21758
|
DropdownMenu,
|
|
20470
21759
|
{
|
|
20471
|
-
trigger: /* @__PURE__ */ (0,
|
|
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,
|
|
20474
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
21782
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20478
21783
|
DropdownMenuItem,
|
|
20479
21784
|
{
|
|
20480
|
-
icon:
|
|
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,
|
|
21791
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20487
21792
|
DropdownMenuItem,
|
|
20488
21793
|
{
|
|
20489
|
-
icon:
|
|
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,
|
|
21800
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20496
21801
|
DropdownMenuItem,
|
|
20497
21802
|
{
|
|
20498
|
-
icon:
|
|
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,
|
|
21809
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20505
21810
|
DropdownMenuItem,
|
|
20506
21811
|
{
|
|
20507
|
-
icon:
|
|
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,
|
|
20517
|
-
/* @__PURE__ */ (0,
|
|
21821
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(ToolbarDivider, {}),
|
|
21822
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
|
|
20518
21823
|
DropdownMenu,
|
|
20519
21824
|
{
|
|
20520
|
-
trigger: /* @__PURE__ */ (0,
|
|
21825
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
|
|
20521
21826
|
}, title: t("toolbar.bulletList"), children: [
|
|
20522
|
-
/* @__PURE__ */ (0,
|
|
20523
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
21831
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20527
21832
|
DropdownMenuItem,
|
|
20528
21833
|
{
|
|
20529
|
-
icon:
|
|
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,
|
|
21841
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20537
21842
|
DropdownMenuItem,
|
|
20538
21843
|
{
|
|
20539
|
-
icon:
|
|
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,
|
|
21851
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20547
21852
|
DropdownMenuItem,
|
|
20548
21853
|
{
|
|
20549
|
-
icon:
|
|
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,
|
|
21864
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
|
|
20560
21865
|
DropdownMenu,
|
|
20561
21866
|
{
|
|
20562
|
-
trigger: /* @__PURE__ */ (0,
|
|
21867
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
|
|
20563
21868
|
}, title: t("toolbar.quote"), children: [
|
|
20564
|
-
/* @__PURE__ */ (0,
|
|
20565
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
21873
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20569
21874
|
DropdownMenuItem,
|
|
20570
21875
|
{
|
|
20571
|
-
icon:
|
|
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,
|
|
21883
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20579
21884
|
DropdownMenuItem,
|
|
20580
21885
|
{
|
|
20581
|
-
icon:
|
|
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,
|
|
21896
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20592
21897
|
DropdownMenu,
|
|
20593
21898
|
{
|
|
20594
|
-
trigger: /* @__PURE__ */ (0,
|
|
21899
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
|
|
20595
21900
|
}, title: t("toolbar.image"), children: [
|
|
20596
|
-
/* @__PURE__ */ (0,
|
|
20597
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
20609
|
-
/* @__PURE__ */ (0,
|
|
20610
|
-
/* @__PURE__ */ (0,
|
|
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:
|
|
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,
|
|
20620
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
21943
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
|
|
20639
21944
|
DropdownMenu,
|
|
20640
21945
|
{
|
|
20641
|
-
trigger: /* @__PURE__ */ (0,
|
|
21946
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(ToolbarButton, { onClick: () => {
|
|
20642
21947
|
}, title: t("toolbar.table"), children: [
|
|
20643
|
-
/* @__PURE__ */ (0,
|
|
20644
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
21952
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20648
21953
|
DropdownMenuItem,
|
|
20649
21954
|
{
|
|
20650
|
-
icon:
|
|
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,
|
|
20656
|
-
/* @__PURE__ */ (0,
|
|
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:
|
|
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,
|
|
21970
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20666
21971
|
DropdownMenuItem,
|
|
20667
21972
|
{
|
|
20668
|
-
icon:
|
|
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,
|
|
21979
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20675
21980
|
DropdownMenuItem,
|
|
20676
21981
|
{
|
|
20677
|
-
icon:
|
|
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,
|
|
21988
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20684
21989
|
DropdownMenuItem,
|
|
20685
21990
|
{
|
|
20686
|
-
icon:
|
|
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,
|
|
20693
|
-
/* @__PURE__ */ (0,
|
|
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:
|
|
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,
|
|
22007
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20703
22008
|
DropdownMenuItem,
|
|
20704
22009
|
{
|
|
20705
|
-
icon:
|
|
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,
|
|
22016
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
20712
22017
|
DropdownMenuItem,
|
|
20713
22018
|
{
|
|
20714
|
-
icon:
|
|
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,
|
|
20724
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
22035
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Subscript, { className: "w-4 h-4" })
|
|
20731
22036
|
}
|
|
20732
22037
|
),
|
|
20733
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
22044
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_lucide_react43.Superscript, { className: "w-4 h-4" })
|
|
20740
22045
|
}
|
|
20741
22046
|
),
|
|
20742
|
-
/* @__PURE__ */ (0,
|
|
20743
|
-
/* @__PURE__ */ (0,
|
|
20744
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
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
|
|
20753
|
-
var
|
|
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,
|
|
20757
|
-
const menuRef = (0,
|
|
20758
|
-
const allCommands = (0,
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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,
|
|
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,
|
|
22139
|
+
(0, import_react49.useEffect)(() => {
|
|
20835
22140
|
setSelectedIndex(0);
|
|
20836
22141
|
}, [filterText]);
|
|
20837
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
20875
|
-
/* @__PURE__ */ (0,
|
|
20876
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
20900
|
-
/* @__PURE__ */ (0,
|
|
20901
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
22216
|
+
const [showCommands, setShowCommands] = (0, import_react49.useState)(false);
|
|
20912
22217
|
if (showCommands) {
|
|
20913
|
-
return /* @__PURE__ */ (0,
|
|
22218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(SlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
|
|
20914
22219
|
}
|
|
20915
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
20923
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
20935
|
-
const [showEditorColorPalette, setShowEditorColorPalette] = (0,
|
|
20936
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
20968
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
20984
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
21011
|
-
/* @__PURE__ */ (0,
|
|
21012
|
-
/* @__PURE__ */ (0,
|
|
21013
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
22324
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Underline, { className: "w-4 h-4" })
|
|
21020
22325
|
}
|
|
21021
22326
|
),
|
|
21022
|
-
/* @__PURE__ */ (0,
|
|
21023
|
-
/* @__PURE__ */ (0,
|
|
21024
|
-
/* @__PURE__ */ (0,
|
|
21025
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
22341
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Link, { className: "w-4 h-4" })
|
|
21037
22342
|
}
|
|
21038
22343
|
),
|
|
21039
|
-
/* @__PURE__ */ (0,
|
|
21040
|
-
/* @__PURE__ */ (0,
|
|
21041
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
22352
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react44.Subscript, { className: "w-4 h-4" })
|
|
21048
22353
|
}
|
|
21049
22354
|
),
|
|
21050
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
21063
|
-
const [position, setPosition] = (0,
|
|
21064
|
-
const menuRef = (0,
|
|
21065
|
-
const keepOpenRef = (0,
|
|
21066
|
-
const setKeepOpen = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
21124
|
-
const [position, setPosition] = (0,
|
|
21125
|
-
(0,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
21179
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
22489
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { children: [
|
|
21185
22490
|
characterCount,
|
|
21186
22491
|
" ",
|
|
21187
22492
|
t("characters")
|
|
21188
22493
|
] }),
|
|
21189
|
-
maxCharacters && /* @__PURE__ */ (0,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
21360
|
-
editable && showBubbleMenu && /* @__PURE__ */ (0,
|
|
21361
|
-
editable && showFloatingMenu && /* @__PURE__ */ (0,
|
|
21362
|
-
/* @__PURE__ */ (0,
|
|
21363
|
-
|
|
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,
|
|
22678
|
+
showCharacterCount && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(CharacterCountDisplay, { editor, maxCharacters })
|
|
21374
22679
|
]
|
|
21375
22680
|
}
|
|
21376
22681
|
);
|