@pie-element/placement-ordering 14.3.2-beta.4 → 14.3.3

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.
@@ -14,6 +14,7 @@ var _debug = _interopRequireDefault(require("debug"));
14
14
  var _lodashEs = require("lodash-es");
15
15
  var _styles = require("@mui/material/styles");
16
16
  var _core = require("@dnd-kit/core");
17
+ var _modifiers = require("@dnd-kit/modifiers");
17
18
  var _renderUi = require("@pie-lib/render-ui");
18
19
  var _mathRendering = require("@pie-lib/math-rendering");
19
20
  var _translator = _interopRequireDefault(require("@pie-lib/translator"));
@@ -22,6 +23,24 @@ var _drag = require("@pie-lib/drag");
22
23
  var _tiler = require("./tiler");
23
24
  var _ordering = require("./ordering");
24
25
  var _utils = require("./utils");
26
+ var _keyboardCoordinates = require("./keyboard-coordinates");
27
+ // A click that lands right after a real drag gesture ends must be ignored by the
28
+ // click-to-select/click-to-place handlers below, or it would immediately reopen or
29
+ // re-trigger a selection for a drag that just completed.
30
+ const CLICK_AFTER_DRAG_GUARD_MS = 250;
31
+ const getKeyboardDragOptions = includeTargets => includeTargets ? {
32
+ keyboardCoordinateGetter: _keyboardCoordinates.closestDroppableKeyboardCoordinates,
33
+ keyboardCodes: {
34
+ start: ['Space', 'Enter'],
35
+ cancel: ['Escape'],
36
+ end: ['Space', 'Enter']
37
+ },
38
+ accessibility: {
39
+ screenReaderInstructions: {
40
+ 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.'
41
+ }
42
+ }
43
+ } : {};
25
44
  const {
26
45
  translator
27
46
  } = _translator.default;
@@ -34,6 +53,26 @@ const PlacementOrderingContainer = (0, _styles.styled)('div')({
34
53
  alignItems: 'center',
35
54
  boxSizing: 'border-box'
36
55
  });
56
+
57
+ // The interactive region - the choices and answers columns for a vertical item, or the choices and
58
+ // answers rows for a horizontal one - scrolls horizontally when it does not fit the available width.
59
+ const InteractiveRegion = (0, _styles.styled)('div')({
60
+ // the ancestors centre their children, which shrink-wraps this box to its content. without a
61
+ // definite width it grows with the tiler and the overflow escapes outwards instead of scrolling.
62
+ alignSelf: 'stretch',
63
+ maxWidth: '100%',
64
+ overflowX: 'auto',
65
+ // tiles are dragged by transform, which counts towards scrollable overflow, so leaving this axis
66
+ // scrollable would pop a vertical scrollbar mid-drag
67
+ overflowY: 'hidden'
68
+ });
69
+
70
+ // keeps the tiler at its natural width, and centred while it still fits
71
+ const InteractiveRegionContent = (0, _styles.styled)('div')({
72
+ display: 'flex',
73
+ justifyContent: 'center',
74
+ minWidth: 'min-content'
75
+ });
37
76
  const StyledPrompt = (0, _styles.styled)('div')(({
38
77
  theme
39
78
  }) => ({
@@ -202,6 +241,12 @@ class PlacementOrdering extends _react.default.Component {
202
241
  active
203
242
  } = event;
204
243
  const ordering = this.createOrdering();
244
+
245
+ // A real drag (pointer or keyboard) just ended — whatever mirrored selection it
246
+ // set on start is now resolved, and any click landing immediately after this must
247
+ // not be misread as a fresh selection/placement
248
+ this.cancelSelection();
249
+ this.lastDragEndAt = Date.now();
205
250
  if (over && active) {
206
251
  const draggedItem = active.data.current;
207
252
  const droppedOnItem = over.data.current;
@@ -219,14 +264,91 @@ class PlacementOrdering extends _react.default.Component {
219
264
  }
220
265
  }
221
266
  });
267
+ (0, _defineProperty2.default)(this, "onDragStart", event => {
268
+ const {
269
+ active
270
+ } = event;
271
+ if (active?.data?.current) {
272
+ // A real drag (pointer or keyboard) is itself a selection — mirror it into the
273
+ // same selectedChoice state that click-to-select uses, so the two interaction
274
+ // models can be freely intermixed
275
+ this.selectChoice(active.data.current);
276
+ }
277
+ });
278
+ (0, _defineProperty2.default)(this, "onDragCancel", () => {
279
+ this.cancelSelection();
280
+ this.lastDragEndAt = Date.now();
281
+ });
282
+ (0, _defineProperty2.default)(this, "isSameChoice", (a, b) => !!a && !!b && a.type === b.type && a.id === b.id && a.index === b.index);
283
+ (0, _defineProperty2.default)(this, "selectChoice", data => {
284
+ this.setState({
285
+ selectedChoice: data
286
+ });
287
+ });
288
+ // Click-to-select semantics: selecting the currently-selected choice again clears
289
+ // the selection instead of re-selecting it.
290
+ (0, _defineProperty2.default)(this, "toggleChoiceSelection", data => {
291
+ this.setState(state => ({
292
+ selectedChoice: this.isSameChoice(state.selectedChoice, data) ? null : data
293
+ }));
294
+ });
295
+ (0, _defineProperty2.default)(this, "cancelSelection", () => {
296
+ this.setState({
297
+ selectedChoice: null
298
+ });
299
+ });
300
+ // If a real dnd-kit drag (started via keyboard Space/Enter) is still live when a
301
+ // click completes the placement below, it needs to be cleanly ended — otherwise
302
+ // dnd-kit would still think a drag is in progress. Escape is already configured as
303
+ // this sensor's cancel key (see getKeyboardDragOptions), and dispatching it as a real
304
+ // DOM KeyboardEvent is how dnd-kit's own document-level listener is reached from
305
+ // outside its sensor. onDragCancel only resets local UI state, not the session, so
306
+ // this is safe to call unconditionally, including when no drag is actually live
307
+ // (dnd-kit simply has no listener attached in that case, and the dispatch is a
308
+ // no-op).
309
+ (0, _defineProperty2.default)(this, "endAnyLiveKeyboardDrag", () => {
310
+ document.dispatchEvent(new KeyboardEvent('keydown', {
311
+ code: 'Escape',
312
+ bubbles: true,
313
+ cancelable: true
314
+ }));
315
+ });
316
+ (0, _defineProperty2.default)(this, "placeSelectedChoice", targetTileData => {
317
+ const {
318
+ selectedChoice
319
+ } = this.state;
320
+ if (!selectedChoice) {
321
+ return;
322
+ }
323
+ const ordering = this.createOrdering();
324
+ this.onDropChoice(targetTileData, selectedChoice, ordering);
325
+ this.cancelSelection();
326
+ this.endAnyLiveKeyboardDrag();
327
+ this.lastDragEndAt = Date.now();
328
+ });
329
+ (0, _defineProperty2.default)(this, "isClickSoonAfterDragEnd", () => Date.now() - this.lastDragEndAt < CLICK_AFTER_DRAG_GUARD_MS);
330
+ (0, _defineProperty2.default)(this, "onChoiceClick", data => {
331
+ if (this.isClickSoonAfterDragEnd()) {
332
+ return;
333
+ }
334
+ this.toggleChoiceSelection(data);
335
+ });
336
+ (0, _defineProperty2.default)(this, "onPlacementClick", targetTileData => {
337
+ if (this.isClickSoonAfterDragEnd()) {
338
+ return;
339
+ }
340
+ this.placeSelectedChoice(targetTileData);
341
+ });
222
342
  this.instanceId = (0, _lodashEs.uniqueId)();
223
343
  const {
224
344
  value: _value,
225
345
  needsReset: _needsReset
226
346
  } = this.validateSession(props);
227
347
  this.state = {
228
- showingCorrect: false
348
+ showingCorrect: false,
349
+ selectedChoice: null
229
350
  };
351
+ this.lastDragEndAt = 0;
230
352
  const {
231
353
  model: _model
232
354
  } = props || {};
@@ -356,13 +478,21 @@ class PlacementOrdering extends _react.default.Component {
356
478
  display: 'flex',
357
479
  flexDirection: 'column',
358
480
  alignItems: 'center',
359
- boxSizing: 'border-box'
481
+ boxSizing: 'border-box',
482
+ width: '100%'
360
483
  };
361
- return /*#__PURE__*/_react.default.createElement(_drag.DragProvider, {
362
- onDragStart: () => {},
484
+ const clickPlacementProps = includeTargets ? {
485
+ selectedChoice: this.state.selectedChoice,
486
+ onChoiceClick: this.onChoiceClick,
487
+ onPlacementClick: this.onPlacementClick
488
+ } : {};
489
+ return /*#__PURE__*/_react.default.createElement(_drag.DragProvider, (0, _extends2.default)({
490
+ onDragStart: this.onDragStart,
363
491
  onDragEnd: this.onDragEnd,
364
- collisionDetection: _core.closestCenter
365
- }, /*#__PURE__*/_react.default.createElement(PlacementOrderingContainer, null, /*#__PURE__*/_react.default.createElement(_renderUi.UiLayout, {
492
+ onDragCancel: this.onDragCancel,
493
+ collisionDetection: _core.rectIntersection,
494
+ modifiers: [_modifiers.restrictToParentElement]
495
+ }, getKeyboardDragOptions(includeTargets)), /*#__PURE__*/_react.default.createElement(PlacementOrderingContainer, null, /*#__PURE__*/_react.default.createElement(_renderUi.UiLayout, {
366
496
  extraCSSRules: extraCSSRules,
367
497
  style: containerStyle
368
498
  }, showTeacherInstructions && /*#__PURE__*/_react.default.createElement(StyledCollapsible, {
@@ -380,7 +510,7 @@ class PlacementOrdering extends _react.default.Component {
380
510
  toggled: showingCorrect,
381
511
  onToggle: this.toggleCorrect,
382
512
  language: language
383
- }), /*#__PURE__*/_react.default.createElement(OrderingTiler, {
513
+ }), /*#__PURE__*/_react.default.createElement(InteractiveRegion, null, /*#__PURE__*/_react.default.createElement(InteractiveRegionContent, null, /*#__PURE__*/_react.default.createElement(OrderingTiler, (0, _extends2.default)({
384
514
  instanceId: this.instanceId,
385
515
  choiceLabel: config.choiceLabel,
386
516
  targetLabel: config.targetLabel,
@@ -391,7 +521,7 @@ class PlacementOrdering extends _react.default.Component {
391
521
  tileSize: config.tileSize,
392
522
  includeTargets: includeTargets,
393
523
  choiceLabelEnabled: model.config && model.config.choiceLabelEnabled
394
- }), displayNote && /*#__PURE__*/_react.default.createElement(StyledNote, {
524
+ }, clickPlacementProps)))), displayNote && /*#__PURE__*/_react.default.createElement(StyledNote, {
395
525
  dangerouslySetInnerHTML: {
396
526
  __html: note
397
527
  }
@@ -1 +1 @@
1
- {"version":3,"file":"placement-ordering.js","names":["_react","_interopRequireDefault","require","_reactDom","_propTypes","_debug","_lodashEs","_styles","_core","_renderUi","_mathRendering","_translator","_correctAnswerToggle","_drag","_tiler","_ordering","_utils","translator","Translator","log","debug","PlacementOrderingContainer","styled","color","text","backgroundColor","background","display","flexDirection","alignItems","boxSizing","StyledPrompt","theme","paddingBottom","spacing","StyledNote","StyledToggle","CorrectAnswerToggle","StyledCollapsible","Collapsible","marginBottom","alignSelf","OrderingTiler","props","tiler","Comp","ordering","onDropChoice","onRemoveChoice","compProps","default","createElement","_extends2","tiles","t","s","propTypes","PropTypes","func","any","PlacementOrdering","React","Component","constructor","_defineProperty2","showingCorrect","setState","model","session","areChoicesShuffled","config","choices","includeTargets","choicesIds","map","c","id","value","needsReset","sessionMissing","length","missingChoiceIds","difference","extraChoiceIds","isEqual","sessionIsMismatched","concat","Array","filter","cId","includes","console","warn","target","source","onSessionChange","from","find","type","index","to","update","reducer","sessionUpdate","Object","assign","response","state","orientation","buildState","correctResponse","outcome","allowSameChoiceInTargets","outcomes","event","over","active","createOrdering","draggedItem","data","current","droppedOnItem","instanceId","uniqueId","validateSession","env","mode","componentDidUpdate","domNode","ReactDOM","findDOMNode","renderMath","UNSAFE_componentWillReceiveProps","nextProps","nextModel","currentModel","nextChoices","newState","isLanguageChanged","language","isDefaultNote","note","lng","haveSameValuesButDifferentOrder","validatedSession","newSession","includeTargetsChanged","render","correctness","extraCSSRules","prompt","rationale","feedback","configs","showNote","disabled","teacherInstructions","showToggle","vertical","role","Tiler","VerticalTiler","HorizontalTiler","displayNote","showRationale","hasText","hasMedia","showTeacherInstructions","containerStyle","DragProvider","onDragStart","onDragEnd","collisionDetection","closestCenter","UiLayout","style","labels","hidden","visible","className","PreviewPrompt","show","toggled","onToggle","toggleCorrect","choiceLabel","targetLabel","addGuide","showOrdering","tileSize","choiceLabelEnabled","dangerouslySetInnerHTML","__html","Feedback","exports","isRequired","object","oneOfType","array","_default"],"sources":["../src/placement-ordering.jsx"],"sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom';\nimport PropTypes from 'prop-types';\nimport debug from 'debug';\nimport { difference, isEqual, uniqueId } from 'lodash-es';\nimport { styled } from '@mui/material/styles';\nimport { closestCenter } from '@dnd-kit/core';\n\nimport { Collapsible, color, Feedback, hasMedia, hasText, PreviewPrompt, UiLayout } from '@pie-lib/render-ui';\nimport { renderMath } from '@pie-lib/math-rendering';\nimport Translator from '@pie-lib/translator';\nimport CorrectAnswerToggle from '@pie-lib/correct-answer-toggle';\nimport { DragProvider } from '@pie-lib/drag';\n\nimport { HorizontalTiler, VerticalTiler } from './tiler';\nimport { buildState, reducer } from './ordering';\nimport { haveSameValuesButDifferentOrder } from './utils';\n\nconst { translator } = Translator;\n\nconst log = debug('pie-elements:placement-ordering');\n\nconst PlacementOrderingContainer = styled('div')({\n color: color.text(),\n backgroundColor: color.background(),\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n boxSizing: 'border-box',\n});\n\nconst StyledPrompt = styled('div')(({ theme }) => ({\n paddingBottom: theme.spacing(1),\n}));\n\nconst StyledNote = styled('div')(({ theme }) => ({\n paddingBottom: theme.spacing(2),\n}));\n\nconst StyledToggle = styled(CorrectAnswerToggle)(({ theme }) => ({\n paddingBottom: theme.spacing(1),\n}));\n\nconst StyledCollapsible = styled(Collapsible)(({ theme }) => ({\n marginBottom: theme.spacing(2),\n alignSelf: 'flex-start',\n}));\n\nconst OrderingTiler = (props) => {\n const { tiler: Comp, ordering, onDropChoice, onRemoveChoice, ...compProps } = props;\n\n return (\n <Comp\n {...compProps}\n tiles={ordering.tiles}\n onDropChoice={(t, s) => onDropChoice(t, s, ordering)}\n onRemoveChoice={(t) => onRemoveChoice(t, ordering)}\n />\n );\n};\n\nOrderingTiler.propTypes = {\n tiler: PropTypes.func,\n ordering: PropTypes.any,\n onDropChoice: PropTypes.func,\n onRemoveChoice: PropTypes.func,\n};\n\nexport class PlacementOrdering extends React.Component {\n static propTypes = {\n onSessionChange: PropTypes.func.isRequired,\n model: PropTypes.object.isRequired,\n session: PropTypes.oneOfType([PropTypes.array.isRequired, PropTypes.object.isRequired]),\n };\n\n constructor(props) {\n super(props);\n\n this.instanceId = uniqueId();\n\n const { value, needsReset } = this.validateSession(props);\n\n this.state = {\n showingCorrect: false,\n };\n\n const { model } = props || {};\n const { env } = model || {};\n const { mode } = env || {};\n\n if (needsReset && mode === 'gather') {\n this.props.onSessionChange({\n ...props.session,\n value,\n });\n }\n }\n\n toggleCorrect = (showingCorrect) => this.setState({ showingCorrect });\n\n componentDidUpdate() {\n //eslint-disable-next-line\n const domNode = ReactDOM.findDOMNode(this);\n\n renderMath(domNode);\n }\n\n validateSession = ({ model, session }, areChoicesShuffled = false) => {\n const { config, choices } = model || {};\n const { includeTargets } = config || {};\n const choicesIds = choices.map((c) => c.id);\n\n let { value } = session || {};\n let needsReset;\n\n if (!includeTargets) {\n // Use all choice IDs if choices were shuffled or session is missing/invalid\n const sessionMissing = !value || !value.length;\n if (sessionMissing || areChoicesShuffled) {\n // if there's no value on session in No Targets Mode, we need to set an initial session\n value = choicesIds;\n } else {\n // in No Targets Mode, all choice ids need to be used\n const missingChoiceIds = difference(choicesIds, value);\n // this is the case that handles extra choice ids in session\n const extraChoiceIds = difference(value, choicesIds);\n\n if (missingChoiceIds.length || extraChoiceIds.length) {\n value = choicesIds;\n }\n }\n\n needsReset = !isEqual(session.value, value);\n } else {\n // in Targets Area selected, it's important to check the length of session\n const sessionIsMismatched = value && value.length !== choicesIds.length;\n if (sessionIsMismatched) {\n needsReset = true;\n\n // if choices were added, add value in session\n if (value.length < choicesIds.length) {\n value = value.concat(new Array(choicesIds.length - value.length));\n } else {\n // if choices were removed, make sure to remove from session as well\n value = value.filter((cId) => choicesIds.includes(cId));\n }\n }\n }\n\n if (needsReset) {\n // eslint-disable-next-line no-console\n console.warn('This session is not valid anymore. It will be reset.');\n }\n\n return { value, needsReset };\n };\n\n UNSAFE_componentWillReceiveProps(nextProps) {\n const { model: nextModel = {} } = nextProps || {};\n const { model: currentModel = {} } = this.props || {};\n const { correctResponse, config, choices: nextChoices = [], env } = nextModel;\n const { includeTargets } = config || {};\n\n const newState = {};\n\n const isLanguageChanged = currentModel.language && currentModel.language !== nextModel.language;\n const isDefaultNote =\n currentModel.note &&\n currentModel.note === translator.t('common:commonCorrectAnswerWithAlternates', { lng: currentModel.language });\n\n // check if the note is the default one for prev language and change to the default one for new language\n // this check is necessary in order to diferanciate between default and authour defined note\n // and only change between languages for default ones\n if (isLanguageChanged && isDefaultNote) {\n currentModel.note = translator.t('common:commonCorrectAnswerWithAlternates', { lng: nextModel.language });\n }\n\n if (!correctResponse) {\n newState.showingCorrect = false;\n }\n\n //PD-4924\n // show student choices same order as in model when teacher changes student choices order\n // for cases when student view and instructor view are on same page\n const areChoicesShuffled = haveSameValuesButDifferentOrder(nextChoices, currentModel.choices);\n\n const validatedSession = this.validateSession(nextProps, areChoicesShuffled);\n let { value, needsReset } = validatedSession;\n\n const newSession = {\n ...nextProps.session,\n value,\n };\n const includeTargetsChanged = currentModel.config?.includeTargets !== includeTargets;\n\n if (includeTargets && includeTargetsChanged) {\n needsReset = true;\n\n delete newSession.value;\n }\n\n this.setState(newState, () => {\n const { mode } = env || {};\n\n if (needsReset && mode === 'gather') {\n this.props.onSessionChange(newSession);\n }\n });\n }\n\n onDropChoice = (target, source, ordering) => {\n const { onSessionChange, session } = this.props;\n const from = ordering.tiles.find((t) => t.id === source.id && t.type === source.type && t.index === source.index);\n const to = target;\n log('[onDropChoice] ', from, to);\n const update = reducer({ type: 'move', from, to }, ordering);\n const sessionUpdate = Object.assign({}, session, {\n value: update.response,\n });\n\n onSessionChange(sessionUpdate);\n };\n\n onRemoveChoice = (target, ordering) => {\n const { onSessionChange, session } = this.props;\n log('[onRemoveChoice]', target);\n const update = reducer({ type: 'remove', target }, ordering);\n const sessionUpdate = Object.assign({}, session, {\n value: update.response,\n });\n onSessionChange(sessionUpdate);\n };\n\n createOrdering = () => {\n const { model, session } = this.props;\n const { showingCorrect } = this.state;\n const config = model.config || {\n orientation: 'vertical',\n includeTargets: true,\n };\n const { includeTargets } = config;\n\n return showingCorrect\n ? buildState(\n model.choices,\n model.correctResponse,\n model.correctResponse.map((id) => ({ id, outcome: 'correct' })),\n {\n includeTargets,\n allowSameChoiceInTargets: model.config.allowSameChoiceInTargets,\n },\n )\n : buildState(model.choices, session.value, model.outcomes, {\n includeTargets,\n allowSameChoiceInTargets: model.config.allowSameChoiceInTargets,\n });\n };\n\n onDragEnd = (event) => {\n const { over, active } = event;\n const ordering = this.createOrdering();\n\n if (over && active) {\n const draggedItem = active.data.current;\n const droppedOnItem = over.data.current;\n\n if (draggedItem && droppedOnItem && droppedOnItem.type === 'target') {\n this.onDropChoice(droppedOnItem, draggedItem, ordering);\n return;\n }\n\n if (draggedItem && droppedOnItem) {\n this.onDropChoice(droppedOnItem, draggedItem, ordering);\n }\n } else if (!over && active) {\n const draggedItem = active.data.current;\n if (draggedItem && draggedItem.type === 'target') {\n this.onRemoveChoice(draggedItem, ordering);\n }\n }\n };\n\n render() {\n const { model } = this.props;\n const {\n correctResponse,\n correctness,\n extraCSSRules,\n prompt,\n rationale,\n feedback,\n config: configs,\n note,\n showNote,\n env,\n disabled,\n teacherInstructions,\n language,\n } = model;\n const showToggle = correctResponse && correctResponse.length > 0;\n const { showingCorrect } = this.state;\n const config = configs || {\n orientation: 'vertical',\n includeTargets: true,\n };\n const { orientation, includeTargets } = config;\n const vertical = orientation === 'vertical';\n const ordering = this.createOrdering();\n const { mode, role } = env || {};\n\n const Tiler = vertical ? VerticalTiler : HorizontalTiler;\n const displayNote = (showingCorrect || (mode === 'view' && role === 'instructor')) && showNote && note;\n const showRationale = rationale && (hasText(rationale) || hasMedia(rationale));\n const showTeacherInstructions =\n teacherInstructions && (hasText(teacherInstructions) || hasMedia(teacherInstructions));\n\n const containerStyle = {\n color: color.text(),\n backgroundColor: color.background(),\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n boxSizing: 'border-box',\n };\n\n return (\n <DragProvider onDragStart={() => { }} onDragEnd={this.onDragEnd} collisionDetection={closestCenter}>\n <PlacementOrderingContainer>\n <UiLayout extraCSSRules={extraCSSRules} style={containerStyle}>\n {showTeacherInstructions && (\n <StyledCollapsible\n labels={{ hidden: 'Show Teacher Instructions', visible: 'Hide Teacher Instructions' }}\n className=\"collapsible\"\n >\n <PreviewPrompt prompt={teacherInstructions} />\n </StyledCollapsible>\n )}\n\n <StyledPrompt>\n <PreviewPrompt prompt={prompt} />\n </StyledPrompt>\n\n <StyledToggle\n show={showToggle}\n toggled={showingCorrect}\n onToggle={this.toggleCorrect}\n language={language}\n />\n\n <OrderingTiler\n instanceId={this.instanceId}\n choiceLabel={config.choiceLabel}\n targetLabel={config.targetLabel}\n ordering={ordering}\n tiler={Tiler}\n disabled={disabled}\n addGuide={config.showOrdering}\n tileSize={config.tileSize}\n includeTargets={includeTargets}\n choiceLabelEnabled={model.config && model.config.choiceLabelEnabled}\n />\n\n {displayNote && <StyledNote dangerouslySetInnerHTML={{ __html: note }} />}\n\n {showRationale && (\n <StyledCollapsible\n labels={{ hidden: 'Show Rationale', visible: 'Hide Rationale' }}\n className=\"collapsible\"\n >\n <PreviewPrompt prompt={rationale} />\n </StyledCollapsible>\n )}\n\n {!showingCorrect && <Feedback correctness={correctness} feedback={feedback} />}\n </UiLayout>\n </PlacementOrderingContainer>\n </DragProvider>\n );\n }\n}\n\nexport default PlacementOrdering;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"placement-ordering.js","names":["_react","_interopRequireDefault","require","_reactDom","_propTypes","_debug","_lodashEs","_styles","_core","_modifiers","_renderUi","_mathRendering","_translator","_correctAnswerToggle","_drag","_tiler","_ordering","_utils","_keyboardCoordinates","CLICK_AFTER_DRAG_GUARD_MS","getKeyboardDragOptions","includeTargets","keyboardCoordinateGetter","closestDroppableKeyboardCoordinates","keyboardCodes","start","cancel","end","accessibility","screenReaderInstructions","draggable","translator","Translator","log","debug","PlacementOrderingContainer","styled","color","text","backgroundColor","background","display","flexDirection","alignItems","boxSizing","InteractiveRegion","alignSelf","maxWidth","overflowX","overflowY","InteractiveRegionContent","justifyContent","minWidth","StyledPrompt","theme","paddingBottom","spacing","StyledNote","StyledToggle","CorrectAnswerToggle","StyledCollapsible","Collapsible","marginBottom","OrderingTiler","props","tiler","Comp","ordering","onDropChoice","onRemoveChoice","compProps","default","createElement","_extends2","tiles","t","s","propTypes","PropTypes","func","any","PlacementOrdering","React","Component","constructor","_defineProperty2","showingCorrect","setState","model","session","areChoicesShuffled","config","choices","choicesIds","map","c","id","value","needsReset","sessionMissing","length","missingChoiceIds","difference","extraChoiceIds","isEqual","sessionIsMismatched","concat","Array","filter","cId","includes","console","warn","target","source","onSessionChange","from","find","type","index","to","update","reducer","sessionUpdate","Object","assign","response","state","orientation","buildState","correctResponse","outcome","allowSameChoiceInTargets","outcomes","event","over","active","createOrdering","cancelSelection","lastDragEndAt","Date","now","draggedItem","data","current","droppedOnItem","selectChoice","a","b","selectedChoice","isSameChoice","document","dispatchEvent","KeyboardEvent","code","bubbles","cancelable","targetTileData","endAnyLiveKeyboardDrag","isClickSoonAfterDragEnd","toggleChoiceSelection","placeSelectedChoice","instanceId","uniqueId","validateSession","env","mode","componentDidUpdate","domNode","ReactDOM","findDOMNode","renderMath","UNSAFE_componentWillReceiveProps","nextProps","nextModel","currentModel","nextChoices","newState","isLanguageChanged","language","isDefaultNote","note","lng","haveSameValuesButDifferentOrder","validatedSession","newSession","includeTargetsChanged","render","correctness","extraCSSRules","prompt","rationale","feedback","configs","showNote","disabled","teacherInstructions","showToggle","vertical","role","Tiler","VerticalTiler","HorizontalTiler","displayNote","showRationale","hasText","hasMedia","showTeacherInstructions","containerStyle","width","clickPlacementProps","onChoiceClick","onPlacementClick","DragProvider","onDragStart","onDragEnd","onDragCancel","collisionDetection","rectIntersection","modifiers","restrictToParentElement","UiLayout","style","labels","hidden","visible","className","PreviewPrompt","show","toggled","onToggle","toggleCorrect","choiceLabel","targetLabel","addGuide","showOrdering","tileSize","choiceLabelEnabled","dangerouslySetInnerHTML","__html","Feedback","exports","isRequired","object","oneOfType","array","_default"],"sources":["../src/placement-ordering.jsx"],"sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom';\nimport PropTypes from 'prop-types';\nimport debug from 'debug';\nimport { difference, isEqual, uniqueId } from 'lodash-es';\nimport { styled } from '@mui/material/styles';\nimport { rectIntersection } from '@dnd-kit/core';\nimport { restrictToParentElement } from '@dnd-kit/modifiers';\n\nimport { Collapsible, color, Feedback, hasMedia, hasText, PreviewPrompt, UiLayout } from '@pie-lib/render-ui';\nimport { renderMath } from '@pie-lib/math-rendering';\nimport Translator from '@pie-lib/translator';\nimport CorrectAnswerToggle from '@pie-lib/correct-answer-toggle';\nimport { DragProvider } from '@pie-lib/drag';\n\nimport { HorizontalTiler, VerticalTiler } from './tiler';\nimport { buildState, reducer } from './ordering';\nimport { haveSameValuesButDifferentOrder } from './utils';\nimport { closestDroppableKeyboardCoordinates } from './keyboard-coordinates';\n\n// A click that lands right after a real drag gesture ends must be ignored by the\n// click-to-select/click-to-place handlers below, or it would immediately reopen or\n// re-trigger a selection for a drag that just completed.\nconst CLICK_AFTER_DRAG_GUARD_MS = 250;\n\nconst getKeyboardDragOptions = (includeTargets) =>\n includeTargets\n ? {\n keyboardCoordinateGetter: closestDroppableKeyboardCoordinates,\n keyboardCodes: {\n start: ['Space', 'Enter'],\n cancel: ['Escape'],\n end: ['Space', 'Enter'],\n },\n accessibility: {\n screenReaderInstructions: {\n draggable:\n '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.',\n },\n },\n }\n : {};\n\nconst { translator } = Translator;\n\nconst log = debug('pie-elements:placement-ordering');\n\nconst PlacementOrderingContainer = styled('div')({\n color: color.text(),\n backgroundColor: color.background(),\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n boxSizing: 'border-box',\n});\n\n// The interactive region - the choices and answers columns for a vertical item, or the choices and\n// answers rows for a horizontal one - scrolls horizontally when it does not fit the available width.\nconst InteractiveRegion = styled('div')({\n // the ancestors centre their children, which shrink-wraps this box to its content. without a\n // definite width it grows with the tiler and the overflow escapes outwards instead of scrolling.\n alignSelf: 'stretch',\n maxWidth: '100%',\n overflowX: 'auto',\n // tiles are dragged by transform, which counts towards scrollable overflow, so leaving this axis\n // scrollable would pop a vertical scrollbar mid-drag\n overflowY: 'hidden',\n});\n\n// keeps the tiler at its natural width, and centred while it still fits\nconst InteractiveRegionContent = styled('div')({\n display: 'flex',\n justifyContent: 'center',\n minWidth: 'min-content',\n});\n\nconst StyledPrompt = styled('div')(({ theme }) => ({\n paddingBottom: theme.spacing(1),\n}));\n\nconst StyledNote = styled('div')(({ theme }) => ({\n paddingBottom: theme.spacing(2),\n}));\n\nconst StyledToggle = styled(CorrectAnswerToggle)(({ theme }) => ({\n paddingBottom: theme.spacing(1),\n}));\n\nconst StyledCollapsible = styled(Collapsible)(({ theme }) => ({\n marginBottom: theme.spacing(2),\n alignSelf: 'flex-start',\n}));\n\nconst OrderingTiler = (props) => {\n const { tiler: Comp, ordering, onDropChoice, onRemoveChoice, ...compProps } = props;\n\n return (\n <Comp\n {...compProps}\n tiles={ordering.tiles}\n onDropChoice={(t, s) => onDropChoice(t, s, ordering)}\n onRemoveChoice={(t) => onRemoveChoice(t, ordering)}\n />\n );\n};\n\nOrderingTiler.propTypes = {\n tiler: PropTypes.func,\n ordering: PropTypes.any,\n onDropChoice: PropTypes.func,\n onRemoveChoice: PropTypes.func,\n};\n\nexport class PlacementOrdering extends React.Component {\n static propTypes = {\n onSessionChange: PropTypes.func.isRequired,\n model: PropTypes.object.isRequired,\n session: PropTypes.oneOfType([PropTypes.array.isRequired, PropTypes.object.isRequired]),\n };\n\n constructor(props) {\n super(props);\n\n this.instanceId = uniqueId();\n\n const { value, needsReset } = this.validateSession(props);\n\n this.state = {\n showingCorrect: false,\n selectedChoice: null,\n };\n this.lastDragEndAt = 0;\n\n const { model } = props || {};\n const { env } = model || {};\n const { mode } = env || {};\n\n if (needsReset && mode === 'gather') {\n this.props.onSessionChange({\n ...props.session,\n value,\n });\n }\n }\n\n toggleCorrect = (showingCorrect) => this.setState({ showingCorrect });\n\n componentDidUpdate() {\n //eslint-disable-next-line\n const domNode = ReactDOM.findDOMNode(this);\n\n renderMath(domNode);\n }\n\n validateSession = ({ model, session }, areChoicesShuffled = false) => {\n const { config, choices } = model || {};\n const { includeTargets } = config || {};\n const choicesIds = choices.map((c) => c.id);\n\n let { value } = session || {};\n let needsReset;\n\n if (!includeTargets) {\n // Use all choice IDs if choices were shuffled or session is missing/invalid\n const sessionMissing = !value || !value.length;\n if (sessionMissing || areChoicesShuffled) {\n // if there's no value on session in No Targets Mode, we need to set an initial session\n value = choicesIds;\n } else {\n // in No Targets Mode, all choice ids need to be used\n const missingChoiceIds = difference(choicesIds, value);\n // this is the case that handles extra choice ids in session\n const extraChoiceIds = difference(value, choicesIds);\n\n if (missingChoiceIds.length || extraChoiceIds.length) {\n value = choicesIds;\n }\n }\n\n needsReset = !isEqual(session.value, value);\n } else {\n // in Targets Area selected, it's important to check the length of session\n const sessionIsMismatched = value && value.length !== choicesIds.length;\n if (sessionIsMismatched) {\n needsReset = true;\n\n // if choices were added, add value in session\n if (value.length < choicesIds.length) {\n value = value.concat(new Array(choicesIds.length - value.length));\n } else {\n // if choices were removed, make sure to remove from session as well\n value = value.filter((cId) => choicesIds.includes(cId));\n }\n }\n }\n\n if (needsReset) {\n // eslint-disable-next-line no-console\n console.warn('This session is not valid anymore. It will be reset.');\n }\n\n return { value, needsReset };\n };\n\n UNSAFE_componentWillReceiveProps(nextProps) {\n const { model: nextModel = {} } = nextProps || {};\n const { model: currentModel = {} } = this.props || {};\n const { correctResponse, config, choices: nextChoices = [], env } = nextModel;\n const { includeTargets } = config || {};\n\n const newState = {};\n\n const isLanguageChanged = currentModel.language && currentModel.language !== nextModel.language;\n const isDefaultNote =\n currentModel.note &&\n currentModel.note === translator.t('common:commonCorrectAnswerWithAlternates', { lng: currentModel.language });\n\n // check if the note is the default one for prev language and change to the default one for new language\n // this check is necessary in order to diferanciate between default and authour defined note\n // and only change between languages for default ones\n if (isLanguageChanged && isDefaultNote) {\n currentModel.note = translator.t('common:commonCorrectAnswerWithAlternates', { lng: nextModel.language });\n }\n\n if (!correctResponse) {\n newState.showingCorrect = false;\n }\n\n //PD-4924\n // show student choices same order as in model when teacher changes student choices order\n // for cases when student view and instructor view are on same page\n const areChoicesShuffled = haveSameValuesButDifferentOrder(nextChoices, currentModel.choices);\n\n const validatedSession = this.validateSession(nextProps, areChoicesShuffled);\n let { value, needsReset } = validatedSession;\n\n const newSession = {\n ...nextProps.session,\n value,\n };\n const includeTargetsChanged = currentModel.config?.includeTargets !== includeTargets;\n\n if (includeTargets && includeTargetsChanged) {\n needsReset = true;\n\n delete newSession.value;\n }\n\n this.setState(newState, () => {\n const { mode } = env || {};\n\n if (needsReset && mode === 'gather') {\n this.props.onSessionChange(newSession);\n }\n });\n }\n\n onDropChoice = (target, source, ordering) => {\n const { onSessionChange, session } = this.props;\n const from = ordering.tiles.find((t) => t.id === source.id && t.type === source.type && t.index === source.index);\n const to = target;\n log('[onDropChoice] ', from, to);\n const update = reducer({ type: 'move', from, to }, ordering);\n const sessionUpdate = Object.assign({}, session, {\n value: update.response,\n });\n\n onSessionChange(sessionUpdate);\n };\n\n onRemoveChoice = (target, ordering) => {\n const { onSessionChange, session } = this.props;\n log('[onRemoveChoice]', target);\n const update = reducer({ type: 'remove', target }, ordering);\n const sessionUpdate = Object.assign({}, session, {\n value: update.response,\n });\n onSessionChange(sessionUpdate);\n };\n\n createOrdering = () => {\n const { model, session } = this.props;\n const { showingCorrect } = this.state;\n const config = model.config || {\n orientation: 'vertical',\n includeTargets: true,\n };\n const { includeTargets } = config;\n\n return showingCorrect\n ? buildState(\n model.choices,\n model.correctResponse,\n model.correctResponse.map((id) => ({ id, outcome: 'correct' })),\n {\n includeTargets,\n allowSameChoiceInTargets: model.config.allowSameChoiceInTargets,\n },\n )\n : buildState(model.choices, session.value, model.outcomes, {\n includeTargets,\n allowSameChoiceInTargets: model.config.allowSameChoiceInTargets,\n });\n };\n\n onDragEnd = (event) => {\n const { over, active } = event;\n const ordering = this.createOrdering();\n\n // A real drag (pointer or keyboard) just ended — whatever mirrored selection it\n // set on start is now resolved, and any click landing immediately after this must\n // not be misread as a fresh selection/placement\n this.cancelSelection();\n this.lastDragEndAt = Date.now();\n\n if (over && active) {\n const draggedItem = active.data.current;\n const droppedOnItem = over.data.current;\n\n if (draggedItem && droppedOnItem && droppedOnItem.type === 'target') {\n this.onDropChoice(droppedOnItem, draggedItem, ordering);\n return;\n }\n\n if (draggedItem && droppedOnItem) {\n this.onDropChoice(droppedOnItem, draggedItem, ordering);\n }\n } else if (!over && active) {\n const draggedItem = active.data.current;\n if (draggedItem && draggedItem.type === 'target') {\n this.onRemoveChoice(draggedItem, ordering);\n }\n }\n };\n\n onDragStart = (event) => {\n const { active } = event;\n\n if (active?.data?.current) {\n // A real drag (pointer or keyboard) is itself a selection — mirror it into the\n // same selectedChoice state that click-to-select uses, so the two interaction\n // models can be freely intermixed\n this.selectChoice(active.data.current);\n }\n };\n\n onDragCancel = () => {\n this.cancelSelection();\n this.lastDragEndAt = Date.now();\n };\n\n isSameChoice = (a, b) => !!a && !!b && a.type === b.type && a.id === b.id && a.index === b.index;\n\n selectChoice = (data) => {\n this.setState({ selectedChoice: data });\n };\n\n // Click-to-select semantics: selecting the currently-selected choice again clears\n // the selection instead of re-selecting it.\n toggleChoiceSelection = (data) => {\n this.setState((state) => ({\n selectedChoice: this.isSameChoice(state.selectedChoice, data) ? null : data,\n }));\n };\n\n cancelSelection = () => {\n this.setState({ selectedChoice: null });\n };\n\n // If a real dnd-kit drag (started via keyboard Space/Enter) is still live when a\n // click completes the placement below, it needs to be cleanly ended — otherwise\n // dnd-kit would still think a drag is in progress. Escape is already configured as\n // this sensor's cancel key (see getKeyboardDragOptions), and dispatching it as a real\n // DOM KeyboardEvent is how dnd-kit's own document-level listener is reached from\n // outside its sensor. onDragCancel only resets local UI state, not the session, so\n // this is safe to call unconditionally, including when no drag is actually live\n // (dnd-kit simply has no listener attached in that case, and the dispatch is a\n // no-op).\n endAnyLiveKeyboardDrag = () => {\n document.dispatchEvent(new KeyboardEvent('keydown', { code: 'Escape', bubbles: true, cancelable: true }));\n };\n\n placeSelectedChoice = (targetTileData) => {\n const { selectedChoice } = this.state;\n\n if (!selectedChoice) {\n return;\n }\n\n const ordering = this.createOrdering();\n\n this.onDropChoice(targetTileData, selectedChoice, ordering);\n this.cancelSelection();\n this.endAnyLiveKeyboardDrag();\n this.lastDragEndAt = Date.now();\n };\n\n isClickSoonAfterDragEnd = () => Date.now() - this.lastDragEndAt < CLICK_AFTER_DRAG_GUARD_MS;\n\n onChoiceClick = (data) => {\n if (this.isClickSoonAfterDragEnd()) {\n return;\n }\n\n this.toggleChoiceSelection(data);\n };\n\n onPlacementClick = (targetTileData) => {\n if (this.isClickSoonAfterDragEnd()) {\n return;\n }\n\n this.placeSelectedChoice(targetTileData);\n };\n\n render() {\n const { model } = this.props;\n const {\n correctResponse,\n correctness,\n extraCSSRules,\n prompt,\n rationale,\n feedback,\n config: configs,\n note,\n showNote,\n env,\n disabled,\n teacherInstructions,\n language,\n } = model;\n const showToggle = correctResponse && correctResponse.length > 0;\n const { showingCorrect } = this.state;\n const config = configs || {\n orientation: 'vertical',\n includeTargets: true,\n };\n const { orientation, includeTargets } = config;\n const vertical = orientation === 'vertical';\n const ordering = this.createOrdering();\n const { mode, role } = env || {};\n\n const Tiler = vertical ? VerticalTiler : HorizontalTiler;\n const displayNote = (showingCorrect || (mode === 'view' && role === 'instructor')) && showNote && note;\n const showRationale = rationale && (hasText(rationale) || hasMedia(rationale));\n const showTeacherInstructions =\n teacherInstructions && (hasText(teacherInstructions) || hasMedia(teacherInstructions));\n\n const containerStyle = {\n color: color.text(),\n backgroundColor: color.background(),\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n boxSizing: 'border-box',\n width: '100%',\n };\n\n const clickPlacementProps = includeTargets\n ? {\n selectedChoice: this.state.selectedChoice,\n onChoiceClick: this.onChoiceClick,\n onPlacementClick: this.onPlacementClick,\n }\n : {};\n\n return (\n <DragProvider\n onDragStart={this.onDragStart}\n onDragEnd={this.onDragEnd}\n onDragCancel={this.onDragCancel}\n collisionDetection={rectIntersection}\n modifiers={[restrictToParentElement]}\n {...getKeyboardDragOptions(includeTargets)}\n >\n <PlacementOrderingContainer>\n <UiLayout extraCSSRules={extraCSSRules} style={containerStyle}>\n {showTeacherInstructions && (\n <StyledCollapsible\n labels={{ hidden: 'Show Teacher Instructions', visible: 'Hide Teacher Instructions' }}\n className=\"collapsible\"\n >\n <PreviewPrompt prompt={teacherInstructions} />\n </StyledCollapsible>\n )}\n\n <StyledPrompt>\n <PreviewPrompt prompt={prompt} />\n </StyledPrompt>\n\n <StyledToggle\n show={showToggle}\n toggled={showingCorrect}\n onToggle={this.toggleCorrect}\n language={language}\n />\n\n <InteractiveRegion>\n <InteractiveRegionContent>\n <OrderingTiler\n instanceId={this.instanceId}\n choiceLabel={config.choiceLabel}\n targetLabel={config.targetLabel}\n ordering={ordering}\n tiler={Tiler}\n disabled={disabled}\n addGuide={config.showOrdering}\n tileSize={config.tileSize}\n includeTargets={includeTargets}\n choiceLabelEnabled={model.config && model.config.choiceLabelEnabled}\n {...clickPlacementProps}\n />\n </InteractiveRegionContent>\n </InteractiveRegion>\n\n {displayNote && <StyledNote dangerouslySetInnerHTML={{ __html: note }} />}\n\n {showRationale && (\n <StyledCollapsible\n labels={{ hidden: 'Show Rationale', visible: 'Hide Rationale' }}\n className=\"collapsible\"\n >\n <PreviewPrompt prompt={rationale} />\n </StyledCollapsible>\n )}\n\n {!showingCorrect && <Feedback correctness={correctness} feedback={feedback} />}\n </UiLayout>\n </PlacementOrderingContainer>\n </DragProvider>\n );\n }\n}\n\nexport default PlacementOrdering;\n"],"mappings":"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","ignoreList":[]}
package/lib/tile.js CHANGED
@@ -41,6 +41,7 @@ Holder.propTypes = {
41
41
  const StyledTileContent = (0, _styles.styled)('div')(({
42
42
  theme,
43
43
  isDragging,
44
+ isSelected,
44
45
  isOver,
45
46
  disabled,
46
47
  outcome,
@@ -53,7 +54,7 @@ const StyledTileContent = (0, _styles.styled)('div')(({
53
54
  padding: '10px',
54
55
  boxSizing: 'border-box',
55
56
  overflow: 'hidden',
56
- border: type === 'choice' || type === 'target' ? `1px solid ${theme.palette.grey[400]}` : '1px solid transparent',
57
+ border: type === 'choice' || type === 'target' ? `1px solid ${_renderUi.color.border()}` : '1px solid transparent',
57
58
  backgroundColor: type === 'choice' || type === 'target' ? _renderUi.color.background() : 'transparent',
58
59
  transition: type === 'choice' || type === 'target' ? 'background-color 150ms ease, border-color 150ms ease, opacity 150ms ease' : 'none',
59
60
  pointerEvents: 'none',
@@ -61,7 +62,9 @@ const StyledTileContent = (0, _styles.styled)('div')(({
61
62
  ...((type === 'choice' || type === 'target') && {
62
63
  '&:hover': {
63
64
  backgroundColor: disabled ? _renderUi.color.background() : _renderUi.color.secondary(),
64
- borderColor: disabled ? theme.palette.grey[400] : theme.palette.primary.main,
65
+ // The disabled branch says "disabled", so it takes the disabled token rather
66
+ // than the neutral stroke the resting state uses.
67
+ borderColor: disabled ? _renderUi.color.disabled() : theme.palette.primary.main,
65
68
  transform: disabled ? 'none' : 'scale(1.02)'
66
69
  }
67
70
  }),
@@ -73,7 +76,7 @@ const StyledTileContent = (0, _styles.styled)('div')(({
73
76
  borderStyle: 'dashed',
74
77
  transform: 'scale(1.05)'
75
78
  }),
76
- ...((type === 'choice' || type === 'target') && isDragging && !disabled && {
79
+ ...((type === 'choice' || type === 'target') && (isDragging || isSelected) && !disabled && {
77
80
  opacity: 0.6,
78
81
  backgroundColor: _renderUi.color.secondaryLight(),
79
82
  transform: 'scale(1.05) rotate(2deg)',
@@ -104,6 +107,7 @@ const TileContent = props => {
104
107
  const {
105
108
  type,
106
109
  isDragging,
110
+ isSelected,
107
111
  empty,
108
112
  isOver,
109
113
  label,
@@ -122,6 +126,7 @@ const TileContent = props => {
122
126
  return /*#__PURE__*/_react.default.createElement(StyledTileContent, {
123
127
  type: type,
124
128
  isDragging: isDragging,
129
+ isSelected: isSelected,
125
130
  isOver: isOver,
126
131
  disabled: disabled,
127
132
  outcome: outcome,
@@ -144,7 +149,10 @@ const Tile = props => {
144
149
  guideIndex,
145
150
  instanceId,
146
151
  draggable,
147
- tileIndex
152
+ tileIndex,
153
+ selectedChoice,
154
+ onChoiceClick,
155
+ onPlacementClick
148
156
  } = props;
149
157
 
150
158
  // Use type + tileIndex in the IDs to guarantee uniqueness in all modes.
@@ -153,6 +161,16 @@ const Tile = props => {
153
161
  // tileIndex (array position from tiler) ensures empty placeholders are also unique.
154
162
  const dragId = `tile-${type}-${id != null ? id : 'empty'}-${tileIndex}-${instanceId}`;
155
163
  const dropId = `drop-${type}-${id != null ? id : 'empty'}-${tileIndex}-${instanceId}`;
164
+
165
+ // Built once and reused for dnd-kit's own drag/drop data and for the click handlers
166
+ // below, so a click carries exactly the same shape a real drag would.
167
+ const tileData = {
168
+ id,
169
+ type,
170
+ instanceId,
171
+ value: label,
172
+ index
173
+ };
156
174
  const {
157
175
  attributes,
158
176
  listeners,
@@ -161,13 +179,7 @@ const Tile = props => {
161
179
  isDragging
162
180
  } = (0, _core.useDraggable)({
163
181
  id: dragId,
164
- data: {
165
- id,
166
- type,
167
- instanceId,
168
- value: label,
169
- index
170
- },
182
+ data: tileData,
171
183
  disabled: !draggable || disabled
172
184
  });
173
185
  const {
@@ -175,17 +187,66 @@ const Tile = props => {
175
187
  isOver: dropIsOver
176
188
  } = (0, _core.useDroppable)({
177
189
  id: dropId,
178
- data: {
179
- id,
180
- type,
181
- instanceId,
182
- value: label,
183
- index
184
- },
190
+ data: tileData,
185
191
  // Disable droppable on the tile currently being dragged so closestCenter
186
192
  // cannot pick it as the drop target (prevents self-collision and wrong matches).
187
193
  disabled: isDragging
188
194
  });
195
+ const isSelected = !!selectedChoice && selectedChoice.type === tileData.type && selectedChoice.id === tileData.id && selectedChoice.index === tileData.index;
196
+
197
+ // dnd-kit's own isOver (dropIsOver) only reflects real collision detection during an
198
+ // active drag, so it stays false while a placement area is merely a candidate for a
199
+ // pending click-based placement. Track hovering locally and fold it into the same
200
+ // isOver signal the styling below already uses, so hovering a response area while
201
+ // something is selected gets the exact same treatment as hovering it during a real
202
+ // drag — one code path, no duplicated CSS.
203
+ const [isHovered, setIsHovered] = _react.default.useState(false);
204
+ const hasSelection = !!selectedChoice && !disabled;
205
+ const showsHoverEffect = dropIsOver || type === 'target' && hasSelection && isHovered;
206
+
207
+ // Click-to-select/click-to-place (both choices and targets are handled by this same
208
+ // component, differentiated by `type`):
209
+ // - Choice tile: selects/switches/deselects it, UNLESS a placed answer (a "target")
210
+ // is currently selected, in which case clicking any choice-row tile returns it to
211
+ // the choices column/row (choice -> choice has no placement meaning in the
212
+ // reducer, so there's no ambiguity there).
213
+ // - Target tile: clicking the already-selected placed answer again deselects it;
214
+ // clicking it while something else is selected places that selection here
215
+ // (empty or occupied); clicking a filled target with nothing selected selects
216
+ // that placed answer for moving, the same way Tab+Space/Enter does. An empty
217
+ // target with nothing selected is a no-op.
218
+ const handleClick = () => {
219
+ if (disabled) return;
220
+ if (type === 'choice') {
221
+ if (selectedChoice?.type === 'target') {
222
+ onPlacementClick?.(tileData);
223
+ } else if (draggable) {
224
+ onChoiceClick?.(tileData);
225
+ }
226
+ } else if (type === 'target') {
227
+ if (isSelected) {
228
+ onChoiceClick?.(tileData);
229
+ } else if (selectedChoice) {
230
+ onPlacementClick?.(tileData);
231
+ } else if (draggable) {
232
+ onChoiceClick?.(tileData);
233
+ }
234
+ }
235
+ };
236
+
237
+ // dnd-kit's own draggable attributes (spread below) already make a draggable tile a
238
+ // native Tab stop with its own Space/Enter activation. An empty tile is never
239
+ // draggable, so without this it wouldn't be reachable by Tab at all — needed for
240
+ // "select a choice, then Tab to a placement area and press Space/Enter" to work.
241
+ // Gated to non-draggable tiles specifically so it never overrides dnd-kit's own
242
+ // keydown handling (see the conditional spread order below).
243
+ const isNativeTabStop = !(draggable && !disabled) && !disabled;
244
+ const handleKeyDown = e => {
245
+ if (e.code === 'Space' || e.code === 'Enter') {
246
+ e.preventDefault();
247
+ handleClick();
248
+ }
249
+ };
189
250
  const ref = _react.default.useRef(null);
190
251
  _react.default.useEffect(() => {
191
252
  const currentRef = ref.current;
@@ -217,13 +278,19 @@ const Tile = props => {
217
278
  margin: 0,
218
279
  textAlign: 'center',
219
280
  pointerEvents: 'auto',
220
- cursor: disabled ? 'not-allowed' : isDragging ? 'grabbing' : 'grab',
281
+ cursor: disabled ? 'not-allowed' : type === 'target' && hasSelection ? 'pointer' : isDragging ? 'grabbing' : 'grab',
221
282
  zIndex: isDragging ? 1000 : 'auto',
222
283
  willChange: isDragging ? 'transform' : 'auto'
223
284
  };
224
285
  return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({
225
286
  ref: setRefs,
226
- style: style
287
+ style: style,
288
+ role: isNativeTabStop ? 'button' : undefined,
289
+ tabIndex: isNativeTabStop ? 0 : undefined,
290
+ onKeyDown: isNativeTabStop ? handleKeyDown : undefined,
291
+ onClick: handleClick,
292
+ onMouseEnter: () => setIsHovered(true),
293
+ onMouseLeave: () => setIsHovered(false)
227
294
  }, draggable && !disabled ? {
228
295
  ...listeners,
229
296
  ...attributes
@@ -233,8 +300,9 @@ const Tile = props => {
233
300
  empty: empty,
234
301
  index: index,
235
302
  guideIndex: guideIndex,
236
- isOver: dropIsOver,
303
+ isOver: showsHoverEffect,
237
304
  isDragging: isDragging,
305
+ isSelected: isSelected,
238
306
  disabled: disabled,
239
307
  outcome: outcome,
240
308
  type: type
@@ -253,7 +321,10 @@ Tile.propTypes = {
253
321
  guideIndex: _propTypes.default.number,
254
322
  instanceId: _propTypes.default.any,
255
323
  draggable: _propTypes.default.bool,
256
- tileIndex: _propTypes.default.number
324
+ tileIndex: _propTypes.default.number,
325
+ selectedChoice: _propTypes.default.object,
326
+ onChoiceClick: _propTypes.default.func,
327
+ onPlacementClick: _propTypes.default.func
257
328
  };
258
329
  var _default = exports.default = Tile;
259
330
  //# sourceMappingURL=tile.js.map