@instructure/platform-modules 0.1.1 → 0.3.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.
- package/README.md +113 -3
- package/dist/adapters/canvasGraphql/index.d.ts +1 -1
- package/dist/adapters/canvasGraphql/normalize.d.ts +7 -6
- package/dist/adapters/canvasGraphql/normalize.d.ts.map +1 -1
- package/dist/adapters/canvasGraphql/queries.d.ts +2 -2
- package/dist/adapters/canvasGraphql/queries.d.ts.map +1 -1
- package/dist/adapters/inMemory.d.ts +4 -4
- package/dist/adapters/limits.d.ts +4 -4
- package/dist/adapters/types.d.ts +6 -6
- package/dist/cache/keys.d.ts +1 -1
- package/dist/components/FilterChips.d.ts +10 -8
- package/dist/components/FilterChips.d.ts.map +1 -1
- package/dist/components/ModuleCard.d.ts +18 -6
- package/dist/components/ModuleCard.d.ts.map +1 -1
- package/dist/components/ModuleCard.stories.d.ts +12 -0
- package/dist/components/ModuleCard.stories.d.ts.map +1 -0
- package/dist/components/ModuleItemRow.d.ts +4 -2
- package/dist/components/ModuleItemRow.d.ts.map +1 -1
- package/dist/components/ModuleNumberBadge.d.ts +8 -0
- package/dist/components/ModuleNumberBadge.d.ts.map +1 -0
- package/dist/components/ModulesList.d.ts +4 -1
- package/dist/components/ModulesList.d.ts.map +1 -1
- package/dist/components/ModulesList.stories.d.ts +36 -8
- package/dist/components/ModulesList.stories.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/labels.d.ts +9 -13
- package/dist/components/labels.d.ts.map +1 -1
- package/dist/config/base.d.ts +8 -0
- package/dist/config/base.d.ts.map +1 -0
- package/dist/config/context.d.ts +11 -0
- package/dist/config/context.d.ts.map +1 -0
- package/dist/config/index.d.ts +6 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/partialModulesConfig.d.ts +4 -0
- package/dist/config/partialModulesConfig.d.ts.map +1 -0
- package/dist/config/registry.d.ts +3 -0
- package/dist/config/registry.d.ts.map +1 -1
- package/dist/config/resolve.d.ts +7 -0
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/schemas.d.ts +2 -0
- package/dist/config/schemas.d.ts.map +1 -1
- package/dist/config/types.d.ts +32 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/fixtures/generate.d.ts +1 -1
- package/dist/fixtures/generate.d.ts.map +1 -1
- package/dist/fixtures/index.d.ts +1 -1
- package/dist/fixtures/index.d.ts.map +1 -1
- package/dist/fixtures/scenarios.d.ts +5 -0
- package/dist/fixtures/scenarios.d.ts.map +1 -1
- package/dist/hooks/constants.d.ts +1 -1
- package/dist/hooks/queryOptions.d.ts +1 -1
- package/dist/hooks/useModuleItemQueries.d.ts +1 -1
- package/dist/hooks/useModuleItems.d.ts +1 -1
- package/dist/hooks/useModules.d.ts +1 -1
- package/dist/i18n.d.ts +33 -63
- package/dist/i18n.d.ts.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1135 -867
- package/dist/types/domain.d.ts +5 -3
- package/dist/types/domain.d.ts.map +1 -1
- package/dist/types/enums.d.ts +2 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/navigation.d.ts +13 -0
- package/dist/types/navigation.d.ts.map +1 -0
- package/dist/types/schemas.d.ts +1 -1
- package/dist/types/schemas.d.ts.map +1 -1
- package/locales/en.json +102 -0
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ const adapter = createCanvasGraphqlAdapter({ executeQuery })
|
|
|
38
38
|
function ModulesPage({ courseId }: { courseId: string }) {
|
|
39
39
|
const data = useModulesPageData({ courseId, adapter, view: 'student' })
|
|
40
40
|
return (
|
|
41
|
-
<ModulesI18nProvider
|
|
41
|
+
<ModulesI18nProvider translations={translations} locale={locale}>
|
|
42
42
|
<ModulesList data={data} courseName={courseName} />
|
|
43
43
|
</ModulesI18nProvider>
|
|
44
44
|
)
|
|
@@ -46,7 +46,116 @@ function ModulesPage({ courseId }: { courseId: string }) {
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Keep the adapter referentially stable. A new adapter identity on every render rebuilds every item
|
|
49
|
-
observer's options on every render.
|
|
49
|
+
observer's options on every render. The same goes for `translations`.
|
|
50
|
+
|
|
51
|
+
## Translations
|
|
52
|
+
|
|
53
|
+
The package ships `locales/en.json` and reads it as the floor, so the provider is optional and
|
|
54
|
+
every key has a default. A host supplies as much or as little as it wants:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
// Partial. Anything omitted renders the English in en.json.
|
|
58
|
+
const translations = useMemo(() => ({ pageTitle: 'Learning Path' }), [])
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The catalog is separately importable when you want to extract from it or build a
|
|
62
|
+
full one — `import en from '@instructure/platform-modules/locales/en.json'`.
|
|
63
|
+
|
|
64
|
+
Resolution walks the host catalog, then `en.json`, then the key itself, taking the
|
|
65
|
+
first entry that is actually a string. Three consequences worth knowing:
|
|
66
|
+
|
|
67
|
+
- **Rebranding and translating are the same edit.** `{ pageTitle: 'Learning Path' }` is the whole
|
|
68
|
+
of the page-title ask, which is why there is no separate `strings` config key.
|
|
69
|
+
- **A key the catalog does not carry renders as its own text**, so a host-registered label passes
|
|
70
|
+
through rather than showing a bare key.
|
|
71
|
+
- **Only a string overrides.** `''` blanks a string deliberately; a `null` or a number from an
|
|
72
|
+
untyped host falls back to English rather than rendering `null` or throwing.
|
|
73
|
+
|
|
74
|
+
Interpolation is `%{token}`. `locale` rides alongside because `Intl` formats the dates and numbers
|
|
75
|
+
that sit beside the words.
|
|
76
|
+
|
|
77
|
+
### Plural forms
|
|
78
|
+
|
|
79
|
+
Where the count changes the sentence, an entry carries CLDR plural categories instead of
|
|
80
|
+
one string, and the package selects between them with `Intl.PluralRules` for your locale:
|
|
81
|
+
|
|
82
|
+
```jsonc
|
|
83
|
+
// in en.json
|
|
84
|
+
"pointsAbbreviated": { "one": "%{count} pt", "other": "%{count} pts" }
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const translations = useMemo(
|
|
89
|
+
() => ({
|
|
90
|
+
pointsAbbreviated: {
|
|
91
|
+
one: '%{count} балл',
|
|
92
|
+
few: '%{count} балла',
|
|
93
|
+
many: '%{count} баллов',
|
|
94
|
+
other: '%{count} балла',
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
[]
|
|
98
|
+
)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Always supply `other`, whatever your language.** It is the floor the package falls back to,
|
|
102
|
+
and in most locales it is also a real category — Russian uses it for any count with a decimal
|
|
103
|
+
part, so a catalog of only `one`/`few`/`many` renders English at `2.5`. A language with one
|
|
104
|
+
form needs `other` alone, or just a plain string. Nothing validates a host catalog, so this
|
|
105
|
+
is a contract rather than a checked rule.
|
|
106
|
+
|
|
107
|
+
Selection reads the `count` option, which is why it arrives as a number rather than a
|
|
108
|
+
pre-formatted string — the same value is then formatted for your locale when rendered.
|
|
109
|
+
|
|
110
|
+
You can also give forms to a key `en.json` ships flat. The quantity a plural form would agree
|
|
111
|
+
with is named `count` on every key, so this works wherever your language needs a distinction
|
|
112
|
+
English does not. A second quantity in the same sentence keeps its own name and cannot drive
|
|
113
|
+
selection — `%{loaded}` in `itemsLoadedAnnouncement` and `loadMoreItems`, `%{percent}` and
|
|
114
|
+
`%{met}` in `progressSummary`:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
// English says "Score at least 8"; Russian needs the noun to agree.
|
|
118
|
+
{ requirementMinScore: { one: 'Не менее %{count} балла', few: 'Не менее %{count} баллов',
|
|
119
|
+
many: 'Не менее %{count} баллов', other: 'Не менее %{count} балла' } }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Configuration
|
|
123
|
+
|
|
124
|
+
Everything customizable is a key in one config object. Start from `baseModulesConfig` and write only
|
|
125
|
+
what you want different.
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
import {
|
|
129
|
+
baseModulesConfig,
|
|
130
|
+
ModulesConfigProvider,
|
|
131
|
+
resolveModulesConfig,
|
|
132
|
+
} from '@instructure/platform-modules'
|
|
133
|
+
|
|
134
|
+
const modulesConfig = resolveModulesConfig(baseModulesConfig, {
|
|
135
|
+
itemStatuses: { missing: { label: 'Overdue', order: 10 } },
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
;<ModulesConfigProvider value={modulesConfig}>
|
|
139
|
+
<ModulesPage courseId={courseId} />
|
|
140
|
+
</ModulesConfigProvider>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Registries merge per entry — `{ ...base[key], ...override[key] }` — so naming a key the base already
|
|
144
|
+
has changes only the fields you state, and a key it doesn't is a new entry that needs the whole
|
|
145
|
+
thing. `formatters` and `navigation` are a shallow spread of the top level. An explicit `undefined`
|
|
146
|
+
keeps the inherited value either way; remove an entry with `hidden: true`.
|
|
147
|
+
|
|
148
|
+
Build the config at module scope, as above. Every key is a developer decision, so `resolveModulesConfig`
|
|
149
|
+
runs once at import and the reference is stable. If you later fold in fetched data — permissions, LTI
|
|
150
|
+
tools, the observed student — move the build into a component and memoize it on that data.
|
|
151
|
+
|
|
152
|
+
The provider is optional: without it the package renders against `baseModulesConfig`. In tests, use
|
|
153
|
+
`partialModulesConfig({ … })` to pin one surface without hand-building the rest.
|
|
154
|
+
|
|
155
|
+
Resolution is eager and validated, so a typo'd key, a malformed entry, or a field on a key that is
|
|
156
|
+
declared but not yet implemented throws at construction rather than rendering nothing.
|
|
157
|
+
|
|
158
|
+
`docs/adr/0001-customization.md` has the reasoning and the full list of mechanisms.
|
|
50
159
|
|
|
51
160
|
## Adapters
|
|
52
161
|
|
|
@@ -70,6 +179,7 @@ pnpm storybook
|
|
|
70
179
|
## Documentation
|
|
71
180
|
|
|
72
181
|
- `CLAUDE.md` describes what is true in `src/` right now.
|
|
73
|
-
- `docs/adr/` holds the decision records.
|
|
182
|
+
- `docs/adr/` holds the decision records. The decision is append-only: supersede a record, never
|
|
183
|
+
rewrite one. Filenames, headings and links may be corrected — see `docs/adr/README.md`.
|
|
74
184
|
- Reasoning local to one file stays in a doc comment there. Start with `adapters/types.ts`,
|
|
75
185
|
`adapters/limits.ts`, `hooks/constants.ts`, and `cache/invalidate.ts`.
|
|
@@ -40,7 +40,7 @@ export interface CanvasGraphqlAdapterOptions {
|
|
|
40
40
|
*/
|
|
41
41
|
studentId?: string | null;
|
|
42
42
|
/**
|
|
43
|
-
* Validate
|
|
43
|
+
* Validate normalized output against the Zod schemas before returning.
|
|
44
44
|
*
|
|
45
45
|
* On by default. This is the check that keeps the GraphQL and REST adapters
|
|
46
46
|
* from drifting, and it is the only place the contract is enforced at
|
|
@@ -2,7 +2,7 @@ import { CompletionRequirement, CompletionRequirementType, Module, ModuleItem, M
|
|
|
2
2
|
/**
|
|
3
3
|
* GraphQL node → domain model.
|
|
4
4
|
*
|
|
5
|
-
* Everything transport-shaped stops here. The three
|
|
5
|
+
* Everything transport-shaped stops here. The three normalization rules from
|
|
6
6
|
* `types/domain.ts` are enforced in this file and nowhere else:
|
|
7
7
|
*
|
|
8
8
|
* 1. **Ids are strings.** Canvas hands back `ID`, which the JSON transport
|
|
@@ -34,7 +34,7 @@ export interface GraphqlSubmission {
|
|
|
34
34
|
submittedAt?: string | null;
|
|
35
35
|
attempt?: number | null;
|
|
36
36
|
missing?: boolean | null;
|
|
37
|
-
/** Per-student, override-applied due date,
|
|
37
|
+
/** Per-student, override-applied due date, denormalized onto the submission. */
|
|
38
38
|
cachedDueDate?: string | null;
|
|
39
39
|
}
|
|
40
40
|
export interface GraphqlSubmissionConnection {
|
|
@@ -72,6 +72,7 @@ export interface GraphqlModuleItemNode {
|
|
|
72
72
|
_id: string | number;
|
|
73
73
|
title?: string | null;
|
|
74
74
|
url?: string | null;
|
|
75
|
+
newTab?: boolean | null;
|
|
75
76
|
position?: number | null;
|
|
76
77
|
indent?: number | null;
|
|
77
78
|
published?: boolean | null;
|
|
@@ -195,18 +196,18 @@ export declare function normalizeItemType(content: GraphqlModuleItemContent | nu
|
|
|
195
196
|
*/
|
|
196
197
|
export declare function parseDurationMinutes(value: string | null | undefined): number | null;
|
|
197
198
|
/**
|
|
198
|
-
* Wire string → closed enum, with anything
|
|
199
|
+
* Wire string → closed enum, with anything unrecognized becoming `'unknown'`.
|
|
199
200
|
*
|
|
200
201
|
* Unlike an unmappable item `__typename`, an unknown requirement type is not
|
|
201
202
|
* dropped: the requirement still exists, the student still has to satisfy it,
|
|
202
|
-
* and hiding the row would be a worse lie than
|
|
203
|
+
* and hiding the row would be a worse lie than labeling it vaguely.
|
|
203
204
|
*/
|
|
204
205
|
export declare function normalizeCompletionRequirementType(type: string): CompletionRequirementType;
|
|
205
206
|
export declare function normalizePageInfo(pageInfo: GraphqlPageInfo | null | undefined): PageInfo;
|
|
206
207
|
/**
|
|
207
208
|
* The module-level student state every item in that module is read against.
|
|
208
209
|
*
|
|
209
|
-
* Built once per module and threaded into the item
|
|
210
|
+
* Built once per module and threaded into the item normalizer so the inline and
|
|
210
211
|
* on-demand paths derive the identical status for the identical item — which is
|
|
211
212
|
* why `GET_MODULE_ITEMS` re-reads `progression` alongside its items.
|
|
212
213
|
*/
|
|
@@ -329,7 +330,7 @@ export declare function deriveModuleProgress(node: GraphqlModuleNode, completion
|
|
|
329
330
|
* A single item, or `null` when its content type is outside the closed enum.
|
|
330
331
|
*
|
|
331
332
|
* `dueAt` prefers `submission.cachedDueDate` — the per-student, override-applied
|
|
332
|
-
* date Canvas
|
|
333
|
+
* date Canvas denormalizes onto the submission row — and falls back to
|
|
333
334
|
* `content.dueAt`. That ordering is what closes the gap a live-Canvas probe
|
|
334
335
|
* found: `dueAt` exists on `Assignment` only, `Quiz` has none, and a graded
|
|
335
336
|
* `Discussion` keeps its date on the backing assignment, but all three carry a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/adapters/canvasGraphql/normalize.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/adapters/canvasGraphql/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,yBAAyB,EACzB,MAAM,EACN,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,WAAW,EACX,YAAY,EACZ,QAAQ,EACT,MAAM,oBAAoB,CAAA;AAG3B;;;;;;;;;;;;;;GAcG;AAOH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,OAAO,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAC5B,iGAAiG;IACjG,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACxB,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,CAAC,iBAAiB,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;CAC5C;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,qBAAqB,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAA;CAC3D;AAED,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,wBAAwB;IACvC,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC1B,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;CACvD;AAED,uEAAuE;AACvE,MAAM,WAAW,uBAAuB;IACtC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvC;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC1B,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,OAAO,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAA;CAC1C;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,CAAC,qBAAqB,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;IAC/C,QAAQ,EAAE,eAAe,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,yBAAyB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC1C,aAAa,CAAC,EAAE,CAAC;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;IACzD,sBAAsB,CAAC,EAAE,CAAC,4BAA4B,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;IACvE,8EAA8E;IAC9E,WAAW,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAA;IAC7C,oBAAoB,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAA;IACrD,qBAAqB,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAA;CAC3D;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,CAAC,iBAAiB,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;IAC3C,QAAQ,EAAE,eAAe,CAAA;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CAC3E;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE;QACX,sBAAsB,CAAC,EAAE,CAAC,4BAA4B,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;QACvE,WAAW,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAA;QAC7C,qBAAqB,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAA;KAC3D,GAAG,IAAI,CAAA;CACT;AAED,oDAAoD;AACpD,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,YAAY,CAAA;AAE5D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAA;IACxC,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;gBAEV,OAAO,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAWvE;AAED,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAA;IACV,oFAAoF;IACpF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAC1D;AA6ED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,GACnD,cAAc,GAAG,IAAI,CAQvB;AAKD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAcpF;AAWD;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,MAAM,GAAG,yBAAyB,CAE1F;AAaD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAMxF;AAiBD;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,MAAM,EAAE,OAAO,CAAA;IACf,sFAAsF;IACtF,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;OAMG;IACH,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAC5C;AASD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,GACnD,iBAAiB,GAAG,IAAI,CAK1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,EACxD,sBAAsB,EAAE,SAAS,qBAAqB,EAAE,GACvD,oBAAoB,GAAG,SAAS,CAmBlC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,EACpD,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,oBAAoB,GAC5B,gBAAgB,CAqBlB;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,EAC7B,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,GAC9B,YAAY,CAYd;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,iBAAiB,EACvB,sBAAsB,EAAE,SAAS,qBAAqB,EAAE,EACxD,OAAO,EAAE,oBAAoB,GAAG,SAAS,EACzC,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,GAC9B,cAAc,GAAG,SAAS,CAgB5B;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,qBAAqB,EAC3B,QAAQ,EAAE,MAAM,EAChB,8BAA8B,EAAE,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,EAC1E,OAAO,GAAE,gBAAqB,EAC9B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,UAAU,GAAG,IAAI,CAgCnB;AA4CD,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CA6C/F;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,EAC3C,OAAO,GAAE,gBAAqB,GAC7B,WAAW,CAUb;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,EAC/C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAYjB"}
|
|
@@ -21,10 +21,10 @@ import { DocumentNode } from 'graphql';
|
|
|
21
21
|
* 3. The response type is a single shape with an optional key, which is
|
|
22
22
|
* exactly how the domain model already treats it (`items?: ModuleItem[]`,
|
|
23
23
|
* where `undefined` means "not fetched"). A second document would force
|
|
24
|
-
* the
|
|
24
|
+
* the normalizer to branch on which document produced the payload.
|
|
25
25
|
*
|
|
26
26
|
* `itemsFirst` bounds the inline item fetch. When a module has more items than
|
|
27
|
-
* that, the
|
|
27
|
+
* that, the normalizer drops the partial list rather than reporting a
|
|
28
28
|
* truncated one — see `normalize.ts`.
|
|
29
29
|
*/
|
|
30
30
|
export declare const GET_MODULES: DocumentNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/adapters/canvasGraphql/queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/adapters/canvasGraphql/queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAkL3C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,WAAW,EAAE,YA0DzB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,EAAE,YAiC9B,CAAA;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,EAAE,OAAO,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,kBAAkB,EAAE,OAAO,CAAA;IAC3B,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB"}
|
|
@@ -9,7 +9,7 @@ import { ModulesDataAdapter } from './types';
|
|
|
9
9
|
* server at all.
|
|
10
10
|
*
|
|
11
11
|
* It is a real implementation of the contract, deliberately: it paginates with
|
|
12
|
-
* opaque cursors,
|
|
12
|
+
* opaque cursors, honors `AbortSignal`, and declines to inline items for modules
|
|
13
13
|
* over `INLINE_ITEM_LIMIT` — so hooks written against it meet the same edges
|
|
14
14
|
* Canvas will hand them, including the one Canvas Career gets wrong.
|
|
15
15
|
*/
|
|
@@ -40,7 +40,7 @@ export interface InMemoryRequest {
|
|
|
40
40
|
export interface InMemoryAdapterOptions {
|
|
41
41
|
/**
|
|
42
42
|
* Invoked once per served request. Test hook for asserting exact request
|
|
43
|
-
* counts, which is how the scaling
|
|
43
|
+
* counts, which is how the scaling behavior is locked in.
|
|
44
44
|
*
|
|
45
45
|
* Receives the operation name for the common case, and the full request for
|
|
46
46
|
* tests that care *which* course or module was asked for.
|
|
@@ -51,8 +51,8 @@ export interface InMemoryAdapterOptions {
|
|
|
51
51
|
* Thrown when a caller asks this adapter for a course it was not built for.
|
|
52
52
|
*
|
|
53
53
|
* A real transport would return that other course's data, or 404. Silently
|
|
54
|
-
* serving the fixture regardless is the one
|
|
55
|
-
* production, so it is the one
|
|
54
|
+
* serving the fixture regardless is the one behavior that could not happen in
|
|
55
|
+
* production, so it is the one behavior the test double must not have.
|
|
56
56
|
*/
|
|
57
57
|
export declare class InMemoryCourseMismatchError extends Error {
|
|
58
58
|
readonly expected: string;
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* Relay connection, and nothing in `app/graphql/types/module_type.rb` caps it.
|
|
36
36
|
*
|
|
37
37
|
* It would be wrong to conclude GraphQL will inline anything you ask for, though.
|
|
38
|
-
* Canvas runs a query-complexity
|
|
38
|
+
* Canvas runs a query-complexity analyzer, and it charges for the *shape of the
|
|
39
39
|
* request* rather than the size of the result: `first: 100, itemsFirst: 100`
|
|
40
40
|
* scores ~1.5M against a 375,000 ceiling and is rejected outright, even on a
|
|
41
41
|
* course holding thirteen items. So the ceiling is real on both transports — just
|
|
@@ -44,13 +44,13 @@
|
|
|
44
44
|
*
|
|
45
45
|
* The GraphQL adapter therefore applies this same 100 as a deliberate *policy*,
|
|
46
46
|
* so both transports fall back to a per-module fetch at the same point and the
|
|
47
|
-
* hooks see one
|
|
47
|
+
* hooks see one behavior rather than two.
|
|
48
48
|
*/
|
|
49
49
|
export declare const INLINE_ITEM_LIMIT = 100;
|
|
50
50
|
/**
|
|
51
51
|
* Ceiling on `pageSize × inlineItemsFirst` for a single inline request.
|
|
52
52
|
*
|
|
53
|
-
* Canvas runs a GraphQL complexity
|
|
53
|
+
* Canvas runs a GraphQL complexity analyzer and rejects anything over 375,000.
|
|
54
54
|
* Complexity is charged on the **shape of the request, not the size of the
|
|
55
55
|
* result** — so a course with 13 items is rejected just as readily as one with
|
|
56
56
|
* 13,000 if the query asks for `first: 100, itemsFirst: 100`.
|
|
@@ -67,7 +67,7 @@ export declare const INLINE_ITEM_LIMIT = 100;
|
|
|
67
67
|
*
|
|
68
68
|
* That is ~151 per requested item node, so the budget is the largest round
|
|
69
69
|
* product comfortably under 375,000/151 ≈ 2,483. Kept as a product rather than
|
|
70
|
-
* two separate caps because the
|
|
70
|
+
* two separate caps because the analyzer multiplies: 100×20 and 10×100 both fit,
|
|
71
71
|
* 25×100 does not.
|
|
72
72
|
*
|
|
73
73
|
* If a page genuinely needs more than this, it is not an inline page — the
|
package/dist/adapters/types.d.ts
CHANGED
|
@@ -5,18 +5,18 @@ import { ModuleItemsPage, ModulesPage } from '../types/domain';
|
|
|
5
5
|
* An adapter owns exactly three things: how a request is made, what fields it
|
|
6
6
|
* asks for, and how the response becomes the domain model. It owns nothing
|
|
7
7
|
* about caching, pagination policy, or React — those live in the hooks, so
|
|
8
|
-
* that swapping GraphQL for REST changes one file and no
|
|
8
|
+
* that swapping GraphQL for REST changes one file and no behavior.
|
|
9
9
|
*
|
|
10
|
-
* Contract every adapter must
|
|
10
|
+
* Contract every adapter must honor:
|
|
11
11
|
*
|
|
12
12
|
* - **Return a real `pageInfo`.** The GraphQL adapter passes through
|
|
13
13
|
* `endCursor`; the REST adapter derives it from the `Link` header. An
|
|
14
14
|
* adapter that hardcodes `hasNextPage: false` silently truncates, which is
|
|
15
15
|
* the live bug in Canvas Career's modules path today.
|
|
16
|
-
* - **
|
|
16
|
+
* - **Honor `signal`.** Collapsing a module aborts its in-flight request.
|
|
17
17
|
* - **Never invent a cursor.** Pass back what the server gave you; do not
|
|
18
|
-
*
|
|
19
|
-
* - **
|
|
18
|
+
* synthesize offsets client-side.
|
|
19
|
+
* - **Normalize fully.** Output must satisfy the Zod schemas. No transport
|
|
20
20
|
* detail (`_id`, `quiz_lti`, snake_case) may reach a caller.
|
|
21
21
|
*/
|
|
22
22
|
export interface ModulesDataAdapter {
|
|
@@ -27,7 +27,7 @@ export interface ModulesDataAdapter {
|
|
|
27
27
|
* one inline request, or `undefined` for "no transport limit of my own".
|
|
28
28
|
*
|
|
29
29
|
* The transport declares its own ceiling rather than the hooks assuming one.
|
|
30
|
-
* Canvas GraphQL has a complexity
|
|
30
|
+
* Canvas GraphQL has a complexity analyzer that rejects the *shape* of a large
|
|
31
31
|
* inline query (@see INLINE_QUERY_NODE_BUDGET); the in-memory double has no
|
|
32
32
|
* such constraint; REST will have a different one again, bounded by
|
|
33
33
|
* `Api::MAX_PER_PAGE` and response size rather than by query complexity.
|
package/dist/cache/keys.d.ts
CHANGED
|
@@ -80,7 +80,7 @@ export declare function modulesListPrefix(courseId: string): readonly ['platform
|
|
|
80
80
|
*
|
|
81
81
|
* This is the one to reach for when acting on "that module's items" without
|
|
82
82
|
* knowing which view or page size rendered them — invalidating after a mutation,
|
|
83
|
-
* or
|
|
83
|
+
* or canceling in flight requests on collapse.
|
|
84
84
|
*/
|
|
85
85
|
export declare function moduleItemsPrefix(courseId: string, moduleId: string): readonly ['platform-modules', string, 'module', string, 'items'];
|
|
86
86
|
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
import { ModulesFilterId } from './labels';
|
|
3
3
|
/**
|
|
4
|
-
* The filter row.
|
|
4
|
+
* The filter row: a toggle group, not tabs.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* R3 says "Filter • tabs", but the design draws five independent secondary
|
|
7
|
+
* Buttons under a caption — no tablist, no tabpanel, nothing tying the
|
|
8
|
+
* selection to the list. So `role="group"` + `aria-pressed`, one tab stop per
|
|
9
|
+
* chip. Checked against the mock in FOUND-355; `Tabs` is the wrong component.
|
|
10
|
+
*
|
|
11
|
+
* The selected chip is `primary`, not the mock's tinted `secondary`: the mock's
|
|
12
|
+
* two fills sit 1.25:1 apart where WCAG 1.4.11 wants 3:1, and its blues come
|
|
13
|
+
* from InstUI Button v2, which `ui-buttons@11` does not ship.
|
|
10
14
|
*/
|
|
11
15
|
export interface FilterChipsProps {
|
|
12
16
|
value: ModulesFilterId;
|
|
13
17
|
onChange: (filter: ModulesFilterId) => void;
|
|
14
|
-
/** Per-chip match counts, rendered when supplied. Cheap: module-level only. */
|
|
15
|
-
counts?: Partial<Record<ModulesFilterId, number>>;
|
|
16
18
|
}
|
|
17
19
|
/** @see FilterChipsProps */
|
|
18
|
-
export declare function FilterChips({ value, onChange
|
|
20
|
+
export declare function FilterChips({ value, onChange }: FilterChipsProps): ReactElement;
|
|
19
21
|
//# sourceMappingURL=FilterChips.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterChips.d.ts","sourceRoot":"","sources":["../../src/components/FilterChips.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,OAAO,CAAA;AAEhD,OAAO,EAAmC,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"FilterChips.d.ts","sourceRoot":"","sources":["../../src/components/FilterChips.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,OAAO,CAAA;AAEhD,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAEhF;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,eAAe,CAAA;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAA;CAC5C;AAED,4BAA4B;AAC5B,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,gBAAgB,GAAG,YAAY,CAmD/E"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { NamedExoticComponent } from 'react';
|
|
2
2
|
import { ModuleItemsState } from '../hooks';
|
|
3
|
-
import { Module } from '../types';
|
|
3
|
+
import { Module, ModuleItemNavigation } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* One module card.
|
|
6
|
+
*
|
|
7
|
+
* Header: number badge, name, byline, status pill, expand toggle.
|
|
8
|
+
* Progress row: **only when `module.progress` exists**.
|
|
9
|
+
*
|
|
10
|
+
* Expanded body: the item rows, plus the per-module "Load more items" control
|
|
11
|
+
* whenever `hasNextPage` is true.
|
|
12
|
+
*/
|
|
4
13
|
export interface ModuleCardProps {
|
|
5
14
|
module: Module;
|
|
6
15
|
expanded: boolean;
|
|
@@ -10,18 +19,21 @@ export interface ModuleCardProps {
|
|
|
10
19
|
today: Date;
|
|
11
20
|
/** Show the `inline` vs `onDemand` provenance line. Dev affordance, off by default. */
|
|
12
21
|
showDiagnostics?: boolean;
|
|
22
|
+
/** Stable reference required; see `ModuleItemNavigation`. */
|
|
23
|
+
navigation?: ModuleItemNavigation;
|
|
13
24
|
/**
|
|
14
25
|
* Heading level for the module name. Defaults to `'h3'`, one below
|
|
15
26
|
* `ModulesList`'s default of `h2`.
|
|
16
|
-
*
|
|
17
|
-
* The name was bold `Text`, which meant a 120-module course offered a screen
|
|
18
|
-
* reader no heading list to navigate by — the only heading in the tree was the
|
|
19
|
-
* page title.
|
|
20
27
|
*/
|
|
21
28
|
headingLevel?: 'h2' | 'h3' | 'h4';
|
|
29
|
+
/**
|
|
30
|
+
* Badge text: omitted derives it from `module.position`, `null` renders no
|
|
31
|
+
* badge, a string overrides.
|
|
32
|
+
*/
|
|
33
|
+
moduleLabel?: string | null;
|
|
22
34
|
}
|
|
23
35
|
/**
|
|
24
|
-
*
|
|
36
|
+
* Memoized, which is only useful because its props are now stable.
|
|
25
37
|
*
|
|
26
38
|
* `itemsState` comes from `useModulesPageData`'s per-module cache and `onToggle`
|
|
27
39
|
* from a ref-backed `useCallback`, so a card re-renders when *its own* module
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModuleCard.d.ts","sourceRoot":"","sources":["../../src/components/ModuleCard.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAQ,KAAK,oBAAoB,EAAwC,MAAM,OAAO,CAAA;AAC7F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"ModuleCard.d.ts","sourceRoot":"","sources":["../../src/components/ModuleCard.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAQ,KAAK,oBAAoB,EAAwC,MAAM,OAAO,CAAA;AAC7F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAO5D;;;;;;;;GAQG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,mEAAmE;IACnE,UAAU,EAAE,gBAAgB,CAAA;IAC5B,KAAK,EAAE,IAAI,CAAA;IACX,uFAAuF;IACvF,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,oBAAoB,CAAA;IACjC;;;OAGG;IACH,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IACjC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAqUD;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,oBAAoB,CAAC,eAAe,CAAwB,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ModuleCard } from './ModuleCard';
|
|
3
|
+
declare const meta: Meta<typeof ModuleCard>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof meta>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const ThreeDigitNumber: Story;
|
|
8
|
+
export declare const Locked: Story;
|
|
9
|
+
/** A label longer than the square widens the badge instead of spilling out of it. */
|
|
10
|
+
export declare const LongLabel: Story;
|
|
11
|
+
export declare const NoBadge: Story;
|
|
12
|
+
//# sourceMappingURL=ModuleCard.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModuleCard.stories.d.ts","sourceRoot":"","sources":["../../src/components/ModuleCard.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGtD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAoBzC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU,CAWjC,CAAA;AAED,eAAe,IAAI,CAAA;AACnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAA;AAElC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAA;AAEhC,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAA;AAED,eAAO,MAAM,MAAM,EAAE,KAEpB,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAA;AAED,eAAO,MAAM,OAAO,EAAE,KAErB,CAAA"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { NamedExoticComponent } from 'react';
|
|
2
|
-
import { ModuleItem } from '../types';
|
|
2
|
+
import { ModuleItem, ModuleItemNavigation } from '../types';
|
|
3
3
|
export interface ModuleItemRowProps {
|
|
4
4
|
item: ModuleItem;
|
|
5
5
|
/** Injected so relative dates ("yesterday") are deterministic. */
|
|
6
6
|
today: Date;
|
|
7
|
+
/** Stable reference required; see `ModuleItemNavigation`. */
|
|
8
|
+
navigation?: ModuleItemNavigation;
|
|
7
9
|
}
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
11
|
+
* Memoized because it is the hottest component in the package.
|
|
10
12
|
*
|
|
11
13
|
* `item` is a stable reference out of the query cache and `today` is pinned per
|
|
12
14
|
* mount, so the default shallow comparison is enough. It is what stops one
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModuleItemRow.d.ts","sourceRoot":"","sources":["../../src/components/ModuleItemRow.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ModuleItemRow.d.ts","sourceRoot":"","sources":["../../src/components/ModuleItemRow.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAyB,KAAK,oBAAoB,EAAqB,MAAM,OAAO,CAAA;AAC3F,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,oBAAoB,EAE1B,MAAM,UAAU,CAAA;AAuDjB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,UAAU,CAAA;IAChB,kEAAkE;IAClE,KAAK,EAAE,IAAI,CAAA;IACX,6DAA6D;IAC7D,UAAU,CAAC,EAAE,oBAAoB,CAAA;CAClC;AAmJD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,oBAAoB,CAAC,kBAAkB,CAA2B,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
export interface ModuleNumberBadgeProps {
|
|
3
|
+
/** `null` renders no badge. */
|
|
4
|
+
label: string | null;
|
|
5
|
+
dimmed?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function ModuleNumberBadge({ label, dimmed, }: ModuleNumberBadgeProps): ReactElement | null;
|
|
8
|
+
//# sourceMappingURL=ModuleNumberBadge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModuleNumberBadge.d.ts","sourceRoot":"","sources":["../../src/components/ModuleNumberBadge.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAIzC,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,MAAc,GACf,EAAE,sBAAsB,GAAG,YAAY,GAAG,IAAI,CAuB9C"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
import { UseModulesPageDataResult } from '../hooks';
|
|
3
|
+
import { ModuleItemNavigation } from '../types';
|
|
3
4
|
import { ModulesFilterId } from './labels';
|
|
4
5
|
/**
|
|
5
6
|
* The student modules page, approximating the Modules Foundation design.
|
|
@@ -47,6 +48,8 @@ export interface ModulesListProps {
|
|
|
47
48
|
showDiagnostics?: boolean;
|
|
48
49
|
/** Which chip starts active. Uncontrolled after mount — the chips own it. */
|
|
49
50
|
initialFilter?: ModulesFilterId;
|
|
51
|
+
/** Stable reference required; see `ModuleItemNavigation`. */
|
|
52
|
+
navigation?: ModuleItemNavigation;
|
|
50
53
|
/**
|
|
51
54
|
* Element for the outer container. Defaults to `'div'`.
|
|
52
55
|
*
|
|
@@ -65,5 +68,5 @@ export interface ModulesListProps {
|
|
|
65
68
|
headingLevel?: 'h1' | 'h2' | 'h3';
|
|
66
69
|
}
|
|
67
70
|
/** @see ModulesListProps */
|
|
68
|
-
export declare function ModulesList({ data, courseName, courseContext, today, requestCounts, showDiagnostics, initialFilter, as, headingLevel, }: ModulesListProps): ReactElement;
|
|
71
|
+
export declare function ModulesList({ data, courseName, courseContext, today, requestCounts, showDiagnostics, initialFilter, navigation, as, headingLevel, }: ModulesListProps): ReactElement;
|
|
69
72
|
//# sourceMappingURL=ModulesList.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModulesList.d.ts","sourceRoot":"","sources":["../../src/components/ModulesList.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,YAAY,EAA+C,MAAM,OAAO,CAAA;AACtF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"ModulesList.d.ts","sourceRoot":"","sources":["../../src/components/ModulesList.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,YAAY,EAA+C,MAAM,OAAO,CAAA;AACtF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AACxD,OAAO,KAAK,EAAU,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAG5D,OAAO,EAA4C,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAGzF;;;;;;;;;;;;;;;;GAgBG;AAEH,iEAAiE;AACjE,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,yEAAyE;IACzE,IAAI,EAAE,wBAAwB,CAAA;IAC9B,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ;;;;;OAKG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAA;IACpC,sGAAsG;IACtG,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,eAAe,CAAA;IAC/B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,oBAAoB,CAAA;IACjC;;;;;;;OAOG;IACH,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;IAC/B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;CAClC;AA0DD,4BAA4B;AAC5B,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,UAAU,EACV,aAAa,EACb,KAAK,EACL,aAAa,EACb,eAA6C,EAC7C,aAAqB,EACrB,UAAU,EACV,EAAU,EACV,YAAmB,GACpB,EAAE,gBAAgB,GAAG,YAAY,CAiRjC"}
|
|
@@ -43,17 +43,21 @@ interface ModulesListStoryProps {
|
|
|
43
43
|
/**
|
|
44
44
|
* Which i18n bridge to render through.
|
|
45
45
|
*
|
|
46
|
-
* `none` is a host that
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
46
|
+
* `none` is a host that supplies no catalog: every string comes from
|
|
47
|
+
* `locales/en.json`. `pseudo` is the standard pre-translation audit — every
|
|
48
|
+
* string is bracketed and padded, so an untranslated literal is visible on
|
|
49
|
+
* sight and a layout that cannot survive a longer language shows up before a
|
|
50
|
+
* translator is ever involved. `rebranded` and `partial` are host catalogs,
|
|
51
|
+
* and both are deliberately incomplete.
|
|
51
52
|
*/
|
|
52
|
-
i18n: 'none' | 'pseudo';
|
|
53
|
+
i18n: 'none' | 'pseudo' | 'rebranded' | 'partial';
|
|
54
|
+
/** Clear it to render the catalog's `pageTitle` instead of a host-supplied name. */
|
|
55
|
+
courseName: string;
|
|
56
|
+
navigation: 'none' | 'rewritten' | 'intercepted';
|
|
53
57
|
}
|
|
54
58
|
/**
|
|
55
59
|
* Its own `QueryClient`, deliberately — the global preview decorator builds one
|
|
56
|
-
* in its render body, and these stories are about cache
|
|
60
|
+
* in its render body, and these stories are about cache behavior.
|
|
57
61
|
*/
|
|
58
62
|
declare function ModulesListHarness(props: ModulesListStoryProps): ReactElement;
|
|
59
63
|
declare const meta: Meta<typeof ModulesListHarness>;
|
|
@@ -83,6 +87,12 @@ export declare const LargeCourse: Story;
|
|
|
83
87
|
* on the card until all 250 are loaded.
|
|
84
88
|
*/
|
|
85
89
|
export declare const FatModuleInlineFallback: Story;
|
|
90
|
+
/** Every shape an item title can take: linked, new tab, sub-header, no url, long, locked. */
|
|
91
|
+
export declare const ItemTitleLinks: Story;
|
|
92
|
+
/** The same module with `getItemHref` rewriting each href the adapter supplied. */
|
|
93
|
+
export declare const ItemTitleLinksRewritten: Story;
|
|
94
|
+
/** `onItemClick` with `preventDefault()`, as a client-side router would. */
|
|
95
|
+
export declare const ItemTitleLinksIntercepted: Story;
|
|
86
96
|
/** No modules. The empty state. */
|
|
87
97
|
export declare const EmptyCourse: Story;
|
|
88
98
|
/**
|
|
@@ -134,5 +144,23 @@ export declare const StatusCoverage: Story;
|
|
|
134
144
|
* The one deliberate exception is the dev diagnostics banner, which is developer
|
|
135
145
|
* text and is documented as untranslated in `ModuleCard`.
|
|
136
146
|
*/
|
|
137
|
-
export declare const
|
|
147
|
+
export declare const PseudoLocalized: Story;
|
|
148
|
+
/**
|
|
149
|
+
* A host rebranding the page in its own language.
|
|
150
|
+
*
|
|
151
|
+
* Career calls the page a Learning Path and its modules units. That is a
|
|
152
|
+
* catalog entry, not a config key — six entries here, and every string they do
|
|
153
|
+
* not name still reads English from `locales/en.json`. Switch the `fixture`
|
|
154
|
+
* control to `empty` to see the rebranded empty state.
|
|
155
|
+
*/
|
|
156
|
+
export declare const HostRebrand: Story;
|
|
157
|
+
/**
|
|
158
|
+
* A deliberately incomplete translation.
|
|
159
|
+
*
|
|
160
|
+
* Four German keys against an English catalog: the filter row is translated
|
|
161
|
+
* and everything else falls back rather than throwing or rendering blank. This
|
|
162
|
+
* is the property that lets a host adopt the package before translating it, and
|
|
163
|
+
* `locale` travels with the catalog so `Intl` dates match the words.
|
|
164
|
+
*/
|
|
165
|
+
export declare const PartialCatalog: Story;
|
|
138
166
|
//# sourceMappingURL=ModulesList.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModulesList.stories.d.ts","sourceRoot":"","sources":["../../src/components/ModulesList.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEtD,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"ModulesList.stories.d.ts","sourceRoot":"","sources":["../../src/components/ModulesList.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEtD,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,OAAO,CAAA;AAE5D,OAAO,EASL,KAAK,eAAe,EACpB,KAAK,SAAS,EAKf,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAG/C;;;;;;;;;;;;GAYG;AAEH,QAAA,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,eAAe,CAMnD,CAAA;AAoBD;;;;;;;;;;GAUG;AAIH,KAAK,YAAY,GAAG,SAAS,GAAG,SAAS,CAAA;AAEzC,UAAU,qBAAqB;IAC7B,OAAO,EAAE,MAAM,OAAO,QAAQ,CAAA;IAC9B,SAAS,EAAE,SAAS,CAAA;IACpB,YAAY,EAAE,YAAY,CAAA;IAC1B,aAAa,EAAE,eAAe,CAAA;IAC9B,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,oFAAoF;IACpF,wBAAwB,EAAE,MAAM,EAAE,CAAA;IAClC;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAA;IACjD,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,aAAa,CAAA;CACjD;AAkJD;;;GAGG;AACH,iBAAS,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,GAAG,YAAY,CAetE;AAkBD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,kBAAkB,CAiCzC,CAAA;AAED,eAAe,IAAI,CAAA;AACnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAA;AAElC;;;;;GAKG;AACH,eAAO,MAAM,OAAO,EAAE,KAErB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,KAErC,CAAA;AAED,6FAA6F;AAC7F,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAA;AAED,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,EAAE,KAErC,CAAA;AAED,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,KAEvC,CAAA;AAED,mCAAmC;AACnC,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAEnC,CAAA;AASD,2CAA2C;AAC3C,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAA;AAED,4DAA4D;AAC5D,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAA;AAED,mCAAmC;AACnC,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,KAO7B,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,KAQzB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,KAO5B,CAAA"}
|
|
@@ -2,6 +2,7 @@ export { FilterChips, type FilterChipsProps } from './FilterChips';
|
|
|
2
2
|
export { calendarDayDiff, DUE_THIS_WEEK_DAYS, filterLabel, formatDateTime, formatDueByline, formatModuleNumber, formatPoints, formatUnlockByline, itemTypeLabel, moduleMatchesFilter, moduleMatchesSearch, MODULES_FILTER_IDS, type ModulesFilterId, progressSummary, requirementLabel, } from './labels';
|
|
3
3
|
export { ModuleCard, type ModuleCardProps } from './ModuleCard';
|
|
4
4
|
export { ModuleItemRow, type ModuleItemRowProps } from './ModuleItemRow';
|
|
5
|
+
export { ModuleNumberBadge, type ModuleNumberBadgeProps } from './ModuleNumberBadge';
|
|
5
6
|
export { ModulesList, type ModulesListProps, type ModulesRequestCounts } from './ModulesList';
|
|
6
7
|
export { moduleItemStatusLabel, ModuleItemStatusPill, type ModuleItemStatusPillProps, moduleStatusLabel, ModuleStatusPill, type ModuleStatusPillProps, } from './StatusPill';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|