@graffiticode/l0179-view 0.1.0

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.
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Evaluate an `expected` that was authored as a formula against the authored grid, so
3
+ * `expected "=A1*2"` grades against whatever A1 actually holds this render.
4
+ */
5
+ export declare const evaluateExpectedFormula: (formula: any, interactionCells: any) => any;
6
+
7
+ /**
8
+ * The answer key, keyed the way the response is: bare `A2` for one sheet, `s2!A2` once there are
9
+ * several. Callers (including Learnosity's suggested-answers list) index the response with these
10
+ * keys, so the two must agree.
11
+ */
12
+ export declare const getCellsValidation: ({ cells, validation }: any) => any;
13
+
14
+ export declare const isDateLike: (text: any) => boolean;
15
+
16
+ export declare const isNumeric: (text: any) => boolean;
17
+
18
+ /**
19
+ * Normalizes date input from various formats into a serial number.
20
+ * @returns the date serial number, or null if not a valid date
21
+ */
22
+ export declare const normalizeDateInput: (text: any) => number | null;
23
+
24
+ /**
25
+ * Normalizes number input from various formats (e.g., "1,234.56", "$1234.56", "1.234,56")
26
+ * into a standard numeric value.
27
+ * @returns the normalized number, or null if not a valid number
28
+ */
29
+ export declare const normalizeNumberInput: (text: any) => number | null;
30
+
31
+ /** Re-key a bare cell map onto one sheet. Used on the way out of the grid. */
32
+ export declare function qualify(sheetId: string, cells: Record<string, any>): Record<string, any>;
33
+
34
+ export declare const qualifyKey: (sheetId: string, name: string) => string;
35
+
36
+ /**
37
+ * The saved answers belonging to one sheet, taken from the flat `interaction.cells`.
38
+ *
39
+ * This exists because of how the Learnosity lifecycle restores a response. `mergeResponse` folds
40
+ * it into `interaction.cells` and nowhere else — which is right for a single sheet, since that is
41
+ * what the grid renders from. A multi-sheet grid renders from `interaction.sheets[i].cells`,
42
+ * which the fold never touches, so without this overlay a learner reopens a two-sheet item and
43
+ * finds every answer they saved gone from the screen while it is still in the response.
44
+ *
45
+ * ONLY qualified keys are taken. An unqualified key in a multi-sheet model is the authored flat
46
+ * mirror of the first sheet, not an answer, and treating it as one would overwrite that sheet
47
+ * with its own pre-response state.
48
+ */
49
+ export declare function responseOverlay(interactionCells: Record<string, any>, sheetId: string): Record<string, any>;
50
+
51
+ /** Score one cell against one `assess` record. Returns `{points, isValid}`, never throws. */
52
+ export declare const scoreCell: ({ method, expected, points }: any, { val, formula, type }?: any, interactionCells?: any) => any;
53
+
54
+ /**
55
+ * Score a response map. Returns the same map with a `score` added to each assessed cell; the
56
+ * caller sums `score.points` and compares against `validation.points`.
57
+ *
58
+ * With several sheets each is scored against its OWN validation rather than a merged one. That
59
+ * is the same separation the compiler makes, and for the same reason: the region record is keyed
60
+ * by row and column with no sheet dimension, so one merged pass has sheet 2's `A1` overwrite
61
+ * sheet 1's answer key — leaving a maximum that no correct response can reach.
62
+ */
63
+ export declare const scoreCells: ({ cells, validation, interactionCells }: any) => any;
64
+
65
+ /**
66
+ * Split a possibly-qualified map into one bare-keyed map per sheet.
67
+ *
68
+ * An unqualified key belongs to the FIRST sheet. That is not a fallback for convenience — it is
69
+ * what makes an existing single-sheet response keep its meaning when the same code path starts
70
+ * handling several sheets.
71
+ */
72
+ export declare function splitBySheet(cells: Record<string, any>, sheetIds: string[]): Record<string, Record<string, any>>;
73
+
74
+ /**
75
+ * Sheet-qualified cell keys: `"s1!A1"`.
76
+ *
77
+ * WHY A FLAT KEY SPACE RATHER THAN A NESTED SHAPE. The Learnosity lifecycle lives in
78
+ * `@graffiticode/learnosity-cqt`, a published package shared with every other cell-scored
79
+ * Graffiticode language, and it is flat-keyed in three places that cannot be changed from here:
80
+ *
81
+ * - `mergeResponse` folds a response back in with `interaction.cells[cellName] = ...`;
82
+ * - the `response` reducer persists `{...interaction.cells, ...args.cells}`;
83
+ * - `Scorer.score()` sums `scoredCells[key].score.points` over one flat map.
84
+ *
85
+ * Two sheets both holding `A1` would collide at all three and mis-score silently. Qualifying the
86
+ * KEY instead of nesting the SHAPE keeps every one of them working untouched, and matches the
87
+ * convention a spreadsheet already uses for a cell on another sheet.
88
+ *
89
+ * A program with one sheet keeps bare `A1` keys, exactly as before — so every response already
90
+ * stored against an existing item still reads correctly.
91
+ */
92
+ /** `"s1!A1"` → `["s1", "A1"]`; `"A1"` → `[undefined, "A1"]`. */
93
+ export declare function splitKey(key: string): [string | undefined, string];
94
+
95
+ /**
96
+ * Upper-case a formula WITHOUT touching quoted text: `=sum(a1:a3)` becomes `=SUM(A1:A3)`, but
97
+ * `="hello"` keeps its string intact. Cell names and function names are case-insensitive; string
98
+ * literals are not.
99
+ */
100
+ export declare const toUpperCase: (text: any) => string;
101
+
102
+ /**
103
+ * Wrap prose in `\text{}` so the LaTeX translator treats it as a string rather than as maths.
104
+ * Formulas, existing `\text{}`, anything carrying a backslash, numbers and dates are left alone.
105
+ */
106
+ export declare const wrapPlainTextInLatex: (text: any) => string;
107
+
108
+ export { }
@@ -0,0 +1,19 @@
1
+ import { c as s, g as l, d as t, i, n as r, a as o, q as p, h as n, r as u, j as m, s as y, k as c, l as x, t as C, w as d } from "./index-3_WJgYM5.js";
2
+ export {
3
+ s as evaluateExpectedFormula,
4
+ l as getCellsValidation,
5
+ t as isDateLike,
6
+ i as isNumeric,
7
+ r as normalizeDateInput,
8
+ o as normalizeNumberInput,
9
+ p as qualify,
10
+ n as qualifyKey,
11
+ u as responseOverlay,
12
+ m as scoreCell,
13
+ y as scoreCells,
14
+ c as splitBySheet,
15
+ x as splitKey,
16
+ C as toUpperCase,
17
+ d as wrapPlainTextInLatex
18
+ };
19
+ //# sourceMappingURL=scoring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoring.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.left-1\/2{left:50%}.top-full{top:100%}.z-50{z-index:50}.mb-0{margin-bottom:0}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.\!table{display:table!important}.table{display:table}.grid{display:grid}.hidden{display:none}.h-0{height:0px}.h-7{height:1.75rem}.w-0{width:0px}.w-7{width:1.75rem}.w-full{width:100%}.max-w-none{max-width:none}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.resize{resize:both}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.border{border-width:1px}.border-0{border-width:0px}.border-b{border-bottom-width:1px}.border-none{border-style:none}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-red-700{--tw-border-opacity: 1;border-color:rgb(185 28 28 / var(--tw-border-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-600{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-900\/50{background-color:#7f1d1d80}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.p-0{padding:0}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.pb-1{padding-bottom:.25rem}.pl-5{padding-left:1.25rem}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.font-serif{font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.italic{font-style:italic}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.ProseMirror-focused{outline:0}.placeholder\:text-gray-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.placeholder\:text-gray-400::placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.focus\:outline-0:focus{outline-width:0px}.focus\:ring-0:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}@media (min-width: 640px){.sm\:text-sm\/6{font-size:.875rem;line-height:1.5rem}}.ProseMirror{position:relative;word-wrap:break-word;white-space:pre-wrap;white-space:break-spaces;font-variant-ligatures:none;font-feature-settings:"liga" 0}.ProseMirror pre{white-space:pre-wrap}.ProseMirror li{position:relative}.ProseMirror-hideselection *::selection{background:transparent}.ProseMirror-hideselection *::-moz-selection{background:transparent}.ProseMirror-hideselection{caret-color:transparent}.ProseMirror [draggable][contenteditable=false]{-webkit-user-select:text;-moz-user-select:text;user-select:text}.ProseMirror-selectednode{outline:2px solid #8cf}li.ProseMirror-selectednode{outline:none}li.ProseMirror-selectednode:after{content:"";position:absolute;left:-32px;right:-2px;top:-2px;bottom:-2px;border:2px solid #8cf;pointer-events:none}img.ProseMirror-separator{display:inline!important;border:none!important;margin:0!important}.ProseMirror table{border-collapse:collapse;table-layout:fixed;width:100%;overflow:hidden}.ProseMirror td,.ProseMirror th{vertical-align:top;box-sizing:border-box;position:relative}.ProseMirror td:not([data-colwidth]):not(.column-resize-dragging),.ProseMirror th:not([data-colwidth]):not(.column-resize-dragging){min-width:var(--default-cell-min-width)}.ProseMirror{border:thin solid #ccc;outline:none}main{margin:auto;width:80%;max-width:700px}.menu{display:flex;margin-bottom:5px}.button{cursor:pointer;width:24px;height:24px;margin-right:5px;display:flex;align-items:center;justify-content:center;box-shadow:none;border:thin solid #ccc;border-radius:.25rem;color:#777;background-color:#fff}.button[aria-pressed=true]{background-color:#ddd;color:#00f}.button:hover{color:#333}.button.bold{font-weight:700}.button.italic{font-style:italic}.visually-hidden{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.ProseMirror .tableWrapper{overflow-x:auto}.ProseMirror table{border-collapse:collapse;table-layout:fixed;width:250;height:250;overflow:hidden;border:1px solid #eee}.ProseMirror td,.ProseMirror th{vertical-align:middle;box-sizing:border-box;position:relative;text-align:right;padding:6px 4px;border:1px solid #eee;min-height:24px;line-height:1.2;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-variant-numeric:tabular-nums}.ProseMirror p{margin:0}.ProseMirror th p{display:flex;align-items:center;justify-content:center;height:100%;margin:0}.ProseMirror .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;z-index:20;background-color:#adf;pointer-events:none}.ProseMirror.resize-cursor{cursor:ew-resize;cursor:col-resize}.ProseMirror .selectedCell:after{z-index:2;position:absolute;content:"";left:0;right:0;top:0;bottom:0;background:#c8c8ff66;pointer-events:none}.ProseMirror th,.ProseMirror .readonly-cell{background-color:#f8f8f8;font-weight:600;color:#bbb;cursor:default;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle!important}.gc-sheet-area{display:flex;flex-direction:column}.gc-sheet-chrome{display:flex;align-items:stretch;gap:.25rem;padding:.25rem .5rem 0;border-top:1px solid #e0e0e0;background:#fff;font-family:Arial,sans-serif;font-size:.8125rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.gc-sheet-menu{position:relative;flex:none;display:flex;align-items:center}.gc-sheet-menu-button{display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border-radius:9999px;color:#5f6368;background:transparent;border:0;cursor:pointer}.gc-sheet-menu-button:hover{background:#f1f3f4}.gc-sheet-menu-list{position:absolute;bottom:2.25rem;left:0;z-index:20;min-width:11rem;max-height:16rem;overflow-y:auto;overscroll-behavior:contain;margin:0;padding:.25rem 0;list-style:none;background:#fff;border:1px solid #e5e7eb;border-radius:.25rem;box-shadow:0 2px 10px #0000002e}.gc-sheet-menu-item{display:block;width:100%;padding:.375rem .875rem;text-align:left;background:transparent;border:0;cursor:pointer;white-space:nowrap}.gc-sheet-menu-item:hover{background:#f1f3f4}.gc-sheet-menu-item.is-active{background:#e8f0fe;color:#0b57d0;font-weight:700}.gc-sheet-tabs{display:flex;align-items:flex-end;gap:.125rem;overflow-x:auto}.gc-sheet-tab{flex:none;max-width:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:.375rem 1rem;border:0;border-radius:.25rem .25rem 0 0;background:transparent;color:#5f6368;cursor:pointer}.gc-sheet-tab:hover{background:#f1f3f4}.gc-sheet-tab.is-active{background:#e8f0fe;color:#0b57d0;font-weight:700}.gc-sheet-tab.is-active:hover{background:#d9e7fd}.ProseMirror .column-resize-handle{display:none}.ProseMirror.resize-cursor{cursor:text}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "publishConfig": {
3
+ "access": "public"
4
+ },
5
+ "name": "@graffiticode/l0179-view",
6
+ "version": "0.1.0",
7
+ "description": "L0179 view \u2014 the spreadsheet Form and its DOM-free scoring, rendered through the shared View inherited from @graffiticode/l0000-view",
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "module": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "//sideEffects": "Only stylesheets have side effects. Declaring this is what lets a bundler drop the renderer from the Learnosity SCORER bundle, which imports scoreCells from this entry but must never pull in React or ProseMirror -- Learnosity runs the scorer server-side. L0166 omits this field, which is why its own scorer ships ~500 kB of dead weight.",
16
+ "sideEffects": [
17
+ "*.css"
18
+ ],
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ },
24
+ "./scoring": {
25
+ "types": "./dist/scoring.d.ts",
26
+ "import": "./dist/scoring.js"
27
+ },
28
+ "./style.css": "./dist/style.css"
29
+ },
30
+ "scripts": {
31
+ "dev": "vite --config vite.embed.config.ts",
32
+ "build": "tsc -p tsconfig.json && vite build",
33
+ "build:embed": "vite build --config vite.embed.config.ts",
34
+ "test": "vitest run",
35
+ "preview": "vite preview --config vite.embed.config.ts",
36
+ "lint": "eslint src embed"
37
+ },
38
+ "peerDependencies": {
39
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
40
+ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
41
+ },
42
+ "dependencies": {
43
+ "@graffiticode/l0000-view": "^0.1.3",
44
+ "@graffiticode/translatex": "^0.24.0",
45
+ "prosemirror-commands": "^1.7.2",
46
+ "prosemirror-history": "^1.5.0",
47
+ "prosemirror-keymap": "^1.2.3",
48
+ "prosemirror-model": "^1.25.11",
49
+ "prosemirror-schema-basic": "^1.2.4",
50
+ "prosemirror-state": "^1.4.4",
51
+ "prosemirror-tables": "^1.8.5",
52
+ "prosemirror-view": "^1.42.3",
53
+ "react-markdown": "^10.1.0"
54
+ },
55
+ "devDependencies": {
56
+ "@types/react": "^18.3.11",
57
+ "@types/react-dom": "^18.3.0",
58
+ "@vitejs/plugin-react": "^4.3.2",
59
+ "autoprefixer": "^10.4.20",
60
+ "postcss": "^8.4.47",
61
+ "react": "^18.3.1",
62
+ "react-dom": "^18.3.1",
63
+ "tailwindcss": "^3.4.13",
64
+ "vite": "^5.4.8",
65
+ "vite-plugin-dts": "^4.2.4",
66
+ "vitest": "^2.1.3"
67
+ }
68
+ }