@pie-element/placement-ordering 14.1.2-next.8 → 14.1.2-next.9

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.
@@ -10,23 +10,35 @@
10
10
  * Custom keyboard coordinate getter for placement-ordering's Tab-based placement mode
11
11
  * (enabled only when the item is configured with `placementArea` / `includeTargets`).
12
12
  *
13
- * Tab/Shift+Tab cycle the dragged choice directly onto the next/previous enabled
14
- * droppable (a placement/target tile, or an empty gap left behind in the choices row),
15
- * in real on-screen position order, placing the dragged item's own top-left corner at
16
- * the target's center-left point.
13
+ * Tab/Shift+Tab cycle the dragged choice through the target column's response areas
14
+ * in on-screen order (first target, then the rest in sequence), followed by exactly
15
+ * one source-column stop as a fixed last step before the cycle wraps back to the first
16
+ * target — so picking up a choice always starts the cycle at the first target,
17
+ * regardless of where that choice's own source-column slot happens to sit on screen.
17
18
  *
18
19
  * Arrow keys are delegated to dnd-kit's own `defaultKeyboardCoordinateGetter` so the
19
20
  * pre-existing free-form arrow-key dragging behavior is left completely unchanged.
20
21
  *
21
- * The tile currently being dragged already disables its own droppable
22
- * (see `useDroppable({ disabled: isDragging })` in tile.jsx), so it's naturally
23
- * excluded from the candidate list here without any extra bookkeeping.
22
+ * Whichever slot a drag started from — a target the choice was already placed in, or
23
+ * (see below) the choice's own pool slot — stays reachable by Tab as a no-op "drop it
24
+ * back where it came from": tile.tsx disables a droppable for the whole duration of
25
+ * its own drag (a self-collision guard for pointer drags), which would otherwise make
26
+ * that exact slot unreachable; that guard is bypassed here specifically for the one
27
+ * droppable matching the active drag's own id. A target slot picked up this way stays
28
+ * in its normal position in the target sequence (it's just another target); nothing
29
+ * special is needed there beyond the bypass itself.
24
30
  *
25
- * When picking up a choice from the choices row, the other not-yet-placed choice
26
- * tiles are also registered droppables (tile.jsx disables a droppable only while it's
27
- * the one being dragged), but dropping a choice onto another choice is a no-op in the
28
- * reducer (ordering.js's updateResponse has no `choice -> choice` case) — so they're
29
- * excluded from the Tab/Shift+Tab cycle, leaving only the real placement targets.
31
+ * The choices column isn't a place a student can choose to relocate an answer within —
32
+ * there's exactly one meaningful "source" stop for whichever choice is currently being
33
+ * dragged: its own fixed slot, whether that's the vacated gap left behind (if the
34
+ * choice is already placed in a target — landing back on it returns the choice to the
35
+ * pool, undoing the placement) or the very tile being dragged (if the choice is still
36
+ * sitting there, unplaced — landing back on it is a no-op that effectively cancels the
37
+ * pick-up; the same disabled-droppable bypass applies here too). Every *other*
38
+ * choice-column tile — filled or an empty gap — is excluded from the cycle:
39
+ * `ordering.ts`'s `updateResponse` has no `choice -> choice` case, so they'd be no-op
40
+ * drop targets anyway. Matching is by id (the vacated gap carries its original choice's
41
+ * id specifically so this comparison works), not by type alone.
30
42
  */
31
43
  export declare const closestDroppableKeyboardCoordinates: (event: any, { active, context, currentCoordinates }: {
32
44
  active: any;
@@ -8,41 +8,44 @@ var n = (n, { active: i, context: a, currentCoordinates: o }) => {
8
8
  currentCoordinates: o
9
9
  });
10
10
  n.preventDefault();
11
- let { droppableRects: u, droppableContainers: d, collisionRect: f } = a;
11
+ let { droppableRects: u, droppableContainers: d, collisionRect: f, draggableNodes: p, active: m } = a;
12
12
  if (!u || u.size === 0) return o;
13
- let p = {
13
+ let h = {
14
14
  x: (f?.width || 0) / 2,
15
15
  y: (f?.height || 0) / 2
16
- }, m = {
17
- x: o.x + p.x,
18
- y: o.y + p.y
19
- }, h = i?.data?.current?.type === "choice", g = [];
16
+ }, g = {
17
+ x: o.x + h.x,
18
+ y: o.y + h.y
19
+ }, _ = p?.get(i)?.data?.current?.id, v = m?.rect?.current?.initial, y = typeof i == "string" ? i.replace(/^tile-/, "drop-") : void 0, b = [], x;
20
20
  for (let [e, t] of d) {
21
- if (t?.disabled || h && t?.data?.current?.type === "choice") continue;
22
- let n = u.get(e);
23
- if (!n) continue;
24
- let r = {
25
- x: n.left + n.width / 2,
26
- y: n.top + n.height / 2
27
- }, i = {
28
- x: n.left,
29
- y: n.top + n.height / 2
30
- };
31
- g.push({
21
+ let n = t?.data?.current, r = e === y;
22
+ if (t?.disabled && !r) continue;
23
+ let i = n?.type === "choice" && n?.id === _;
24
+ if (n?.type === "choice" && !i) continue;
25
+ let a = (r ? v : null) || u.get(e);
26
+ if (!a) continue;
27
+ let o = {
28
+ x: a.left + a.width / 2,
29
+ y: a.top + a.height / 2
30
+ }, s = {
32
31
  id: e,
33
- dropPosition: i,
34
- center: r
35
- });
32
+ dropPosition: {
33
+ x: a.left,
34
+ y: a.top + a.height / 2 - h.y
35
+ },
36
+ center: o
37
+ };
38
+ i ? x = s : b.push(s);
36
39
  }
37
- if (g.length === 0) return o;
38
- let _ = n.shiftKey;
39
- g.sort((e, t) => Math.abs(e.center.y - t.center.y) > 10 ? e.center.y - t.center.y : e.center.x - t.center.x);
40
- let v = 0, y = Infinity;
41
- for (let e = 0; e < g.length; e++) {
42
- let t = r(m, g[e].center);
43
- t < y && (y = t, v = e);
40
+ if (b.length === 0 && !x) return o;
41
+ let S = n.shiftKey;
42
+ b.sort((e, t) => Math.abs(e.center.y - t.center.y) > 10 ? e.center.y - t.center.y : e.center.x - t.center.x), x && b.push(x);
43
+ let C = 0, w = Infinity;
44
+ for (let e = 0; e < b.length; e++) {
45
+ let t = r(g, b[e].center);
46
+ t < w && (w = t, C = e);
44
47
  }
45
- return g[_ ? (v - 1 + g.length) % g.length : (v + 1) % g.length].dropPosition;
48
+ return b[S ? (C - 1 + b.length) % b.length : (C + 1) % b.length].dropPosition;
46
49
  }, r = (e, t) => Math.sqrt((e.x - t.x) ** 2 + (e.y - t.y) ** 2);
47
50
  //#endregion
48
51
  export { n as closestDroppableKeyboardCoordinates };
@@ -40,6 +40,7 @@ function u(e, t, n, r) {
40
40
  }
41
41
  return e.map((e) => t.indexOf(e.id) !== -1 && !r.allowSameChoiceInTargets ? {
42
42
  type: "choice",
43
+ id: e.id,
43
44
  empty: !0,
44
45
  droppable: !0,
45
46
  draggable: !1
@@ -24,7 +24,11 @@ function A(e) {
24
24
  function j(e, t) {
25
25
  return !e || A(e) ? e : A(e.default) ? e.default : t && A(e[t]) ? e[t] : t && A(e[t]?.default) ? e[t].default : e;
26
26
  }
27
- var M = j(x, "UiLayout") || j(R.UiLayout, "UiLayout"), N = j(b, "PreviewPrompt") || j(R.PreviewPrompt, "PreviewPrompt"), P = j(y, "Feedback") || j(R.Feedback, "Feedback"), F = j(v, "Collapsible") || j(R.Collapsible, "Collapsible"), I = _, L = I.default, R = L && typeof L == "object" ? L : I, z = 250, B = (e) => e ? {
27
+ var M = j(x, "UiLayout") || j(R.UiLayout, "UiLayout"), N = j(b, "PreviewPrompt") || j(R.PreviewPrompt, "PreviewPrompt"), P = j(y, "Feedback") || j(R.Feedback, "Feedback"), F = j(v, "Collapsible") || j(R.Collapsible, "Collapsible"), I = _, L = I.default, R = L && typeof L == "object" ? L : I, z = 250, B = (e, t) => {
28
+ if (!e || !t) return !1;
29
+ let n = t.left + t.width / 2, r = t.top + t.height / 2;
30
+ return n >= e.left && n <= e.right && r >= e.top && r <= e.bottom;
31
+ }, V = (e) => e ? {
28
32
  keyboardCoordinateGetter: a,
29
33
  keyboardCodes: {
30
34
  start: ["Space", "Enter"],
@@ -32,26 +36,26 @@ var M = j(x, "UiLayout") || j(R.UiLayout, "UiLayout"), N = j(b, "PreviewPrompt")
32
36
  end: ["Space", "Enter"]
33
37
  },
34
38
  accessibility: { screenReaderInstructions: { draggable: "Press Space or Enter to pick up this answer choice. Once picked up, use Tab or Shift+Tab to cycle through response areas, or use arrow keys to move it freely. Press Space or Enter to drop, or Escape to cancel." } }
35
- } : {}, { translator: V } = D, H = u("pie-elements:placement-ordering"), U = m("div")({
39
+ } : {}, { translator: H } = D, U = u("pie-elements:placement-ordering"), W = m("div")({
36
40
  color: S.text(),
37
41
  backgroundColor: S.background(),
38
42
  display: "flex",
39
43
  flexDirection: "column",
40
44
  alignItems: "center",
41
45
  boxSizing: "border-box"
42
- }), W = m("div")({
46
+ }), G = m("div")({
43
47
  alignSelf: "stretch",
44
48
  maxWidth: "100%",
45
49
  overflowX: "auto",
46
50
  overflowY: "hidden"
47
- }), G = m("div")({
51
+ }), K = m("div")({
48
52
  display: "flex",
49
53
  justifyContent: "center",
50
54
  minWidth: "min-content"
51
- }), K = m("div")(({ theme: e }) => ({ paddingBottom: e.spacing(1) })), q = m("div")(({ theme: e }) => ({ paddingBottom: e.spacing(2) })), J = m(O)(({ theme: e }) => ({ paddingBottom: e.spacing(1) })), Y = m(F)(({ theme: e }) => ({
55
+ }), q = m("div")(({ theme: e }) => ({ paddingBottom: e.spacing(1) })), J = m("div")(({ theme: e }) => ({ paddingBottom: e.spacing(2) })), Y = m(O)(({ theme: e }) => ({ paddingBottom: e.spacing(1) })), X = m(F)(({ theme: e }) => ({
52
56
  marginBottom: e.spacing(2),
53
57
  alignSelf: "flex-start"
54
- })), X = (e) => {
58
+ })), Z = (e) => {
55
59
  let { tiler: t, ordering: n, onDropChoice: r, onRemoveChoice: i, ...a } = e;
56
60
  return /* @__PURE__ */ T(t, {
57
61
  ...a,
@@ -60,13 +64,13 @@ var M = j(x, "UiLayout") || j(R.UiLayout, "UiLayout"), N = j(b, "PreviewPrompt")
60
64
  onRemoveChoice: (e) => i(e, n)
61
65
  });
62
66
  };
63
- X.propTypes = {
67
+ Z.propTypes = {
64
68
  tiler: f.func,
65
69
  ordering: f.any,
66
70
  onDropChoice: f.func,
67
71
  onRemoveChoice: f.func
68
72
  };
69
- var Z = class extends o.Component {
73
+ var Q = class extends o.Component {
70
74
  static propTypes = {
71
75
  onSessionChange: f.func.isRequired,
72
76
  model: f.object.isRequired,
@@ -106,8 +110,8 @@ var Z = class extends o.Component {
106
110
  };
107
111
  };
108
112
  UNSAFE_componentWillReceiveProps(e) {
109
- let { model: t = {} } = e || {}, { model: n = {} } = this.props || {}, { correctResponse: r, config: a, choices: o = [], env: s } = t, { includeTargets: c } = a || {}, l = {}, u = n.language && n.language !== t.language, d = n.note && n.note === V.t("common:commonCorrectAnswerWithAlternates", { lng: n.language });
110
- u && d && (n.note = V.t("common:commonCorrectAnswerWithAlternates", { lng: t.language })), r || (l.showingCorrect = !1);
113
+ let { model: t = {} } = e || {}, { model: n = {} } = this.props || {}, { correctResponse: r, config: a, choices: o = [], env: s } = t, { includeTargets: c } = a || {}, l = {}, u = n.language && n.language !== t.language, d = n.note && n.note === H.t("common:commonCorrectAnswerWithAlternates", { lng: n.language });
114
+ u && d && (n.note = H.t("common:commonCorrectAnswerWithAlternates", { lng: t.language })), r || (l.showingCorrect = !1);
111
115
  let f = i(o, n.choices), { value: p, needsReset: m } = this.validateSession(e, f), h = {
112
116
  ...e.session,
113
117
  value: p
@@ -119,7 +123,7 @@ var Z = class extends o.Component {
119
123
  }
120
124
  onDropChoice = (e, t, n) => {
121
125
  let { onSessionChange: i, session: a } = this.props, o = n.tiles.find((e) => e.id === t.id && e.type === t.type && e.index === t.index), s = e;
122
- H("[onDropChoice] ", o, s);
126
+ U("[onDropChoice] ", o, s);
123
127
  let c = r({
124
128
  type: "move",
125
129
  from: o,
@@ -129,7 +133,7 @@ var Z = class extends o.Component {
129
133
  };
130
134
  onRemoveChoice = (e, t) => {
131
135
  let { onSessionChange: n, session: i } = this.props;
132
- H("[onRemoveChoice]", e);
136
+ U("[onRemoveChoice]", e);
133
137
  let a = r({
134
138
  type: "remove",
135
139
  target: e
@@ -162,8 +166,8 @@ var Z = class extends o.Component {
162
166
  }
163
167
  e && i && this.onDropChoice(i, e, r);
164
168
  } else if (!t && n) {
165
- let e = n.data.current;
166
- e && e.type === "target" && this.onRemoveChoice(e, r);
169
+ let e = n.data.current, t = B(n.rect?.current?.initial, n.rect?.current?.translated);
170
+ e && e.type === "target" && !t && this.onRemoveChoice(e, r);
167
171
  }
168
172
  };
169
173
  onDragStart = (e) => {
@@ -207,7 +211,7 @@ var Z = class extends o.Component {
207
211
  let { model: n } = this.props, { correctResponse: r, correctness: i, extraCSSRules: a, prompt: o, rationale: s, feedback: c, config: l, note: u, showNote: d, env: f, disabled: p, teacherInstructions: m, language: _ } = n, v = r && r.length > 0, { showingCorrect: y } = this.state, b = l || {
208
212
  orientation: "vertical",
209
213
  includeTargets: !0
210
- }, { orientation: x, includeTargets: D } = b, O = x === "vertical", A = this.createOrdering(), { mode: j, role: F } = f || {}, I = O ? t : e, L = (y || j === "view" && F === "instructor") && d && u, R = s && (w(s) || C(s)), z = m && (w(m) || C(m)), V = {
214
+ }, { orientation: x, includeTargets: D } = b, O = x === "vertical", A = this.createOrdering(), { mode: j, role: F } = f || {}, I = O ? t : e, L = (y || j === "view" && F === "instructor") && d && u, R = s && (w(s) || C(s)), z = m && (w(m) || C(m)), B = {
211
215
  color: S.text(),
212
216
  backgroundColor: S.background(),
213
217
  display: "flex",
@@ -226,12 +230,12 @@ var Z = class extends o.Component {
226
230
  onDragCancel: this.onDragCancel,
227
231
  collisionDetection: h,
228
232
  modifiers: [g],
229
- ...B(D),
230
- children: /* @__PURE__ */ T(U, { children: /* @__PURE__ */ E(M, {
233
+ ...V(D),
234
+ children: /* @__PURE__ */ T(W, { children: /* @__PURE__ */ E(M, {
231
235
  extraCSSRules: a,
232
- style: V,
236
+ style: B,
233
237
  children: [
234
- z && /* @__PURE__ */ T(Y, {
238
+ z && /* @__PURE__ */ T(X, {
235
239
  labels: {
236
240
  hidden: "Show Teacher Instructions",
237
241
  visible: "Hide Teacher Instructions"
@@ -239,14 +243,14 @@ var Z = class extends o.Component {
239
243
  className: "collapsible",
240
244
  children: /* @__PURE__ */ T(N, { prompt: m })
241
245
  }),
242
- /* @__PURE__ */ T(K, { children: /* @__PURE__ */ T(N, { prompt: o }) }),
243
- /* @__PURE__ */ T(J, {
246
+ /* @__PURE__ */ T(q, { children: /* @__PURE__ */ T(N, { prompt: o }) }),
247
+ /* @__PURE__ */ T(Y, {
244
248
  show: v,
245
249
  toggled: y,
246
250
  onToggle: this.toggleCorrect,
247
251
  language: _
248
252
  }),
249
- /* @__PURE__ */ T(W, { children: /* @__PURE__ */ T(G, { children: /* @__PURE__ */ T(X, {
253
+ /* @__PURE__ */ T(G, { children: /* @__PURE__ */ T(K, { children: /* @__PURE__ */ T(Z, {
250
254
  instanceId: this.instanceId,
251
255
  choiceLabel: b.choiceLabel,
252
256
  targetLabel: b.targetLabel,
@@ -259,8 +263,8 @@ var Z = class extends o.Component {
259
263
  choiceLabelEnabled: n.config && n.config.choiceLabelEnabled,
260
264
  ...H
261
265
  }) }) }),
262
- L && /* @__PURE__ */ T(q, { dangerouslySetInnerHTML: { __html: u } }),
263
- R && /* @__PURE__ */ T(Y, {
266
+ L && /* @__PURE__ */ T(J, { dangerouslySetInnerHTML: { __html: u } }),
267
+ R && /* @__PURE__ */ T(X, {
264
268
  labels: {
265
269
  hidden: "Show Rationale",
266
270
  visible: "Hide Rationale"
@@ -278,4 +282,4 @@ var Z = class extends o.Component {
278
282
  }
279
283
  };
280
284
  //#endregion
281
- export { Z as PlacementOrdering, Z as default };
285
+ export { Q as PlacementOrdering, Q as default };