eat-js-sdk 2.0.42 → 2.0.44

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.
@@ -5114,6 +5114,15 @@ const CATEGORISE = {
5114
5114
  CONTAINER_WORD_BIN_ID: "container-word-bin",
5115
5115
  DASH: "@eat-dash@"
5116
5116
  };
5117
+ const DROPDOWN_POSITION = {
5118
+ MIN_WIDTH: 240,
5119
+ MAX_WIDTH: 500,
5120
+ VIEWPORT_PADDING: 16
5121
+ };
5122
+ const DROPDOWN_INTERACTION = {
5123
+ KEY_PRESS_TIMEOUT: 1e3,
5124
+ PAGE_NAVIGATION_STEP: 10
5125
+ };
5117
5126
  const INTERACTION_TYPE_MAP = {
5118
5127
  [INTERACTION_TYPES.MCQ]: "mcq",
5119
5128
  [INTERACTION_TYPES.CATEGORISE]: "categorise",
@@ -5853,7 +5862,7 @@ function FeedbackAlert($$anchor, $$props) {
5853
5862
  }
5854
5863
  };
5855
5864
  if_block(node_1, ($$render) => {
5856
- if (showIcon() && type() !== "skipped") $$render(consequent);
5865
+ if (showIcon()) $$render(consequent);
5857
5866
  });
5858
5867
  }
5859
5868
  var div_1 = sibling(node_1, 2);
@@ -5884,7 +5893,7 @@ function FeedbackAlert($$anchor, $$props) {
5884
5893
  append($$anchor2, div);
5885
5894
  };
5886
5895
  if_block(node, ($$render) => {
5887
- if (message()) $$render(consequent_2);
5896
+ if (message() && type() !== "skipped") $$render(consequent_2);
5888
5897
  });
5889
5898
  }
5890
5899
  append($$anchor, fragment);
@@ -7870,6 +7879,7 @@ const DEFAULT_TWO_COLUMN_ORDER = [
7870
7879
  "divider",
7871
7880
  "feedback",
7872
7881
  "interaction",
7882
+ "divider-bottom",
7873
7883
  "desktop-column"
7874
7884
  ];
7875
7885
  const DEFAULT_SINGLE_COLUMN_ORDER = [
@@ -7880,6 +7890,7 @@ const DEFAULT_SINGLE_COLUMN_ORDER = [
7880
7890
  "prompt",
7881
7891
  "divider",
7882
7892
  "feedback",
7893
+ "divider-bottom",
7883
7894
  "interaction"
7884
7895
  ];
7885
7896
  const FEEDBACK_LAST_TWO_COLUMN_ORDER = [
@@ -7893,6 +7904,7 @@ const FEEDBACK_LAST_TWO_COLUMN_ORDER = [
7893
7904
  "stimulus-mobile-text-second",
7894
7905
  "divider",
7895
7906
  "interaction",
7907
+ "divider-bottom",
7896
7908
  "feedback",
7897
7909
  "desktop-column"
7898
7910
  ];
@@ -7904,6 +7916,7 @@ const FEEDBACK_LAST_SINGLE_COLUMN_ORDER = [
7904
7916
  "prompt",
7905
7917
  "divider",
7906
7918
  "interaction",
7919
+ "divider-bottom",
7907
7920
  "feedback"
7908
7921
  ];
7909
7922
  const FEEDBACK_LAST_INTERACTIONS = [INTERACTION_TYPES.TYPEIN, INTERACTION_TYPES.DROPDOWN];
@@ -7963,6 +7976,7 @@ const twoColumnTemplate = {
7963
7976
  },
7964
7977
  { name: "divider", component: "divider", condition: context.hasDivider },
7965
7978
  { name: "interaction", component: "slot", slot: "interaction" },
7979
+ { name: "divider-bottom", component: "divider-bottom", condition: context.hasDividerBottom },
7966
7980
  { name: "feedback", component: "slot", slot: "feedback" },
7967
7981
  {
7968
7982
  name: "desktop-column",
@@ -8005,6 +8019,7 @@ const singleColumnTemplate = {
8005
8019
  { name: "prompt", component: "prompt" },
8006
8020
  { name: "divider", component: "divider", condition: context.hasDivider },
8007
8021
  { name: "interaction", component: "slot", slot: "interaction" },
8022
+ { name: "divider-bottom", component: "divider-bottom", condition: context.hasDividerBottom },
8008
8023
  { name: "feedback", component: "slot", slot: "feedback" }
8009
8024
  ];
8010
8025
  const order = getSingleColumnOrder(context.interactionType);
@@ -8042,6 +8057,7 @@ const fullWidthStimulusTextTemplate = {
8042
8057
  { name: "prompt", component: "prompt", classes: ["lg:max-w-[50%]"] },
8043
8058
  { name: "divider", component: "divider", condition: context.hasDivider, classes: ["lg:max-w-[50%]"] },
8044
8059
  { name: "interaction", component: "slot", slot: "interaction", classes: ["lg:max-w-[50%]"] },
8060
+ { name: "divider-bottom", component: "divider-bottom", condition: context.hasDividerBottom, classes: ["lg:max-w-[50%]"] },
8045
8061
  { name: "feedback", component: "slot", slot: "feedback", classes: ["lg:max-w-[50%]"] }
8046
8062
  ];
8047
8063
  const order = getSingleColumnOrder(context.interactionType);
@@ -8496,13 +8512,14 @@ create_custom_element(
8496
8512
  true
8497
8513
  );
8498
8514
  var root_8$3 = /* @__PURE__ */ from_html(`<div class="divider my-6"></div>`);
8499
- var root_13$1 = /* @__PURE__ */ from_html(`<div aria-live="polite"><!></div>`);
8515
+ var root_13$1 = /* @__PURE__ */ from_html(`<div class="divider my-6"></div>`);
8516
+ var root_15$1 = /* @__PURE__ */ from_html(`<div aria-live="polite"><!></div>`);
8500
8517
  var root_1$h = /* @__PURE__ */ from_html(`<div><!></div>`);
8501
- var root_14 = /* @__PURE__ */ from_html(`<div><!></div>`);
8518
+ var root_16 = /* @__PURE__ */ from_html(`<div><!></div>`);
8502
8519
  var root$e = /* @__PURE__ */ from_html(`<div class="prompt-container"><div><div></div> <!></div></div> <!>`, 1);
8503
8520
  function PromptContainer($$anchor, $$props) {
8504
8521
  push($$props, true);
8505
- let rubric = prop($$props, "rubric", 7, ""), prompt = prop($$props, "prompt", 7, ""), interactionType = prop($$props, "interactionType", 7), hasDivider = prop($$props, "hasDivider", 7, true), stimulus = prop($$props, "stimulus", 7, null), optionHasMedia = prop($$props, "optionHasMedia", 7, false), interaction = prop($$props, "interaction", 7), feedback = prop($$props, "feedback", 7);
8522
+ let rubric = prop($$props, "rubric", 7, ""), prompt = prop($$props, "prompt", 7, ""), interactionType = prop($$props, "interactionType", 7), hasDivider = prop($$props, "hasDivider", 7, true), hasDividerBottom = prop($$props, "hasDividerBottom", 7, false), stimulus = prop($$props, "stimulus", 7, null), optionHasMedia = prop($$props, "optionHasMedia", 7, false), interaction = prop($$props, "interaction", 7), feedback = prop($$props, "feedback", 7);
8506
8523
  let stimulusData = /* @__PURE__ */ user_derived(() => useStimulusData(stimulus()));
8507
8524
  const windowWidth = getReactiveWindowWidth();
8508
8525
  let interactionWidthValue = /* @__PURE__ */ user_derived(() => getInteractionWidth(interactionType(), get$1(stimulusData), windowWidth.value));
@@ -8513,6 +8530,7 @@ function PromptContainer($$anchor, $$props) {
8513
8530
  rubric: rubric(),
8514
8531
  prompt: prompt(),
8515
8532
  hasDivider: hasDivider(),
8533
+ hasDividerBottom: hasDividerBottom(),
8516
8534
  interactionWidthValue: get$1(interactionWidthValue),
8517
8535
  windowWidth: windowWidth.value
8518
8536
  }));
@@ -8577,6 +8595,13 @@ function PromptContainer($$anchor, $$props) {
8577
8595
  hasDivider($$value);
8578
8596
  flushSync();
8579
8597
  },
8598
+ get hasDividerBottom() {
8599
+ return hasDividerBottom();
8600
+ },
8601
+ set hasDividerBottom($$value = false) {
8602
+ hasDividerBottom($$value);
8603
+ flushSync();
8604
+ },
8580
8605
  get stimulus() {
8581
8606
  return stimulus();
8582
8607
  },
@@ -8621,7 +8646,7 @@ function PromptContainer($$anchor, $$props) {
8621
8646
  }
8622
8647
  });
8623
8648
  };
8624
- var alternate_4 = ($$anchor3) => {
8649
+ var alternate_5 = ($$anchor3) => {
8625
8650
  var fragment_2 = comment();
8626
8651
  var node_1 = first_child(fragment_2);
8627
8652
  {
@@ -8632,7 +8657,7 @@ function PromptContainer($$anchor, $$props) {
8632
8657
  }
8633
8658
  });
8634
8659
  };
8635
- var alternate_3 = ($$anchor4) => {
8660
+ var alternate_4 = ($$anchor4) => {
8636
8661
  var fragment_4 = comment();
8637
8662
  var node_2 = first_child(fragment_4);
8638
8663
  {
@@ -8653,7 +8678,7 @@ function PromptContainer($$anchor, $$props) {
8653
8678
  });
8654
8679
  }
8655
8680
  };
8656
- var alternate_2 = ($$anchor5) => {
8681
+ var alternate_3 = ($$anchor5) => {
8657
8682
  var fragment_6 = comment();
8658
8683
  var node_3 = first_child(fragment_6);
8659
8684
  {
@@ -8661,7 +8686,7 @@ function PromptContainer($$anchor, $$props) {
8661
8686
  var div_4 = root_8$3();
8662
8687
  append($$anchor6, div_4);
8663
8688
  };
8664
- var alternate_1 = ($$anchor6) => {
8689
+ var alternate_2 = ($$anchor6) => {
8665
8690
  var fragment_7 = comment();
8666
8691
  var node_4 = first_child(fragment_7);
8667
8692
  {
@@ -8676,21 +8701,40 @@ function PromptContainer($$anchor, $$props) {
8676
8701
  $$slots: { default: true }
8677
8702
  });
8678
8703
  };
8679
- var alternate = ($$anchor7) => {
8704
+ var alternate_1 = ($$anchor7) => {
8680
8705
  var fragment_10 = comment();
8681
8706
  var node_6 = first_child(fragment_10);
8682
8707
  {
8683
8708
  var consequent_5 = ($$anchor8) => {
8684
8709
  var div_5 = root_13$1();
8685
- var node_7 = child(div_5);
8686
- snippet(node_7, () => feedback() ?? noop);
8687
- reset(div_5);
8688
8710
  append($$anchor8, div_5);
8689
8711
  };
8712
+ var alternate = ($$anchor8) => {
8713
+ var fragment_11 = comment();
8714
+ var node_7 = first_child(fragment_11);
8715
+ {
8716
+ var consequent_6 = ($$anchor9) => {
8717
+ var div_6 = root_15$1();
8718
+ var node_8 = child(div_6);
8719
+ snippet(node_8, () => feedback() ?? noop);
8720
+ reset(div_6);
8721
+ append($$anchor9, div_6);
8722
+ };
8723
+ if_block(
8724
+ node_7,
8725
+ ($$render) => {
8726
+ if (get$1(section).component === "slot" && get$1(section).slot === "feedback") $$render(consequent_6);
8727
+ },
8728
+ true
8729
+ );
8730
+ }
8731
+ append($$anchor8, fragment_11);
8732
+ };
8690
8733
  if_block(
8691
8734
  node_6,
8692
8735
  ($$render) => {
8693
- if (get$1(section).component === "slot" && get$1(section).slot === "feedback") $$render(consequent_5);
8736
+ if (get$1(section).component === "divider-bottom") $$render(consequent_5);
8737
+ else $$render(alternate, false);
8694
8738
  },
8695
8739
  true
8696
8740
  );
@@ -8701,7 +8745,7 @@ function PromptContainer($$anchor, $$props) {
8701
8745
  node_4,
8702
8746
  ($$render) => {
8703
8747
  if (get$1(section).component === "slot" && get$1(section).slot === "interaction") $$render(consequent_4);
8704
- else $$render(alternate, false);
8748
+ else $$render(alternate_1, false);
8705
8749
  },
8706
8750
  true
8707
8751
  );
@@ -8712,7 +8756,7 @@ function PromptContainer($$anchor, $$props) {
8712
8756
  node_3,
8713
8757
  ($$render) => {
8714
8758
  if (get$1(section).component === "divider") $$render(consequent_3);
8715
- else $$render(alternate_1, false);
8759
+ else $$render(alternate_2, false);
8716
8760
  },
8717
8761
  true
8718
8762
  );
@@ -8723,7 +8767,7 @@ function PromptContainer($$anchor, $$props) {
8723
8767
  node_2,
8724
8768
  ($$render) => {
8725
8769
  if (get$1(section).component === "stimulus-text" || get$1(section).component === "stimulus-media") $$render(consequent_2);
8726
- else $$render(alternate_2, false);
8770
+ else $$render(alternate_3, false);
8727
8771
  },
8728
8772
  true
8729
8773
  );
@@ -8734,7 +8778,7 @@ function PromptContainer($$anchor, $$props) {
8734
8778
  node_1,
8735
8779
  ($$render) => {
8736
8780
  if (get$1(section).component === "prompt") $$render(consequent_1);
8737
- else $$render(alternate_3, false);
8781
+ else $$render(alternate_4, false);
8738
8782
  },
8739
8783
  true
8740
8784
  );
@@ -8743,7 +8787,7 @@ function PromptContainer($$anchor, $$props) {
8743
8787
  };
8744
8788
  if_block(node, ($$render) => {
8745
8789
  if (get$1(section).component === "rubric") $$render(consequent);
8746
- else $$render(alternate_4, false);
8790
+ else $$render(alternate_5, false);
8747
8791
  });
8748
8792
  }
8749
8793
  reset(div_3);
@@ -8760,12 +8804,12 @@ function PromptContainer($$anchor, $$props) {
8760
8804
  append($$anchor2, div_3);
8761
8805
  });
8762
8806
  reset(div_2);
8763
- var node_8 = sibling(div_2, 2);
8807
+ var node_9 = sibling(div_2, 2);
8764
8808
  {
8765
- var consequent_6 = ($$anchor2) => {
8766
- var div_6 = root_14();
8767
- var node_9 = child(div_6);
8768
- StimulusSection(node_9, {
8809
+ var consequent_7 = ($$anchor2) => {
8810
+ var div_7 = root_16();
8811
+ var node_10 = child(div_7);
8812
+ StimulusSection(node_10, {
8769
8813
  get stimulusData() {
8770
8814
  return get$1(stimulusData);
8771
8815
  },
@@ -8774,29 +8818,29 @@ function PromptContainer($$anchor, $$props) {
8774
8818
  },
8775
8819
  onexpandImage: openStimulusModal
8776
8820
  });
8777
- reset(div_6);
8778
- bind_this(div_6, ($$value) => set(containerElement, $$value), () => get$1(containerElement));
8821
+ reset(div_7);
8822
+ bind_this(div_7, ($$value) => set(containerElement, $$value), () => get$1(containerElement));
8779
8823
  template_effect(
8780
8824
  ($0, $1) => {
8781
- set_class(div_6, 1, $0);
8782
- set_style(div_6, `${$1 ?? ""}; ${get$1(dynamicMarginTop) ?? ""}`);
8825
+ set_class(div_7, 1, $0);
8826
+ set_style(div_7, `${$1 ?? ""}; ${get$1(dynamicMarginTop) ?? ""}`);
8783
8827
  },
8784
8828
  [
8785
8829
  () => clsx(getClassString(get$1(desktopColumnSection).classes)),
8786
8830
  () => getStyleString(get$1(desktopColumnSection).styles)
8787
8831
  ]
8788
8832
  );
8789
- append($$anchor2, div_6);
8833
+ append($$anchor2, div_7);
8790
8834
  };
8791
- if_block(node_8, ($$render) => {
8792
- if (get$1(desktopColumnSection)) $$render(consequent_6);
8835
+ if_block(node_9, ($$render) => {
8836
+ if (get$1(desktopColumnSection)) $$render(consequent_7);
8793
8837
  });
8794
8838
  }
8795
8839
  reset(div_1);
8796
8840
  reset(div);
8797
- var node_10 = sibling(div, 2);
8841
+ var node_11 = sibling(div, 2);
8798
8842
  {
8799
- var consequent_7 = ($$anchor2) => {
8843
+ var consequent_8 = ($$anchor2) => {
8800
8844
  PromptStimulusImageModal($$anchor2, {
8801
8845
  get isOpen() {
8802
8846
  return get$1(isStimulusModalOpen);
@@ -8813,8 +8857,8 @@ function PromptContainer($$anchor, $$props) {
8813
8857
  onclose: closeStimulusModal
8814
8858
  });
8815
8859
  };
8816
- if_block(node_10, ($$render) => {
8817
- if (get$1(isStimulusModalOpen)) $$render(consequent_7);
8860
+ if_block(node_11, ($$render) => {
8861
+ if (get$1(isStimulusModalOpen)) $$render(consequent_8);
8818
8862
  });
8819
8863
  }
8820
8864
  template_effect(
@@ -8838,6 +8882,7 @@ create_custom_element(
8838
8882
  prompt: {},
8839
8883
  interactionType: {},
8840
8884
  hasDivider: {},
8885
+ hasDividerBottom: {},
8841
8886
  stimulus: {},
8842
8887
  optionHasMedia: {},
8843
8888
  interaction: {},
@@ -11672,6 +11717,138 @@ const useFilterUniqueObject = (data, identifier = "id") => {
11672
11717
  const uniqueMap = new Map(data.map((obj) => [obj[identifier], obj]));
11673
11718
  return Array.from(uniqueMap.values());
11674
11719
  };
11720
+ const stripStatus = (itemId) => {
11721
+ return itemId.includes(CATEGORISE.DASH) ? itemId.split(CATEGORISE.DASH)[0] : itemId;
11722
+ };
11723
+ function useCategoriseFeedback(interactionState, config, api) {
11724
+ const totalRemainingItems = interactionState.data.wordBinItems.filter((id) => {
11725
+ const status = id.split(CATEGORISE.DASH)[1];
11726
+ return status !== "missed";
11727
+ }).length;
11728
+ let isFeedbackShown = false;
11729
+ let allAnswersCorrect = false;
11730
+ let isItemSkipped = false;
11731
+ let resultFeedback = "";
11732
+ if (config.isFinished && config.mode !== "preview") {
11733
+ const { answerList } = config.scoringMetadata || {};
11734
+ if (!answerList) {
11735
+ return {
11736
+ isFeedbackShown,
11737
+ allAnswersCorrect,
11738
+ isItemSkipped,
11739
+ resultFeedback
11740
+ };
11741
+ }
11742
+ const { correct: correctFeedback, incorrect: incorrectFeedback } = config.feedback || {};
11743
+ let hasIncorrect = false;
11744
+ let hasCorrect = false;
11745
+ const hasWordBinItems = totalRemainingItems > 0;
11746
+ config.category_groups.forEach((category) => {
11747
+ const categoryAnswerList = answerList[category.id] || [];
11748
+ const categoryItems = api.getCategoryItems(interactionState, category.id);
11749
+ categoryItems.forEach((item) => {
11750
+ const itemIdNoStatus = stripStatus(item);
11751
+ if (categoryAnswerList.includes(itemIdNoStatus)) {
11752
+ hasCorrect = true;
11753
+ } else {
11754
+ hasIncorrect = true;
11755
+ }
11756
+ });
11757
+ });
11758
+ allAnswersCorrect = hasCorrect && !hasIncorrect && !hasWordBinItems;
11759
+ isItemSkipped = totalRemainingItems === config.totalCategoryItems;
11760
+ resultFeedback = allAnswersCorrect ? correctFeedback : incorrectFeedback;
11761
+ isFeedbackShown = !allAnswersCorrect;
11762
+ } else if (config.mode === "interactive") {
11763
+ const allItemsPlaced = totalRemainingItems === 0;
11764
+ if (allItemsPlaced) {
11765
+ const { answerList } = config.scoringMetadata || {};
11766
+ if (answerList) {
11767
+ let hasIncorrect = false;
11768
+ let hasCorrect = false;
11769
+ config.category_groups.forEach((category) => {
11770
+ const categoryAnswerList = answerList[category.id] || [];
11771
+ const categoryItems = api.getCategoryItems(interactionState, category.id);
11772
+ categoryItems.forEach((item) => {
11773
+ const itemIdNoStatus = stripStatus(item);
11774
+ if (categoryAnswerList.includes(itemIdNoStatus)) {
11775
+ hasCorrect = true;
11776
+ } else {
11777
+ hasIncorrect = true;
11778
+ }
11779
+ });
11780
+ });
11781
+ allAnswersCorrect = hasCorrect && !hasIncorrect;
11782
+ resultFeedback = allAnswersCorrect ? config.feedback?.correct : config.feedback?.incorrect;
11783
+ isFeedbackShown = true;
11784
+ }
11785
+ } else {
11786
+ isFeedbackShown = false;
11787
+ }
11788
+ } else {
11789
+ isFeedbackShown = false;
11790
+ }
11791
+ return {
11792
+ isFeedbackShown,
11793
+ allAnswersCorrect,
11794
+ isItemSkipped,
11795
+ resultFeedback
11796
+ };
11797
+ }
11798
+ function CategoriseFeedback($$anchor, $$props) {
11799
+ push($$props, true);
11800
+ let feedbackState = prop($$props, "feedbackState", 7), isInteractiveMode2 = prop($$props, "isInteractiveMode", 7, false);
11801
+ const feedbackType = /* @__PURE__ */ user_derived(() => {
11802
+ if (feedbackState().isItemSkipped) return "skipped";
11803
+ if (feedbackState().allAnswersCorrect) return "correct";
11804
+ return "incorrect";
11805
+ });
11806
+ var $$exports = {
11807
+ get feedbackState() {
11808
+ return feedbackState();
11809
+ },
11810
+ set feedbackState($$value) {
11811
+ feedbackState($$value);
11812
+ flushSync();
11813
+ },
11814
+ get isInteractiveMode() {
11815
+ return isInteractiveMode2();
11816
+ },
11817
+ set isInteractiveMode($$value = false) {
11818
+ isInteractiveMode2($$value);
11819
+ flushSync();
11820
+ }
11821
+ };
11822
+ var fragment = comment();
11823
+ var node = first_child(fragment);
11824
+ {
11825
+ var consequent = ($$anchor2) => {
11826
+ {
11827
+ let $0 = /* @__PURE__ */ user_derived(() => !isInteractiveMode2());
11828
+ FeedbackAlert($$anchor2, {
11829
+ get type() {
11830
+ return get$1(feedbackType);
11831
+ },
11832
+ get message() {
11833
+ return feedbackState().resultFeedback;
11834
+ },
11835
+ showIcon: true,
11836
+ get isAlert() {
11837
+ return get$1($0);
11838
+ },
11839
+ iconProps: "h-6 w-6 flex items-center pt-0.5 mr-2",
11840
+ iconType: "info"
11841
+ });
11842
+ }
11843
+ };
11844
+ if_block(node, ($$render) => {
11845
+ if (feedbackState().isFeedbackShown) $$render(consequent);
11846
+ });
11847
+ }
11848
+ append($$anchor, fragment);
11849
+ return pop($$exports);
11850
+ }
11851
+ create_custom_element(CategoriseFeedback, { feedbackState: {}, isInteractiveMode: {} }, [], [], true);
11675
11852
  function ownKeys(object, enumerableOnly) {
11676
11853
  var keys = Object.keys(object);
11677
11854
  if (Object.getOwnPropertySymbols) {
@@ -15407,71 +15584,7 @@ function CategoriseComponent($$anchor, $$props) {
15407
15584
  return status !== "missed";
15408
15585
  }).length);
15409
15586
  const totalPlacedItems = /* @__PURE__ */ user_derived(() => config().totalCategoryItems - get$1(totalRemainingItems));
15410
- let isFeedbackShown = /* @__PURE__ */ state(false);
15411
- let allAnswersCorrect = /* @__PURE__ */ state(false);
15412
- let isItemSkipped = /* @__PURE__ */ state(false);
15413
- let resultFeedback = /* @__PURE__ */ state("");
15414
- const stripStatus = (itemId) => {
15415
- return itemId.includes(CATEGORISE.DASH) ? itemId.split(CATEGORISE.DASH)[0] : itemId;
15416
- };
15417
- user_effect(() => {
15418
- if (config().isFinished && config().mode !== "preview") {
15419
- const { answerList } = config().scoringMetadata || {};
15420
- if (!answerList) return;
15421
- const { correct: correctFeedback, incorrect: incorrectFeedback } = config().feedback || {};
15422
- let hasIncorrect = false;
15423
- let hasCorrect = false;
15424
- const hasWordBinItems = get$1(totalRemainingItems) > 0;
15425
- config().category_groups.forEach((category) => {
15426
- const categoryAnswerList = answerList[category.id] || [];
15427
- const categoryItems = api().getCategoryItems(get$1(interactionState), category.id);
15428
- categoryItems.forEach((item) => {
15429
- const itemIdNoStatus = stripStatus(item);
15430
- if (categoryAnswerList.includes(itemIdNoStatus)) {
15431
- hasCorrect = true;
15432
- } else {
15433
- hasIncorrect = true;
15434
- }
15435
- });
15436
- });
15437
- set(allAnswersCorrect, hasCorrect && !hasIncorrect && !hasWordBinItems, true);
15438
- set(isItemSkipped, get$1(totalRemainingItems) === config().totalCategoryItems);
15439
- set(resultFeedback, get$1(allAnswersCorrect) ? correctFeedback : incorrectFeedback, true);
15440
- set(isFeedbackShown, !get$1(allAnswersCorrect));
15441
- } else if (config().mode === "interactive") {
15442
- const allItemsPlaced = get$1(totalRemainingItems) === 0;
15443
- if (allItemsPlaced) {
15444
- const { answerList } = config().scoringMetadata || {};
15445
- if (answerList) {
15446
- let hasIncorrect = false;
15447
- let hasCorrect = false;
15448
- config().category_groups.forEach((category) => {
15449
- const categoryAnswerList = answerList[category.id] || [];
15450
- const categoryItems = api().getCategoryItems(get$1(interactionState), category.id);
15451
- categoryItems.forEach((item) => {
15452
- const itemIdNoStatus = stripStatus(item);
15453
- if (categoryAnswerList.includes(itemIdNoStatus)) {
15454
- hasCorrect = true;
15455
- } else {
15456
- hasIncorrect = true;
15457
- }
15458
- });
15459
- });
15460
- set(allAnswersCorrect, hasCorrect && !hasIncorrect, true);
15461
- set(
15462
- resultFeedback,
15463
- get$1(allAnswersCorrect) ? config().feedback?.correct : config().feedback?.incorrect,
15464
- true
15465
- );
15466
- set(isFeedbackShown, true);
15467
- }
15468
- } else {
15469
- set(isFeedbackShown, false);
15470
- }
15471
- } else {
15472
- set(isFeedbackShown, false);
15473
- }
15474
- });
15587
+ const feedbackState = /* @__PURE__ */ user_derived(() => useCategoriseFeedback(get$1(interactionState), config(), api()));
15475
15588
  const dropContainerId = /* @__PURE__ */ user_derived(() => get$1(interactionState).data.dropContainerId);
15476
15589
  const hasAddItemAnimation = /* @__PURE__ */ user_derived(() => get$1(interactionState).data.hasAddItemAnimation);
15477
15590
  const wordBinItems = /* @__PURE__ */ user_derived(() => get$1(interactionState).data.wordBinItems.map((id) => ({
@@ -15628,6 +15741,8 @@ function CategoriseComponent($$anchor, $$props) {
15628
15741
  }
15629
15742
  }
15630
15743
  }
15744
+ } else {
15745
+ set(dragSourceContainerId, null);
15631
15746
  }
15632
15747
  });
15633
15748
  user_effect(() => {
@@ -15844,6 +15959,7 @@ function CategoriseComponent($$anchor, $$props) {
15844
15959
  set(interactionState, api().reset(get$1(interactionState)), true);
15845
15960
  dispatchStateChange();
15846
15961
  set(currentMobileIndex, 0);
15962
+ set(dragSourceContainerId, null);
15847
15963
  set(isModalOpen, false);
15848
15964
  };
15849
15965
  var $$exports = {
@@ -16083,34 +16199,17 @@ function CategoriseComponent($$anchor, $$props) {
16083
16199
  append($$anchor2, fragment_1);
16084
16200
  };
16085
16201
  const feedback = ($$anchor2) => {
16086
- var fragment_4 = comment();
16087
- var node_7 = first_child(fragment_4);
16088
16202
  {
16089
- var consequent_1 = ($$anchor3) => {
16090
- {
16091
- let $02 = /* @__PURE__ */ user_derived(() => get$1(allAnswersCorrect) ? "correct" : get$1(isItemSkipped) ? "skipped" : "incorrect");
16092
- let $12 = /* @__PURE__ */ user_derived(() => config().mode !== "interactive");
16093
- FeedbackAlert($$anchor3, {
16094
- get type() {
16095
- return get$1($02);
16096
- },
16097
- get message() {
16098
- return get$1(resultFeedback);
16099
- },
16100
- showIcon: true,
16101
- get isAlert() {
16102
- return get$1($12);
16103
- },
16104
- iconProps: "h-6 w-6 flex items-center pt-0.5 mr-2",
16105
- iconType: "info"
16106
- });
16203
+ let $02 = /* @__PURE__ */ user_derived(() => config().mode === "interactive");
16204
+ CategoriseFeedback($$anchor2, {
16205
+ get feedbackState() {
16206
+ return get$1(feedbackState);
16207
+ },
16208
+ get isInteractiveMode() {
16209
+ return get$1($02);
16107
16210
  }
16108
- };
16109
- if_block(node_7, ($$render) => {
16110
- if (get$1(isFeedbackShown)) $$render(consequent_1);
16111
16211
  });
16112
16212
  }
16113
- append($$anchor2, fragment_4);
16114
16213
  };
16115
16214
  let $0 = /* @__PURE__ */ user_derived(() => config().rubric?.text || "");
16116
16215
  let $1 = /* @__PURE__ */ user_derived(() => config().prompt || "");
@@ -16686,7 +16785,6 @@ function useDropdown(prompt, options) {
16686
16785
  parseText
16687
16786
  };
16688
16787
  }
16689
- const KEY_PRESS_TIMEOUT = 1e3;
16690
16788
  function useDropdownState() {
16691
16789
  const scrollToActive = async (listElement, activeIndex) => {
16692
16790
  if (!listElement || activeIndex === null || activeIndex < 0) return;
@@ -16702,7 +16800,7 @@ function useDropdownState() {
16702
16800
  };
16703
16801
  const handleTypeAhead = (char, state2, options) => {
16704
16802
  const now2 = Date.now();
16705
- let searchString = now2 - state2.lastKeyPressTime > KEY_PRESS_TIMEOUT ? "" : state2.searchString;
16803
+ let searchString = now2 - state2.lastKeyPressTime > DROPDOWN_INTERACTION.KEY_PRESS_TIMEOUT ? "" : state2.searchString;
16706
16804
  searchString += char.toLowerCase();
16707
16805
  const matchIndex = options.findIndex((option) => {
16708
16806
  const cleanOption = option.replace(/<[^>]*>/g, "").toLowerCase();
@@ -16812,7 +16910,7 @@ function useDropdownState() {
16812
16910
  if (state2.activeIndex === null) {
16813
16911
  newState.activeIndex = 0;
16814
16912
  } else {
16815
- const newIndex = state2.activeIndex - 10;
16913
+ const newIndex = state2.activeIndex - DROPDOWN_INTERACTION.PAGE_NAVIGATION_STEP;
16816
16914
  newState.activeIndex = newIndex < 0 ? 0 : newIndex;
16817
16915
  }
16818
16916
  return newState;
@@ -16821,7 +16919,7 @@ function useDropdownState() {
16821
16919
  if (state2.activeIndex === null) {
16822
16920
  newState.activeIndex = 0;
16823
16921
  } else {
16824
- const newIndex = state2.activeIndex + 10;
16922
+ const newIndex = state2.activeIndex + DROPDOWN_INTERACTION.PAGE_NAVIGATION_STEP;
16825
16923
  newState.activeIndex = newIndex >= options.length ? options.length - 1 : newIndex;
16826
16924
  }
16827
16925
  return newState;
@@ -16954,6 +17052,29 @@ function calculateDropdownFeedback(state2, config, validateFn) {
16954
17052
  sessionAnswer
16955
17053
  };
16956
17054
  }
17055
+ function useDropdownPosition(config) {
17056
+ const minWidth = DROPDOWN_POSITION.MIN_WIDTH;
17057
+ const maxWidth = DROPDOWN_POSITION.MAX_WIDTH;
17058
+ const viewportPadding = DROPDOWN_POSITION.VIEWPORT_PADDING;
17059
+ const adjustDropdownWidth = async (containerRef, listRef) => {
17060
+ if (!containerRef || !listRef) return;
17061
+ const containerRect = containerRef.getBoundingClientRect();
17062
+ const viewportWidth = window.innerWidth;
17063
+ listRef.style.left = "0";
17064
+ listRef.style.right = "auto";
17065
+ const availableWidth = viewportWidth - containerRect.left - viewportPadding;
17066
+ if (availableWidth >= maxWidth) {
17067
+ listRef.style.maxWidth = `${maxWidth}px`;
17068
+ } else if (availableWidth >= minWidth) {
17069
+ listRef.style.maxWidth = `${availableWidth}px`;
17070
+ } else {
17071
+ listRef.style.maxWidth = `${minWidth}px`;
17072
+ }
17073
+ };
17074
+ return {
17075
+ adjustDropdownWidth
17076
+ };
17077
+ }
16957
17078
  var root_1$3 = /* @__PURE__ */ from_html(`<div class="absolute inset-0 bg-transparent z-10"></div>`);
16958
17079
  var root_2 = /* @__PURE__ */ from_html(`<span class="text-green-900 mr-2"><span aria-hidden="true"><!></span> <span class="sr-only">Correct</span></span>`);
16959
17080
  var root_5$1 = /* @__PURE__ */ from_html(`<span class="text-green-900 mr-2"><span aria-hidden="true"><!></span> <span class="sr-only">Correct</span></span>`);
@@ -16970,6 +17091,7 @@ function DropdownContainer($$anchor, $$props) {
16970
17091
  push($$props, true);
16971
17092
  let dropdownId = prop($$props, "dropdownId", 7), dropdownNumber = prop($$props, "dropdownNumber", 7), options = prop($$props, "options", 7), selected = prop($$props, "selected", 7), correctAnswers = prop($$props, "correctAnswers", 23, () => []), isCorrect = prop($$props, "isCorrect", 7, false), isFinished = prop($$props, "isFinished", 7, false), isLocked = prop($$props, "isLocked", 7, false), isDataSaving = prop($$props, "isDataSaving", 7, false), mode = prop($$props, "mode", 7), showFeedback = prop($$props, "showFeedback", 7, false), onselect = prop($$props, "onselect", 7), viewportBuffer = prop($$props, "viewportBuffer", 7, 60);
16972
17093
  const dropdownActions = useDropdownState();
17094
+ const dropdownPosition = useDropdownPosition();
16973
17095
  let initializedOptions = /* @__PURE__ */ user_derived(() => {
16974
17096
  if (options().length === 0) return [];
16975
17097
  return [...options()];
@@ -16982,6 +17104,7 @@ function DropdownContainer($$anchor, $$props) {
16982
17104
  let hoveredIndex = /* @__PURE__ */ state(null);
16983
17105
  let isFirstNavigation = /* @__PURE__ */ state(false);
16984
17106
  let pageExtensionElement = /* @__PURE__ */ state(null);
17107
+ let resizeTimeout = null;
16985
17108
  user_effect(() => {
16986
17109
  get$1(state$1).selected = selected();
16987
17110
  });
@@ -17005,6 +17128,7 @@ function DropdownContainer($$anchor, $$props) {
17005
17128
  const ensureDropdownVisibility = async () => {
17006
17129
  if (!get$1(containerRef) || !get$1(listRef)) return;
17007
17130
  await tick();
17131
+ await dropdownPosition.adjustDropdownWidth(get$1(containerRef), get$1(listRef));
17008
17132
  const listRect = get$1(listRef).getBoundingClientRect();
17009
17133
  const viewportHeight = window.innerHeight;
17010
17134
  const documentHeight = document.documentElement.scrollHeight;
@@ -17154,11 +17278,32 @@ function DropdownContainer($$anchor, $$props) {
17154
17278
  }
17155
17279
  handleCloseMenu();
17156
17280
  };
17281
+ const handleResize = () => {
17282
+ if (!get$1(state$1).isOpen || !get$1(containerRef) || !get$1(listRef)) return;
17283
+ if (resizeTimeout) {
17284
+ clearTimeout(resizeTimeout);
17285
+ }
17286
+ resizeTimeout = setTimeout(
17287
+ () => {
17288
+ if (get$1(state$1).isOpen && get$1(containerRef) && get$1(listRef)) {
17289
+ dropdownPosition.adjustDropdownWidth(get$1(containerRef), get$1(listRef));
17290
+ }
17291
+ resizeTimeout = null;
17292
+ },
17293
+ 150
17294
+ );
17295
+ };
17157
17296
  onMount(() => {
17158
17297
  document.addEventListener("mousedown", handleClickOutside);
17298
+ window.addEventListener("resize", handleResize);
17159
17299
  });
17160
17300
  onDestroy(() => {
17161
17301
  document.removeEventListener("mousedown", handleClickOutside);
17302
+ window.removeEventListener("resize", handleResize);
17303
+ if (resizeTimeout) {
17304
+ clearTimeout(resizeTimeout);
17305
+ resizeTimeout = null;
17306
+ }
17162
17307
  removePageExtension();
17163
17308
  });
17164
17309
  const buttonId = `dropdown-button-${dropdownId()}`;
@@ -18049,7 +18194,8 @@ function DropdownComponent($$anchor, $$props) {
18049
18194
  return config().stimulus;
18050
18195
  },
18051
18196
  optionHasMedia: false,
18052
- hasDivider: true,
18197
+ hasDivider: false,
18198
+ hasDividerBottom: true,
18053
18199
  interaction,
18054
18200
  feedback,
18055
18201
  $$slots: { interaction: true, feedback: true }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eat-js-sdk",
3
- "version": "2.0.42",
3
+ "version": "2.0.44",
4
4
  "change version": "2.0.0",
5
5
  "description": "Authoring tool frontend SDK",
6
6
  "contributors": [