@bagelink/vue 0.0.1262 → 0.0.1268

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/components/AddressSearch.vue.d.ts +6 -0
  2. package/dist/components/AddressSearch.vue.d.ts.map +1 -1
  3. package/dist/components/DropDown.vue.d.ts +51 -48
  4. package/dist/components/DropDown.vue.d.ts.map +1 -1
  5. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  6. package/dist/components/form/inputs/DateInput.vue.d.ts +4 -1
  7. package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
  8. package/dist/components/form/inputs/PasswordInput.vue.d.ts.map +1 -1
  9. package/dist/components/form/inputs/RadioGroup.vue.d.ts +1 -1
  10. package/dist/components/form/inputs/RichText/composables/useCommands.d.ts.map +1 -1
  11. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts +31 -23
  12. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts.map +1 -1
  13. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts +2 -1
  14. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts.map +1 -1
  15. package/dist/components/form/inputs/RichText/config.d.ts +2 -1
  16. package/dist/components/form/inputs/RichText/config.d.ts.map +1 -1
  17. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  18. package/dist/components/form/inputs/RichText/utils/commands.d.ts +1 -0
  19. package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
  20. package/dist/components/form/inputs/RichText/utils/media.d.ts +5 -3
  21. package/dist/components/form/inputs/RichText/utils/media.d.ts.map +1 -1
  22. package/dist/components/form/inputs/RichText/utils/selection.d.ts.map +1 -1
  23. package/dist/components/form/inputs/SelectInput.vue.d.ts +12 -0
  24. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  25. package/dist/components/form/inputs/TelInput.vue.d.ts +8 -2
  26. package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
  27. package/dist/editor-7QC0nG_c.js +4 -0
  28. package/dist/editor-CpMNx6Eo.cjs +4 -0
  29. package/dist/index.cjs +1327 -756
  30. package/dist/index.mjs +1327 -756
  31. package/dist/style.css +90 -83
  32. package/package.json +1 -1
  33. package/src/components/DataTable/DataTable.vue +1 -1
  34. package/src/components/Dropdown.vue +5 -2
  35. package/src/components/form/FieldArray.vue +3 -0
  36. package/src/components/form/inputs/DateInput.vue +341 -162
  37. package/src/components/form/inputs/PasswordInput.vue +5 -1
  38. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +2 -2
  39. package/src/components/form/inputs/RichText/composables/useCommands.ts +53 -97
  40. package/src/components/form/inputs/RichText/composables/useEditor.ts +377 -270
  41. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +124 -58
  42. package/src/components/form/inputs/RichText/config.ts +27 -3
  43. package/src/components/form/inputs/RichText/editor.css +29 -0
  44. package/src/components/form/inputs/RichText/index.vue +129 -55
  45. package/src/components/form/inputs/RichText/richTextTypes.d.ts +35 -49
  46. package/src/components/form/inputs/RichText/utils/commands.ts +181 -0
  47. package/src/components/form/inputs/RichText/utils/media.ts +64 -3
  48. package/src/components/form/inputs/RichText/utils/selection.ts +40 -5
package/dist/index.cjs CHANGED
@@ -11470,7 +11470,7 @@ const _sfc_main$X = /* @__PURE__ */ vue.defineComponent({
11470
11470
  emits: /* @__PURE__ */ vue.mergeModels(["update:selectedItems", "orderBy", "select", "lastItemVisible"], ["update:loading", "update:itemHeight", "update:selectedItems"]),
11471
11471
  setup(__props, { emit: __emit }) {
11472
11472
  vue.useCssVars((_ctx) => ({
11473
- "1ab0cc24": vue.unref(computedItemHeight)
11473
+ "40bb5b9a": vue.unref(computedItemHeight)
11474
11474
  }));
11475
11475
  const props2 = __props;
11476
11476
  const emit2 = __emit;
@@ -11654,7 +11654,7 @@ const _sfc_main$X = /* @__PURE__ */ vue.defineComponent({
11654
11654
  };
11655
11655
  }
11656
11656
  });
11657
- const DataTable = /* @__PURE__ */ _export_sfc(_sfc_main$X, [["__scopeId", "data-v-8e14fc71"]]);
11657
+ const DataTable = /* @__PURE__ */ _export_sfc(_sfc_main$X, [["__scopeId", "data-v-89f6838b"]]);
11658
11658
  function useDraggable(options = {}) {
11659
11659
  const isDragging = vue.ref(false);
11660
11660
  const dragElement = vue.ref(null);
@@ -14764,7 +14764,9 @@ const _sfc_main$V = /* @__PURE__ */ vue.defineComponent({
14764
14764
  round: { type: Boolean },
14765
14765
  placement: {},
14766
14766
  noAutoFocus: { type: Boolean },
14767
- positioningDisabled: { type: Boolean }
14767
+ positioningDisabled: { type: Boolean },
14768
+ autoHide: { type: Boolean },
14769
+ triggers: {}
14768
14770
  }, {
14769
14771
  "shown": {
14770
14772
  type: Boolean,
@@ -14797,6 +14799,8 @@ const _sfc_main$V = /* @__PURE__ */ vue.defineComponent({
14797
14799
  disabled: _ctx.disabled,
14798
14800
  noAutoFocus: _ctx.noAutoFocus,
14799
14801
  placement: _ctx.placement,
14802
+ autoHide: _ctx.autoHide,
14803
+ triggers: _ctx.triggers,
14800
14804
  onHide: _cache[1] || (_cache[1] = ($event) => emit2("hide")),
14801
14805
  onShow: _cache[2] || (_cache[2] = ($event) => emit2("show"))
14802
14806
  }, {
@@ -14823,7 +14827,7 @@ const _sfc_main$V = /* @__PURE__ */ vue.defineComponent({
14823
14827
  ])
14824
14828
  ]),
14825
14829
  _: 3
14826
- }, 8, ["shown", "disabled", "noAutoFocus", "placement"]);
14830
+ }, 8, ["shown", "disabled", "noAutoFocus", "placement", "autoHide", "triggers"]);
14827
14831
  };
14828
14832
  }
14829
14833
  });
@@ -15771,33 +15775,31 @@ const _hoisted_3$o = {
15771
15775
  key: 0,
15772
15776
  class: "required"
15773
15777
  };
15774
- const _hoisted_4$g = { class: "date-picker-container" };
15775
- const _hoisted_5$f = { class: "flex gap-075 p-05 m_flex-wrap calendar-container justify-content-center h-100p" };
15776
- const _hoisted_6$c = { class: "calendar-section m_border-none pe-05 m_p-0" };
15777
- const _hoisted_7$9 = { class: "flex space-between pb-1" };
15778
- const _hoisted_8$6 = { class: "flex gap-05" };
15779
- const _hoisted_9$5 = { class: "month-year" };
15780
- const _hoisted_10$5 = {
15778
+ const _hoisted_4$g = { class: "calendar-section m_border-none pe-05 m_p-0" };
15779
+ const _hoisted_5$f = { class: "flex space-between pb-1" };
15780
+ const _hoisted_6$c = { class: "flex gap-05" };
15781
+ const _hoisted_7$9 = { class: "month-year" };
15782
+ const _hoisted_8$6 = {
15781
15783
  key: 0,
15782
15784
  class: "calendar-grid grid gap-025"
15783
15785
  };
15784
- const _hoisted_11$5 = ["disabled", "onClick"];
15785
- const _hoisted_12$5 = {
15786
+ const _hoisted_9$5 = ["disabled", "onClick"];
15787
+ const _hoisted_10$5 = {
15786
15788
  key: 1,
15787
15789
  class: "month-grid grid gap-05 p-05"
15788
15790
  };
15789
- const _hoisted_13$4 = ["disabled", "onClick"];
15790
- const _hoisted_14$4 = {
15791
+ const _hoisted_11$5 = ["disabled", "onClick"];
15792
+ const _hoisted_12$5 = {
15791
15793
  key: 2,
15792
15794
  class: "year-grid grid gap-05 p-0"
15793
15795
  };
15794
- const _hoisted_15$4 = ["disabled", "onClick"];
15795
- const _hoisted_16$4 = {
15796
+ const _hoisted_13$4 = ["disabled", "onClick"];
15797
+ const _hoisted_14$4 = {
15796
15798
  key: 0,
15797
15799
  class: "time-picker border-start flex column gap-1 w-120px"
15798
15800
  };
15799
- const _hoisted_17$4 = { class: "flex gap-025" };
15800
- const _hoisted_18$2 = { class: "txt-center opacity-6 txt14" };
15801
+ const _hoisted_15$4 = { class: "flex gap-025" };
15802
+ const _hoisted_16$4 = { class: "txt-center opacity-6 txt14" };
15801
15803
  const _sfc_main$M = /* @__PURE__ */ vue.defineComponent({
15802
15804
  __name: "DateInput",
15803
15805
  props: {
@@ -15811,7 +15813,7 @@ const _sfc_main$M = /* @__PURE__ */ vue.defineComponent({
15811
15813
  max: {},
15812
15814
  timezone: { default: "UTC" },
15813
15815
  mode: { default: "day" },
15814
- firstDayOfWeek: { default: WEEK_START_DAY.MONDAY },
15816
+ firstDayOfWeek: { default: WEEK_START_DAY.SUNDAY },
15815
15817
  locale: { default: "" },
15816
15818
  center: { type: Boolean }
15817
15819
  },
@@ -15819,235 +15821,392 @@ const _sfc_main$M = /* @__PURE__ */ vue.defineComponent({
15819
15821
  setup(__props, { emit: __emit }) {
15820
15822
  const props2 = __props;
15821
15823
  const emit2 = __emit;
15822
- let isOpen = vue.ref(false);
15823
- let currentMonth = vue.ref(/* @__PURE__ */ new Date());
15824
- let currentView = vue.ref("days");
15824
+ const isOpen = vue.ref(false);
15825
+ const currentMonth = vue.ref(/* @__PURE__ */ new Date());
15826
+ const currentView = vue.ref("days");
15825
15827
  const time = new Time(props2.firstDayOfWeek, props2.locale);
15826
- function formatDisplayDate(date2) {
15827
- if (!date2) return "";
15828
- const dateObj = typeof date2 === "string" ? new Date(date2) : date2;
15829
- if (props2.enableTime) {
15830
- return dateObj.toLocaleString(props2.locale || void 0, {
15828
+ function useFormatting() {
15829
+ const formatDisplayDate = (date2) => {
15830
+ if (!date2) return "";
15831
+ const dateObj = typeof date2 === "string" ? new Date(date2) : date2;
15832
+ const options = {
15831
15833
  year: "numeric",
15832
15834
  month: "short",
15833
15835
  day: "numeric",
15834
- hour: "2-digit",
15835
- minute: "2-digit",
15836
+ ...props2.enableTime && {
15837
+ hour: "2-digit",
15838
+ minute: "2-digit"
15839
+ },
15836
15840
  timeZone: props2.timezone
15837
- });
15838
- }
15839
- return dateObj.toLocaleString(props2.locale || void 0, {
15840
- year: "numeric",
15841
- month: "short",
15842
- day: "numeric",
15843
- timeZone: props2.timezone
15844
- });
15841
+ };
15842
+ return dateObj.toLocaleString(props2.locale || void 0, options);
15843
+ };
15844
+ const formatDate = (date2) => {
15845
+ if (!date2) return "";
15846
+ const dateObj = typeof date2 === "string" ? new Date(date2) : date2;
15847
+ return props2.enableTime ? dateObj.toISOString().slice(0, 16) : dateObj.toISOString().split("T")[0];
15848
+ };
15849
+ const parseUserInput = (input) => {
15850
+ const date2 = new Date(input);
15851
+ if (!Number.isNaN(date2.getTime())) {
15852
+ return date2;
15853
+ }
15854
+ const parts = input.split(/[/.-]/);
15855
+ if (parts.length === 3) {
15856
+ const [day, month, year] = parts.map((p2) => Number.parseInt(p2, 10));
15857
+ if (!Number.isNaN(day) && !Number.isNaN(month) && !Number.isNaN(year)) {
15858
+ const date22 = new Date(year, month - 1, day);
15859
+ if (date22.getFullYear() === year && date22.getMonth() === month - 1 && date22.getDate() === day) {
15860
+ return date22;
15861
+ }
15862
+ }
15863
+ }
15864
+ return null;
15865
+ };
15866
+ return {
15867
+ formatDisplayDate,
15868
+ formatDate,
15869
+ parseUserInput
15870
+ };
15845
15871
  }
15846
- function formatDate(date2) {
15847
- if (!date2) return "";
15848
- const dateObj = typeof date2 === "string" ? new Date(date2) : date2;
15849
- return props2.enableTime ? dateObj.toISOString().slice(0, 16) : dateObj.toISOString().split("T")[0];
15872
+ function useDateValidation() {
15873
+ const isDateDisabled2 = (date2) => {
15874
+ if (!date2) return true;
15875
+ const minDate = props2.min ? new Date(props2.min) : null;
15876
+ const maxDate = props2.max ? new Date(props2.max) : null;
15877
+ if (minDate && date2 < minDate) return true;
15878
+ if (maxDate && date2 > maxDate) return true;
15879
+ return false;
15880
+ };
15881
+ const isYearDisabled2 = (year) => {
15882
+ const minDate = props2.min ? new Date(props2.min) : null;
15883
+ const maxDate = props2.max ? new Date(props2.max) : null;
15884
+ if (minDate && year < minDate.getFullYear()) return true;
15885
+ if (maxDate && year > maxDate.getFullYear()) return true;
15886
+ return false;
15887
+ };
15888
+ return {
15889
+ isDateDisabled: isDateDisabled2,
15890
+ isYearDisabled: isYearDisabled2
15891
+ };
15850
15892
  }
15851
- const formattedDisplayValue = vue.computed(() => formatDisplayDate(props2.modelValue));
15852
- const formattedMin = vue.computed(() => formatDate(props2.min));
15853
- const formattedMax = vue.computed(() => formatDate(props2.max));
15854
- const selectedDate = vue.computed(() => {
15855
- if (!props2.modelValue) return null;
15856
- return typeof props2.modelValue === "string" ? new Date(props2.modelValue) : props2.modelValue;
15857
- });
15858
- const currentMonthDays = vue.computed(() => {
15859
- const year = currentMonth.value.getFullYear();
15860
- const month = currentMonth.value.getMonth();
15861
- return time.getCalendarMonthSplitInWeeks(year, month).flat();
15862
- });
15863
- const currentMonthValue = vue.computed(() => ({
15864
- month: currentMonth.value.getMonth(),
15865
- year: currentMonth.value.getFullYear(),
15866
- formatted: {
15867
- month: time.getLocalizedNameOfMonth(currentMonth.value, "long"),
15868
- year: time.getLocalizedDateString(currentMonth.value).split("/").pop()
15869
- // Get just the year part
15870
- }
15871
- }));
15872
- const months = vue.computed(() => Array.from({ length: 12 }, (_2, i2) => {
15873
- const date2 = new Date(currentMonthValue.value.year, i2, 1);
15893
+ function useDateState() {
15894
+ const { formatDisplayDate, formatDate } = useFormatting();
15895
+ const formattedDisplayValue2 = vue.computed(() => formatDisplayDate(props2.modelValue));
15896
+ const formattedMin2 = vue.computed(() => formatDate(props2.min));
15897
+ const formattedMax2 = vue.computed(() => formatDate(props2.max));
15898
+ const selectedDate2 = vue.computed(() => {
15899
+ if (!props2.modelValue) return null;
15900
+ return typeof props2.modelValue === "string" ? new Date(props2.modelValue) : props2.modelValue;
15901
+ });
15874
15902
  return {
15875
- name: time.getLocalizedNameOfMonth(date2, "short"),
15876
- value: i2,
15877
- disabled: isDateDisabled(date2)
15903
+ formattedDisplayValue: formattedDisplayValue2,
15904
+ formattedMin: formattedMin2,
15905
+ formattedMax: formattedMax2,
15906
+ selectedDate: selectedDate2
15878
15907
  };
15879
- }));
15880
- const years = vue.computed(() => {
15881
- const startYear = currentMonthValue.value.year - 10;
15882
- return Array.from({ length: 21 }, (_2, i2) => ({
15883
- value: startYear + i2,
15884
- disabled: isYearDisabled(startYear + i2)
15908
+ }
15909
+ const { isDateDisabled, isYearDisabled } = useDateValidation();
15910
+ const { formattedDisplayValue, formattedMin, formattedMax, selectedDate } = useDateState();
15911
+ function useCalendarView() {
15912
+ const currentMonthDays2 = vue.computed(() => {
15913
+ const year = currentMonth.value.getFullYear();
15914
+ const month = currentMonth.value.getMonth();
15915
+ return time.getCalendarMonthSplitInWeeks(year, month).flat();
15916
+ });
15917
+ const currentMonthValue2 = vue.computed(() => ({
15918
+ month: currentMonth.value.getMonth(),
15919
+ year: currentMonth.value.getFullYear(),
15920
+ formatted: {
15921
+ month: time.getLocalizedNameOfMonth(currentMonth.value, "long"),
15922
+ year: time.getLocalizedDateString(currentMonth.value).split("/").pop()
15923
+ }
15885
15924
  }));
15886
- });
15887
- const weekDays = vue.computed(() => {
15888
- const weekStart = /* @__PURE__ */ new Date();
15889
- weekStart.setDate(weekStart.getDate() - weekStart.getDay() + (props2.firstDayOfWeek === WEEK_START_DAY.MONDAY ? 1 : 0));
15890
- return Array.from({ length: 7 }, (_2, i2) => {
15891
- const day = new Date(weekStart);
15892
- day.setDate(weekStart.getDate() + i2);
15893
- return time.getLocalizedNameOfWeekday(day, "short");
15925
+ const months2 = vue.computed(() => Array.from({ length: 12 }, (_2, i2) => {
15926
+ const date2 = new Date(currentMonthValue2.value.year, i2, 1);
15927
+ return {
15928
+ name: time.getLocalizedNameOfMonth(date2, "short"),
15929
+ value: i2,
15930
+ disabled: isDateDisabled(date2)
15931
+ };
15932
+ }));
15933
+ const years2 = vue.computed(() => {
15934
+ const startYear = currentMonthValue2.value.year - 10;
15935
+ return Array.from({ length: 21 }, (_2, i2) => ({
15936
+ value: startYear + i2,
15937
+ disabled: isYearDisabled(startYear + i2)
15938
+ }));
15894
15939
  });
15895
- });
15896
- function isDateDisabled(date2) {
15897
- if (!date2) return true;
15898
- const minDate = props2.min ? new Date(props2.min) : null;
15899
- const maxDate = props2.max ? new Date(props2.max) : null;
15900
- if (minDate && date2 < minDate) return true;
15901
- if (maxDate && date2 > maxDate) return true;
15902
- return false;
15903
- }
15904
- function isYearDisabled(year) {
15905
- const minDate = props2.min ? new Date(props2.min) : null;
15906
- const maxDate = props2.max ? new Date(props2.max) : null;
15907
- if (minDate && year < minDate.getFullYear()) return true;
15908
- if (maxDate && year > maxDate.getFullYear()) return true;
15909
- return false;
15910
- }
15911
- function selectMonth(monthIndex) {
15912
- currentMonth.value = new Date(currentMonth.value.getFullYear(), monthIndex, 1);
15913
- currentView.value = "days";
15914
- }
15915
- function selectYear(year) {
15916
- currentMonth.value = new Date(year, currentMonth.value.getMonth(), 1);
15917
- currentView.value = "months";
15918
- }
15919
- function previousMonth() {
15920
- currentMonth.value = new Date(currentMonth.value.getFullYear(), currentMonth.value.getMonth() - 1, 1);
15940
+ const weekDays2 = vue.computed(() => {
15941
+ const weekStart = /* @__PURE__ */ new Date();
15942
+ weekStart.setDate(weekStart.getDate() - weekStart.getDay() + (props2.firstDayOfWeek === WEEK_START_DAY.MONDAY ? 1 : 0));
15943
+ return Array.from({ length: 7 }, (_2, i2) => {
15944
+ const day = new Date(weekStart);
15945
+ day.setDate(weekStart.getDate() + i2);
15946
+ return time.getLocalizedNameOfWeekday(day, "short");
15947
+ });
15948
+ });
15949
+ const isSelected2 = (date2) => {
15950
+ if (!date2 || !selectedDate.value) return false;
15951
+ return date2.getFullYear() === selectedDate.value.getFullYear() && date2.getMonth() === selectedDate.value.getMonth() && date2.getDate() === selectedDate.value.getDate();
15952
+ };
15953
+ const isToday2 = (date2) => {
15954
+ if (!date2) return false;
15955
+ return time.dateIsToday(date2);
15956
+ };
15957
+ const isNotInMonth2 = (date2) => {
15958
+ return time.isTrailingOrLeadingDate(date2, currentMonth.value.getMonth());
15959
+ };
15960
+ return {
15961
+ currentMonthDays: currentMonthDays2,
15962
+ currentMonthValue: currentMonthValue2,
15963
+ months: months2,
15964
+ years: years2,
15965
+ weekDays: weekDays2,
15966
+ isSelected: isSelected2,
15967
+ isToday: isToday2,
15968
+ isNotInMonth: isNotInMonth2
15969
+ };
15921
15970
  }
15922
- function nextMonth() {
15923
- currentMonth.value = new Date(currentMonth.value.getFullYear(), currentMonth.value.getMonth() + 1, 1);
15971
+ function useNavigation() {
15972
+ const selectMonth2 = (monthIndex) => {
15973
+ currentMonth.value = new Date(currentMonth.value.getFullYear(), monthIndex, 1);
15974
+ currentView.value = "days";
15975
+ };
15976
+ const selectYear2 = (year) => {
15977
+ currentMonth.value = new Date(year, currentMonth.value.getMonth(), 1);
15978
+ currentView.value = "months";
15979
+ };
15980
+ const previousMonth2 = () => {
15981
+ currentMonth.value = new Date(currentMonth.value.getFullYear(), currentMonth.value.getMonth() - 1, 1);
15982
+ };
15983
+ const nextMonth2 = () => {
15984
+ currentMonth.value = new Date(currentMonth.value.getFullYear(), currentMonth.value.getMonth() + 1, 1);
15985
+ };
15986
+ const previousYear2 = () => {
15987
+ const offset2 = currentView.value === "months" ? 1 : 21;
15988
+ currentMonth.value = new Date(currentMonth.value.getFullYear() - offset2, currentMonth.value.getMonth(), 1);
15989
+ };
15990
+ const nextYear2 = () => {
15991
+ const offset2 = currentView.value === "months" ? 1 : 21;
15992
+ currentMonth.value = new Date(currentMonth.value.getFullYear() + offset2, currentMonth.value.getMonth(), 1);
15993
+ };
15994
+ return {
15995
+ selectMonth: selectMonth2,
15996
+ selectYear: selectYear2,
15997
+ previousMonth: previousMonth2,
15998
+ nextMonth: nextMonth2,
15999
+ previousYear: previousYear2,
16000
+ nextYear: nextYear2
16001
+ };
15924
16002
  }
15925
- function previousYear() {
15926
- const offset2 = currentView.value === "months" ? 1 : 21;
15927
- currentMonth.value = new Date(currentMonth.value.getFullYear() - offset2, currentMonth.value.getMonth(), 1);
16003
+ function useTimeHandling() {
16004
+ const hours2 = vue.computed(() => {
16005
+ var _a2;
16006
+ return ((_a2 = selectedDate.value) == null ? void 0 : _a2.getHours()) ?? 0;
16007
+ });
16008
+ const minutes2 = vue.computed(() => {
16009
+ var _a2;
16010
+ return ((_a2 = selectedDate.value) == null ? void 0 : _a2.getMinutes()) ?? 0;
16011
+ });
16012
+ const handleHourInput2 = (value) => {
16013
+ if (!selectedDate.value) return;
16014
+ const newDate = new Date(selectedDate.value);
16015
+ newDate.setHours(value);
16016
+ emit2("update:modelValue", newDate.toISOString());
16017
+ };
16018
+ const handleMinuteInput2 = (value) => {
16019
+ if (!selectedDate.value) return;
16020
+ const newDate = new Date(selectedDate.value);
16021
+ newDate.setMinutes(value);
16022
+ emit2("update:modelValue", newDate.toISOString());
16023
+ };
16024
+ const timezoneDisplay2 = vue.computed(() => {
16025
+ if (!props2.enableTime) return "";
16026
+ try {
16027
+ return (/* @__PURE__ */ new Date()).toLocaleString("en-US", {
16028
+ timeZoneName: "short",
16029
+ timeZone: props2.timezone
16030
+ }).split(" ").pop();
16031
+ } catch {
16032
+ return "UTC";
16033
+ }
16034
+ });
16035
+ return {
16036
+ hours: hours2,
16037
+ minutes: minutes2,
16038
+ handleHourInput: handleHourInput2,
16039
+ handleMinuteInput: handleMinuteInput2,
16040
+ timezoneDisplay: timezoneDisplay2
16041
+ };
15928
16042
  }
15929
- function nextYear() {
15930
- const offset2 = currentView.value === "months" ? 1 : 21;
15931
- currentMonth.value = new Date(currentMonth.value.getFullYear() + offset2, currentMonth.value.getMonth(), 1);
16043
+ function useInputHandling() {
16044
+ const { parseUserInput } = useFormatting();
16045
+ const inputValue2 = vue.ref("");
16046
+ const handleInput2 = (event) => {
16047
+ const input = event.target;
16048
+ inputValue2.value = input.value;
16049
+ const date2 = parseUserInput(input.value);
16050
+ if (date2) {
16051
+ if (props2.enableTime) {
16052
+ emit2("update:modelValue", date2.toISOString());
16053
+ } else {
16054
+ const utcDate = new Date(Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate()));
16055
+ emit2("update:modelValue", utcDate.toISOString().split("T")[0]);
16056
+ }
16057
+ }
16058
+ };
16059
+ const handleFocus2 = (e) => {
16060
+ e.preventDefault();
16061
+ e.stopPropagation();
16062
+ isOpen.value = true;
16063
+ };
16064
+ const handleClick2 = (e) => {
16065
+ e.preventDefault();
16066
+ e.stopPropagation();
16067
+ };
16068
+ const handleKeydown2 = (event) => {
16069
+ if (event.key === "Escape") {
16070
+ isOpen.value = false;
16071
+ } else if (event.key === "Enter" && inputValue2.value) {
16072
+ const date2 = parseUserInput(inputValue2.value);
16073
+ if (date2) {
16074
+ if (props2.enableTime) {
16075
+ emit2("update:modelValue", date2.toISOString());
16076
+ } else {
16077
+ const utcDate = new Date(Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate()));
16078
+ emit2("update:modelValue", utcDate.toISOString().split("T")[0]);
16079
+ }
16080
+ isOpen.value = false;
16081
+ }
16082
+ }
16083
+ };
16084
+ return {
16085
+ inputValue: inputValue2,
16086
+ handleInput: handleInput2,
16087
+ handleFocus: handleFocus2,
16088
+ handleClick: handleClick2,
16089
+ handleKeydown: handleKeydown2
16090
+ };
15932
16091
  }
16092
+ const { inputValue, handleInput, handleFocus, handleClick, handleKeydown } = useInputHandling();
16093
+ const { currentMonthDays, currentMonthValue, months, years, weekDays, isSelected, isToday, isNotInMonth } = useCalendarView();
16094
+ const { selectMonth, selectYear, previousMonth, nextMonth, previousYear, nextYear } = useNavigation();
16095
+ const { hours, minutes, handleHourInput, handleMinuteInput, timezoneDisplay } = useTimeHandling();
15933
16096
  function selectDate(date2) {
15934
16097
  var _a2, _b;
15935
16098
  if (!date2 || !props2.editMode) return;
16099
+ const tzOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
15936
16100
  const newDate = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
15937
16101
  if (props2.enableTime) {
15938
16102
  const currentHours = ((_a2 = selectedDate.value) == null ? void 0 : _a2.getHours()) ?? (/* @__PURE__ */ new Date()).getHours();
15939
16103
  const currentMinutes = ((_b = selectedDate.value) == null ? void 0 : _b.getMinutes()) ?? (/* @__PURE__ */ new Date()).getMinutes();
15940
16104
  newDate.setHours(currentHours);
15941
16105
  newDate.setMinutes(currentMinutes);
16106
+ if (props2.timezone === "UTC") {
16107
+ newDate.setMinutes(newDate.getMinutes() + tzOffset);
16108
+ }
15942
16109
  emit2("update:modelValue", newDate.toISOString());
15943
16110
  } else {
15944
- newDate.setUTCHours(0, 0, 0, 0);
15945
- emit2("update:modelValue", newDate.toISOString().split("T")[0]);
16111
+ const utcDate = new Date(Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate()));
16112
+ emit2("update:modelValue", utcDate.toISOString().split("T")[0]);
15946
16113
  isOpen.value = false;
15947
16114
  }
15948
16115
  }
15949
- const hours = vue.computed(() => {
15950
- var _a2;
15951
- return ((_a2 = selectedDate.value) == null ? void 0 : _a2.getHours()) ?? 0;
15952
- });
15953
- const minutes = vue.computed(() => {
15954
- var _a2;
15955
- return ((_a2 = selectedDate.value) == null ? void 0 : _a2.getMinutes()) ?? 0;
15956
- });
15957
- function handleHourInput(value) {
15958
- if (!selectedDate.value) return;
15959
- const newDate = new Date(selectedDate.value);
15960
- newDate.setHours(value);
15961
- emit2("update:modelValue", newDate.toISOString());
15962
- }
15963
- function handleMinuteInput(value) {
15964
- if (!selectedDate.value) return;
15965
- const newDate = new Date(selectedDate.value);
15966
- newDate.setMinutes(value);
15967
- emit2("update:modelValue", newDate.toISOString());
15968
- }
15969
- function isSelected(date2) {
15970
- if (!date2 || !selectedDate.value) return false;
15971
- return date2.toISOString().split("T")[0] === selectedDate.value.toISOString().split("T")[0];
15972
- }
15973
- function isToday(date2) {
15974
- if (!date2) return false;
15975
- return time.dateIsToday(date2);
15976
- }
15977
- const timezoneDisplay = vue.computed(() => {
15978
- if (!props2.enableTime) return "";
15979
- try {
15980
- return (/* @__PURE__ */ new Date()).toLocaleString("en-US", {
15981
- timeZoneName: "short",
15982
- timeZone: props2.timezone
15983
- }).split(" ").pop();
15984
- } catch {
15985
- return "UTC";
15986
- }
16116
+ const datePickerRef = vue.ref(null);
16117
+ const calendarRef = vue.ref(null);
16118
+ vue.onMounted(() => {
16119
+ const handleDocumentClick = (e) => {
16120
+ var _a2, _b;
16121
+ const target = e.target;
16122
+ if (!((_a2 = datePickerRef.value) == null ? void 0 : _a2.contains(target)) && !((_b = calendarRef.value) == null ? void 0 : _b.contains(target))) {
16123
+ isOpen.value = false;
16124
+ }
16125
+ };
16126
+ document.addEventListener("click", handleDocumentClick);
16127
+ vue.onBeforeUnmount(() => {
16128
+ document.removeEventListener("click", handleDocumentClick);
16129
+ });
15987
16130
  });
15988
- function isNotInMonth(date2) {
15989
- return time.isTrailingOrLeadingDate(date2, currentMonth.value.getMonth());
15990
- }
15991
16131
  return (_ctx, _cache) => {
15992
16132
  return vue.openBlock(), vue.createElementBlock("div", {
15993
16133
  class: vue.normalizeClass(["bagel-input", { small: _ctx.small }]),
15994
- title: _ctx.label
16134
+ title: _ctx.label,
16135
+ onFocusin: _cache[6] || (_cache[6] = //@ts-ignore
16136
+ (...args) => vue.unref(handleFocus) && vue.unref(handleFocus)(...args))
15995
16137
  }, [
15996
16138
  _ctx.label ? (vue.openBlock(), vue.createElementBlock("label", _hoisted_2$t, [
15997
16139
  vue.createTextVNode(vue.toDisplayString(_ctx.label) + " ", 1),
15998
16140
  _ctx.required ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_3$o, "*")) : vue.createCommentVNode("", true)
15999
16141
  ])) : vue.createCommentVNode("", true),
16000
16142
  vue.createVNode(vue.unref(_sfc_main$V), {
16001
- shown: vue.unref(isOpen),
16143
+ shown: isOpen.value,
16002
16144
  placement: "bottom-start",
16003
- onApplyShow: _cache[4] || (_cache[4] = ($event) => vue.isRef(isOpen) ? isOpen.value = true : isOpen = true),
16004
- onApplyHide: _cache[5] || (_cache[5] = ($event) => vue.isRef(isOpen) ? isOpen.value = false : isOpen = false)
16145
+ autoHide: false,
16146
+ triggers: ["click"]
16005
16147
  }, {
16006
16148
  trigger: vue.withCtx(() => [
16007
- vue.createElementVNode("div", _hoisted_4$g, [
16149
+ vue.createElementVNode("div", {
16150
+ ref_key: "datePickerRef",
16151
+ ref: datePickerRef,
16152
+ class: "date-picker-container",
16153
+ onMousedown: _cache[0] || (_cache[0] = vue.withModifiers(() => {
16154
+ }, ["stop"])),
16155
+ onClick: _cache[1] || (_cache[1] = vue.withModifiers(() => {
16156
+ }, ["stop"]))
16157
+ }, [
16008
16158
  vue.createVNode(vue.unref(TextInput), {
16009
- modelValue: formattedDisplayValue.value,
16159
+ modelValue: vue.unref(formattedDisplayValue),
16010
16160
  icon: "calendar",
16011
- min: formattedMin.value,
16012
- max: formattedMax.value,
16161
+ min: vue.unref(formattedMin),
16162
+ max: vue.unref(formattedMax),
16013
16163
  required: _ctx.required,
16014
16164
  disabled: !_ctx.editMode,
16015
16165
  class: vue.normalizeClass(["date-input", {
16016
16166
  "txt-center": _ctx.center
16017
16167
  }]),
16018
- readonly: "",
16019
- onClick: _cache[0] || (_cache[0] = ($event) => vue.isRef(isOpen) ? isOpen.value = true : isOpen = true)
16020
- }, null, 8, ["modelValue", "min", "max", "required", "disabled", "class"])
16021
- ])
16168
+ readonly: false,
16169
+ onInput: vue.unref(handleInput),
16170
+ onFocus: vue.unref(handleFocus),
16171
+ onClick: vue.unref(handleClick),
16172
+ onKeydown: vue.unref(handleKeydown)
16173
+ }, null, 8, ["modelValue", "min", "max", "required", "disabled", "class", "onInput", "onFocus", "onClick", "onKeydown"])
16174
+ ], 544)
16022
16175
  ]),
16023
16176
  default: vue.withCtx(() => [
16024
- vue.createElementVNode("div", _hoisted_5$f, [
16025
- vue.createElementVNode("div", _hoisted_6$c, [
16026
- vue.createElementVNode("div", _hoisted_7$9, [
16027
- vue.unref(currentView) === "days" ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
16177
+ vue.createElementVNode("div", {
16178
+ ref_key: "calendarRef",
16179
+ ref: calendarRef,
16180
+ class: "ltr flex gap-075 p-05 m_flex-wrap calendar-container justify-content-center h-100p",
16181
+ onClick: _cache[5] || (_cache[5] = vue.withModifiers(() => {
16182
+ }, ["stop"]))
16183
+ }, [
16184
+ vue.createElementVNode("div", _hoisted_4$g, [
16185
+ vue.createElementVNode("div", _hoisted_5$f, [
16186
+ currentView.value === "days" ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
16028
16187
  vue.createVNode(vue.unref(Btn), {
16029
16188
  flat: "",
16030
16189
  icon: "chevron_left",
16031
- onClick: previousMonth
16032
- }),
16033
- vue.createElementVNode("div", _hoisted_8$6, [
16190
+ onClick: vue.unref(previousMonth)
16191
+ }, null, 8, ["onClick"]),
16192
+ vue.createElementVNode("div", _hoisted_6$c, [
16034
16193
  vue.createVNode(vue.unref(Btn), {
16035
16194
  flat: "",
16036
16195
  class: "month-btn",
16037
- onClick: _cache[1] || (_cache[1] = ($event) => vue.isRef(currentView) ? currentView.value = "months" : currentView = "months")
16196
+ onClick: _cache[2] || (_cache[2] = ($event) => currentView.value = "months")
16038
16197
  }, {
16039
16198
  default: vue.withCtx(() => [
16040
- vue.createTextVNode(vue.toDisplayString(currentMonthValue.value.formatted.month), 1)
16199
+ vue.createTextVNode(vue.toDisplayString(vue.unref(currentMonthValue).formatted.month), 1)
16041
16200
  ]),
16042
16201
  _: 1
16043
16202
  }),
16044
16203
  vue.createVNode(vue.unref(Btn), {
16045
16204
  flat: "",
16046
16205
  class: "year-btn",
16047
- onClick: _cache[2] || (_cache[2] = ($event) => vue.isRef(currentView) ? currentView.value = "years" : currentView = "years")
16206
+ onClick: _cache[3] || (_cache[3] = ($event) => currentView.value = "years")
16048
16207
  }, {
16049
16208
  default: vue.withCtx(() => [
16050
- vue.createTextVNode(vue.toDisplayString(currentMonthValue.value.formatted.year), 1)
16209
+ vue.createTextVNode(vue.toDisplayString(vue.unref(currentMonthValue).formatted.year), 1)
16051
16210
  ]),
16052
16211
  _: 1
16053
16212
  })
@@ -16055,114 +16214,114 @@ const _sfc_main$M = /* @__PURE__ */ vue.defineComponent({
16055
16214
  vue.createVNode(vue.unref(Btn), {
16056
16215
  flat: "",
16057
16216
  icon: "chevron_right",
16058
- onClick: nextMonth
16059
- })
16217
+ onClick: vue.unref(nextMonth)
16218
+ }, null, 8, ["onClick"])
16060
16219
  ], 64)) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
16061
16220
  vue.createVNode(vue.unref(Btn), {
16062
16221
  flat: "",
16063
16222
  icon: "chevron_left",
16064
- onClick: previousYear
16065
- }),
16066
- vue.createElementVNode("span", _hoisted_9$5, vue.toDisplayString(currentMonthValue.value.formatted.year), 1),
16223
+ onClick: vue.unref(previousYear)
16224
+ }, null, 8, ["onClick"]),
16225
+ vue.createElementVNode("span", _hoisted_7$9, vue.toDisplayString(vue.unref(currentMonthValue).formatted.year), 1),
16067
16226
  vue.createVNode(vue.unref(Btn), {
16068
16227
  flat: "",
16069
16228
  icon: "chevron_right",
16070
- onClick: nextYear
16071
- })
16229
+ onClick: vue.unref(nextYear)
16230
+ }, null, 8, ["onClick"])
16072
16231
  ], 64))
16073
16232
  ]),
16074
- vue.unref(currentView) === "days" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_10$5, [
16075
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(weekDays.value, (day) => {
16233
+ currentView.value === "days" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_8$6, [
16234
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(weekDays), (day) => {
16076
16235
  return vue.openBlock(), vue.createElementBlock("div", {
16077
16236
  key: day,
16078
16237
  class: "txt-center txt-12 opacity-6"
16079
16238
  }, vue.toDisplayString(day), 1);
16080
16239
  }), 128)),
16081
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(currentMonthDays.value, (date2) => {
16240
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(currentMonthDays), (date2) => {
16082
16241
  return vue.openBlock(), vue.createElementBlock("button", {
16083
16242
  key: date2 == null ? void 0 : date2.toISOString(),
16084
16243
  type: "button",
16085
16244
  class: vue.normalizeClass(["day aspect-ratio-1 flex align-items-center justify-content-center pointer round txt14 p-0", {
16086
- "selected": isSelected(date2),
16087
- "today": isToday(date2),
16088
- "disabled": isDateDisabled(date2),
16089
- "not-in-month": isNotInMonth(date2)
16245
+ "selected": vue.unref(isSelected)(date2),
16246
+ "today": vue.unref(isToday)(date2),
16247
+ "disabled": vue.unref(isDateDisabled)(date2),
16248
+ "not-in-month": vue.unref(isNotInMonth)(date2)
16090
16249
  }]),
16091
- disabled: isDateDisabled(date2),
16250
+ disabled: vue.unref(isDateDisabled)(date2),
16092
16251
  onClick: ($event) => selectDate(date2)
16093
- }, vue.toDisplayString(date2 == null ? void 0 : date2.getDate()), 11, _hoisted_11$5);
16252
+ }, vue.toDisplayString(date2 == null ? void 0 : date2.getDate()), 11, _hoisted_9$5);
16094
16253
  }), 128))
16095
- ])) : vue.unref(currentView) === "months" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_12$5, [
16096
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(months.value, (month) => {
16254
+ ])) : currentView.value === "months" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_10$5, [
16255
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(months), (month) => {
16097
16256
  return vue.openBlock(), vue.createElementBlock("button", {
16098
16257
  key: month.value,
16099
16258
  class: vue.normalizeClass(["month-item flex align-items-center justify-content-center pointer rounded p-05 txt14 border-none", {
16100
- selected: month.value === currentMonthValue.value.month,
16259
+ selected: month.value === vue.unref(currentMonthValue).month,
16101
16260
  disabled: month.disabled
16102
16261
  }]),
16103
16262
  disabled: month.disabled,
16104
- onClick: ($event) => selectMonth(month.value)
16105
- }, vue.toDisplayString(month.name), 11, _hoisted_13$4);
16263
+ onClick: ($event) => vue.unref(selectMonth)(month.value)
16264
+ }, vue.toDisplayString(month.name), 11, _hoisted_11$5);
16106
16265
  }), 128))
16107
- ])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_14$4, [
16108
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(years.value, (year) => {
16266
+ ])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_12$5, [
16267
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(years), (year) => {
16109
16268
  return vue.openBlock(), vue.createElementBlock("button", {
16110
16269
  key: year.value,
16111
16270
  class: vue.normalizeClass(["year-item flex align-items-center justify-content-center pointer rounded p-05 txt14 border-none", {
16112
- selected: year.value === currentMonthValue.value.year,
16271
+ selected: year.value === vue.unref(currentMonthValue).year,
16113
16272
  disabled: year.disabled
16114
16273
  }]),
16115
16274
  disabled: year.disabled,
16116
- onClick: ($event) => selectYear(year.value)
16117
- }, vue.toDisplayString(year.value), 11, _hoisted_15$4);
16275
+ onClick: ($event) => vue.unref(selectYear)(year.value)
16276
+ }, vue.toDisplayString(year.value), 11, _hoisted_13$4);
16118
16277
  }), 128))
16119
16278
  ]))
16120
16279
  ]),
16121
- _ctx.enableTime && vue.unref(currentView) === "days" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_16$4, [
16122
- vue.createElementVNode("div", _hoisted_17$4, [
16280
+ _ctx.enableTime && currentView.value === "days" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_14$4, [
16281
+ vue.createElementVNode("div", _hoisted_15$4, [
16123
16282
  vue.createVNode(vue.unref(NumberInput), {
16124
16283
  center: "",
16125
- "model-value": hours.value,
16126
- disabled: !selectedDate.value,
16284
+ "model-value": vue.unref(hours),
16285
+ disabled: !vue.unref(selectedDate),
16127
16286
  min: 0,
16128
16287
  max: 23,
16129
16288
  layout: "vertical",
16130
16289
  padZero: 2,
16131
- "onUpdate:modelValue": handleHourInput
16132
- }, null, 8, ["model-value", "disabled"]),
16133
- _cache[6] || (_cache[6] = vue.createElementVNode("p", { class: "pb-075" }, " : ", -1)),
16290
+ "onUpdate:modelValue": vue.unref(handleHourInput)
16291
+ }, null, 8, ["model-value", "disabled", "onUpdate:modelValue"]),
16292
+ _cache[7] || (_cache[7] = vue.createElementVNode("p", { class: "pb-075" }, " : ", -1)),
16134
16293
  vue.createVNode(vue.unref(NumberInput), {
16135
16294
  center: "",
16136
- "model-value": minutes.value,
16137
- disabled: !selectedDate.value,
16295
+ "model-value": vue.unref(minutes),
16296
+ disabled: !vue.unref(selectedDate),
16138
16297
  min: 0,
16139
16298
  max: 59,
16140
16299
  padZero: 2,
16141
16300
  layout: "vertical",
16142
- "onUpdate:modelValue": handleMinuteInput
16143
- }, null, 8, ["model-value", "disabled"])
16301
+ "onUpdate:modelValue": vue.unref(handleMinuteInput)
16302
+ }, null, 8, ["model-value", "disabled", "onUpdate:modelValue"])
16144
16303
  ]),
16145
- vue.createElementVNode("span", _hoisted_18$2, vue.toDisplayString(timezoneDisplay.value), 1),
16146
- selectedDate.value ? (vue.openBlock(), vue.createBlock(vue.unref(Btn), {
16304
+ vue.createElementVNode("span", _hoisted_16$4, vue.toDisplayString(vue.unref(timezoneDisplay)), 1),
16305
+ vue.unref(selectedDate) ? (vue.openBlock(), vue.createBlock(vue.unref(Btn), {
16147
16306
  key: 0,
16148
16307
  flat: "",
16149
- onClick: _cache[3] || (_cache[3] = ($event) => vue.isRef(isOpen) ? isOpen.value = false : isOpen = false)
16308
+ onClick: _cache[4] || (_cache[4] = ($event) => isOpen.value = false)
16150
16309
  }, {
16151
- default: vue.withCtx(() => _cache[7] || (_cache[7] = [
16310
+ default: vue.withCtx(() => _cache[8] || (_cache[8] = [
16152
16311
  vue.createTextVNode(" Done ")
16153
16312
  ])),
16154
16313
  _: 1
16155
16314
  })) : vue.createCommentVNode("", true)
16156
16315
  ])) : vue.createCommentVNode("", true)
16157
- ])
16316
+ ], 512)
16158
16317
  ]),
16159
16318
  _: 1
16160
16319
  }, 8, ["shown"])
16161
- ], 10, _hoisted_1$F);
16320
+ ], 42, _hoisted_1$F);
16162
16321
  };
16163
16322
  }
16164
16323
  });
16165
- const DateInput = /* @__PURE__ */ _export_sfc(_sfc_main$M, [["__scopeId", "data-v-a2f98d6e"]]);
16324
+ const DateInput = /* @__PURE__ */ _export_sfc(_sfc_main$M, [["__scopeId", "data-v-5d1b6a15"]]);
16166
16325
  const _hoisted_1$E = ["title"];
16167
16326
  const _hoisted_2$s = { key: 0 };
16168
16327
  const _hoisted_3$n = {
@@ -25989,7 +26148,7 @@ const _sfc_main$G = /* @__PURE__ */ vue.defineComponent({
25989
26148
  }
25990
26149
  });
25991
26150
  const OTP = /* @__PURE__ */ _export_sfc(_sfc_main$G, [["__scopeId", "data-v-8e8db33e"]]);
25992
- const _hoisted_1$y = { class: "relative" };
26151
+ const _hoisted_1$y = { class: "relative passwordInput" };
25993
26152
  const _hoisted_2$n = { class: "m-password position-bottom-end flex column justify-content-center" };
25994
26153
  const _sfc_main$F = /* @__PURE__ */ vue.defineComponent({
25995
26154
  __name: "PasswordInput",
@@ -26404,53 +26563,27 @@ const _sfc_main$C = /* @__PURE__ */ vue.defineComponent({
26404
26563
  }
26405
26564
  });
26406
26565
  const RangeInput = /* @__PURE__ */ _export_sfc(_sfc_main$C, [["__scopeId", "data-v-25d991e5"]]);
26407
- const tableTools = [
26408
- "mergeCells",
26409
- "splitCells",
26410
- "addRowBefore",
26411
- "addRowAfter",
26412
- "deleteRow",
26413
- "insertColumnLeft",
26414
- "insertColumnRight",
26415
- "deleteColumn",
26416
- "alignLeft",
26417
- "alignCenter",
26418
- "alignRight",
26419
- "alignJustify",
26420
- "deleteTable"
26421
- ];
26422
- const defaultToolbarConfig = [
26566
+ const basicToolbarConfig = [
26423
26567
  "h2",
26424
26568
  "h3",
26425
26569
  "h4",
26426
26570
  "h5",
26427
26571
  "h6",
26428
26572
  "separator",
26429
- "bold",
26430
- "italic",
26431
- "underline",
26432
- "separator",
26433
- "fontColor",
26434
- "bgColor",
26435
- "separator",
26436
26573
  "p",
26437
26574
  "blockquote",
26438
26575
  "orderedList",
26439
26576
  "unorderedList",
26440
- "indent",
26441
- "outdent",
26577
+ "separator",
26578
+ "bold",
26579
+ "italic",
26580
+ "underline",
26442
26581
  "separator",
26443
26582
  "link",
26444
26583
  "image",
26445
- // 'youtube',
26446
- "separator",
26447
- "splitView",
26584
+ "embed",
26448
26585
  "clear",
26449
- "insertTable",
26450
- ...tableTools,
26451
- "separator",
26452
- "undo",
26453
- "redo",
26586
+ "splitView",
26454
26587
  "fullScreen"
26455
26588
  ];
26456
26589
  const toolbarOptions = [
@@ -26468,7 +26601,7 @@ const toolbarOptions = [
26468
26601
  { name: "unorderedList", label: "Unordered List", icon: "format_list_bulleted" },
26469
26602
  { name: "link", label: "Link", icon: "add_link" },
26470
26603
  { name: "image", label: "Image", icon: "add_photo_alternate" },
26471
- { name: "youtube", label: "YouTube", icon: "youtube_activity" },
26604
+ { name: "embed", label: "Embed", icon: "media_link" },
26472
26605
  { name: "splitView", label: "Split View", icon: "code" },
26473
26606
  { name: "clear", label: "Clear Formatting", icon: "format_clear" },
26474
26607
  { name: "alignLeft", label: "Align Left", icon: "format_align_left" },
@@ -26558,7 +26691,7 @@ const _hoisted_1$t = {
26558
26691
  const _sfc_main$A = /* @__PURE__ */ vue.defineComponent({
26559
26692
  __name: "EditorToolbar",
26560
26693
  props: {
26561
- config: { default: defaultToolbarConfig },
26694
+ config: { default: basicToolbarConfig },
26562
26695
  selectedStyles: {}
26563
26696
  },
26564
26697
  emits: ["action"],
@@ -26613,45 +26746,50 @@ const _sfc_main$A = /* @__PURE__ */ vue.defineComponent({
26613
26746
  };
26614
26747
  }
26615
26748
  });
26616
- const EditorToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$A, [["__scopeId", "data-v-bcd681b9"]]);
26617
- function createCommandExecutor(state2, commands) {
26618
- return {
26619
- execute(command, value) {
26620
- const cmd = commands[command];
26621
- if (cmd) {
26622
- cmd.execute(state2, value);
26623
- }
26624
- },
26625
- isActive(command) {
26626
- var _a2;
26627
- const cmd = commands[command];
26628
- return ((_a2 = cmd.isActive) == null ? void 0 : _a2.call(cmd, state2)) || false;
26629
- },
26630
- getValue(command) {
26631
- var _a2;
26632
- const cmd = commands[command];
26633
- return ((_a2 = cmd.getValue) == null ? void 0 : _a2.call(cmd, state2)) || null;
26634
- }
26635
- };
26636
- }
26749
+ const EditorToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$A, [["__scopeId", "data-v-9d8a6eb6"]]);
26637
26750
  function isStyleActive(style, doc) {
26638
26751
  const selection = doc.getSelection();
26639
26752
  if (!selection || !selection.rangeCount) return false;
26640
26753
  const range2 = selection.getRangeAt(0);
26641
26754
  const container = range2.commonAncestorContainer;
26642
- const parent = container.nodeType === 3 ? container.parentElement : container;
26755
+ const parent = container.nodeType === Node.TEXT_NODE ? container.parentElement : container;
26643
26756
  if (!parent) return false;
26644
- const checkParent = (element, tags) => {
26645
- if (!element) return false;
26646
- if (tags.includes(element.tagName.toLowerCase())) return true;
26647
- return checkParent(element.parentElement, tags);
26648
- };
26649
- const styleTags = {
26757
+ const checkParent = (element, tags2) => {
26758
+ if (!element || !element.tagName) return false;
26759
+ const tagName = element.tagName.toLowerCase();
26760
+ if (tags2.includes(tagName)) return true;
26761
+ return checkParent(element.parentElement, tags2);
26762
+ };
26763
+ const styleMappings = {
26764
+ // Inline styles
26650
26765
  bold: ["strong", "b"],
26651
26766
  italic: ["em", "i"],
26652
- underline: ["u"]
26653
- };
26654
- return checkParent(parent, styleTags[style] ?? [style]);
26767
+ underline: ["u"],
26768
+ // Block styles
26769
+ h1: ["h1"],
26770
+ h2: ["h2"],
26771
+ h3: ["h3"],
26772
+ h4: ["h4"],
26773
+ h5: ["h5"],
26774
+ h6: ["h6"],
26775
+ p: ["p"],
26776
+ blockquote: ["blockquote"],
26777
+ // List styles
26778
+ orderedList: ["ol"],
26779
+ unorderedList: ["ul"]
26780
+ };
26781
+ if (["splitView", "codeView", "fullScreen"].includes(style)) {
26782
+ return false;
26783
+ }
26784
+ if (style === "orderedList" || style === "unorderedList") {
26785
+ const listParent = parent.closest(style === "orderedList" ? "ol" : "ul");
26786
+ return !!listParent;
26787
+ }
26788
+ const tags = styleMappings[style];
26789
+ if (tags) {
26790
+ return checkParent(parent, tags);
26791
+ }
26792
+ return checkParent(parent, [style]);
26655
26793
  }
26656
26794
  function analyzeSelection(doc, range2) {
26657
26795
  const container = range2.commonAncestorContainer;
@@ -26911,6 +27049,52 @@ function insertLink(modal, state2) {
26911
27049
  }
26912
27050
  });
26913
27051
  }
27052
+ function insertEmbed(modal, state2) {
27053
+ const { range: range2, doc } = state2;
27054
+ if (!range2 || !doc) return;
27055
+ modal.showModalForm({
27056
+ title: "Insert Embed",
27057
+ schema: [
27058
+ { id: "url", $el: "text", label: "URL", attrs: { placeholder: "Enter URL (YouTube, Vimeo, etc.)" } },
27059
+ frmRow(
27060
+ numField("width", "Width", { min: 200, placeholder: "560" }),
27061
+ numField("height", "Height", { min: 200, placeholder: "315" })
27062
+ ),
27063
+ { id: "allowFullscreen", $el: "check", label: "Allow Fullscreen", value: true }
27064
+ ],
27065
+ onSubmit: (data2) => {
27066
+ if (!data2.url) return;
27067
+ const url = new URL(data2.url);
27068
+ let embedUrl = data2.url;
27069
+ if (url.hostname.includes("youtube.com") || url.hostname === "youtu.be") {
27070
+ const videoId = url.hostname === "youtu.be" ? url.pathname.slice(1) : url.searchParams.get("v");
27071
+ if (videoId) {
27072
+ embedUrl = `https://www.youtube.com/embed/${videoId}`;
27073
+ }
27074
+ } else if (url.hostname.includes("vimeo.com")) {
27075
+ const videoId = url.pathname.split("/").pop();
27076
+ if (videoId) {
27077
+ embedUrl = `https://player.vimeo.com/video/${videoId}`;
27078
+ }
27079
+ }
27080
+ const iframe = doc.createElement("iframe");
27081
+ Object.assign(iframe, {
27082
+ src: embedUrl,
27083
+ width: data2.width || 560,
27084
+ height: data2.height || 315,
27085
+ frameBorder: "0",
27086
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
27087
+ allowFullscreen: data2.allowFullscreen
27088
+ });
27089
+ const wrapper = doc.createElement("div");
27090
+ wrapper.style.textAlign = "center";
27091
+ wrapper.style.margin = "1em 0";
27092
+ wrapper.appendChild(iframe);
27093
+ range2.deleteContents();
27094
+ range2.insertNode(wrapper);
27095
+ }
27096
+ });
27097
+ }
26914
27098
  function insertTable(rows, cols, state2) {
26915
27099
  if (!state2.doc) return;
26916
27100
  const table = state2.doc.createElement("table");
@@ -27032,145 +27216,393 @@ function alignColumn(range2, alignment) {
27032
27216
  }
27033
27217
  }
27034
27218
  }
27035
- function useCommands(state2, debug) {
27036
- const format2 = () => formatting(state2);
27037
- const commands = {
27038
- // Text formatting commands
27039
- bold: {
27040
- name: "Bold",
27041
- execute: (state22) => {
27042
- format2().text("bold");
27043
- },
27044
- isActive: (state22) => state22.selectedStyles.has("bold")
27045
- },
27046
- italic: {
27047
- name: "Italic",
27048
- execute: (state22) => {
27049
- format2().text("italic");
27050
- },
27051
- isActive: (state22) => state22.selectedStyles.has("italic")
27052
- },
27053
- underline: {
27054
- name: "Underline",
27055
- execute: (state22) => {
27056
- format2().text("underline");
27057
- },
27058
- isActive: (state22) => state22.selectedStyles.has("underline")
27059
- },
27060
- // Block formatting commands
27061
- h1: { name: "Heading 1", execute: (state22) => {
27062
- format2().block("h1", "h1");
27063
- }, isActive: (state22) => state22.selectedStyles.has("h1") },
27064
- h2: { name: "Heading 2", execute: (state22) => {
27065
- format2().block("h2", "h2");
27066
- }, isActive: (state22) => state22.selectedStyles.has("h2") },
27067
- h3: { name: "Heading 3", execute: (state22) => {
27068
- format2().block("h3", "h3");
27069
- }, isActive: (state22) => state22.selectedStyles.has("h3") },
27070
- h4: { name: "Heading 4", execute: (state22) => {
27071
- format2().block("h4", "h4");
27072
- }, isActive: (state22) => state22.selectedStyles.has("h4") },
27073
- h5: { name: "Heading 5", execute: (state22) => {
27074
- format2().block("h5", "h5");
27075
- }, isActive: (state22) => state22.selectedStyles.has("h5") },
27076
- h6: { name: "Heading 6", execute: (state22) => {
27077
- format2().block("h6", "h6");
27078
- }, isActive: (state22) => state22.selectedStyles.has("h6") },
27079
- p: { name: "Paragraph", execute: (state22) => {
27080
- format2().block("p", "p");
27081
- }, isActive: (state22) => state22.selectedStyles.has("p") },
27082
- blockquote: {
27083
- name: "Blockquote",
27084
- execute: (state22) => {
27085
- format2().block("blockquote", "blockquote");
27086
- },
27087
- isActive: (state22) => state22.selectedStyles.has("blockquote")
27219
+ function createCommand(name, execute, isActive) {
27220
+ return {
27221
+ name,
27222
+ execute: (state2, value) => {
27223
+ if (!state2.doc) return;
27224
+ execute(state2, value);
27088
27225
  },
27089
- // List commands
27090
- orderedList: {
27091
- name: "Ordered List",
27092
- execute: (state22) => {
27093
- format2().list("orderedList");
27094
- },
27095
- isActive: (state22) => state22.selectedStyles.has("orderedList")
27226
+ isActive
27227
+ };
27228
+ }
27229
+ function createFormattingCommand(state2, type3, command, tag) {
27230
+ const format2 = formatting(state2);
27231
+ return createCommand(
27232
+ command,
27233
+ () => {
27234
+ var _a2, _b;
27235
+ if (!state2.doc) return;
27236
+ if (type3 === "text") {
27237
+ if (command === "bold") state2.doc.execCommand("bold", false);
27238
+ else if (command === "italic") state2.doc.execCommand("italic", false);
27239
+ else if (command === "underline") state2.doc.execCommand("underline", false);
27240
+ else format2.text(command);
27241
+ } else if (type3 === "block") {
27242
+ state2.doc.execCommand("formatBlock", false, `<${command}>`);
27243
+ } else if (type3 === "list") {
27244
+ const selection = state2.doc.getSelection();
27245
+ if (!selection || !selection.rangeCount) return;
27246
+ const range2 = selection.getRangeAt(0);
27247
+ if (range2.collapsed && (!((_a2 = range2.startContainer.textContent) == null ? void 0 : _a2.trim()) || range2.startContainer === state2.doc.body)) {
27248
+ const list = state2.doc.createElement(command === "orderedList" ? "ol" : "ul");
27249
+ const li = state2.doc.createElement("li");
27250
+ li.innerHTML = "&nbsp;<br>";
27251
+ list.appendChild(li);
27252
+ const currentBlock = range2.startContainer.nodeType === 1 ? range2.startContainer : range2.startContainer.parentElement;
27253
+ if ((currentBlock == null ? void 0 : currentBlock.tagName.toLowerCase()) === "p" && isNodeEmpty$1(currentBlock)) {
27254
+ (_b = currentBlock.parentNode) == null ? void 0 : _b.replaceChild(list, currentBlock);
27255
+ } else {
27256
+ range2.insertNode(list);
27257
+ }
27258
+ range2.selectNodeContents(li);
27259
+ range2.collapse(true);
27260
+ selection.removeAllRanges();
27261
+ selection.addRange(range2);
27262
+ } else {
27263
+ state2.doc.execCommand(
27264
+ command === "orderedList" ? "insertOrderedList" : "insertUnorderedList",
27265
+ false
27266
+ );
27267
+ }
27268
+ }
27096
27269
  },
27097
- unorderedList: {
27098
- name: "Unordered List",
27099
- execute: (state22) => {
27100
- format2().list("unorderedList");
27101
- },
27102
- isActive: (state22) => state22.selectedStyles.has("unorderedList")
27103
- },
27104
- // Table commands
27105
- insertTable: {
27106
- name: "Insert Table",
27107
- execute: (state22, value) => {
27108
- const [rows, cols] = (value == null ? void 0 : value.split("x").map(Number)) || [3, 3];
27109
- insertTable(rows, cols, state22);
27110
- }
27111
- },
27112
- deleteTable: { name: "Delete Table", execute: (state22) => state22.range && deleteTable(state22.range) },
27113
- mergeCells: { name: "Merge Cells", execute: (state22) => state22.range && state22.doc && mergeCells(state22.range, state22.doc) },
27114
- splitCells: { name: "Split Cells", execute: (state22) => state22.range && state22.doc && splitCell(state22.range, state22.doc) },
27115
- addRowBefore: { name: "Add Row Before", execute: (state22) => state22.range && state22.doc && addRow("before", state22.range, state22.doc) },
27116
- addRowAfter: { name: "Add Row After", execute: (state22) => state22.range && state22.doc && addRow("after", state22.range, state22.doc) },
27117
- deleteRow: { name: "Delete Row", execute: (state22) => state22.range && deleteRow(state22.range) },
27118
- insertColumnLeft: { name: "Insert Column Left", execute: (state22) => state22.range && insertColumn("before", state22.range) },
27119
- insertColumnRight: { name: "Insert Column Right", execute: (state22) => state22.range && insertColumn("after", state22.range) },
27120
- deleteColumn: { name: "Delete Column", execute: (state22) => state22.range && deleteColumn(state22.range) },
27121
- // Alignment commands
27122
- alignLeft: { name: "Align Left", execute: (state22) => state22.range && alignColumn(state22.range, "left") },
27123
- alignCenter: { name: "Align Center", execute: (state22) => state22.range && alignColumn(state22.range, "center") },
27124
- alignRight: { name: "Align Right", execute: (state22) => state22.range && alignColumn(state22.range, "right") },
27125
- alignJustify: { name: "Align Justify", execute: (state22) => state22.range && alignColumn(state22.range, "justify") },
27126
- // Media commands
27127
- image: { name: "Insert Image", execute: (state22) => state22.modal && insertImage(state22.modal, state22) },
27128
- link: { name: "Insert Link", execute: (state22) => state22.modal && state22.range && insertLink(state22.modal, state22) },
27129
- // Other commands
27130
- clear: { name: "Clear Formatting", execute: (state22) => {
27131
- format2().clear();
27132
- } },
27133
- indent: { name: "Indent", execute: (state22) => {
27134
- format2().text("indent");
27135
- } },
27136
- outdent: { name: "Outdent", execute: (state22) => {
27137
- format2().text("outdent");
27138
- } },
27139
- fullScreen: {
27140
- name: "Full Screen",
27141
- execute: (state22) => {
27142
- state22.isFullscreen = !state22.isFullscreen;
27143
- },
27144
- isActive: (state22) => state22.isFullscreen
27270
+ () => state2.selectedStyles.has(command)
27271
+ );
27272
+ }
27273
+ function isNodeEmpty$1(node) {
27274
+ var _a2;
27275
+ const text = ((_a2 = node.textContent) == null ? void 0 : _a2.trim()) || "";
27276
+ if (text) return false;
27277
+ const brElements = node.getElementsByTagName("br");
27278
+ if (brElements.length === 0) return true;
27279
+ return brElements.length === 1 && node.childNodes.length === 1;
27280
+ }
27281
+ function createCommandRegistry(state2) {
27282
+ const format2 = formatting(state2);
27283
+ const historyCommands = {
27284
+ undo: createCommand("Undo", () => {
27285
+ var _a2;
27286
+ return (_a2 = state2.doc) == null ? void 0 : _a2.execCommand("undo", false);
27287
+ }),
27288
+ redo: createCommand("Redo", () => {
27289
+ var _a2;
27290
+ return (_a2 = state2.doc) == null ? void 0 : _a2.execCommand("redo", false);
27291
+ })
27292
+ };
27293
+ const textCommands = ["bold", "italic", "underline"].reduce((acc, cmd) => ({
27294
+ ...acc,
27295
+ [cmd]: createFormattingCommand(state2, "text", cmd)
27296
+ }), {});
27297
+ const headingCommands = ["h1", "h2", "h3", "h4", "h5", "h6"].reduce((acc, cmd) => ({
27298
+ ...acc,
27299
+ [cmd]: createFormattingCommand(state2, "block", cmd)
27300
+ }), {});
27301
+ const blockCommands = {
27302
+ p: createFormattingCommand(state2, "block", "p"),
27303
+ blockquote: createFormattingCommand(state2, "block", "blockquote")
27304
+ };
27305
+ const listCommands = {
27306
+ orderedList: createFormattingCommand(state2, "list", "orderedList"),
27307
+ unorderedList: createFormattingCommand(state2, "list", "unorderedList")
27308
+ };
27309
+ const tableCommands = {
27310
+ insertTable: createCommand("Insert Table", (state22, value) => {
27311
+ const [rows, cols] = (value == null ? void 0 : value.split("x").map(Number)) || [3, 3];
27312
+ insertTable(rows, cols, state22);
27313
+ }),
27314
+ deleteTable: createCommand("Delete Table", (state22) => state22.range && deleteTable(state22.range)),
27315
+ mergeCells: createCommand("Merge Cells", (state22) => state22.range && state22.doc && mergeCells(state22.range, state22.doc)),
27316
+ splitCells: createCommand("Split Cells", (state22) => state22.range && state22.doc && splitCell(state22.range, state22.doc)),
27317
+ addRowBefore: createCommand("Add Row Before", (state22) => state22.range && state22.doc && addRow("before", state22.range, state22.doc)),
27318
+ addRowAfter: createCommand("Add Row After", (state22) => state22.range && state22.doc && addRow("after", state22.range, state22.doc)),
27319
+ deleteRow: createCommand("Delete Row", (state22) => state22.range && deleteRow(state22.range)),
27320
+ insertColumnLeft: createCommand("Insert Column Left", (state22) => state22.range && insertColumn("before", state22.range)),
27321
+ insertColumnRight: createCommand("Insert Column Right", (state22) => state22.range && insertColumn("after", state22.range)),
27322
+ deleteColumn: createCommand("Delete Column", (state22) => state22.range && deleteColumn(state22.range))
27323
+ };
27324
+ const alignmentCommands = ["Left", "Center", "Right", "Justify"].reduce((acc, align) => ({
27325
+ ...acc,
27326
+ [`align${align}`]: createCommand(`Align ${align}`, (state22) => state22.range && alignColumn(state22.range, align.toLowerCase()))
27327
+ }), {});
27328
+ const viewCommands = {
27329
+ fullScreen: createCommand("Full Screen", (state22) => {
27330
+ state22.isFullscreen = !state22.isFullscreen;
27331
+ }, (state22) => state22.isFullscreen),
27332
+ splitView: createCommand("Split View", (state22) => {
27333
+ state22.isSplitView = !state22.isSplitView;
27334
+ }, (state22) => state22.isSplitView),
27335
+ codeView: createCommand("Code View", (state22) => {
27336
+ state22.isCodeView = !state22.isCodeView;
27337
+ }, (state22) => state22.isCodeView)
27338
+ };
27339
+ const mediaCommands = {
27340
+ image: createCommand("Insert Image", (state22) => state22.modal && insertImage(state22.modal, state22)),
27341
+ link: createCommand("Insert Link", (state22) => state22.modal && state22.range && insertLink(state22.modal, state22)),
27342
+ embed: createCommand("Insert Embed", (state22) => state22.modal && insertEmbed(state22.modal, state22))
27343
+ };
27344
+ const otherCommands = {
27345
+ clear: createCommand("Clear Formatting", () => {
27346
+ format2.clear();
27347
+ }),
27348
+ indent: createCommand("Indent", () => {
27349
+ format2.text("indent");
27350
+ }),
27351
+ outdent: createCommand("Outdent", () => {
27352
+ format2.text("outdent");
27353
+ })
27354
+ };
27355
+ return {
27356
+ ...historyCommands,
27357
+ ...textCommands,
27358
+ ...headingCommands,
27359
+ ...blockCommands,
27360
+ ...listCommands,
27361
+ ...tableCommands,
27362
+ ...alignmentCommands,
27363
+ ...viewCommands,
27364
+ ...mediaCommands,
27365
+ ...otherCommands
27366
+ };
27367
+ }
27368
+ function createCommandExecutor(state2, commands) {
27369
+ return {
27370
+ execute(command, value) {
27371
+ const cmd = commands[command];
27372
+ if (cmd) {
27373
+ cmd.execute(state2, value);
27374
+ }
27145
27375
  },
27146
- splitView: {
27147
- name: "Split View",
27148
- execute: (state22) => {
27149
- state22.isSplitView = !state22.isSplitView;
27150
- },
27151
- isActive: (state22) => state22.isSplitView
27376
+ isActive(command) {
27377
+ var _a2;
27378
+ const cmd = commands[command];
27379
+ return ((_a2 = cmd.isActive) == null ? void 0 : _a2.call(cmd, state2)) || false;
27152
27380
  },
27153
- codeView: {
27154
- name: "Code View",
27155
- execute: (state22) => {
27156
- state22.isCodeView = !state22.isCodeView;
27157
- },
27158
- isActive: (state22) => state22.isCodeView
27381
+ getValue(command) {
27382
+ var _a2;
27383
+ const cmd = commands[command];
27384
+ return ((_a2 = cmd.getValue) == null ? void 0 : _a2.call(cmd, state2)) || null;
27159
27385
  }
27160
27386
  };
27387
+ }
27388
+ function useCommands(state2, debug) {
27389
+ const commands = createCommandRegistry(state2);
27161
27390
  const executor = createCommandExecutor(state2, commands);
27162
27391
  return {
27163
27392
  execute: (command, value) => {
27393
+ if (!state2.doc) return;
27394
+ console.log("[useCommands.execute] Starting command execution:", command, value);
27164
27395
  debug == null ? void 0 : debug.logCommand(command, value);
27396
+ if (["splitView", "codeView", "fullScreen"].includes(command)) {
27397
+ console.log("[useCommands.execute] Handling view state command:", command);
27398
+ switch (command) {
27399
+ case "splitView":
27400
+ state2.isSplitView = !state2.isSplitView;
27401
+ return;
27402
+ case "codeView":
27403
+ state2.isCodeView = !state2.isCodeView;
27404
+ return;
27405
+ case "fullScreen":
27406
+ state2.isFullscreen = !state2.isFullscreen;
27407
+ return;
27408
+ }
27409
+ }
27410
+ console.log("[useCommands.execute] Focusing editor");
27411
+ state2.doc.body.focus();
27412
+ console.log("[useCommands.execute] Executing command");
27165
27413
  executor.execute(command, value);
27414
+ const newContent = state2.doc.body.innerHTML;
27415
+ console.log("[useCommands.execute] Checking content changes");
27416
+ console.log("[useCommands.execute] Old content length:", state2.content.length);
27417
+ console.log("[useCommands.execute] New content length:", newContent.length);
27418
+ if (newContent !== state2.content) {
27419
+ console.log("[useCommands.execute] Content changed, updating state");
27420
+ state2.content = newContent;
27421
+ }
27422
+ console.log("[useCommands.execute] Checking selection changes");
27423
+ const selection = state2.doc.getSelection();
27424
+ if (selection == null ? void 0 : selection.rangeCount) {
27425
+ const hasSelectionChanged = !state2.selection || state2.selection !== selection || state2.rangeCount !== selection.rangeCount;
27426
+ console.log("[useCommands.execute] Selection changed:", hasSelectionChanged);
27427
+ if (hasSelectionChanged) {
27428
+ console.log("[useCommands.execute] Updating selection state");
27429
+ state2.selection = selection;
27430
+ state2.range = selection.getRangeAt(0).cloneRange();
27431
+ state2.rangeCount = selection.rangeCount;
27432
+ }
27433
+ }
27166
27434
  },
27167
27435
  isActive: executor.isActive,
27168
27436
  getValue: executor.getValue
27169
27437
  };
27170
27438
  }
27439
+ class EditorDebugger {
27440
+ constructor(maxActions = 1e3) {
27441
+ __publicField(this, "session");
27442
+ __publicField(this, "maxActions");
27443
+ __publicField(this, "isDevelopment");
27444
+ this.maxActions = maxActions;
27445
+ this.session = this.createNewSession();
27446
+ this.isDevelopment = false;
27447
+ }
27448
+ createNewSession() {
27449
+ return {
27450
+ id: `session_${Date.now()}`,
27451
+ startTime: Date.now(),
27452
+ actions: []
27453
+ };
27454
+ }
27455
+ getNodeDescription(node) {
27456
+ var _a2;
27457
+ if (node.nodeType === Node.TEXT_NODE) {
27458
+ return `Text("${(_a2 = node.textContent) == null ? void 0 : _a2.slice(0, 20)}${node.textContent && node.textContent.length > 20 ? "..." : ""}")`;
27459
+ }
27460
+ const element = node;
27461
+ return `${element.tagName.toLowerCase()}${element.id ? `#${element.id}` : ""}`;
27462
+ }
27463
+ captureState(state2) {
27464
+ if (!state2.doc || !state2.selection) {
27465
+ return {
27466
+ content: "",
27467
+ selection: null,
27468
+ activeStyles: [],
27469
+ caretPosition: null
27470
+ };
27471
+ }
27472
+ const { selection } = state2;
27473
+ const range2 = selection.rangeCount ? selection.getRangeAt(0) : null;
27474
+ return {
27475
+ content: state2.doc.body.innerHTML,
27476
+ selection: range2 ? {
27477
+ start: range2.startOffset,
27478
+ end: range2.endOffset,
27479
+ collapsed: range2.collapsed,
27480
+ text: range2.toString()
27481
+ } : null,
27482
+ activeStyles: Array.from(state2.selectedStyles),
27483
+ caretPosition: range2 ? {
27484
+ node: this.getNodeDescription(range2.startContainer),
27485
+ offset: range2.startOffset
27486
+ } : null
27487
+ };
27488
+ }
27489
+ logCommand(command, value, state2) {
27490
+ this.addAction({
27491
+ type: "command",
27492
+ name: command,
27493
+ timestamp: Date.now(),
27494
+ details: { value },
27495
+ state: this.captureState(state2)
27496
+ });
27497
+ }
27498
+ logPaste(data2, state2) {
27499
+ this.addAction({
27500
+ type: "paste",
27501
+ name: "paste",
27502
+ timestamp: Date.now(),
27503
+ details: {
27504
+ html: data2.getData("text/html"),
27505
+ text: data2.getData("text/plain"),
27506
+ types: Array.from(data2.types)
27507
+ },
27508
+ state: this.captureState(state2)
27509
+ });
27510
+ }
27511
+ logKeyboard(event, state2) {
27512
+ this.addAction({
27513
+ type: "keyboard",
27514
+ name: "keypress",
27515
+ timestamp: Date.now(),
27516
+ details: {
27517
+ key: event.key,
27518
+ code: event.code,
27519
+ ctrl: event.ctrlKey,
27520
+ alt: event.altKey,
27521
+ shift: event.shiftKey,
27522
+ meta: event.metaKey
27523
+ },
27524
+ state: this.captureState(state2)
27525
+ });
27526
+ }
27527
+ logSelection(state2) {
27528
+ this.addAction({
27529
+ type: "selection",
27530
+ name: "selection_change",
27531
+ timestamp: Date.now(),
27532
+ details: {},
27533
+ state: this.captureState(state2)
27534
+ });
27535
+ }
27536
+ logInput(inputType, data2, state2) {
27537
+ this.addAction({
27538
+ type: "input",
27539
+ name: inputType,
27540
+ timestamp: Date.now(),
27541
+ details: { data: data2 },
27542
+ state: this.captureState(state2)
27543
+ });
27544
+ }
27545
+ addAction(action) {
27546
+ this.session.actions.push(action);
27547
+ if (this.session.actions.length > this.maxActions) {
27548
+ this.session.actions.shift();
27549
+ }
27550
+ if (this.isDevelopment) {
27551
+ console.log("Editor Action:", action);
27552
+ }
27553
+ }
27554
+ getSession() {
27555
+ return this.session;
27556
+ }
27557
+ clearSession() {
27558
+ this.session = this.createNewSession();
27559
+ }
27560
+ exportSession() {
27561
+ return JSON.stringify(this.session, null, 2);
27562
+ }
27563
+ downloadSession() {
27564
+ const blob = new Blob([this.exportSession()], { type: "application/json" });
27565
+ const url = URL.createObjectURL(blob);
27566
+ const a2 = document.createElement("a");
27567
+ a2.href = url;
27568
+ a2.download = `editor_session_${this.session.id}.json`;
27569
+ document.body.appendChild(a2);
27570
+ a2.click();
27571
+ document.body.removeChild(a2);
27572
+ URL.revokeObjectURL(url);
27573
+ }
27574
+ exportSessionWithPrompt(userMessage) {
27575
+ const prompt = {
27576
+ message: userMessage || "here is a debug log, can you analyze and fix accordingly?",
27577
+ session: this.session
27578
+ };
27579
+ return JSON.stringify(prompt, null, 2);
27580
+ }
27581
+ }
27582
+ function preserveIframes(content) {
27583
+ const temp = document.createElement("div");
27584
+ temp.innerHTML = content;
27585
+ const iframes = [];
27586
+ temp.querySelectorAll("iframe").forEach((iframe, index2) => {
27587
+ const placeholder = `<!--iframe-${index2}-->`;
27588
+ iframes.push(iframe.cloneNode(true));
27589
+ iframe.replaceWith(placeholder);
27590
+ });
27591
+ return {
27592
+ html: temp.innerHTML,
27593
+ iframes
27594
+ };
27595
+ }
27596
+ function restoreIframes(doc, content, iframes) {
27597
+ const placeholderPattern = /<!--iframe-(\d+)-->/g;
27598
+ doc.body.innerHTML = content.replace(placeholderPattern, (_2, index2) => {
27599
+ const iframe = iframes[Number(index2)];
27600
+ return iframe ? iframe.outerHTML : "";
27601
+ });
27602
+ }
27171
27603
  function useEditor() {
27172
- const editorDebugger = vue.ref();
27173
27604
  const modal = useModal();
27605
+ let cleanupListeners = null;
27174
27606
  const state2 = vue.reactive({
27175
27607
  content: "",
27176
27608
  doc: void 0,
@@ -27184,95 +27616,142 @@ function useEditor() {
27184
27616
  redoStack: [],
27185
27617
  rangeCount: 0,
27186
27618
  range: null,
27187
- modal
27619
+ modal,
27620
+ debug: void 0
27188
27621
  });
27189
- function updateActiveStyles() {
27190
- if (!state2.doc) return;
27191
- const styles = /* @__PURE__ */ new Set();
27192
- const styleTypes = [
27193
- "bold",
27194
- "italic",
27195
- "underline",
27196
- "h1",
27197
- "h2",
27198
- "h3",
27199
- "h4",
27200
- "h5",
27201
- "h6",
27202
- "blockquote",
27203
- "table",
27204
- "p",
27205
- "ol",
27206
- "li"
27207
- ];
27208
- styleTypes.forEach((style) => {
27209
- if (state2.doc && isStyleActive(style, state2.doc)) {
27210
- styles.add(style);
27622
+ const updateState = {
27623
+ styles: () => {
27624
+ if (!state2.doc) return;
27625
+ console.log("[updateState.styles] Starting style update");
27626
+ const styles = /* @__PURE__ */ new Set();
27627
+ const styleTypes = [
27628
+ "bold",
27629
+ "italic",
27630
+ "underline",
27631
+ "h1",
27632
+ "h2",
27633
+ "h3",
27634
+ "h4",
27635
+ "h5",
27636
+ "h6",
27637
+ "blockquote",
27638
+ "table",
27639
+ "p",
27640
+ "ol",
27641
+ "li"
27642
+ ];
27643
+ styleTypes.forEach((style) => {
27644
+ if (state2.doc && isStyleActive(style, state2.doc)) {
27645
+ styles.add(style);
27646
+ }
27647
+ });
27648
+ console.log("[updateState.styles] New styles:", Array.from(styles));
27649
+ state2.selectedStyles = styles;
27650
+ },
27651
+ content: (source) => {
27652
+ if (!state2.doc) return;
27653
+ console.log("[updateState.content] Starting content update, source:", source);
27654
+ const currentContent = state2.doc.body.innerHTML;
27655
+ console.log("[updateState.content] Current content length:", currentContent.length);
27656
+ console.log("[updateState.content] State content length:", state2.content.length);
27657
+ if (currentContent !== state2.content) {
27658
+ console.log("[updateState.content] Content changed, pushing to undo stack");
27659
+ state2.undoStack.push(state2.content);
27660
+ state2.redoStack = [];
27661
+ }
27662
+ const selection = state2.doc.getSelection();
27663
+ const range2 = (selection == null ? void 0 : selection.rangeCount) ? selection.getRangeAt(0).cloneRange() : null;
27664
+ console.log("[updateState.content] Has selection:", !!selection, "Has range:", !!range2);
27665
+ if (source === "html") {
27666
+ console.log("[updateState.content] Processing HTML content");
27667
+ const preserved = preserveIframes(state2.content);
27668
+ console.log("[updateState.content] Preserved iframes count:", preserved.iframes.length);
27669
+ state2.doc.body.innerHTML = preserved.html;
27670
+ setTimeout(() => {
27671
+ console.log("[updateState.content] Restoring iframes");
27672
+ if (state2.doc) {
27673
+ restoreIframes(state2.doc, state2.content, preserved.iframes);
27674
+ if (range2 && selection) {
27675
+ try {
27676
+ selection.removeAllRanges();
27677
+ selection.addRange(range2);
27678
+ console.log("[updateState.content] Selection restored");
27679
+ } catch (e) {
27680
+ console.warn("[updateState.content] Could not restore selection:", e);
27681
+ }
27682
+ }
27683
+ }
27684
+ }, 0);
27685
+ } else {
27686
+ console.log("[updateState.content] Setting text content");
27687
+ state2.doc.body.textContent = state2.content;
27211
27688
  }
27212
- });
27213
- state2.selectedStyles = styles;
27214
- }
27215
- function updateContent(source) {
27216
- if (!state2.doc) return;
27217
- state2.undoStack.push(state2.content);
27218
- state2.redoStack = [];
27219
- if (source === "html") {
27220
- state2.doc.body.innerHTML = state2.content;
27221
- } else {
27222
- state2.doc.body.textContent = state2.content;
27223
- }
27224
- updateActiveStyles();
27225
- }
27226
- function updateSelection() {
27227
- if (!state2.doc) return;
27228
- state2.selection = state2.doc.getSelection();
27229
- if (!state2.selection) return;
27230
- try {
27231
- if (!state2.doc.body.contains(state2.selection.anchorNode)) {
27232
- state2.doc.body.focus();
27689
+ },
27690
+ selection: () => {
27691
+ if (!state2.doc) return;
27692
+ console.log("[updateState.selection] Starting selection update");
27693
+ const newSelection = state2.doc.getSelection();
27694
+ if (!newSelection) {
27695
+ console.log("[updateState.selection] No selection available");
27233
27696
  return;
27234
27697
  }
27235
- state2.rangeCount = state2.selection.rangeCount;
27236
- if (!state2.rangeCount) {
27237
- const range2 = state2.doc.createRange();
27238
- range2.selectNodeContents(state2.doc.body);
27239
- range2.collapse(false);
27240
- state2.selection.removeAllRanges();
27241
- state2.selection.addRange(range2);
27698
+ try {
27699
+ if (!state2.doc.body.contains(newSelection.anchorNode)) {
27700
+ console.log("[updateState.selection] Selection outside editor body, refocusing");
27701
+ state2.doc.body.focus();
27702
+ return;
27703
+ }
27704
+ const hasSelectionChanged = !state2.selection || state2.selection !== newSelection || state2.rangeCount !== newSelection.rangeCount || newSelection.rangeCount > 0 && state2.range && (state2.range.startContainer !== newSelection.getRangeAt(0).startContainer || state2.range.startOffset !== newSelection.getRangeAt(0).startOffset || state2.range.endContainer !== newSelection.getRangeAt(0).endContainer || state2.range.endOffset !== newSelection.getRangeAt(0).endOffset);
27705
+ console.log("[updateState.selection] Selection changed:", hasSelectionChanged);
27706
+ if (hasSelectionChanged) {
27707
+ state2.selection = newSelection;
27708
+ state2.rangeCount = newSelection.rangeCount;
27709
+ if (newSelection.rangeCount > 0) {
27710
+ state2.range = newSelection.getRangeAt(0).cloneRange();
27711
+ console.log("[updateState.selection] New range:", {
27712
+ startOffset: state2.range.startOffset,
27713
+ endOffset: state2.range.endOffset,
27714
+ collapsed: state2.range.collapsed
27715
+ });
27716
+ }
27717
+ requestAnimationFrame(() => {
27718
+ console.log("[updateState.selection] Updating styles in RAF");
27719
+ updateState.styles();
27720
+ });
27721
+ }
27722
+ } catch (e) {
27723
+ console.warn("[updateState.selection] Selection error:", e);
27724
+ state2.selection = null;
27725
+ state2.range = null;
27726
+ state2.rangeCount = 0;
27727
+ state2.selectedStyles = /* @__PURE__ */ new Set();
27242
27728
  }
27243
- state2.range = state2.selection.getRangeAt(0).cloneRange();
27244
- updateActiveStyles();
27245
- } catch (e) {
27246
- console.warn("Selection error:", e);
27247
- state2.selection = null;
27248
- state2.range = null;
27249
- state2.rangeCount = 0;
27250
- state2.selectedStyles = /* @__PURE__ */ new Set();
27251
27729
  }
27252
- }
27253
- function setupEventListeners(doc) {
27254
- doc.addEventListener("input", () => {
27255
- state2.content = doc.body.innerHTML;
27256
- updateActiveStyles();
27257
- });
27258
- doc.addEventListener("selectionchange", () => {
27259
- updateSelection();
27260
- });
27261
- doc.addEventListener("mouseup", () => {
27262
- updateSelection();
27263
- });
27264
- doc.addEventListener("keyup", (e) => {
27265
- if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
27266
- updateSelection();
27730
+ };
27731
+ const history = {
27732
+ undo: () => {
27733
+ if (state2.undoStack.length === 0) return;
27734
+ state2.redoStack.push(state2.content);
27735
+ const lastContent = state2.undoStack.pop();
27736
+ if (lastContent !== void 0) {
27737
+ state2.content = lastContent;
27738
+ updateState.content("html");
27267
27739
  }
27268
- });
27269
- const cleanEmptyTags = () => {
27740
+ },
27741
+ redo: () => {
27742
+ if (state2.redoStack.length === 0) return;
27743
+ state2.undoStack.push(state2.content);
27744
+ const nextContent = state2.redoStack.pop();
27745
+ if (nextContent !== void 0) {
27746
+ state2.content = nextContent;
27747
+ updateState.content("html");
27748
+ }
27749
+ }
27750
+ };
27751
+ const cleanup = {
27752
+ emptyTags: (doc) => {
27270
27753
  var _a2, _b;
27271
- const walker = doc.createTreeWalker(
27272
- doc.body,
27273
- NodeFilter.SHOW_ELEMENT,
27274
- null
27275
- );
27754
+ const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ELEMENT, null);
27276
27755
  const nodesToRemove = [];
27277
27756
  let node = walker.nextNode();
27278
27757
  while (node) {
@@ -27287,12 +27766,10 @@ function useEditor() {
27287
27766
  const isEmpty = !textContent && !innerHTML;
27288
27767
  const isDirectChildOfBody = node.parentElement === doc.body;
27289
27768
  if (isEmpty || hasOnlyNbsp || hasOnlyBr && !isDirectChildOfBody) {
27290
- if (isDirectChildOfBody) {
27291
- if (!node.matches("p")) {
27292
- const p2 = doc.createElement("p");
27293
- p2.innerHTML = "<br>";
27294
- (_b = node.parentNode) == null ? void 0 : _b.replaceChild(p2, node);
27295
- }
27769
+ if (isDirectChildOfBody && !node.matches("p")) {
27770
+ const p2 = doc.createElement("p");
27771
+ p2.innerHTML = "<br>";
27772
+ (_b = node.parentNode) == null ? void 0 : _b.replaceChild(p2, node);
27296
27773
  } else {
27297
27774
  nodesToRemove.push(node);
27298
27775
  }
@@ -27302,237 +27779,283 @@ function useEditor() {
27302
27779
  nodesToRemove.forEach((node2) => {
27303
27780
  node2.remove();
27304
27781
  });
27782
+ },
27783
+ normalizeContent: (doc) => {
27784
+ if (!doc.body.firstElementChild) {
27785
+ const p2 = doc.createElement("p");
27786
+ p2.dir = doc.body.dir;
27787
+ p2.innerHTML = "<br>";
27788
+ doc.body.appendChild(p2);
27789
+ } else {
27790
+ const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
27791
+ const textNodes = [];
27792
+ let node;
27793
+ while (node = walker.nextNode()) {
27794
+ if (node.parentElement === doc.body) {
27795
+ textNodes.push(node);
27796
+ }
27797
+ }
27798
+ textNodes.forEach((textNode) => {
27799
+ var _a2;
27800
+ if ((_a2 = textNode.textContent) == null ? void 0 : _a2.trim()) {
27801
+ const p2 = doc.createElement("p");
27802
+ p2.dir = doc.body.dir;
27803
+ p2.appendChild(textNode.cloneNode());
27804
+ doc.body.replaceChild(p2, textNode);
27805
+ } else {
27806
+ doc.body.removeChild(textNode);
27807
+ }
27808
+ });
27809
+ }
27810
+ }
27811
+ };
27812
+ function setupEventListeners(doc) {
27813
+ console.log("[setupEventListeners] Starting setup");
27814
+ if (cleanupListeners) {
27815
+ console.log("[setupEventListeners] Cleaning up existing listeners");
27816
+ cleanupListeners();
27817
+ cleanupListeners = null;
27818
+ }
27819
+ let isUpdating = false;
27820
+ let contentUpdateTimeout = null;
27821
+ let selectionUpdateTimeout = null;
27822
+ let updateCount = 0;
27823
+ const events = {
27824
+ input: () => {
27825
+ updateCount++;
27826
+ console.log(`[input event #${updateCount}] Starting, isUpdating:`, isUpdating);
27827
+ if (isUpdating) {
27828
+ console.log(`[input event #${updateCount}] Skipped - already updating`);
27829
+ return;
27830
+ }
27831
+ isUpdating = true;
27832
+ if (contentUpdateTimeout) {
27833
+ console.log(`[input event #${updateCount}] Clearing previous timeout`);
27834
+ window.clearTimeout(contentUpdateTimeout);
27835
+ }
27836
+ contentUpdateTimeout = window.setTimeout(() => {
27837
+ console.log(`[input event #${updateCount}] Timeout fired`);
27838
+ const newContent = doc.body.innerHTML;
27839
+ if (newContent !== state2.content) {
27840
+ console.log(`[input event #${updateCount}] Content changed, updating state`);
27841
+ state2.content = newContent;
27842
+ } else {
27843
+ console.log(`[input event #${updateCount}] Content unchanged`);
27844
+ }
27845
+ isUpdating = false;
27846
+ }, 100);
27847
+ },
27848
+ selectionchange: () => {
27849
+ updateCount++;
27850
+ console.log(`[selectionchange #${updateCount}] Starting, isUpdating:`, isUpdating);
27851
+ if (isUpdating) {
27852
+ console.log(`[selectionchange #${updateCount}] Skipped - already updating`);
27853
+ return;
27854
+ }
27855
+ if (selectionUpdateTimeout) {
27856
+ console.log(`[selectionchange #${updateCount}] Clearing previous timeout`);
27857
+ window.clearTimeout(selectionUpdateTimeout);
27858
+ }
27859
+ selectionUpdateTimeout = window.setTimeout(() => {
27860
+ console.log(`[selectionchange #${updateCount}] Timeout fired`);
27861
+ if (!isUpdating) {
27862
+ updateState.selection();
27863
+ } else {
27864
+ console.log(`[selectionchange #${updateCount}] Skipped - still updating`);
27865
+ }
27866
+ }, 150);
27867
+ },
27868
+ mouseup: () => {
27869
+ updateCount++;
27870
+ console.log(`[mouseup #${updateCount}] Starting, isUpdating:`, isUpdating);
27871
+ if (isUpdating) return;
27872
+ updateState.selection();
27873
+ },
27874
+ keyup: (e) => {
27875
+ updateCount++;
27876
+ console.log(`[keyup #${updateCount}] Key:`, e.key, "isUpdating:", isUpdating);
27877
+ if (isUpdating) return;
27878
+ if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
27879
+ updateState.selection();
27880
+ }
27881
+ }
27882
+ };
27883
+ Object.entries(events).forEach(([event, handler]) => {
27884
+ doc.addEventListener(event, handler);
27885
+ console.log("[setupEventListeners] Added listener for:", event);
27886
+ });
27887
+ cleanupListeners = () => {
27888
+ console.log("[setupEventListeners] Cleaning up event listeners");
27889
+ if (contentUpdateTimeout) window.clearTimeout(contentUpdateTimeout);
27890
+ if (selectionUpdateTimeout) window.clearTimeout(selectionUpdateTimeout);
27891
+ Object.entries(events).forEach(([event, handler]) => {
27892
+ doc.removeEventListener(event, handler);
27893
+ });
27305
27894
  };
27306
- const observer = new MutationObserver(() => {
27307
- cleanEmptyTags();
27308
- });
27309
- observer.observe(doc.body, {
27310
- childList: true,
27311
- subtree: true,
27312
- characterData: true
27313
- });
27895
+ return cleanupListeners;
27314
27896
  }
27315
27897
  function init(doc) {
27898
+ console.log("[init] Starting initialization");
27899
+ if (state2.hasInit) {
27900
+ console.log("[init] Already initialized, cleaning up first");
27901
+ if (cleanupListeners) {
27902
+ cleanupListeners();
27903
+ cleanupListeners = null;
27904
+ }
27905
+ }
27316
27906
  state2.doc = doc;
27317
27907
  state2.hasInit = true;
27318
- setupEventListeners(doc);
27319
- updateContent("html");
27320
- }
27321
- function handleUndo() {
27322
- if (state2.undoStack.length === 0) return;
27323
- state2.redoStack.push(state2.content);
27324
- const lastContent = state2.undoStack.pop();
27325
- if (lastContent !== void 0) {
27326
- state2.content = lastContent;
27327
- updateContent("html");
27328
- }
27329
- }
27330
- function handleRedo() {
27331
- if (state2.redoStack.length === 0) return;
27332
- state2.undoStack.push(state2.content);
27333
- const nextContent = state2.redoStack.pop();
27334
- if (nextContent !== void 0) {
27335
- state2.content = nextContent;
27336
- updateContent("html");
27337
- }
27338
- }
27339
- function handleToolbarAction(action, value) {
27340
- if (!state2.doc) return;
27341
- if (action === "undo") {
27342
- handleUndo();
27343
- return;
27344
- }
27345
- if (action === "redo") {
27346
- handleRedo();
27347
- return;
27348
- }
27349
- if (action === "fullScreen") {
27350
- state2.isFullscreen = !state2.isFullscreen;
27351
- return;
27352
- }
27353
- if (action === "splitView") {
27354
- state2.isSplitView = !state2.isSplitView;
27355
- return;
27908
+ if (state2.content) {
27909
+ const preserved = preserveIframes(state2.content);
27910
+ doc.body.innerHTML = preserved.html;
27911
+ setTimeout(() => {
27912
+ if (state2.doc) {
27913
+ restoreIframes(doc, state2.content, preserved.iframes);
27914
+ }
27915
+ }, 0);
27356
27916
  }
27357
- if (action === "codeView") {
27358
- state2.isCodeView = !state2.isCodeView;
27359
- return;
27917
+ cleanup.normalizeContent(doc);
27918
+ const range2 = doc.createRange();
27919
+ const selection = doc.getSelection();
27920
+ if (selection) {
27921
+ range2.selectNodeContents(doc.body);
27922
+ range2.collapse(false);
27923
+ selection.removeAllRanges();
27924
+ selection.addRange(range2);
27925
+ state2.range = range2.cloneRange();
27926
+ state2.selection = selection;
27927
+ state2.rangeCount = selection.rangeCount;
27928
+ }
27929
+ cleanupListeners = setupEventListeners(doc);
27930
+ }
27931
+ function initDebugger() {
27932
+ if (!state2.debug) {
27933
+ const debugInstance = new EditorDebugger();
27934
+ const debug = {
27935
+ debugger: debugInstance,
27936
+ logCommand: (command, value) => {
27937
+ debugInstance.logCommand(command, value, state2);
27938
+ },
27939
+ getSession: () => debugInstance.getSession(),
27940
+ clearSession: () => {
27941
+ debugInstance.clearSession();
27942
+ },
27943
+ downloadSession: () => {
27944
+ debugInstance.downloadSession();
27945
+ },
27946
+ exportDebugWithPrompt: (message2) => debugInstance.exportSessionWithPrompt(message2)
27947
+ };
27948
+ state2.debug = debug;
27360
27949
  }
27361
- const format2 = formatting(state2);
27362
- state2.doc.body.focus();
27363
- switch (action) {
27364
- case "bold":
27365
- case "italic":
27366
- case "underline":
27367
- format2.text(action);
27368
- break;
27369
- case "orderedList":
27370
- format2.list("ol");
27371
- break;
27372
- case "unorderedList":
27373
- format2.list("ul");
27374
- break;
27375
- case "blockquote":
27376
- case "p":
27377
- case "h1":
27378
- case "h2":
27379
- case "h3":
27380
- case "h4":
27381
- case "h5":
27382
- case "h6":
27383
- format2.block(action, action);
27384
- break;
27385
- case "insertTable": {
27386
- const [rows, cols] = (value == null ? void 0 : value.split("x").map(Number)) || [3, 3];
27387
- insertTable(rows, cols, state2);
27388
- break;
27950
+ }
27951
+ if (typeof window !== "undefined") {
27952
+ window.addEventListener("beforeunload", () => {
27953
+ if (cleanupListeners) {
27954
+ cleanupListeners();
27389
27955
  }
27390
- case "deleteTable":
27391
- if (state2.range) deleteTable(state2.range);
27392
- break;
27393
- case "mergeCells":
27394
- if (state2.range && state2.doc) mergeCells(state2.range, state2.doc);
27395
- break;
27396
- case "splitCells":
27397
- if (state2.range && state2.doc) splitCell(state2.range, state2.doc);
27398
- break;
27399
- case "addRowBefore":
27400
- case "addRowAfter":
27401
- if (state2.range && state2.doc) {
27402
- addRow(action === "addRowBefore" ? "before" : "after", state2.range, state2.doc);
27403
- }
27404
- break;
27405
- case "deleteRow":
27406
- if (state2.range) deleteRow(state2.range);
27407
- break;
27408
- case "insertColumnLeft":
27409
- case "insertColumnRight":
27410
- if (state2.range) {
27411
- insertColumn(action === "insertColumnLeft" ? "before" : "after", state2.range);
27412
- }
27413
- break;
27414
- case "deleteColumn":
27415
- if (state2.range) deleteColumn(state2.range);
27416
- break;
27417
- case "alignLeft":
27418
- case "alignCenter":
27419
- case "alignRight":
27420
- case "alignJustify":
27421
- if (state2.range) {
27422
- alignColumn(state2.range, action.replace("align", "").toLowerCase());
27423
- }
27424
- break;
27425
- case "clear":
27426
- format2.clear();
27427
- break;
27428
- default:
27429
- format2.text(action);
27430
- }
27431
- updateContent("html");
27956
+ });
27432
27957
  }
27433
- const getDebugSession = () => {
27434
- var _a2;
27435
- return (_a2 = editorDebugger.value) == null ? void 0 : _a2.getSession();
27436
- };
27437
- const clearDebugSession = () => {
27438
- var _a2;
27439
- return (_a2 = editorDebugger.value) == null ? void 0 : _a2.clearSession();
27440
- };
27441
- const downloadDebugSession = () => {
27442
- var _a2;
27443
- return (_a2 = editorDebugger.value) == null ? void 0 : _a2.downloadSession();
27444
- };
27445
- const logCommand = (command, value) => {
27446
- var _a2;
27447
- return (_a2 = editorDebugger.value) == null ? void 0 : _a2.logCommand(command, value, state2);
27448
- };
27449
- const exportDebugWithPrompt = (message2) => {
27450
- var _a2;
27451
- return (_a2 = editorDebugger.value) == null ? void 0 : _a2.exportSessionWithPrompt(message2);
27452
- };
27453
27958
  return {
27454
27959
  state: state2,
27455
27960
  init,
27456
- handleToolbarAction,
27457
- updateContent,
27458
- handleUndo,
27459
- handleRedo,
27460
- // Debug methods
27461
- debug: {
27462
- getSession: getDebugSession,
27463
- clearSession: clearDebugSession,
27464
- downloadSession: downloadDebugSession,
27465
- logCommand,
27466
- exportDebugWithPrompt
27467
- }
27468
- };
27469
- }
27470
- function useEditorKeyboard(doc, handleToolbarAction) {
27961
+ updateState,
27962
+ history,
27963
+ initDebugger,
27964
+ cleanup: () => {
27965
+ if (cleanupListeners) {
27966
+ cleanupListeners();
27967
+ cleanupListeners = null;
27968
+ }
27969
+ }
27970
+ };
27971
+ }
27972
+ const shortcuts = [
27973
+ { key: "b", command: "bold" },
27974
+ { key: "i", command: "italic" },
27975
+ { key: "u", command: "underline" },
27976
+ { key: "z", command: "undo" },
27977
+ { key: "z", modifiers: { shift: true }, command: "redo" },
27978
+ { key: "y", command: "redo" },
27979
+ { key: ".", modifiers: { shift: true }, command: "orderedList" },
27980
+ { key: "/", modifiers: { shift: true }, command: "unorderedList" },
27981
+ { key: "]", command: "indent" },
27982
+ { key: "[", command: "outdent" },
27983
+ ...Array.from({ length: 6 }, (_2, i2) => ({
27984
+ key: String(i2 + 1),
27985
+ modifiers: { alt: true },
27986
+ command: `h${i2 + 1}`
27987
+ }))
27988
+ ];
27989
+ function useEditorKeyboard(doc, executor) {
27471
27990
  doc.addEventListener("keydown", (e) => {
27472
- if (e.ctrlKey || e.metaKey) {
27473
- switch (e.key) {
27474
- case "b":
27475
- e.preventDefault();
27476
- handleToolbarAction("bold");
27477
- break;
27478
- case "i":
27479
- e.preventDefault();
27480
- handleToolbarAction("italic");
27481
- break;
27482
- case "u":
27483
- e.preventDefault();
27484
- handleToolbarAction("underline");
27485
- break;
27486
- case "z":
27487
- e.preventDefault();
27488
- if (e.shiftKey) {
27489
- handleToolbarAction("redo");
27490
- } else {
27491
- handleToolbarAction("undo");
27492
- }
27493
- break;
27494
- case "y":
27495
- e.preventDefault();
27496
- handleToolbarAction("redo");
27497
- break;
27498
- // List shortcuts
27499
- case ".":
27500
- if (e.shiftKey) {
27501
- e.preventDefault();
27502
- handleToolbarAction("orderedList");
27503
- }
27504
- break;
27505
- case "/":
27506
- if (e.shiftKey) {
27991
+ var _a2, _b;
27992
+ if (e.key === "Enter" && !e.shiftKey) {
27993
+ const selection = doc.getSelection();
27994
+ if (!selection || !selection.rangeCount) return;
27995
+ const range2 = selection.getRangeAt(0);
27996
+ const container = range2.commonAncestorContainer;
27997
+ const listItem = (_a2 = container.nodeType === 3 ? container.parentElement : container) == null ? void 0 : _a2.closest("li");
27998
+ if (listItem) {
27999
+ if (range2.collapsed && isAtEndOfNode(listItem, range2)) {
28000
+ if (isNodeEmpty(listItem)) {
27507
28001
  e.preventDefault();
27508
- handleToolbarAction("unorderedList");
27509
- }
27510
- break;
27511
- // Heading shortcuts
27512
- case "1":
27513
- case "2":
27514
- case "3":
27515
- case "4":
27516
- case "5":
27517
- case "6":
27518
- if (e.altKey) {
28002
+ const list = listItem.parentElement;
28003
+ if (!list) return;
28004
+ listItem.remove();
28005
+ if (!list.querySelector("li")) {
28006
+ const p2 = doc.createElement("p");
28007
+ p2.innerHTML = "<br>";
28008
+ (_b = list.parentNode) == null ? void 0 : _b.replaceChild(p2, list);
28009
+ range2.selectNodeContents(p2);
28010
+ range2.collapse(true);
28011
+ selection.removeAllRanges();
28012
+ selection.addRange(range2);
28013
+ }
28014
+ } else {
27519
28015
  e.preventDefault();
27520
- handleToolbarAction(`h${e.key}`);
28016
+ const newLi = doc.createElement("li");
28017
+ newLi.innerHTML = "&nbsp;<br>";
28018
+ listItem.insertAdjacentElement("afterend", newLi);
28019
+ range2.selectNodeContents(newLi);
28020
+ range2.collapse(true);
28021
+ selection.removeAllRanges();
28022
+ selection.addRange(range2);
27521
28023
  }
27522
- break;
27523
- // Indentation
27524
- case "]":
27525
- e.preventDefault();
27526
- handleToolbarAction("indent");
27527
- break;
27528
- case "[":
27529
- e.preventDefault();
27530
- handleToolbarAction("outdent");
27531
- break;
28024
+ }
27532
28025
  }
27533
28026
  }
28027
+ if (!e.ctrlKey && !e.metaKey) return;
28028
+ const matchingShortcut = shortcuts.find((shortcut) => {
28029
+ const keyMatch = shortcut.key === e.key;
28030
+ const modifiersMatch = !shortcut.modifiers || (!shortcut.modifiers.ctrl || e.ctrlKey || e.metaKey) && (!shortcut.modifiers.alt || e.altKey) && (!shortcut.modifiers.shift || e.shiftKey);
28031
+ return keyMatch && modifiersMatch;
28032
+ });
28033
+ if (matchingShortcut) {
28034
+ e.preventDefault();
28035
+ executor.execute(matchingShortcut.command);
28036
+ }
27534
28037
  });
27535
28038
  }
28039
+ function isAtEndOfNode(node, range2) {
28040
+ var _a2;
28041
+ if (node.nodeType === 3) {
28042
+ return range2.startOffset === node.length;
28043
+ }
28044
+ const { lastChild: lastChild2 } = node;
28045
+ if (!lastChild2) return true;
28046
+ if (lastChild2.nodeType === 3) {
28047
+ return range2.startContainer === lastChild2 && range2.startOffset === ((_a2 = lastChild2.textContent) == null ? void 0 : _a2.length);
28048
+ }
28049
+ return range2.startContainer === node && range2.startOffset === node.childNodes.length;
28050
+ }
28051
+ function isNodeEmpty(node) {
28052
+ var _a2;
28053
+ const text = ((_a2 = node.textContent) == null ? void 0 : _a2.replace(/\s/g, "")) || "";
28054
+ if (text) return false;
28055
+ const brElements = node.getElementsByTagName("br");
28056
+ if (brElements.length === 0) return true;
28057
+ return brElements.length === 1 && node.childNodes.length <= 2;
28058
+ }
27536
28059
  const _hoisted_1$s = { class: "bagel-input" };
27537
28060
  const _hoisted_2$i = { class: "content-area radius-05" };
27538
28061
  const _hoisted_3$e = {
@@ -27553,58 +28076,104 @@ const _sfc_main$z = /* @__PURE__ */ vue.defineComponent({
27553
28076
  const emit2 = __emit;
27554
28077
  const iframe = vue.ref();
27555
28078
  const editor = useEditor();
27556
- const commands = useCommands(editor.state, props2.debug ? editor.debug : void 0);
27557
- const debugMethods = vue.computed(() => props2.debug ? editor.debug : void 0);
28079
+ const isInitializing = vue.ref(false);
28080
+ const hasInitialized = vue.ref(false);
28081
+ if (props2.debug) {
28082
+ editor.initDebugger();
28083
+ }
28084
+ const commands = useCommands(editor.state, editor.state.debug);
28085
+ const debugMethods = vue.computed(() => editor.state.debug);
27558
28086
  const hasRTL = vue.computed(() => /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/.test(props2.modelValue));
28087
+ vue.onUnmounted(() => {
28088
+ editor.cleanup();
28089
+ });
27559
28090
  async function initEditor() {
27560
28091
  var _a2;
27561
- if (!iframe.value) {
27562
- setTimeout(initEditor, 100);
28092
+ console.log("[initEditor] Starting, isInitializing:", isInitializing.value, "hasInitialized:", hasInitialized.value);
28093
+ if (isInitializing.value || !iframe.value || hasInitialized.value) {
28094
+ console.log("[initEditor] Skipped - already initializing/initialized or no iframe");
27563
28095
  return;
27564
28096
  }
27565
- editor.state.content = props2.modelValue || "";
27566
- const doc = iframe.value.contentDocument || ((_a2 = iframe.value.contentWindow) == null ? void 0 : _a2.document);
27567
- if (!doc) return;
27568
- doc.designMode = "on";
27569
- doc.body.contentEditable = "true";
27570
- doc.body.dir = hasRTL.value ? "rtl" : "ltr";
27571
- const style = doc.createElement("style");
27572
- style.textContent = (await Promise.resolve().then(() => require("./editor-B3mMCQSg.cjs"))).default;
27573
- doc.head.appendChild(style);
27574
- editor.init(doc);
27575
- useEditorKeyboard(doc, commands.execute);
27576
- if (!doc.body.firstElementChild) {
27577
- const p2 = doc.createElement("p");
27578
- p2.dir = doc.body.dir;
27579
- p2.innerHTML = "<br>";
27580
- doc.body.appendChild(p2);
27581
- } else {
27582
- const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
27583
- const textNodes = [];
27584
- let node;
27585
- while (node = walker.nextNode()) {
27586
- if (node.parentElement === doc.body) {
27587
- textNodes.push(node);
27588
- }
28097
+ isInitializing.value = true;
28098
+ try {
28099
+ const editorStyles = await Promise.resolve().then(() => require("./editor-CpMNx6Eo.cjs"));
28100
+ const htmlContent = `
28101
+ <!DOCTYPE html>
28102
+ <html>
28103
+ <head>
28104
+ <meta charset="UTF-8">
28105
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
28106
+ <meta http-equiv="Content-Security-Policy" content="
28107
+ default-src * data: blob: 'unsafe-inline' 'unsafe-eval';
28108
+ img-src * data: blob:;
28109
+ style-src * 'unsafe-inline';
28110
+ script-src * 'unsafe-inline' 'unsafe-eval';
28111
+ frame-src * data: blob:;
28112
+ connect-src *;
28113
+ media-src *;
28114
+ ">
28115
+ <base target="_blank">
28116
+ <style id="editor-styles">${editorStyles.default}</style>
28117
+ </head>
28118
+ <body>${props2.modelValue || ""}</body>
28119
+ </html>
28120
+ `;
28121
+ const doc = iframe.value.contentDocument || ((_a2 = iframe.value.contentWindow) == null ? void 0 : _a2.document);
28122
+ if (!doc) {
28123
+ console.warn("[initEditor] No document found");
28124
+ return;
27589
28125
  }
27590
- textNodes.forEach((textNode) => {
27591
- var _a3;
27592
- if ((_a3 = textNode.textContent) == null ? void 0 : _a3.trim()) {
27593
- const p2 = doc.createElement("p");
27594
- p2.dir = doc.body.dir;
27595
- p2.appendChild(textNode.cloneNode());
27596
- doc.body.replaceChild(p2, textNode);
27597
- } else {
27598
- doc.body.removeChild(textNode);
28126
+ doc.open();
28127
+ doc.write(htmlContent);
28128
+ doc.close();
28129
+ await new Promise((resolve) => setTimeout(resolve, 0));
28130
+ doc.designMode = "on";
28131
+ doc.body.contentEditable = "true";
28132
+ doc.body.dir = hasRTL.value ? "rtl" : "ltr";
28133
+ editor.init(doc);
28134
+ useEditorKeyboard(doc, commands);
28135
+ if (!doc.body.firstElementChild) {
28136
+ const p2 = doc.createElement("p");
28137
+ p2.dir = doc.body.dir;
28138
+ p2.innerHTML = "<br>";
28139
+ doc.body.appendChild(p2);
28140
+ } else {
28141
+ const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
28142
+ const textNodes = [];
28143
+ let node;
28144
+ while (node = walker.nextNode()) {
28145
+ if (node.parentElement === doc.body) {
28146
+ textNodes.push(node);
28147
+ }
27599
28148
  }
27600
- });
28149
+ textNodes.forEach((textNode) => {
28150
+ var _a3;
28151
+ if ((_a3 = textNode.textContent) == null ? void 0 : _a3.trim()) {
28152
+ const p2 = doc.createElement("p");
28153
+ p2.dir = doc.body.dir;
28154
+ p2.appendChild(textNode.cloneNode());
28155
+ doc.body.replaceChild(p2, textNode);
28156
+ } else {
28157
+ doc.body.removeChild(textNode);
28158
+ }
28159
+ });
28160
+ }
28161
+ doc.body.focus();
28162
+ hasInitialized.value = true;
28163
+ } catch (error) {
28164
+ console.error("[initEditor] Error during initialization:", error);
28165
+ } finally {
28166
+ isInitializing.value = false;
27601
28167
  }
27602
- doc.body.focus();
27603
28168
  }
27604
- vue.watch(() => props2.modelValue, (newValue) => {
28169
+ vue.watch(() => props2.modelValue, (newValue, oldValue) => {
27605
28170
  if (newValue !== editor.state.content) {
27606
- editor.state.content = newValue;
27607
- editor.updateContent("html");
28171
+ if (!oldValue || Math.abs(newValue.length - oldValue.length) > 50) {
28172
+ console.log("[watch] Significant content change, resetting initialization state");
28173
+ hasInitialized.value = false;
28174
+ editor.state.content = newValue;
28175
+ editor.updateState.content("html");
28176
+ }
27608
28177
  }
27609
28178
  });
27610
28179
  vue.watch(() => editor.state.content, (newValue) => {
@@ -27637,6 +28206,8 @@ const _sfc_main$z = /* @__PURE__ */ vue.defineComponent({
27637
28206
  ref: iframe,
27638
28207
  class: "editableContent",
27639
28208
  title: "Editor",
28209
+ sandbox: "allow-same-origin allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts allow-top-navigation allow-top-navigation-by-user-activation",
28210
+ src: "about:blank",
27640
28211
  onLoad: initEditor
27641
28212
  }, null, 544)
27642
28213
  ]),
@@ -27645,7 +28216,7 @@ const _sfc_main$z = /* @__PURE__ */ vue.defineComponent({
27645
28216
  modelValue: vue.unref(editor).state.content,
27646
28217
  "onUpdate:modelValue": [
27647
28218
  _cache[0] || (_cache[0] = ($event) => vue.unref(editor).state.content = $event),
27648
- _cache[1] || (_cache[1] = ($event) => vue.unref(editor).updateContent("html"))
28219
+ _cache[1] || (_cache[1] = ($event) => vue.unref(editor).updateState.content("html"))
27649
28220
  ],
27650
28221
  language: "html"
27651
28222
  }, null, 8, ["modelValue"])) : vue.createCommentVNode("", true)
@@ -27694,7 +28265,7 @@ const _sfc_main$z = /* @__PURE__ */ vue.defineComponent({
27694
28265
  };
27695
28266
  }
27696
28267
  });
27697
- const RichText = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["__scopeId", "data-v-08117333"]]);
28268
+ const RichText = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["__scopeId", "data-v-b58de58d"]]);
27698
28269
  const _hoisted_1$r = { class: "flex gap-05" };
27699
28270
  const _hoisted_2$h = ["disabled"];
27700
28271
  const _hoisted_3$d = { key: 1 };