@micha.bigler/ui-core-micha 3.14.4 → 4.0.1
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/CHANGELOG.md +29 -0
- package/README.md +7 -0
- package/dist/chat/kitSxRegistry.js +9 -0
- package/dist/components/charts/kitSxRegistry.js +6 -0
- package/dist/entries/charts.js +6 -0
- package/dist/entries/chat.js +8 -0
- package/dist/entries/markdown.js +1 -0
- package/dist/index.js +0 -14
- package/dist/pages/AccountPage.js +1 -2
- package/dist/pages/LoginPage.js +1 -2
- package/dist/pages/PasswordChangePage.js +1 -2
- package/dist/pages/PasswordInvitePage.js +1 -2
- package/dist/pages/PasswordResetRequestPage.js +1 -2
- package/dist/pages/SignUpPage.js +1 -2
- package/dist/pages/SignupConfirmPage.js +1 -2
- package/dist/theme/kitSxEntry.js +11 -0
- package/dist/theme/kitSxRegistry.js +2 -15
- package/package.json +31 -7
- package/.github/workflows/ci.yml +0 -35
- package/.github/workflows/publish.yml +0 -126
- package/DESIGN.md +0 -60
- package/WORK_ORDERS.md +0 -150
- package/dev/entries.jsx +0 -721
- package/dev/fixtures.js +0 -26
- package/dev/main.jsx +0 -75
- package/dev/mockTransport.jsx +0 -128
- package/docs/CHART-LAYOUT.md +0 -157
- package/docs/DARK-TOKENS.md +0 -140
- package/docs/TYPE-SCALE.md +0 -111
- package/docs/messaging-deviations.md +0 -118
- package/index.html +0 -12
- package/renovate.json +0 -10
- package/scripts/chart-api-census.mjs +0 -415
- package/src/auth/AuthContext.jsx +0 -158
- package/src/auth/ReauthModal.jsx +0 -82
- package/src/auth/UserMenu.jsx +0 -121
- package/src/auth/apiClient.jsx +0 -232
- package/src/auth/authApi.jsx +0 -539
- package/src/auth/authConfig.jsx +0 -34
- package/src/auth/reauth.js +0 -47
- package/src/chat/ChatComposer.jsx +0 -36
- package/src/chat/ChatList.jsx +0 -87
- package/src/chat/ChatThread.jsx +0 -128
- package/src/chat/ChatWorkspace.jsx +0 -244
- package/src/chat/MarkdownReply.jsx +0 -22
- package/src/chat/ModelPicker.jsx +0 -85
- package/src/chat/api.js +0 -18
- package/src/chat/useChatSocket.js +0 -32
- package/src/chat/wire.js +0 -7
- package/src/components/AccessCodeManager.jsx +0 -288
- package/src/components/AccessCodeSingleUseToggle.jsx +0 -92
- package/src/components/AllowedEmailDomainsManager.jsx +0 -92
- package/src/components/AuthFactorRequirementCard.jsx +0 -95
- package/src/components/BulkInviteCsvTab.jsx +0 -198
- package/src/components/EmptyState.jsx +0 -38
- package/src/components/LoginForm.jsx +0 -159
- package/src/components/MFAComponent.jsx +0 -350
- package/src/components/MfaLoginComponent.jsx +0 -252
- package/src/components/MobileBottomNav.jsx +0 -82
- package/src/components/PasskeysComponent.jsx +0 -252
- package/src/components/PasswordChangeForm.jsx +0 -87
- package/src/components/PasswordResetRequestForm.jsx +0 -43
- package/src/components/PasswordSetForm.jsx +0 -97
- package/src/components/ProfileComponent.jsx +0 -348
- package/src/components/QrSignupManager.jsx +0 -404
- package/src/components/QrSignupValidityManager.jsx +0 -106
- package/src/components/RegistrationMethodsManager.jsx +0 -150
- package/src/components/SecurityComponent.jsx +0 -141
- package/src/components/SocialLoginButtons.jsx +0 -83
- package/src/components/SoftChip.jsx +0 -93
- package/src/components/StatTile.jsx +0 -39
- package/src/components/SupportRecoveryRequestsTab.jsx +0 -482
- package/src/components/TurnstileWidget.jsx +0 -99
- package/src/components/UserInviteComponent.jsx +0 -76
- package/src/components/UserListComponent.jsx +0 -618
- package/src/components/charts/BarChart.jsx +0 -102
- package/src/components/charts/ChartFrame.jsx +0 -214
- package/src/components/charts/LineChart.jsx +0 -126
- package/src/components/charts/ScatterChart.jsx +0 -299
- package/src/components/charts/TimeSeriesChart.jsx +0 -300
- package/src/components/charts/chartDefaults.js +0 -644
- package/src/components/charts/chartLabels.js +0 -36
- package/src/components/charts/exportChart.js +0 -258
- package/src/components/charts/formatters.js +0 -39
- package/src/components/charts/palette.js +0 -33
- package/src/components/charts/yearTickInterval.js +0 -7
- package/src/i18n/authTranslations.ts +0 -2651
- package/src/i18n/chartsTranslations.ts +0 -91
- package/src/i18n/chatTranslations.ts +0 -55
- package/src/i18n/messagingTranslations.ts +0 -120
- package/src/i18n/notificationsTranslations.ts +0 -32
- package/src/i18n/onboardingTranslations.ts +0 -29
- package/src/i18n/sectionNavTranslations.ts +0 -20
- package/src/i18n/uiCoreTranslations.js +0 -29
- package/src/i18n/userMenuTranslations.ts +0 -5
- package/src/index.js +0 -158
- package/src/layout/PageLayout.jsx +0 -36
- package/src/layout/SectionNav.jsx +0 -320
- package/src/messaging/AttachmentList.jsx +0 -145
- package/src/messaging/Composer.jsx +0 -197
- package/src/messaging/ConversationLaunchers.jsx +0 -51
- package/src/messaging/ConversationList.jsx +0 -109
- package/src/messaging/DirectMessageLauncher.jsx +0 -112
- package/src/messaging/MessageBubble.jsx +0 -183
- package/src/messaging/MessagingProvider.jsx +0 -0
- package/src/messaging/MessagingScopeConfig.jsx +0 -24
- package/src/messaging/PollCard.jsx +0 -163
- package/src/messaging/ReactionBar.jsx +0 -43
- package/src/messaging/ReadTicks.jsx +0 -82
- package/src/messaging/Thread.jsx +0 -195
- package/src/messaging/api.js +0 -48
- package/src/messaging/composerImageCompression.js +0 -35
- package/src/messaging/linkifyText.jsx +0 -37
- package/src/notifications/NotificationBell.jsx +0 -84
- package/src/notifications/NotificationSettings.jsx +0 -330
- package/src/notifications/NotificationsProvider.jsx +0 -224
- package/src/notifications/PopupSurface.jsx +0 -105
- package/src/notifications/api.js +0 -55
- package/src/notifications/feedApi.js +0 -18
- package/src/notifications/realtime.jsx +0 -138
- package/src/notifications/serviceWorker/sw.js +0 -50
- package/src/onboarding/OnboardingProvider.jsx +0 -326
- package/src/onboarding/OnboardingWizard.jsx +0 -61
- package/src/onboarding/WizardDialogShell.jsx +0 -51
- package/src/onboarding/api.js +0 -13
- package/src/onboarding/stepSelection.js +0 -16
- package/src/onboarding/steps/BrowserPushStep.jsx +0 -121
- package/src/onboarding/steps/CompleteNameStep.jsx +0 -46
- package/src/onboarding/steps/CookieConsentStep.jsx +0 -133
- package/src/onboarding/steps/PwaInstallStep.jsx +0 -47
- package/src/pages/AccountPage.jsx +0 -394
- package/src/pages/LoginPage.jsx +0 -343
- package/src/pages/PasswordChangePage.jsx +0 -62
- package/src/pages/PasswordInvitePage.jsx +0 -177
- package/src/pages/PasswordResetRequestPage.jsx +0 -68
- package/src/pages/SignUpPage.jsx +0 -268
- package/src/pages/SignupConfirmPage.jsx +0 -155
- package/src/testing/checkKitIntegration.js +0 -233
- package/src/theme/createAppTheme.js +0 -423
- package/src/theme/fonts.js +0 -3
- package/src/theme/index.js +0 -21
- package/src/theme/kitSxRegistry.js +0 -285
- package/src/theme/themeCompleteness.js +0 -1045
- package/src/theme/tokens.js +0 -478
- package/src/utils/auth-errors.js +0 -76
- package/src/utils/authService.js +0 -223
- package/src/utils/resolveErrorText.js +0 -28
- package/src/utils/webauthn.js +0 -51
- package/tests/AccountPage.profileStatements.test.jsx +0 -162
- package/tests/AccountPage.test.jsx +0 -200
- package/tests/AuthContext.test.jsx +0 -129
- package/tests/BarChart.test.jsx +0 -112
- package/tests/BrowserPushStep.test.jsx +0 -110
- package/tests/ChartFrame.test.jsx +0 -336
- package/tests/ConversationList.test.jsx +0 -144
- package/tests/CookieConsentStep.test.jsx +0 -69
- package/tests/EmptyState.test.jsx +0 -62
- package/tests/LineChart.test.jsx +0 -80
- package/tests/MessagingProvider.test.jsx +0 -50
- package/tests/MobileBottomNav.test.jsx +0 -319
- package/tests/NotificationBell.test.jsx +0 -60
- package/tests/NotificationSettings.test.jsx +0 -276
- package/tests/NotificationsProvider.test.jsx +0 -240
- package/tests/OnboardingProvider.test.jsx +0 -294
- package/tests/OnboardingWizard.test.jsx +0 -143
- package/tests/PasswordChangeForm.test.jsx +0 -70
- package/tests/PasswordInvitePage.test.jsx +0 -142
- package/tests/PasswordSetForm.test.jsx +0 -70
- package/tests/PopupSurface.test.jsx +0 -142
- package/tests/ProfileComponent.refresh.test.jsx +0 -194
- package/tests/QrSignupManager.registrationContext.test.jsx +0 -106
- package/tests/QrSignupManagerInfoBox.test.jsx +0 -49
- package/tests/ScatterChart.test.jsx +0 -270
- package/tests/SectionNav.test.jsx +0 -363
- package/tests/SignUpPage.test.jsx +0 -208
- package/tests/SoftChip.test.jsx +0 -105
- package/tests/StatTile.test.jsx +0 -57
- package/tests/Thread.test.jsx +0 -151
- package/tests/TimeSeriesChart.test.jsx +0 -367
- package/tests/UserListComponent.test.jsx +0 -192
- package/tests/UserMenu.test.jsx +0 -171
- package/tests/apiClientLanguage.test.js +0 -33
- package/tests/apiClientPublicPaths.test.js +0 -178
- package/tests/authApiLogin.test.js +0 -42
- package/tests/authApiRegistration.test.js +0 -31
- package/tests/authErrorCodeRendering.test.jsx +0 -77
- package/tests/authErrors.test.js +0 -74
- package/tests/authTranslations.test.js +0 -74
- package/tests/chart-api-census.test.js +0 -366
- package/tests/chartAxisTickBand.test.jsx +0 -95
- package/tests/chartDefaults.test.js +0 -902
- package/tests/chartLabels.test.js +0 -50
- package/tests/chartsPalette.test.js +0 -99
- package/tests/chatApi.test.js +0 -48
- package/tests/chatDriverNames.test.jsx +0 -71
- package/tests/chatExports.test.js +0 -3
- package/tests/chatList.test.jsx +0 -84
- package/tests/chatPicker.test.jsx +0 -82
- package/tests/chatSocket.test.jsx +0 -26
- package/tests/chatThread.test.jsx +0 -116
- package/tests/chatTranslations.test.js +0 -47
- package/tests/chatWorkspace.test.jsx +0 -234
- package/tests/checkKitIntegration.test.jsx +0 -219
- package/tests/createAppTheme.test.js +0 -132
- package/tests/createAppThemeDark.test.js +0 -127
- package/tests/createAppThemeLightGuard.test.js +0 -40
- package/tests/createAppThemePageContrast.test.js +0 -108
- package/tests/createAppThemeTypography.test.js +0 -53
- package/tests/errorCallSiteGuard.test.js +0 -32
- package/tests/exportChart.test.js +0 -313
- package/tests/feedApi.test.js +0 -46
- package/tests/fixtures/light-theme-baseline.json +0 -2234
- package/tests/i18nAggregate.test.js +0 -120
- package/tests/i18nGermanVariant.test.js +0 -65
- package/tests/loginPageErrorResolution.test.jsx +0 -102
- package/tests/messagingApi.test.js +0 -32
- package/tests/messagingChunk6.test.jsx +0 -116
- package/tests/messagingCompactBubble.test.jsx +0 -64
- package/tests/messagingComposer.test.jsx +0 -136
- package/tests/messagingComposerChunk5.test.jsx +0 -113
- package/tests/messagingContractConformance.test.js +0 -69
- package/tests/messagingDirectMessageLauncher.test.jsx +0 -151
- package/tests/messagingExports.test.js +0 -21
- package/tests/messagingInteractions.test.jsx +0 -136
- package/tests/messagingLastMessagePreview.test.jsx +0 -93
- package/tests/messagingLinkify.test.jsx +0 -51
- package/tests/messagingMessageActions.test.jsx +0 -163
- package/tests/messagingMsg6.test.jsx +0 -105
- package/tests/messagingMsg6f.test.jsx +0 -155
- package/tests/messagingMsg6g.test.jsx +0 -166
- package/tests/messagingMsg6h.test.jsx +0 -136
- package/tests/messagingMsg6i.test.jsx +0 -129
- package/tests/messagingPollRendering.test.jsx +0 -142
- package/tests/messagingReactionMerge.test.jsx +0 -77
- package/tests/messagingReadTicksTooltip.test.jsx +0 -36
- package/tests/messagingThreadReceipts.test.jsx +0 -178
- package/tests/messagingThreadingQuoting.test.jsx +0 -87
- package/tests/messagingUnreadLifecycle.test.jsx +0 -78
- package/tests/notificationsApi.test.js +0 -41
- package/tests/notificationsExports.test.js +0 -34
- package/tests/onboardingDescriptors.test.js +0 -132
- package/tests/packageTreeShaking.test.js +0 -126
- package/tests/realtime.test.jsx +0 -219
- package/tests/resolveErrorText.test.js +0 -72
- package/tests/stepSelection.test.js +0 -53
- package/tests/themeCompleteness.test.js +0 -626
- package/tests/timeSeriesLegend.test.js +0 -99
- package/tests/userScreenTranslations.test.jsx +0 -218
- package/tsconfig.build.json +0 -18
- package/vite.config.mjs +0 -6
- package/work-orders/AUTH-1.md +0 -74
- package/work-orders/AUTH-2.md +0 -74
- package/work-orders/AUTH-4.md +0 -183
- package/work-orders/AUTH-5.md +0 -154
- package/work-orders/AUTH-7.md +0 -181
- package/work-orders/AUTH-8.md +0 -184
- package/work-orders/CHART-1.md +0 -285
- package/work-orders/CHART-2.md +0 -222
- package/work-orders/CHART-3.md +0 -163
- package/work-orders/CHART-4.md +0 -203
- package/work-orders/CHART-5.md +0 -226
- package/work-orders/CHART-6.md +0 -428
- package/work-orders/CHART-7.md +0 -175
- package/work-orders/DX-1.md +0 -169
- package/work-orders/DX-2.md +0 -188
- package/work-orders/DX-3.md +0 -195
- package/work-orders/I18N-1.md +0 -254
- package/work-orders/I18N-3.md +0 -207
- package/work-orders/MSG-3.md +0 -375
- package/work-orders/MSG-3b.md +0 -1002
- package/work-orders/MSG-3c.md +0 -378
- package/work-orders/MSG-3d.md +0 -268
- package/work-orders/MSG-3e.md +0 -164
- package/work-orders/MSG-3f.md +0 -391
- package/work-orders/MSG-6e.md +0 -308
- package/work-orders/MSG-6f.md +0 -214
- package/work-orders/MSG-6g.md +0 -244
- package/work-orders/MSG-6h.md +0 -238
- package/work-orders/MSG-6i.md +0 -271
- package/work-orders/MSG-6j.md +0 -117
- package/work-orders/NOTIF-12.md +0 -214
- package/work-orders/NOTIF-13.md +0 -142
- package/work-orders/NOTIF-14.md +0 -151
- package/work-orders/PRIM-1.md +0 -177
- package/work-orders/SHELL-1.md +0 -255
- package/work-orders/SHELL-2.md +0 -197
- package/work-orders/SHELL-3.md +0 -359
- package/work-orders/SHELL-4.md +0 -351
- package/work-orders/SHELL-5.md +0 -345
- package/work-orders/SHELL-6.md +0 -210
- package/work-orders/THEME-1.md +0 -587
- package/work-orders/THEME-10.md +0 -303
- package/work-orders/THEME-11.md +0 -208
- package/work-orders/THEME-2.md +0 -339
- package/work-orders/THEME-3.md +0 -210
- package/work-orders/THEME-4.md +0 -271
- package/work-orders/THEME-5.md +0 -341
- package/work-orders/THEME-6.md +0 -247
- package/work-orders/THEME-7.md +0 -82
- package/work-orders/THEME-8.md +0 -211
- package/work-orders/THEME-9.md +0 -194
- package/work-orders/UCM-AUTH-10.md +0 -490
- package/work-orders/UCM-AUTH-11.md +0 -185
- package/work-orders/UCM-AUTH-12.md +0 -98
- package/work-orders/UCM-AUTH-13.md +0 -47
- package/work-orders/UCM-AUTH-9.md +0 -207
- package/work-orders/UCM-CHART-10.md +0 -150
- package/work-orders/UCM-CHART-11.md +0 -132
- package/work-orders/UCM-CHART-12.md +0 -348
- package/work-orders/UCM-CHART-13.md +0 -122
- package/work-orders/UCM-CHART-14.md +0 -198
- package/work-orders/UCM-CHART-15.md +0 -187
- package/work-orders/UCM-CHART-16.md +0 -169
- package/work-orders/UCM-CHART-17.md +0 -195
- package/work-orders/UCM-CHART-18.md +0 -200
- package/work-orders/UCM-CHART-8.md +0 -147
- package/work-orders/UCM-CHART-9.md +0 -265
- package/work-orders/UCM-CHAT-1.md +0 -190
- package/work-orders/UCM-CHAT-2.md +0 -75
- package/work-orders/UCM-CI-1.md +0 -65
- package/work-orders/UCM-DEP-1.md +0 -63
- package/work-orders/UCM-I18N-4.md +0 -226
- package/work-orders/UCM-I18N-5.md +0 -211
- package/work-orders/UCM-MSG-20.md +0 -192
- package/work-orders/UCM-PRIM-2.md +0 -114
- package/work-orders/UCM-SHELL-7.md +0 -134
- package/work-orders/UCM-SHELL-8.md +0 -125
- package/work-orders/UCM-TEST-1.md +0 -304
- package/work-orders/UCM-THEME-13.md +0 -69
- package/work-orders/UCM-THEME-14.md +0 -312
- package/work-orders/UCM-THEME-15.md +0 -356
- package/work-orders/UCM-THEME-16.md +0 -80
- package/work-orders/UCM-THEME-17.md +0 -111
- package/work-orders/UCM-THEME-18.md +0 -184
- package/work-orders/assets/AUTH-4-user-list-card.html +0 -407
- package/work-orders/assets/PRIM-1-dashboard-primitives.html +0 -624
- package/work-orders/assets/SHELL-2-account-navigation.html +0 -1159
- package/work-orders/assets/THEME-1-baseline-reference-sheet.html +0 -1352
- package/work-orders/assets/UCM-CHAT-1-ai-chat.html +0 -447
- package/work-orders/assets/UCM-THEME-13-dark-prototype.html +0 -390
- package/work-orders/assets/UCM-THEME-17-type-scale.html +0 -391
package/work-orders/CHART-5.md
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
# WORK ORDER CHART-5 (ui-core-micha) — dual y-axis + always-visible x-axis ticks
|
|
2
|
-
|
|
3
|
-
**EXECUTION DIRECTIVE.** If you are the implementer reading this as your own spec, this section is not
|
|
4
|
-
addressed to you — it tells the Orchestrator how to invoke you; you ARE that invocation, do not shell
|
|
5
|
-
out to `codex exec`. Orchestrator: implement through `codex exec` in the background, invoked **directly
|
|
6
|
-
via Bash** (never the `debugger`/`*_coder` Agent wrappers) with **both** flags `--skip-git-repo-check`
|
|
7
|
-
and `--dangerously-bypass-approvals-and-sandbox`, prompt passed as a positional argument from this
|
|
8
|
-
file. Fall back to direct Claude implementation only on Codex quota / rate-limit / non-zero exit.
|
|
9
|
-
**Known at WO authoring time: the Codex workspace is out of credits for this session — the fallback
|
|
10
|
-
applies immediately, do not spend time retrying `codex exec` first.**
|
|
11
|
-
|
|
12
|
-
Feature WO on `TimeSeriesChart` (CHART-2/3/4). Operator request, found live in jg-ferien's Aktivität
|
|
13
|
-
screen: (a) the shared y-axis mixes an integer count series ("Eindeutige Nutzer") with a fractional
|
|
14
|
-
hours series ("Anwesenheitszeit"), producing decimal ticks (0.2, 0.4, ...) that don't make sense for a
|
|
15
|
-
user count; (b) the x-axis (time buckets) shows **zero** visible tick labels once there are enough
|
|
16
|
-
buckets that MUI X-Charts' built-in collision-avoidance decides none of them fit — worse than showing
|
|
17
|
-
a sparse subset, this shows nothing at all.
|
|
18
|
-
|
|
19
|
-
## TIER
|
|
20
|
-
Tier 2 — shared-core UI, new public surface (a new optional per-series field). Independent `reviewer`
|
|
21
|
-
+ `ui_reviewer` mandatory.
|
|
22
|
-
|
|
23
|
-
## WHY
|
|
24
|
-
|
|
25
|
-
**Y-axis.** CHART-2 deliberately rejected a second y-axis in favor of series toggles ("if you do not
|
|
26
|
-
add one, say so deliberately" — CHART-2 said so, choosing toggles). The operator has now explicitly
|
|
27
|
-
requested the second y-axis for this exact case, with full awareness of that prior decision (asked
|
|
28
|
-
in-chat, chose it knowingly over forcing shared-axis integer ticks — which would make the fractional
|
|
29
|
-
series nearly invisible — and over hiding the tick label only when one series is toggled off). This
|
|
30
|
-
WO reverses CHART-2's choice on operator authority, it does not silently second-guess it.
|
|
31
|
-
|
|
32
|
-
**X-axis.** `node_modules/@mui/x-charts/ChartsXAxis/getVisibleLabels.js`'s default behaviour drops a
|
|
33
|
-
tick label the moment it would overlap the previous one (`tickLabelMinGap`) — with many narrow-band
|
|
34
|
-
categories (e.g. 24 hourly buckets) and non-trivial label text (jg-ferien's `formatBucketLabel`
|
|
35
|
-
produces e.g. `"08/06, 08:00"`), every label can end up colliding and the *entire* axis goes blank.
|
|
36
|
-
MUI's own escape hatch is `tickLabelInterval` as a **function** — when provided, it fully replaces the
|
|
37
|
-
collision-based filtering (`getVisibleLabels.js`: `if (typeof tickLabelInterval === 'function') return
|
|
38
|
-
new Set(xTicks.filter((item, index) => tickLabelInterval(item.value, index)))`), so a deterministic,
|
|
39
|
-
evenly-spaced selection can guarantee *some* labels always render regardless of container width or
|
|
40
|
-
label length.
|
|
41
|
-
|
|
42
|
-
## SCOPE
|
|
43
|
-
|
|
44
|
-
**A. Per-series `axis` field, backward-compatible.** Each entry in `data.series[i]` gains an optional
|
|
45
|
-
`axis: 'primary' | 'secondary'` field. Default (omitted, or every series `'primary'`): **byte-for-byte
|
|
46
|
-
today's single-shared-axis behaviour** — no `yAxis` array change, no `yAxisKey` on series, nothing
|
|
47
|
-
observably different for existing consumers (jg-ferien pre-adoption, or any future host that doesn't
|
|
48
|
-
use the field). Only when **at least one** series declares `axis: 'secondary'` does dual-axis mode
|
|
49
|
-
activate:
|
|
50
|
-
- Build `yAxis` as two entries: primary (`id: 'primary'`, label = existing `yAxisLabel` prop) and
|
|
51
|
-
secondary (`id: 'secondary'`, label = new prop `secondaryYAxisLabel`).
|
|
52
|
-
- Each series passed to `BarChart` gets `yAxisKey: 'secondary'` when its `axis` is `'secondary'`,
|
|
53
|
-
omitted (defaults to the first/primary axis) otherwise — `series` items already pass straight
|
|
54
|
-
through `BarChart`'s `...chartProps` to the real `MuiBarChart`, which natively supports
|
|
55
|
-
`yAxisKey` per series; no `BarChart.jsx` change needed for this part, verify that during
|
|
56
|
-
implementation rather than assuming.
|
|
57
|
-
- `secondaryYAxisLabel` is required (throw, matching `BarChart`'s own `xAxisLabel`/`yAxisLabel`
|
|
58
|
-
required-prop convention) **only when dual-axis mode is actually active** (i.e. when computing
|
|
59
|
-
it: if any series has `axis === 'secondary'` and `secondaryYAxisLabel` is falsy, throw with a
|
|
60
|
-
clear message) — do not require it unconditionally, that would break every existing single-axis
|
|
61
|
-
caller.
|
|
62
|
-
|
|
63
|
-
**B. Auto-detected integer-only ticks per axis group, not a new prop.** For each y-axis actually in
|
|
64
|
-
use (primary always; secondary only in dual-axis mode), if **every** data value across that axis's
|
|
65
|
-
currently-**visible** series (respecting the existing series-toggle `visibleKeys` state — an axis
|
|
66
|
-
whose only integer series just got toggled off should not keep forcing integer ticks on whatever
|
|
67
|
-
remains) is a whole number (`Number.isInteger`), apply a `valueFormatter` to that axis's config that
|
|
68
|
-
only emits a label for integer tick values and an empty string otherwise (mirrors the X-axis
|
|
69
|
-
collision convention: `getVisibleLabels.js` already treats `formattedValue === ''` as "don't show
|
|
70
|
-
this tick" for the X axis; verify the Y-axis tick renderer honours the same convention during
|
|
71
|
-
implementation — if it does not, use whatever mechanism it actually supports to the same effect, and
|
|
72
|
-
say so in the completion note). If not all-integer, leave the axis's default (no custom formatter) —
|
|
73
|
-
this is what keeps `Anwesenheitszeit` (fractional hours) unaffected on its own axis, and correctly
|
|
74
|
-
does nothing extra for a primary axis that legitimately has fractional data.
|
|
75
|
-
|
|
76
|
-
**C. Deterministic x-axis tick visibility.** Replace MUI's default collision-based tick filtering with
|
|
77
|
-
an explicit `tickLabelInterval` function on the x-axis config, evenly sampling up to `MAX_X_TICKS`
|
|
78
|
-
(pick a sensible constant, e.g. 8) labels across `data.xLabels`, e.g. `index % Math.max(1,
|
|
79
|
-
Math.ceil(xLabels.length / MAX_X_TICKS)) === 0` (adjust as needed so the *last* category is also
|
|
80
|
-
reachable/considered, not just an artifact of the modulo — check this doesn't systematically drop the
|
|
81
|
-
final bucket). This must apply regardless of dual-axis mode (independent scope).
|
|
82
|
-
|
|
83
|
-
## NON-GOALS / DO NOT TOUCH
|
|
84
|
-
- No third axis, no per-axis custom colors, no new axis-styling props beyond what SCOPE describes.
|
|
85
|
-
- Do not touch the range picker, series-toggle checkboxes' own rendering, `chartsTranslations`, or the
|
|
86
|
-
CHART-3/CHART-4 fixes (`visibleKeys` sync, `CHART_HEIGHT`).
|
|
87
|
-
- Do not change `BarChart.jsx`/`ChartFrame.jsx` unless SCOPE A's `yAxisKey` passthrough turns out to
|
|
88
|
-
need it (verify first, per SCOPE A's own note) — if it does, extend deliberately and say so, matching
|
|
89
|
-
CHART-2's own "do not work around a primitive gap in the preset" rule.
|
|
90
|
-
- jg-ferien's own adoption (setting `axis: 'secondary'` on `presence_hours`, adding a
|
|
91
|
-
`secondaryYAxisLabel`, shortening `formatBucketLabel`) is **explicitly out of scope for this WO** —
|
|
92
|
-
a separate companion change in that repo, after this publishes.
|
|
93
|
-
|
|
94
|
-
## RISKS
|
|
95
|
-
- `tickLabelInterval` as a function fully bypasses MUI's built-in overlap detection (per SCOPE C's
|
|
96
|
-
quoted source) — a fixed `MAX_X_TICKS` could still produce overlapping text at extreme narrow
|
|
97
|
-
widths with very long labels. Accepted: "some labels, deterministically" is strictly better than
|
|
98
|
-
"zero labels, unpredictably" (today's bug), and host-side label shortening (jg-ferien's future
|
|
99
|
-
companion change) is the complementary fix for extreme cases, not this WO's job.
|
|
100
|
-
- Every host that adopts `axis: 'secondary'` changes its chart's visual scale contract (two
|
|
101
|
-
independent y-domains can visually mislead if not clearly labelled) — mitigated by requiring
|
|
102
|
-
`secondaryYAxisLabel`, not by this WO deciding it's always fine.
|
|
103
|
-
- The integer-tick auto-detection (SCOPE B) re-evaluates on every toggle (depends on `visibleKeys`) —
|
|
104
|
-
confirm this doesn't cause a visible axis-label flicker/jump on toggle beyond the intended "ticks
|
|
105
|
-
change because domain changed" behaviour the toggles already produce today.
|
|
106
|
-
|
|
107
|
-
## REQUIRED TESTS TO WRITE
|
|
108
|
-
Extend `tests/TimeSeriesChart.test.jsx`. Do NOT run the full suite.
|
|
109
|
-
|
|
110
|
-
**Learn from CHART-4's own history in this file (read `WORK_ORDERS.md`'s CHART-4 row before writing
|
|
111
|
-
these): an unmocked test asserting real rendered DOM/tick visibility was proven VACUOUS in this exact
|
|
112
|
-
component (jsdom's layout/ResizeObserver handling doesn't reproduce real-browser collision behaviour).
|
|
113
|
-
Do not repeat that mistake here.** For anything about tick *visibility* or *positions* (SCOPE C, and
|
|
114
|
-
SCOPE B's empty-string-for-non-integer-ticks mechanism), assert on the **function/config actually
|
|
115
|
-
passed** to the mocked `MuiBarChart` (`chartSpy.mock.calls`) — e.g. call the captured
|
|
116
|
-
`tickLabelInterval` function directly with sample `(value, index)` pairs and assert its boolean
|
|
117
|
-
results, or call the captured y-axis `valueFormatter` directly with sample tick values and assert its
|
|
118
|
-
string output — never assert on rendered pixel positions or DOM overlap in jsdom.
|
|
119
|
-
|
|
120
|
-
1. **Dual-axis backward compatibility**: with no series declaring `axis`, `chartSpy`'s `yAxis` prop
|
|
121
|
-
must be unchanged from today's single-entry shape (or however it's currently constructed — assert
|
|
122
|
-
equivalently to the existing tests, not a new shape).
|
|
123
|
-
2. **Dual-axis activation**: with one series `axis: 'secondary'`, assert `chartSpy`'s `yAxis` has two
|
|
124
|
-
entries (primary/secondary ids, correct labels from `yAxisLabel`/`secondaryYAxisLabel`), and assert
|
|
125
|
-
the secondary series' entry in `chartSpy`'s `series` prop carries `yAxisKey` matching the secondary
|
|
126
|
-
axis id while the other series' entry does not (or carries the primary id — whichever the
|
|
127
|
-
implementation settles on, be explicit and consistent).
|
|
128
|
-
3. **Missing `secondaryYAxisLabel` throws** when a series declares `axis: 'secondary'` but the prop is
|
|
129
|
-
absent — mirrors `BarChart`'s own required-prop throw test convention (check
|
|
130
|
-
`tests/BarChart.test.jsx` for that pattern).
|
|
131
|
-
4. **Integer-tick auto-detection, both directions**: one case where a y-axis's visible series are all
|
|
132
|
-
whole numbers (assert the captured `valueFormatter` returns a non-empty string for an integer tick
|
|
133
|
-
value and `''` for a non-integer one), and one case where they are not all whole numbers (assert no
|
|
134
|
-
custom `valueFormatter` is applied, or that it returns the value formatted normally for every tick —
|
|
135
|
-
whichever the implementation does, assert it explicitly).
|
|
136
|
-
5. **Toggle re-evaluation**: toggling off the one non-integer series on a shared/primary axis (single-
|
|
137
|
-
axis mode) changes that axis from "not all-integer" to "all-integer" — assert the formatter
|
|
138
|
-
behaviour changes accordingly after the toggle. (This is the SCOPE B "re-evaluates on toggle" case,
|
|
139
|
-
RISKS section.)
|
|
140
|
-
6. **X-axis `tickLabelInterval` guarantees coverage**: call the captured function against a large
|
|
141
|
-
`xLabels` array (e.g. 24 entries) and assert it returns `true` for at least `N` evenly-spread
|
|
142
|
-
indices (pick a concrete, checkable lower bound, e.g. at least 3 for 24 items at `MAX_X_TICKS=8`)
|
|
143
|
-
and that it does not return `true` for literally zero indices (the non-vacuity check for the whole
|
|
144
|
-
WO — the very bug this section fixes).
|
|
145
|
-
7. **Non-vacuity**: each new test must fail against the current (pre-fix) code — verify before
|
|
146
|
-
considering the fix complete. (SCOPE C's test 6 obviously fails today since there is no
|
|
147
|
-
`tickLabelInterval` at all; confirm the others similarly.)
|
|
148
|
-
|
|
149
|
-
## TARGET REPO
|
|
150
|
-
`C:\Users\biglmi\Documents\webapps\ui-core-micha`. Branch `main`. Publish per the repo's release flow
|
|
151
|
-
(minor bump — new optional field/prop, additive, no breaking change to existing callers).
|
|
152
|
-
|
|
153
|
-
## TEST SCOPE FOR THE GATE (orchestrator)
|
|
154
|
-
`tests/TimeSeriesChart.test.jsx`. Not the full suite.
|
|
155
|
-
|
|
156
|
-
## CONTEXT PACKAGE — verified current state (Orchestrator, Implementation map)
|
|
157
|
-
|
|
158
|
-
Work from this package; do not explore broadly from scratch — open only the named files to verify.
|
|
159
|
-
|
|
160
|
-
**File to change: `src/components/charts/TimeSeriesChart.jsx`** — current full return statement and
|
|
161
|
-
surrounding derived-state variables (`:117-189`, verified current):
|
|
162
|
-
```jsx
|
|
163
|
-
const visibleSeries = seriesConfig.filter((series) => visibleKeys.has(series.key));
|
|
164
|
-
const visiblePalette = visibleSeries.map((series) => palette[seriesConfig.indexOf(series) % palette.length]);
|
|
165
|
-
const isDataEmpty = seriesConfig.length === 0 || visibleSeries.length === 0;
|
|
166
|
-
...
|
|
167
|
-
return (
|
|
168
|
-
<ChartFrame ... minHeight={CHART_HEIGHT}>
|
|
169
|
-
{!isDataEmpty && (
|
|
170
|
-
<BarChart
|
|
171
|
-
xAxisLabel={xAxisLabel}
|
|
172
|
-
yAxisLabel={yAxisLabel}
|
|
173
|
-
xAxis={[{ data: data?.xLabels || [] }]}
|
|
174
|
-
series={visibleSeries.map((series) => ({ data: series.data, label: series.label }))}
|
|
175
|
-
palette={visiblePalette}
|
|
176
|
-
height={CHART_HEIGHT}
|
|
177
|
-
/>
|
|
178
|
-
)}
|
|
179
|
-
</ChartFrame>
|
|
180
|
-
);
|
|
181
|
-
```
|
|
182
|
-
Component signature currently: `{ title, subtitle, xAxisLabel, yAxisLabel, data, loading, error,
|
|
183
|
-
onRangeChange, defaultRange }` (`:56-66`) — add `secondaryYAxisLabel` here.
|
|
184
|
-
|
|
185
|
-
**`BarChart.jsx`** (full file, unchanged by this WO unless SCOPE A's verification says otherwise):
|
|
186
|
-
`series`/`xAxis`/`yAxis` are BarChart's own named props; `series` is passed straight through
|
|
187
|
-
(`series={series}` onto `MuiBarChart`, `:35`) with NO per-item transformation — so a `yAxisKey` field
|
|
188
|
-
already present on a series object the caller builds should reach `MuiBarChart` unmodified. `yAxis`
|
|
189
|
-
goes through `labelledAxis(yAxis, yAxisLabel, {scaleType:'linear'})` (`:37`), which preserves any
|
|
190
|
-
`label` already set on an axis entry (only fills in the default when absent) — so `TimeSeriesChart`
|
|
191
|
-
passing two fully-labelled `yAxis` entries will not have `BarChart`'s own `yAxisLabel` prop override
|
|
192
|
-
them; **`TimeSeriesChart` should stop passing a single top-level `yAxisLabel` to `BarChart` once it is
|
|
193
|
-
building its own multi-entry `yAxis` array explicitly** (or `BarChart`'s `yAxisLabel` requirement
|
|
194
|
-
throws — check `BarChart.jsx:27-29`'s `if (!xAxisLabel || !yAxisLabel) throw` and account for it:
|
|
195
|
-
either keep passing `yAxisLabel` as before, since `labelledAxis` won't clobber pre-labelled entries
|
|
196
|
-
anyway, or restructure — pick whichever keeps `BarChart`'s existing required-prop contract intact
|
|
197
|
-
without a special case).
|
|
198
|
-
|
|
199
|
-
**X-axis**: `xAxis={[{ data: data?.xLabels || [] }]}` (`:181` current) — add `tickLabelInterval` to
|
|
200
|
-
this object; `labelledAxis` will preserve it (only fills `label`, spreads everything else through).
|
|
201
|
-
|
|
202
|
-
**Existing tests to model conventions on**: `tests/TimeSeriesChart.test.jsx` (chartSpy mock pattern,
|
|
203
|
-
already described above) and `tests/BarChart.test.jsx` (required-prop-throws test pattern for the
|
|
204
|
-
`secondaryYAxisLabel` throw case).
|
|
205
|
-
|
|
206
|
-
## MINI-HANDOVER (pastable)
|
|
207
|
-
|
|
208
|
-
> Repo: `C:\Users\biglmi\Documents\webapps\ui-core-micha` (branch `main`).
|
|
209
|
-
> Work order: `work-orders/CHART-5.md` — read it fully, then follow the `orchestrate-codex` skill.
|
|
210
|
-
> **Codex workspace is out of credits this session — go straight to the direct-Claude fallback.**
|
|
211
|
-
>
|
|
212
|
-
> Two independent additions to `TimeSeriesChart`, both operator-requested after seeing the shipped
|
|
213
|
-
> CHART-2/3/4 chart live: (1) an opt-in second y-axis via a new per-series `axis: 'secondary'` field,
|
|
214
|
-
> fully backward-compatible when unused, with auto-detected integer-only tick labels per axis group
|
|
215
|
-
> (not a new prop — derived from whether that axis's visible series data is all whole numbers); (2) a
|
|
216
|
-
> deterministic x-axis `tickLabelInterval` so time-bucket labels never all vanish under MUI's default
|
|
217
|
-
> collision-avoidance, which is exactly what happened live (zero labels shown with 24 hourly buckets).
|
|
218
|
-
> **Test-writing pitfall already hit once in this file (CHART-4): do not write a test that asserts on
|
|
219
|
-
> real jsdom-rendered tick visibility/position — it will be vacuous. Assert on the captured
|
|
220
|
-
> `tickLabelInterval`/`valueFormatter` functions' own return values instead**, calling them directly
|
|
221
|
-
> with sample inputs against the mocked `chartSpy` call's props.
|
|
222
|
-
|
|
223
|
-
## PROGRESS CONTRACT
|
|
224
|
-
Emit `PLAN: <steps>` up front, then a single-line `PROGRESS: [<n>/<total>] <action>` before every
|
|
225
|
-
relevant action and `PROGRESS: [<n>/<total>] done` on completion, spaced so no gap exceeds ~2 min,
|
|
226
|
-
stdout unbuffered, and exactly one final `RESULT: DONE|BLOCKED <reason>`.
|