@instructure/platform-modules 0.3.0 → 1.0.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.
Files changed (108) hide show
  1. package/README.md +3 -2
  2. package/dist/adapters/canvasGraphql/index.d.ts +4 -40
  3. package/dist/adapters/canvasGraphql/index.d.ts.map +1 -1
  4. package/dist/adapters/canvasGraphql/normalize.d.ts +9 -220
  5. package/dist/adapters/canvasGraphql/normalize.d.ts.map +1 -1
  6. package/dist/adapters/canvasGraphql/queries.d.ts +7 -49
  7. package/dist/adapters/canvasGraphql/queries.d.ts.map +1 -1
  8. package/dist/adapters/inMemory.d.ts +0 -40
  9. package/dist/adapters/inMemory.d.ts.map +1 -1
  10. package/dist/adapters/limits.d.ts +3 -81
  11. package/dist/adapters/limits.d.ts.map +1 -1
  12. package/dist/adapters/types.d.ts +11 -61
  13. package/dist/adapters/types.d.ts.map +1 -1
  14. package/dist/cache/invalidate.d.ts +0 -46
  15. package/dist/cache/invalidate.d.ts.map +1 -1
  16. package/dist/cache/keys.d.ts +3 -55
  17. package/dist/cache/keys.d.ts.map +1 -1
  18. package/dist/components/FilterChips.d.ts +4 -17
  19. package/dist/components/FilterChips.d.ts.map +1 -1
  20. package/dist/components/ModuleCard.d.ts +5 -29
  21. package/dist/components/ModuleCard.d.ts.map +1 -1
  22. package/dist/components/ModuleCard.stories.d.ts +14 -1
  23. package/dist/components/ModuleCard.stories.d.ts.map +1 -1
  24. package/dist/components/ModuleItemRow.d.ts +0 -10
  25. package/dist/components/ModuleItemRow.d.ts.map +1 -1
  26. package/dist/components/ModuleNumberBadge.d.ts +0 -1
  27. package/dist/components/ModuleNumberBadge.d.ts.map +1 -1
  28. package/dist/components/ModulesList.d.ts +2 -54
  29. package/dist/components/ModulesList.d.ts.map +1 -1
  30. package/dist/components/ModulesList.stories.d.ts +11 -128
  31. package/dist/components/ModulesList.stories.d.ts.map +1 -1
  32. package/dist/components/StatusPill.d.ts +4 -6
  33. package/dist/components/StatusPill.d.ts.map +1 -1
  34. package/dist/components/index.d.ts +1 -1
  35. package/dist/components/index.d.ts.map +1 -1
  36. package/dist/components/labels.d.ts +8 -78
  37. package/dist/components/labels.d.ts.map +1 -1
  38. package/dist/components/lightThemeDecorator.d.ts +3 -0
  39. package/dist/components/lightThemeDecorator.d.ts.map +1 -0
  40. package/dist/config/base.d.ts +0 -5
  41. package/dist/config/base.d.ts.map +1 -1
  42. package/dist/config/capabilities.d.ts +8 -0
  43. package/dist/config/capabilities.d.ts.map +1 -0
  44. package/dist/config/context.d.ts +1 -2
  45. package/dist/config/context.d.ts.map +1 -1
  46. package/dist/config/filters.d.ts +15 -0
  47. package/dist/config/filters.d.ts.map +1 -0
  48. package/dist/config/formatters.d.ts +15 -0
  49. package/dist/config/formatters.d.ts.map +1 -0
  50. package/dist/config/index.d.ts +9 -4
  51. package/dist/config/index.d.ts.map +1 -1
  52. package/dist/config/itemMeta.d.ts +5 -0
  53. package/dist/config/itemMeta.d.ts.map +1 -0
  54. package/dist/config/itemTypes.d.ts +4 -0
  55. package/dist/config/itemTypes.d.ts.map +1 -0
  56. package/dist/config/partialModulesConfig.d.ts +0 -1
  57. package/dist/config/partialModulesConfig.d.ts.map +1 -1
  58. package/dist/config/registry.d.ts +2 -30
  59. package/dist/config/registry.d.ts.map +1 -1
  60. package/dist/config/resolve.d.ts +0 -4
  61. package/dist/config/resolve.d.ts.map +1 -1
  62. package/dist/config/schemas.d.ts +37 -7
  63. package/dist/config/schemas.d.ts.map +1 -1
  64. package/dist/config/types.d.ts +8 -14
  65. package/dist/config/types.d.ts.map +1 -1
  66. package/dist/config/useFormatters.d.ts +10 -0
  67. package/dist/config/useFormatters.d.ts.map +1 -0
  68. package/dist/fixtures/generate.d.ts +1 -37
  69. package/dist/fixtures/generate.d.ts.map +1 -1
  70. package/dist/fixtures/index.d.ts +1 -1
  71. package/dist/fixtures/index.d.ts.map +1 -1
  72. package/dist/fixtures/scenarios.d.ts +4 -34
  73. package/dist/fixtures/scenarios.d.ts.map +1 -1
  74. package/dist/hooks/constants.d.ts +6 -40
  75. package/dist/hooks/constants.d.ts.map +1 -1
  76. package/dist/hooks/queryOptions.d.ts +2 -26
  77. package/dist/hooks/queryOptions.d.ts.map +1 -1
  78. package/dist/hooks/useItemsMode.d.ts +3 -84
  79. package/dist/hooks/useItemsMode.d.ts.map +1 -1
  80. package/dist/hooks/useModuleItemQueries.d.ts +1 -45
  81. package/dist/hooks/useModuleItemQueries.d.ts.map +1 -1
  82. package/dist/hooks/useModuleItems.d.ts +0 -16
  83. package/dist/hooks/useModuleItems.d.ts.map +1 -1
  84. package/dist/hooks/useModules.d.ts +3 -24
  85. package/dist/hooks/useModules.d.ts.map +1 -1
  86. package/dist/hooks/useModulesPageData.d.ts +9 -33
  87. package/dist/hooks/useModulesPageData.d.ts.map +1 -1
  88. package/dist/i18n.d.ts +8 -45
  89. package/dist/i18n.d.ts.map +1 -1
  90. package/dist/index.d.ts +5 -12
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +1874 -1344
  93. package/dist/types/domain.d.ts +9 -87
  94. package/dist/types/domain.d.ts.map +1 -1
  95. package/dist/types/enums.d.ts +5 -58
  96. package/dist/types/enums.d.ts.map +1 -1
  97. package/dist/types/extensions.d.ts +0 -43
  98. package/dist/types/extensions.d.ts.map +1 -1
  99. package/dist/types/filterClause.d.ts +18 -0
  100. package/dist/types/filterClause.d.ts.map +1 -0
  101. package/dist/types/index.d.ts +3 -2
  102. package/dist/types/index.d.ts.map +1 -1
  103. package/dist/types/navigation.d.ts +0 -6
  104. package/dist/types/navigation.d.ts.map +1 -1
  105. package/dist/types/schemas.d.ts +2 -28
  106. package/dist/types/schemas.d.ts.map +1 -1
  107. package/locales/en.json +20 -9
  108. package/package.json +35 -31
@@ -1,166 +1,49 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
  import { ReactElement } from 'react';
3
3
  import { InMemoryFixture, ItemsMode } from '../index';
4
- import { ModulesFilterId } from './labels';
5
- /**
6
- * The Modules Foundation design over the real data layer.
7
- *
8
- * Harness: `createInMemoryAdapter` over a fixture, a
9
- * `QueryClient` whose identity survives a re-render, and the adapter's
10
- * `onRequest` feeding a live counter. Nothing is mocked — the adapter is a real
11
- * implementation of the contract, including declining to inline a module above
12
- * `INLINE_ITEM_LIMIT` as Canvas REST does — so the request count in the dev
13
- * banner is the genuine cost of what is on screen.
14
- *
15
- * The counter is the most useful thing here. Switch `itemsMode` to `onDemand`,
16
- * hit "Expand all" on the large course, and watch what the design costs.
17
- */
18
4
  declare const FIXTURES: Record<string, () => InMemoryFixture>;
19
- /**
20
- * The four scales, as either audience.
21
- *
22
- * The teacher shape comes from `buildFixture`'s own `view` option rather than
23
- * being derived here by stripping fields. That matters for what the story shows:
24
- * a teacher sees unpublished modules and items — which is the whole reason the
25
- * teacher view exists — and no progress, because Canvas resolves `progression`
26
- * to null for a viewer with no progression record. Deriving it by deletion used
27
- * to produce the one combination Canvas cannot: an unpublished module with a
28
- * progress bar beside it.
29
- */
5
+ type ThemeName = 'light' | 'canvas-high-contrast';
30
6
  type ProgressMode = 'student' | 'teacher';
31
7
  interface ModulesListStoryProps {
32
8
  fixture: keyof typeof FIXTURES;
33
9
  itemsMode: ItemsMode;
34
10
  progressMode: ProgressMode;
35
- initialFilter: ModulesFilterId;
36
- /** Modules per `listModules` request. Canvas caps this at 100. */
11
+ initialFilter: string;
37
12
  pageSize: number;
38
- /** Items per `listModuleItems` request. Canvas caps this at 100. */
39
13
  itemPageSize: number;
40
14
  itemConcurrency: number;
41
- /** Expand these module ids on mount, so a story shows item rows without a click. */
42
15
  initialExpandedModuleIds: string[];
43
- /**
44
- * Which i18n bridge to render through.
45
- *
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.
52
- */
53
16
  i18n: 'none' | 'pseudo' | 'rebranded' | 'partial';
54
- /** Clear it to render the catalog's `pageTitle` instead of a host-supplied name. */
17
+ timezone: 'none' | 'America/Denver' | 'America/Los_Angeles' | 'Australia/Sydney';
55
18
  courseName: string;
56
19
  navigation: 'none' | 'rewritten' | 'intercepted';
20
+ config: HostConfigName;
21
+ theme: ThemeName;
57
22
  }
58
- /**
59
- * Its own `QueryClient`, deliberately — the global preview decorator builds one
60
- * in its render body, and these stories are about cache behavior.
61
- */
23
+ type HostConfigName = 'none' | 'itemTypes' | 'itemMeta' | 'filters';
62
24
  declare function ModulesListHarness(props: ModulesListStoryProps): ReactElement;
63
25
  declare const meta: Meta<typeof ModulesListHarness>;
64
26
  export default meta;
65
27
  type Story = StoryObj<typeof meta>;
66
- /**
67
- * The design, near enough: 5 modules × 8 items with module 1 open.
68
- *
69
- * `auto` resolves to `inline`, so opening any other module costs zero extra
70
- * requests — the counter in the dev banner stays put as you click around.
71
- */
72
28
  export declare const Default: Story;
73
- /**
74
- * 120 modules × 25 items. `auto` resolves to `onDemand` and first paint is a
75
- * single request no matter how big the course is.
76
- *
77
- * The point of this story is the button at the bottom: `hasNextPage` is true,
78
- * it says so, and the remaining 20 modules are one click away rather than gone.
79
- * Canvas Career shows 100 and says nothing.
80
- */
29
+ export declare const HighContrast: Story;
81
30
  export declare const LargeCourse: Story;
82
- /**
83
- * 3 modules, the middle one 250 items, pinned to `inline` — the Canvas fallback
84
- * in miniature. Modules 1 and 3 come back with items attached; module 2 is over
85
- * `INLINE_ITEM_LIMIT` so the server omits its items and that *one module* falls
86
- * back to a per-module fetch, then pages 100 at a time. "Load more items" stays
87
- * on the card until all 250 are loaded.
88
- */
89
31
  export declare const FatModuleInlineFallback: Story;
90
- /** Every shape an item title can take: linked, new tab, sub-header, no url, long, locked. */
91
32
  export declare const ItemTitleLinks: Story;
92
- /** The same module with `getItemHref` rewriting each href the adapter supplied. */
33
+ export declare const ItemRowVariants: Story;
93
34
  export declare const ItemTitleLinksRewritten: Story;
94
- /** `onItemClick` with `preventDefault()`, as a client-side router would. */
95
35
  export declare const ItemTitleLinksIntercepted: Story;
96
- /** No modules. The empty state. */
97
36
  export declare const EmptyCourse: Story;
98
- /**
99
- * Teacher / anonymous: `progress` is undefined on every module and `status` on
100
- * every item.
101
- *
102
- * The card renders no progress bar and no status pill, and nowhere does it say
103
- * "0%" — "we did not fetch progress" and "the student has done none of it" are
104
- * different facts. Every filter chip except "All" correctly matches nothing,
105
- * because a module-level filter has nothing to read.
106
- */
107
37
  export declare const TeacherViewNoProgress: Story;
108
- /** `progress.status === 'in_progress'`. */
109
38
  export declare const FilterInProgress: Story;
110
- /** `progress.status` is `all_submitted` or `all_graded`. */
111
39
  export declare const FilterComplete: Story;
112
- /**
113
- * `progress.latestDueAt` within 7 days of the injected "today" (2025-01-08).
114
- *
115
- * On the small fixture rather than the large one, deliberately: `latestDueAt` is
116
- * the *latest* due date in a module, and a 25-item module's latest date is
117
- * always months out, so the large course legitimately has nothing in a 7-day
118
- * window. A story that only ever showed the empty state would prove nothing
119
- * about the chip.
120
- */
121
40
  export declare const FilterDueThisWeek: Story;
122
- /** `progress.missingCount > 0`. */
123
41
  export declare const FilterMissing: Story;
124
- /**
125
- * Every module status and every item status on one screen.
126
- *
127
- * `courseSmall` is sized to `MODULE_STATUS_CYCLE.length` precisely so it can
128
- * show all six `ModuleStatus` values; expanding every module then shows every
129
- * `ModuleItemStatus` too, so a reviewer can check the whole pill mapping in one
130
- * screenshot. Note the mock's single green "All items complete" pill is split
131
- * here into "All items complete" (`all_submitted`) and "All items graded"
132
- * (`all_graded`), because the domain distinguishes them and the view should not
133
- * quietly collapse the two.
134
- */
135
42
  export declare const StatusCoverage: Story;
136
- /**
137
- * Every user-visible string, bracketed and padded.
138
- *
139
- * This is the story that makes the i18n seam reviewable rather than asserted: a
140
- * string rendering *without* `⟦ ⟧` never went through `t`. Padding to ~135%
141
- * approximates German, so it also shows whether the card header, the chip row
142
- * and the "Load more" button survive a longer language.
143
- *
144
- * The one deliberate exception is the dev diagnostics banner, which is developer
145
- * text and is documented as untranslated in `ModuleCard`.
146
- */
147
43
  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
44
  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
45
  export declare const PartialCatalog: Story;
46
+ export declare const ItemTypesCustomized: Story;
47
+ export declare const FiltersCustomized: Story;
48
+ export declare const ItemMetaCustomized: Story;
166
49
  //# 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;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"}
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;AAKtD,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,OAAO,CAAA;AAE5D,OAAO,EAaL,KAAK,eAAe,EACpB,KAAK,SAAS,EAUf,MAAM,UAAU,CAAA;AAGjB,QAAA,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,eAAe,CAQnD,CAAA;AAED,KAAK,SAAS,GAAG,OAAO,GAAG,sBAAsB,CAAA;AAmBjD,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,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,wBAAwB,EAAE,MAAM,EAAE,CAAA;IAClC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAA;IACjD,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,qBAAqB,GAAG,kBAAkB,CAAA;IAChF,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,aAAa,CAAA;IAChD,MAAM,EAAE,cAAc,CAAA;IACtB,KAAK,EAAE,SAAS,CAAA;CACjB;AAiDD,KAAK,cAAc,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAA;AAsKnE,iBAAS,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,GAAG,YAAY,CAetE;AAkBD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,kBAAkB,CAiDzC,CAAA;AAED,eAAe,IAAI,CAAA;AACnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAA;AAElC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,KAErC,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,KAE7B,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,KAErC,CAAA;AAED,eAAO,MAAM,yBAAyB,EAAE,KAEvC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,KAEnC,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,KAO7B,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,KAQzB,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,KAO5B,CAAA;AAED,eAAO,MAAM,mBAAmB,EAAE,KAEjC,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,KAOhC,CAAA"}
@@ -1,18 +1,16 @@
1
1
  import { ReactElement } from 'react';
2
2
  import { TranslateFunction } from '../i18n';
3
3
  import { ModuleItemStatus, ModuleStatus } from '../types';
4
- /** Exhaustive: a new `ModuleStatus` is a compile error until it has a label. */
5
- export declare function moduleStatusLabel(t: TranslateFunction, status: ModuleStatus): string;
6
- /** @see moduleStatusLabel */
4
+ export declare function moduleStatusLabel(t: TranslateFunction, status: ModuleStatus, missingCount: number, incompleteCount: number): string;
7
5
  export declare function moduleItemStatusLabel(t: TranslateFunction, status: ModuleItemStatus): string;
8
6
  export interface ModuleStatusPillProps {
9
7
  status: ModuleStatus;
8
+ missingCount: number;
9
+ incompleteCount: number;
10
10
  }
11
- /** @see ModuleStatusPillProps */
12
- export declare function ModuleStatusPill({ status }: ModuleStatusPillProps): ReactElement;
11
+ export declare function ModuleStatusPill({ status, missingCount, incompleteCount, }: ModuleStatusPillProps): ReactElement;
13
12
  export interface ModuleItemStatusPillProps {
14
13
  status: ModuleItemStatus;
15
14
  }
16
- /** @see ModuleItemStatusPillProps */
17
15
  export declare function ModuleItemStatusPill({ status }: ModuleItemStatusPillProps): ReactElement;
18
16
  //# sourceMappingURL=StatusPill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StatusPill.d.ts","sourceRoot":"","sources":["../../src/components/StatusPill.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,SAAS,CAAA;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AA4C9D,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,iBAAiB,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAepF;AAED,6BAA6B;AAC7B,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,iBAAiB,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAe5F;AAUD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,YAAY,CAAA;CACrB;AAED,iCAAiC;AACjC,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE,qBAAqB,GAAG,YAAY,CAOhF;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,qCAAqC;AACrC,wBAAgB,oBAAoB,CAAC,EAAE,MAAM,EAAE,EAAE,yBAAyB,GAAG,YAAY,CAOxF"}
1
+ {"version":3,"file":"StatusPill.d.ts","sourceRoot":"","sources":["../../src/components/StatusPill.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,OAAO,CAAA;AACzD,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,SAAS,CAAA;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAuC9D,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,iBAAiB,EACpB,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,GACtB,MAAM,CAoBR;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,iBAAiB,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAmB5F;AAeD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,YAAY,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,YAAY,EACZ,eAAe,GAChB,EAAE,qBAAqB,GAAG,YAAY,CAOtC;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,MAAM,EAAE,EAAE,yBAAyB,GAAG,YAAY,CAOxF"}
@@ -1,5 +1,5 @@
1
1
  export { FilterChips, type FilterChipsProps } from './FilterChips';
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';
2
+ export { calendarDayDiff, type DateFormatOptions, formatDateTime, formatModuleNumber, formatPoints, moduleMatchesSearch, progressScreenReaderValue, progressSummary, requirementLabel, } from './labels';
3
3
  export { ModuleCard, type ModuleCardProps } from './ModuleCard';
4
4
  export { ModuleItemRow, type ModuleItemRowProps } from './ModuleItemRow';
5
5
  export { ModuleNumberBadge, type ModuleNumberBadgeProps } from './ModuleNumberBadge';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAClE,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,eAAe,EACpB,eAAe,EACf,gBAAgB,GACjB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACpF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAC7F,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,yBAAyB,EAC9B,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAClE,OAAO,EACL,eAAe,EACf,KAAK,iBAAiB,EACtB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,eAAe,EACf,gBAAgB,GACjB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACpF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAC7F,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,yBAAyB,EAC9B,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,cAAc,CAAA"}
@@ -1,85 +1,15 @@
1
1
  import { TranslateFunction } from '../i18n';
2
- import { CompletionRequirement, Module, ModuleItemType } from '../types';
3
- /** Whole calendar days between two dates, ignoring the time of day. */
4
- export declare function calendarDayDiff(a: Date, b: Date): number;
5
- /**
6
- * "today, 11:59 PM" / "yesterday, 11:59 PM" / "January 12, 11:59 PM".
7
- *
8
- * The relative words are separate keys rather than one string with a placeholder,
9
- * because a language that puts the time first, or inflects "yesterday" by what
10
- * follows it, needs to move the pieces independently.
11
- *
12
- * No timezone suffix. The domain model carries none and this package may not read
13
- * one off the host, so printing one would be a guess — see `src/i18n.tsx`.
14
- */
15
- export declare function formatDateTime(t: TranslateFunction, iso: string, today: Date, locale?: string): string;
16
- /** The module header byline when the module is open: "Due yesterday, 11:59 PM". */
17
- export declare function formatDueByline(t: TranslateFunction, iso: string, today: Date, locale?: string): string;
18
- /** The module header byline when the module is locked. */
19
- export declare function formatUnlockByline(t: TranslateFunction, iso: string, today: Date, locale?: string): string;
20
- /**
21
- * "01", "02", … "120". `Intl` rather than `padStart` so a locale's own digits show.
22
- * Anything but a positive integer is an unknown position and returns `null`.
23
- */
2
+ import { CompletionRequirement, Module } from '../types';
3
+ export interface DateFormatOptions {
4
+ locale?: string;
5
+ timezone?: string;
6
+ }
7
+ export declare function calendarDayDiff(a: Date, b: Date, timezone?: string): number;
8
+ export declare function formatDateTime(t: TranslateFunction, iso: string, today: Date, { locale, timezone }?: DateFormatOptions): string;
24
9
  export declare function formatModuleNumber(position: number, locale?: string): string | null;
25
- export declare function itemTypeLabel(t: TranslateFunction, type: ModuleItemType): string;
26
- /** "10 pts". Null/undefined points render nothing at all, not "0 pts". */
27
10
  export declare function formatPoints(t: TranslateFunction, pointsPossible: number | null | undefined): string | null;
28
- /**
29
- * The requirement column, e.g. "Submit the assignment".
30
- *
31
- * Exhaustive over `CompletionRequirementType` — no `default`, so adding a member
32
- * to the enum is a compile error here rather than a silently unlabeled row. The
33
- * `unknown` member is what absorbs a seventh Canvas type, and it still renders
34
- * something: an unlabeled requirement would look like *no* requirement, which
35
- * is the wrong failure.
36
- */
37
11
  export declare function requirementLabel(t: TranslateFunction, requirement: CompletionRequirement): string;
38
- /**
39
- * "75% | 3 of 4 requirements met", straight off the design.
40
- *
41
- * The `|` is baked into the translatable string, which is not ideal — a translator
42
- * cannot tell it is a divider rather than punctuation, and a screen reader may
43
- * either skip it or announce "vertical bar". Left as one key because splitting it
44
- * changes the design's copy; flagged rather than quietly restructured.
45
- */
46
12
  export declare function progressSummary(t: TranslateFunction, percentComplete: number, met: number, total: number): string;
47
- export type ModulesFilterId = 'all' | 'in_progress' | 'complete' | 'due_this_week' | 'missing';
48
- /**
49
- * The chip order the design draws, as ids only.
50
- *
51
- * Ids rather than `{ id, label }` pairs because a label is now a function of the
52
- * host's `t`, and a module-level constant cannot call one. `filterLabel` supplies
53
- * the text.
54
- */
55
- export declare const MODULES_FILTER_IDS: readonly ModulesFilterId[];
56
- export declare function filterLabel(t: TranslateFunction, id: ModulesFilterId): string;
57
- /** How far ahead "Due this week" looks. */
58
- export declare const DUE_THIS_WEEK_DAYS = 7;
59
- /**
60
- * Filter chips are **module-level only**, by design.
61
- *
62
- * Every predicate reads `module.progress`, which the adapter returns with the
63
- * module list. None of them touch items. That is deliberate: in `onDemand` mode
64
- * the items of a collapsed module have not been fetched, so an item-level
65
- * filter would either lie or cost one request per module. The designer's
66
- * annotation says the filters describe the *module's* overall status, which is
67
- * exactly the cheap version.
68
- *
69
- * A module with no `progress` (teacher/anonymous view) matches only "All" —
70
- * "we did not fetch progress" is not the same as "not in progress".
71
- */
72
- export declare function moduleMatchesFilter(module: Module, filter: ModulesFilterId, today: Date): boolean;
73
- /**
74
- * Search matches **module names only**, never item titles.
75
- *
76
- * Same reason as the filters: with `onDemand` pagination the items of collapsed
77
- * modules are not in memory, so an item-level search would silently under-report
78
- * — the one thing this package exists to prevent. The input is labeled
79
- * "Search module names" so the limit is on screen rather than in a comment.
80
- *
81
- * `toLocaleLowerCase` rather than `toLowerCase`: the Turkish dotless i is the
82
- * standard counterexample, and a course in Turkish should find its own modules.
83
- */
13
+ export declare function progressScreenReaderValue(t: TranslateFunction, percentComplete: number, met: number, total: number): string;
84
14
  export declare function moduleMatchesSearch(module: Module, query: string, locale?: string): boolean;
85
15
  //# sourceMappingURL=labels.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../../src/components/labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAEhD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AA8D7E,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAIxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,iBAAiB,EACpB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,EACX,MAAM,GAAE,MAAuB,GAC9B,MAAM,CAiBR;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAC7B,CAAC,EAAE,iBAAiB,EACpB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,EACX,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAER;AAED,0DAA0D;AAC1D,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,iBAAiB,EACpB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,EACX,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAuB,GAC9B,MAAM,GAAG,IAAI,CAGf;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,CAmBhF;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAC1B,CAAC,EAAE,iBAAiB,EACpB,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACxC,MAAM,GAAG,IAAI,CAGf;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,iBAAiB,EAAE,WAAW,EAAE,qBAAqB,GAAG,MAAM,CAqBjG;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,CAAC,EAAE,iBAAiB,EACpB,eAAe,EAAE,MAAM,EACvB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,CAER;AAID,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,aAAa,GAAG,UAAU,GAAG,eAAe,GAAG,SAAS,CAAA;AAE9F;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,eAAe,EAMxD,CAAA;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,eAAe,GAAG,MAAM,CAa7E;AAED,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,IAAI,CAAA;AAEnC;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAqCjG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAI3F"}
1
+ {"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../../src/components/labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAEhD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAM7D,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAmFD,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3E;AAMD,wBAAgB,cAAc,CAC5B,CAAC,EAAE,iBAAiB,EACpB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,EACX,EAAE,MAAuB,EAAE,QAAQ,EAAE,GAAE,iBAAsB,GAC5D,MAAM,CAiBR;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAuB,GAC9B,MAAM,GAAG,IAAI,CAGf;AAED,wBAAgB,YAAY,CAC1B,CAAC,EAAE,iBAAiB,EACpB,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACxC,MAAM,GAAG,IAAI,CAGf;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,iBAAiB,EAAE,WAAW,EAAE,qBAAqB,GAAG,MAAM,CAqBjG;AAED,wBAAgB,eAAe,CAC7B,CAAC,EAAE,iBAAiB,EACpB,eAAe,EAAE,MAAM,EACvB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,CAER;AAED,wBAAgB,yBAAyB,CACvC,CAAC,EAAE,iBAAiB,EACpB,eAAe,EAAE,MAAM,EACvB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,CAER;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAI3F"}
@@ -0,0 +1,3 @@
1
+ import { Decorator } from '@storybook/react';
2
+ export declare const withLightTheme: Decorator;
3
+ //# sourceMappingURL=lightThemeDecorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lightThemeDecorator.d.ts","sourceRoot":"","sources":["../../src/components/lightThemeDecorator.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD,eAAO,MAAM,cAAc,EAAE,SAI5B,CAAA"}
@@ -1,8 +1,3 @@
1
1
  import { ModulesConfig } from './types';
2
- /**
3
- * The starting point every host resolves against. Empty until each mechanism
4
- * lands; `docs/adr/0001-customization.md` decides what each key then carries.
5
- * Frozen: it is what `useModulesConfig` returns with no provider mounted.
6
- */
7
2
  export declare const baseModulesConfig: ModulesConfig;
8
3
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/config/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,aAS/B,CAAA"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/config/base.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,eAAO,MAAM,iBAAiB,EAAE,aAS/B,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { FilterCapabilities } from '../types';
2
+ import { Registry } from './registry';
3
+ import { FilterEntry } from './schemas';
4
+ export declare function unservableFilters(filters: Registry<FilterEntry>, capabilities: FilterCapabilities | undefined): string[];
5
+ export declare function unservableFilterMessage(keys: readonly string[]): string;
6
+ /** Do not fall back to the predicate. That trades complete results for partial ones. */
7
+ export declare function hideUnservableFilters(filters: Registry<FilterEntry>, capabilities: FilterCapabilities | undefined): Registry<FilterEntry>;
8
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/config/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAgB,MAAM,UAAU,CAAA;AAEhE,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,YAAY,CAAA;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC9B,YAAY,EAAE,kBAAkB,GAAG,SAAS,GAC3C,MAAM,EAAE,CAOV;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAKvE;AAED,wFAAwF;AACxF,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC9B,YAAY,EAAE,kBAAkB,GAAG,SAAS,GAC3C,QAAQ,CAAC,WAAW,CAAC,CAWvB"}
@@ -4,8 +4,7 @@ export interface ModulesConfigProviderProps {
4
4
  value: ModulesConfig;
5
5
  children: ReactNode;
6
6
  }
7
- /** Optional. Without it the package renders against `baseModulesConfig`. */
8
7
  export declare function ModulesConfigProvider({ value, children }: ModulesConfigProviderProps): ReactNode;
9
- /** The resolved config, falling back to `baseModulesConfig`. */
10
8
  export declare function useModulesConfig(): ModulesConfig;
9
+ export declare function useFieldVisible(key: string): boolean;
11
10
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/config/context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAA;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAI5C,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,aAAa,CAAA;IACpB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,0BAA0B,GAAG,SAAS,CAEhG;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/config/context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAA;AAGjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAI5C,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,aAAa,CAAA;IACpB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,qBAAqB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,0BAA0B,GAAG,SAAS,CAEhG;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD"}
@@ -0,0 +1,15 @@
1
+ import { FilterClause } from '../types';
2
+ import { Registry } from './registry';
3
+ import { FilterEntry } from './schemas';
4
+ export declare const ALL_FILTER = "all";
5
+ /** How far ahead "Due this week" looks. */
6
+ export declare const DUE_THIS_WEEK_DAYS = 7;
7
+ /**
8
+ * In design order. See `docs/adr/0008-filtering-and-the-data-layer.md`.
9
+ * Read `module.progress` only. A collapsed module has no items in `onDemand` mode.
10
+ */
11
+ export declare const baseFilters: Registry<FilterEntry>;
12
+ /** `clientOnly` is the only way to un-write an inherited clause. */
13
+ export declare function filterClauseOf(entry: FilterEntry | undefined): FilterClause | undefined;
14
+ export declare function isPredicateServed(entry: FilterEntry | undefined): boolean;
15
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../src/config/filters.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,eAAO,MAAM,UAAU,QAAQ,CAAA;AAE/B,2CAA2C;AAC3C,eAAO,MAAM,kBAAkB,IAAI,CAAA;AAEnC;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,WAAW,CAyC4B,CAAA;AAE1E,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAGvF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAEzE"}
@@ -0,0 +1,15 @@
1
+ import { TranslateFunction } from '../i18n';
2
+ import { Module } from '../types';
3
+ export interface FormatterContext {
4
+ t: TranslateFunction;
5
+ locale: string;
6
+ timezone?: string;
7
+ }
8
+ export interface ModulesFormatters {
9
+ moduleLabel: (position: number, module: Module, ctx: FormatterContext) => string | null;
10
+ dateTime: (iso: string, today: Date, ctx: FormatterContext) => string;
11
+ points: (pointsPossible: number | null | undefined, ctx: FormatterContext) => string | null;
12
+ progress: (percentComplete: number, met: number, total: number, ctx: FormatterContext) => string;
13
+ }
14
+ export declare const defaultFormatters: ModulesFormatters;
15
+ //# sourceMappingURL=formatters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/config/formatters.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEtC,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,iBAAiB,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,gBAAgB,KAAK,MAAM,GAAG,IAAI,CAAA;IACvF,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAgB,KAAK,MAAM,CAAA;IACrE,MAAM,EAAE,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,EAAE,gBAAgB,KAAK,MAAM,GAAG,IAAI,CAAA;IAC3F,QAAQ,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,gBAAgB,KAAK,MAAM,CAAA;CACjG;AAED,eAAO,MAAM,iBAAiB,EAAE,iBAS/B,CAAA"}
@@ -1,8 +1,13 @@
1
1
  export { baseModulesConfig } from './base';
2
- export { ModulesConfigProvider, type ModulesConfigProviderProps, useModulesConfig, } from './context';
2
+ export { ALL_FILTER, baseFilters, DUE_THIS_WEEK_DAYS, filterClauseOf, isPredicateServed, } from './filters';
3
+ export { hideUnservableFilters, unservableFilters } from './capabilities';
4
+ export { TYPE_FIELD } from './itemMeta';
5
+ export { ModulesConfigProvider, type ModulesConfigProviderProps, useFieldVisible, useModulesConfig, } from './context';
6
+ export { defaultFormatters, type FormatterContext, type ModulesFormatters, } from './formatters';
3
7
  export { partialModulesConfig } from './partialModulesConfig';
4
- export { mergeRegistry, visibleEntries, type Registry, type RegistryOverride, type VisibleEntry, } from './registry';
8
+ export { mergeRegistry, visibleEntries, visibleEntry, type Registry, type RegistryOverride, type VisibleEntry, } from './registry';
5
9
  export { resolveModulesConfig } from './resolve';
6
- export { ModulesConfigSchema, registrySchema, RegistryEntrySchema, type RegistryEntry, } from './schemas';
7
- export type { ModulesConfig, ModulesConfigOverride, ModulesFormatters, ModulesNavigation, } from './types';
10
+ export { type FilterContext, type FilterEntry, FilterEntrySchema, type ItemTypeContext, type ItemTypeEntry, ItemTypeEntrySchema, type MetaFieldContext, type MetaFieldEntry, MetaFieldEntrySchema, ModulesConfigSchema, registrySchema, RegistryEntrySchema, type RegistryEntry, } from './schemas';
11
+ export type { ModulesConfig, ModulesConfigOverride, ModulesNavigation } from './types';
12
+ export { type BoundFormatters, useFormatters } from './useFormatters';
8
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAC1C,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EACL,aAAa,EACb,cAAc,EACd,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAC1C,OAAO,EACL,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,iBAAiB,GAClB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,eAAe,EACf,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EACL,aAAa,EACb,cAAc,EACd,YAAY,EACZ,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AACtF,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { Registry } from './registry';
2
+ import { MetaFieldEntry } from './schemas';
3
+ export declare const TYPE_FIELD = "type";
4
+ export declare const baseItemMeta: Registry<MetaFieldEntry>;
5
+ //# sourceMappingURL=itemMeta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"itemMeta.d.ts","sourceRoot":"","sources":["../../src/config/itemMeta.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,QAAQ,EAAgB,MAAM,YAAY,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE/C,eAAO,MAAM,UAAU,SAAS,CAAA;AAEhC,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,cAAc,CA4C2B,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { ModuleItemType } from '../types';
2
+ import { ItemTypeEntry } from './schemas';
3
+ export declare const baseItemTypes: Record<ModuleItemType, ItemTypeEntry>;
4
+ //# sourceMappingURL=itemTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"itemTypes.d.ts","sourceRoot":"","sources":["../../src/config/itemTypes.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAI9C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,cAAc,EAAE,aAAa,CAyBoB,CAAA"}
@@ -1,4 +1,3 @@
1
1
  import { ModulesConfig, ModulesConfigOverride } from './types';
2
- /** Use for tests where you don't need a full config. */
3
2
  export declare function partialModulesConfig(override?: ModulesConfigOverride): ModulesConfig;
4
3
  //# sourceMappingURL=partialModulesConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"partialModulesConfig.d.ts","sourceRoot":"","sources":["../../src/config/partialModulesConfig.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAEnE,wDAAwD;AACxD,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,qBAA0B,GAAG,aAAa,CAExF"}
1
+ {"version":3,"file":"partialModulesConfig.d.ts","sourceRoot":"","sources":["../../src/config/partialModulesConfig.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAEnE,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,qBAA0B,GAAG,aAAa,CAExF"}
@@ -1,41 +1,13 @@
1
1
  import { RegistryEntry } from './schemas';
2
- /**
3
- * The registry primitive: merge one over another, then read the visible entries
4
- * in a deterministic order. No React, no validation — the schemas in
5
- * `./schemas` validate once, at config resolution.
6
- */
7
2
  export type Registry<E extends RegistryEntry = RegistryEntry> = Record<string, E>;
8
- /** `Partial<E>` because an overlay states only what it changes. An addition still needs a whole entry, which only the schema can enforce. */
9
3
  export type RegistryOverride<E extends RegistryEntry = RegistryEntry> = Record<string, Partial<E>>;
10
4
  export type VisibleEntry<E extends RegistryEntry = RegistryEntry> = E & {
11
5
  key: string;
12
6
  };
7
+ /** Own properties only: a host override parsed from JSON must not reach `Object.prototype`. */
13
8
  export declare const hasOwn: (target: object, key: string) => boolean;
14
- /** Spread one object over another, skipping explicit `undefined` so a stated key cannot blank an inherited value. */
15
9
  export declare function overlay<T extends object>(base: Partial<T>, over: Partial<T> | undefined): T;
16
- /**
17
- * Fold an override over a base registry, one entry at a time:
18
- * `{ ...base[key], ...override[key] }`. A key the base has is an overlay; a key
19
- * it doesn't is an addition.
20
- *
21
- * Key order of the result is what `visibleEntries` breaks ties on: base keys in
22
- * base order, then additions sorted by key so a host cannot change the rendered
23
- * order by reordering its own literal.
24
- *
25
- * Copies every entry, so neither argument is mutated or shared. Built by spread
26
- * rather than assignment, and keyed by own properties only, so an override
27
- * parsed from host JSON cannot reach `Object.prototype` through a `__proto__`
28
- * or `constructor` key.
29
- */
30
10
  export declare function mergeRegistry<E extends RegistryEntry>(base: Registry<E>, override?: RegistryOverride<E>): Registry<E>;
31
- /**
32
- * The entries a host has left switched on, sorted by `order` ascending.
33
- *
34
- * Ties fall through to key order, per `mergeRegistry` above — `Array#sort` is
35
- * stable by specification from ES2019.
36
- *
37
- * Filtering `hidden` here rather than at the merge is what lets a host inspect
38
- * what it turned off.
39
- */
11
+ export declare function visibleEntry<E extends RegistryEntry>(registry: Registry<E>, key: string): E | undefined;
40
12
  export declare function visibleEntries<E extends RegistryEntry>(registry: Registry<E>): ReadonlyArray<VisibleEntry<E>>;
41
13
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/config/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAE9C;;;;GAIG;AAEH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;AAEjF,6IAA6I;AAC7I,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AAElG,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAAI,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvF,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,OACF,CAAA;AAEnD,qHAAqH;AACrH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAI3F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,aAAa,EACnD,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EACjB,QAAQ,GAAE,gBAAgB,CAAC,CAAC,CAAM,GACjC,QAAQ,CAAC,CAAC,CAAC,CAYb;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,EACpD,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GACpB,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAKhC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/config/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAE9C,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;AAEjF,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AAElG,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAAI,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvF,+FAA+F;AAC/F,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,OACF,CAAA;AAEnD,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAI3F;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,aAAa,EACnD,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EACjB,QAAQ,GAAE,gBAAgB,CAAC,CAAC,CAAM,GACjC,QAAQ,CAAC,CAAC,CAAC,CAYb;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,aAAa,EAClD,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EACrB,GAAG,EAAE,MAAM,GACV,CAAC,GAAG,SAAS,CAGf;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,EACpD,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GACpB,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAKhC"}
@@ -1,7 +1,3 @@
1
1
  import { ModulesConfig, ModulesConfigOverride } from './types';
2
- /**
3
- * Fold an override over a base config, one key at a time, and validate the
4
- * result.
5
- */
6
2
  export declare function resolveModulesConfig(base: ModulesConfig, override?: ModulesConfigOverride): ModulesConfig;
7
3
  //# sourceMappingURL=resolve.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAEnE;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,EACnB,QAAQ,GAAE,qBAA0B,GACnC,aAAa,CAwBf"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAEnE,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,EACnB,QAAQ,GAAE,qBAA0B,GACnC,aAAa,CAuBf"}