@nadicodeai/ui 0.20.0 → 0.22.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/AGENTS.md +4 -3
- package/README.md +14 -21
- package/dist/agents.d.ts +10 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +9 -0
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/brand-icons/apple.d.ts +18 -0
- package/dist/components/brand-icons/apple.d.ts.map +1 -0
- package/dist/components/brand-icons/apple.js +22 -0
- package/dist/components/brand-icons/brand-icon.d.ts +22 -0
- package/dist/components/brand-icons/brand-icon.d.ts.map +1 -0
- package/dist/components/brand-icons/brand-icon.js +26 -0
- package/dist/components/brand-icons/linux.d.ts +18 -0
- package/dist/components/brand-icons/linux.d.ts.map +1 -0
- package/dist/components/brand-icons/linux.js +25 -0
- package/dist/components/brand-icons/windows.d.ts +18 -0
- package/dist/components/brand-icons/windows.d.ts.map +1 -0
- package/dist/components/brand-icons/windows.js +22 -0
- package/dist/components/brand-icons.d.ts +5 -0
- package/dist/components/brand-icons.d.ts.map +1 -0
- package/dist/components/brand-icons.js +10 -0
- package/dist/components/button.d.ts +1 -1
- package/dist/components/button.js +1 -1
- package/dist/components/card-marketing.js +2 -2
- package/dist/components/card.d.ts +4 -3
- package/dist/components/card.d.ts.map +1 -1
- package/dist/components/card.js +12 -2
- package/dist/components/chart-breakdown-table.js +1 -1
- package/dist/components/chart-bullet-bar.d.ts +18 -2
- package/dist/components/chart-bullet-bar.d.ts.map +1 -1
- package/dist/components/chart-bullet-bar.js +62 -9
- package/dist/components/chart-date-range-control.d.ts +11 -1
- package/dist/components/chart-date-range-control.d.ts.map +1 -1
- package/dist/components/chart-date-range-control.js +13 -3
- package/dist/components/chart-entity-colors.d.ts +7 -1
- package/dist/components/chart-entity-colors.d.ts.map +1 -1
- package/dist/components/chart-entity-colors.js +7 -1
- package/dist/components/chart-kpi-stat.d.ts.map +1 -1
- package/dist/components/chart-kpi-stat.js +1 -1
- package/dist/components/chart-time-series.d.ts.map +1 -1
- package/dist/components/chart-time-series.js +62 -4
- package/dist/components/chart.js +2 -2
- package/dist/components/code-editor-mockup.js +1 -1
- package/dist/components/nav-bar.js +1 -1
- package/dist/components/radio-group.d.ts +1 -1
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js +2 -2
- package/dist/components/theme-mode-switcher.d.ts +10 -3
- package/dist/components/theme-mode-switcher.d.ts.map +1 -1
- package/dist/components/theme-mode-switcher.js +14 -7
- package/dist/components/use-case-bento.d.ts +2 -4
- package/dist/components/use-case-bento.d.ts.map +1 -1
- package/dist/components/use-case-bento.js +2 -3
- package/dist/eslint/index.js +91 -0
- package/dist/eslint/rules/jsx-class-utility.js +231 -0
- package/dist/eslint/rules/no-deprecated-zod-api.js +156 -0
- package/dist/eslint/rules/no-design-system-src-import.js +11 -0
- package/dist/eslint/rules/no-invalid-token-utility.js +46 -0
- package/dist/eslint/rules/no-native-visible-control.js +86 -0
- package/dist/eslint/rules/no-raw-color-utility.js +109 -0
- package/dist/eslint/rules/no-raw-focus-ring-width.js +30 -0
- package/dist/eslint/rules/no-raw-logo-import.js +41 -0
- package/dist/eslint/rules/no-shadcn-appearance-override.js +191 -0
- package/dist/eslint/rules/no-token-category-bypass.js +53 -0
- package/dist/eslint/rules/no-ui-src-import.js +10 -0
- package/dist/eslint/rules/no-unpinned-vercel-functions-import.js +100 -0
- package/dist/eslint/rules/src-import-boundary.js +207 -0
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/index.d.ts +1 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -16
- package/dist/internal/assistant-ui/attachment.d.ts +5 -0
- package/dist/internal/assistant-ui/attachment.d.ts.map +1 -0
- package/dist/internal/assistant-ui/attachment.js +93 -0
- package/dist/internal/assistant-ui/follow-up-suggestions.d.ts +3 -0
- package/dist/internal/assistant-ui/follow-up-suggestions.d.ts.map +1 -0
- package/dist/internal/assistant-ui/follow-up-suggestions.js +8 -0
- package/dist/internal/assistant-ui/markdown-text.d.ts +2 -0
- package/dist/internal/assistant-ui/markdown-text.d.ts.map +1 -0
- package/dist/internal/assistant-ui/markdown-text.js +54 -0
- package/dist/internal/assistant-ui/reasoning.d.ts +31 -0
- package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -0
- package/dist/internal/assistant-ui/reasoning.js +118 -0
- package/dist/internal/assistant-ui/thread.d.ts +26 -0
- package/dist/internal/assistant-ui/thread.d.ts.map +1 -0
- package/dist/internal/assistant-ui/thread.js +118 -0
- package/dist/internal/assistant-ui/tool-fallback.d.ts +10 -0
- package/dist/internal/assistant-ui/tool-fallback.d.ts.map +1 -0
- package/dist/internal/assistant-ui/tool-fallback.js +163 -0
- package/dist/internal/assistant-ui/tool-group.d.ts +18 -0
- package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -0
- package/dist/internal/assistant-ui/tool-group.js +44 -0
- package/dist/internal/assistant-ui/tooltip-icon-button.d.ts +8 -0
- package/dist/internal/assistant-ui/tooltip-icon-button.d.ts.map +1 -0
- package/dist/internal/assistant-ui/tooltip-icon-button.js +10 -0
- package/dist/styles/globals.css +3 -209
- package/docs/agents/nadicodeai-ui.md +4 -6
- package/docs/component-classification.md +1 -1
- package/docs/consuming-cross-repo.md +32 -3
- package/docs/contract.md +16 -6
- package/docs/migration/base-ui-migration.md +0 -11
- package/docs/product-compositions.md +1 -1
- package/llms.txt +5 -6
- package/package.json +17 -29
- package/skills/nadicodeai-ui/SKILL.md +5 -7
- package/dist/ai-elements.d.ts +0 -49
- package/dist/ai-elements.d.ts.map +0 -1
- package/dist/ai-elements.js +0 -48
- package/dist/components/agent-avatar.d.ts +0 -7
- package/dist/components/agent-avatar.d.ts.map +0 -1
- package/dist/components/agent-avatar.js +0 -6
- package/dist/components/agent-chat.d.ts +0 -20
- package/dist/components/agent-chat.d.ts.map +0 -1
- package/dist/components/agent-chat.js +0 -10
- package/dist/components/agent-composer.d.ts +0 -56
- package/dist/components/agent-composer.d.ts.map +0 -1
- package/dist/components/agent-composer.js +0 -56
- package/dist/components/agent-message.d.ts +0 -117
- package/dist/components/agent-message.d.ts.map +0 -1
- package/dist/components/agent-message.js +0 -99
- package/dist/components/agent-thread.d.ts +0 -26
- package/dist/components/agent-thread.d.ts.map +0 -1
- package/dist/components/agent-thread.js +0 -63
- package/dist/components/agent-tool-approval.d.ts +0 -27
- package/dist/components/agent-tool-approval.d.ts.map +0 -1
- package/dist/components/agent-tool-approval.js +0 -43
- package/dist/components/ai-elements/agent.d.ts +0 -27
- package/dist/components/ai-elements/agent.d.ts.map +0 -1
- package/dist/components/ai-elements/agent.js +0 -25
- package/dist/components/ai-elements/artifact.d.ts +0 -24
- package/dist/components/ai-elements/artifact.d.ts.map +0 -1
- package/dist/components/ai-elements/artifact.js +0 -20
- package/dist/components/ai-elements/attachments.d.ts +0 -55
- package/dist/components/ai-elements/attachments.d.ts.map +0 -1
- package/dist/components/ai-elements/attachments.js +0 -125
- package/dist/components/ai-elements/audio-player.d.ts +0 -30
- package/dist/components/ai-elements/audio-player.d.ts.map +0 -1
- package/dist/components/ai-elements/audio-player.js +0 -41
- package/dist/components/ai-elements/canvas.d.ts +0 -8
- package/dist/components/ai-elements/canvas.d.ts.map +0 -1
- package/dist/components/ai-elements/canvas.js +0 -5
- package/dist/components/ai-elements/chain-of-thought.d.ts +0 -30
- package/dist/components/ai-elements/chain-of-thought.d.ts.map +0 -1
- package/dist/components/ai-elements/chain-of-thought.js +0 -49
- package/dist/components/ai-elements/checkpoint.d.ts +0 -12
- package/dist/components/ai-elements/checkpoint.d.ts.map +0 -1
- package/dist/components/ai-elements/checkpoint.js +0 -10
- package/dist/components/ai-elements/code-block.d.ts +0 -53
- package/dist/components/ai-elements/code-block.d.ts.map +0 -1
- package/dist/components/ai-elements/code-block.js +0 -239
- package/dist/components/ai-elements/commit.d.ts +0 -65
- package/dist/components/ai-elements/commit.d.ts.map +0 -1
- package/dist/components/ai-elements/commit.js +0 -83
- package/dist/components/ai-elements/confirmation.d.ts +0 -50
- package/dist/components/ai-elements/confirmation.d.ts.map +0 -1
- package/dist/components/ai-elements/confirmation.js +0 -57
- package/dist/components/ai-elements/connection.d.ts +0 -6
- package/dist/components/ai-elements/connection.d.ts.map +0 -1
- package/dist/components/ai-elements/connection.js +0 -10
- package/dist/components/ai-elements/context.d.ts +0 -33
- package/dist/components/ai-elements/context.d.ts.map +0 -1
- package/dist/components/ai-elements/context.js +0 -147
- package/dist/components/ai-elements/controls.d.ts +0 -5
- package/dist/components/ai-elements/controls.d.ts.map +0 -1
- package/dist/components/ai-elements/controls.js +0 -5
- package/dist/components/ai-elements/conversation.d.ts +0 -24
- package/dist/components/ai-elements/conversation.d.ts.map +0 -1
- package/dist/components/ai-elements/conversation.js +0 -41
- package/dist/components/ai-elements/edge.d.ts +0 -6
- package/dist/components/ai-elements/edge.d.ts.map +0 -1
- package/dist/components/ai-elements/edge.js +0 -88
- package/dist/components/ai-elements/environment-variables.d.ts +0 -39
- package/dist/components/ai-elements/environment-variables.d.ts.map +0 -1
- package/dist/components/ai-elements/environment-variables.js +0 -60
- package/dist/components/ai-elements/file-tree.d.ts +0 -27
- package/dist/components/ai-elements/file-tree.d.ts.map +0 -1
- package/dist/components/ai-elements/file-tree.js +0 -73
- package/dist/components/ai-elements/image.d.ts +0 -7
- package/dist/components/ai-elements/image.d.ts.map +0 -1
- package/dist/components/ai-elements/image.js +0 -3
- package/dist/components/ai-elements/inline-citation.d.ts +0 -39
- package/dist/components/ai-elements/inline-citation.d.ts.map +0 -1
- package/dist/components/ai-elements/inline-citation.js +0 -86
- package/dist/components/ai-elements/jsx-preview.d.ts +0 -30
- package/dist/components/ai-elements/jsx-preview.d.ts.map +0 -1
- package/dist/components/ai-elements/jsx-preview.js +0 -159
- package/dist/components/ai-elements/message.d.ts +0 -38
- package/dist/components/ai-elements/message.d.ts.map +0 -1
- package/dist/components/ai-elements/message.js +0 -91
- package/dist/components/ai-elements/mic-selector.d.ts +0 -46
- package/dist/components/ai-elements/mic-selector.d.ts.map +0 -1
- package/dist/components/ai-elements/mic-selector.js +0 -180
- package/dist/components/ai-elements/model-selector.d.ts +0 -36
- package/dist/components/ai-elements/model-selector.d.ts.map +0 -1
- package/dist/components/ai-elements/model-selector.js +0 -18
- package/dist/components/ai-elements/node.d.ts +0 -22
- package/dist/components/ai-elements/node.d.ts.map +0 -1
- package/dist/components/ai-elements/node.js +0 -12
- package/dist/components/ai-elements/open-in-chat.d.ts +0 -27
- package/dist/components/ai-elements/open-in-chat.d.ts.map +0 -1
- package/dist/components/ai-elements/open-in-chat.js +0 -81
- package/dist/components/ai-elements/package-info.d.ts +0 -30
- package/dist/components/ai-elements/package-info.d.ts.map +0 -1
- package/dist/components/ai-elements/package-info.js +0 -50
- package/dist/components/ai-elements/panel.d.ts +0 -6
- package/dist/components/ai-elements/panel.d.ts.map +0 -1
- package/dist/components/ai-elements/panel.js +0 -5
- package/dist/components/ai-elements/persona.d.ts +0 -49
- package/dist/components/ai-elements/persona.d.ts.map +0 -1
- package/dist/components/ai-elements/persona.js +0 -175
- package/dist/components/ai-elements/plan.d.ts +0 -27
- package/dist/components/ai-elements/plan.d.ts.map +0 -1
- package/dist/components/ai-elements/plan.js +0 -34
- package/dist/components/ai-elements/prompt-input.d.ts +0 -149
- package/dist/components/ai-elements/prompt-input.d.ts.map +0 -1
- package/dist/components/ai-elements/prompt-input.js +0 -704
- package/dist/components/ai-elements/queue.d.ts +0 -62
- package/dist/components/ai-elements/queue.d.ts.map +0 -1
- package/dist/components/ai-elements/queue.js +0 -24
- package/dist/components/ai-elements/reasoning.d.ts +0 -27
- package/dist/components/ai-elements/reasoning.d.ts.map +0 -1
- package/dist/components/ai-elements/reasoning.js +0 -92
- package/dist/components/ai-elements/sandbox.d.ts +0 -25
- package/dist/components/ai-elements/sandbox.d.ts.map +0 -1
- package/dist/components/ai-elements/sandbox.js +0 -15
- package/dist/components/ai-elements/schema-display.d.ts +0 -56
- package/dist/components/ai-elements/schema-display.d.ts.map +0 -1
- package/dist/components/ai-elements/schema-display.js +0 -90
- package/dist/components/ai-elements/shimmer.d.ts +0 -10
- package/dist/components/ai-elements/shimmer.d.ts.map +0 -1
- package/dist/components/ai-elements/shimmer.js +0 -11
- package/dist/components/ai-elements/snippet.d.ts +0 -19
- package/dist/components/ai-elements/snippet.d.ts.map +0 -1
- package/dist/components/ai-elements/snippet.js +0 -32
- package/dist/components/ai-elements/sources.d.ts +0 -13
- package/dist/components/ai-elements/sources.d.ts.map +0 -1
- package/dist/components/ai-elements/sources.js +0 -9
- package/dist/components/ai-elements/speech-input.d.ts +0 -55
- package/dist/components/ai-elements/speech-input.d.ts.map +0 -1
- package/dist/components/ai-elements/speech-input.js +0 -187
- package/dist/components/ai-elements/stack-trace.d.ts +0 -38
- package/dist/components/ai-elements/stack-trace.d.ts.map +0 -1
- package/dist/components/ai-elements/stack-trace.js +0 -181
- package/dist/components/ai-elements/suggestion.d.ts +0 -11
- package/dist/components/ai-elements/suggestion.d.ts.map +0 -1
- package/dist/components/ai-elements/suggestion.js +0 -13
- package/dist/components/ai-elements/task.d.ts +0 -15
- package/dist/components/ai-elements/task.d.ts.map +0 -1
- package/dist/components/ai-elements/task.js +0 -10
- package/dist/components/ai-elements/terminal.d.ts +0 -28
- package/dist/components/ai-elements/terminal.d.ts.map +0 -1
- package/dist/components/ai-elements/terminal.js +0 -55
- package/dist/components/ai-elements/test-results.d.ts +0 -59
- package/dist/components/ai-elements/test-results.d.ts.map +0 -1
- package/dist/components/ai-elements/test-results.js +0 -98
- package/dist/components/ai-elements/tool.d.ts +0 -32
- package/dist/components/ai-elements/tool.d.ts.map +0 -1
- package/dist/components/ai-elements/tool.js +0 -49
- package/dist/components/ai-elements/toolbar.d.ts +0 -6
- package/dist/components/ai-elements/toolbar.d.ts.map +0 -1
- package/dist/components/ai-elements/toolbar.js +0 -5
- package/dist/components/ai-elements/transcription.d.ts +0 -17
- package/dist/components/ai-elements/transcription.d.ts.map +0 -1
- package/dist/components/ai-elements/transcription.js +0 -36
- package/dist/components/ai-elements/voice-selector.d.ts +0 -65
- package/dist/components/ai-elements/voice-selector.d.ts.map +0 -1
- package/dist/components/ai-elements/voice-selector.js +0 -224
- package/dist/components/ai-elements/web-preview.d.ts +0 -35
- package/dist/components/ai-elements/web-preview.d.ts.map +0 -1
- package/dist/components/ai-elements/web-preview.js +0 -66
- package/dist/components/artifact-panel.d.ts +0 -130
- package/dist/components/artifact-panel.d.ts.map +0 -1
- package/dist/components/artifact-panel.js +0 -180
- package/dist/components/attachment.d.ts +0 -24
- package/dist/components/attachment.d.ts.map +0 -1
- package/dist/components/attachment.js +0 -68
- package/dist/components/bubble.d.ts +0 -17
- package/dist/components/bubble.d.ts.map +0 -1
- package/dist/components/bubble.js +0 -59
- package/dist/components/demo-surface.d.ts +0 -34
- package/dist/components/demo-surface.d.ts.map +0 -1
- package/dist/components/demo-surface.js +0 -21
- package/dist/components/files-preview.d.ts +0 -36
- package/dist/components/files-preview.d.ts.map +0 -1
- package/dist/components/files-preview.js +0 -85
- package/dist/components/marker.d.ts +0 -11
- package/dist/components/marker.d.ts.map +0 -1
- package/dist/components/marker.js +0 -34
- package/dist/components/message-scroller.d.ts +0 -17
- package/dist/components/message-scroller.d.ts.map +0 -1
- package/dist/components/message-scroller.js +0 -29
- package/dist/components/message.d.ts +0 -11
- package/dist/components/message.d.ts.map +0 -1
- package/dist/components/message.js +0 -21
- package/dist/components/state-notice.d.ts +0 -13
- package/dist/components/state-notice.d.ts.map +0 -1
- package/dist/components/state-notice.js +0 -8
- package/dist/components/watch-it-work-band.d.ts +0 -12
- package/dist/components/watch-it-work-band.d.ts.map +0 -1
- package/dist/components/watch-it-work-band.js +0 -8
- package/dist/hooks/use-controllable-state.d.ts +0 -9
- package/dist/hooks/use-controllable-state.d.ts.map +0 -1
- package/dist/hooks/use-controllable-state.js +0 -23
- package/dist/lib/agent-attachment.d.ts +0 -11
- package/dist/lib/agent-attachment.d.ts.map +0 -1
- package/dist/lib/agent-attachment.js +0 -19
- package/dist/lib/agent-contracts.d.ts +0 -132
- package/dist/lib/agent-contracts.d.ts.map +0 -1
- package/dist/lib/agent-contracts.js +0 -6
- package/dist/lib/agent-state.d.ts +0 -22
- package/dist/lib/agent-state.d.ts.map +0 -1
- package/dist/lib/agent-state.js +0 -96
- package/dist/lib/agent-work-state.d.ts +0 -36
- package/dist/lib/agent-work-state.d.ts.map +0 -1
- package/dist/lib/agent-work-state.js +0 -36
- package/dist/lib/message-scroller-primitive/components.d.ts +0 -17
- package/dist/lib/message-scroller-primitive/components.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/components.js +0 -204
- package/dist/lib/message-scroller-primitive/geometry.d.ts +0 -51
- package/dist/lib/message-scroller-primitive/geometry.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/geometry.js +0 -199
- package/dist/lib/message-scroller-primitive/index.d.ts +0 -12
- package/dist/lib/message-scroller-primitive/index.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/index.js +0 -12
- package/dist/lib/message-scroller-primitive/stores.d.ts +0 -6
- package/dist/lib/message-scroller-primitive/stores.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/stores.js +0 -53
- package/dist/lib/message-scroller-primitive/types.d.ts +0 -88
- package/dist/lib/message-scroller-primitive/types.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/types.js +0 -40
- package/dist/lib/message-scroller-primitive/use-message-scroller-commands.d.ts +0 -19
- package/dist/lib/message-scroller-primitive/use-message-scroller-commands.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/use-message-scroller-commands.js +0 -188
- package/dist/lib/message-scroller-primitive/use-message-scroller-controller.d.ts +0 -7
- package/dist/lib/message-scroller-primitive/use-message-scroller-controller.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/use-message-scroller-controller.js +0 -506
- package/dist/lib/message-scroller-primitive/use-message-scroller-refs.d.ts +0 -49
- package/dist/lib/message-scroller-primitive/use-message-scroller-refs.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/use-message-scroller-refs.js +0 -90
- package/dist/lib/message-scroller-primitive/use-render.d.ts +0 -22
- package/dist/lib/message-scroller-primitive/use-render.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/use-render.js +0 -113
- package/dist/lib/message-scroller-primitive/utils.d.ts +0 -4
- package/dist/lib/message-scroller-primitive/utils.d.ts.map +0 -1
- package/dist/lib/message-scroller-primitive/utils.js +0 -9
- package/docs/agent-work-surfaces.md +0 -132
- package/docs/migration/ai-elements-vendoring.md +0 -29
- package/docs/terminal-tui-semantics.md +0 -172
|
@@ -1,9 +1,31 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* The tip value is TEXT, so it takes the feedback pair's deep tone, not the
|
|
5
|
+
* rail tone the segments wear: `--nc-state-review` / `--nc-state-blocked` are
|
|
6
|
+
* fill tones (0.85 amber reads at 1.6:1 on the light canvas), while
|
|
7
|
+
* `--nc-warning-deep` and `--nc-error-deep` are authored light AND dark so the
|
|
8
|
+
* percentage stays readable in both modes — and it is loudest exactly when it
|
|
9
|
+
* crosses a threshold.
|
|
10
|
+
*/
|
|
3
11
|
const BULLET_BAR_VALUE_TONE = {
|
|
4
12
|
ok: "text-foreground",
|
|
5
|
-
warn: "text-(--nc-
|
|
6
|
-
over: "text-(--nc-
|
|
13
|
+
warn: "text-(--nc-warning-deep)",
|
|
14
|
+
over: "text-(--nc-error-deep)",
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* The consumed length carries the severity too, not only the tip figure: a
|
|
18
|
+
* meter at its cap and a meter at 40% drew the same calm ramp fill, so the one
|
|
19
|
+
* state where the reader is actually blocked was legible only from a 10px
|
|
20
|
+
* percentage. Position stays the primary signal (the threshold and cap ticks
|
|
21
|
+
* do not move); the tone reinforces it, per DESIGN.md's meter grammar. These
|
|
22
|
+
* are the rail tones of the feedback pairs, the same register the overflow
|
|
23
|
+
* segment already wears.
|
|
24
|
+
*/
|
|
25
|
+
const BULLET_BAR_FILL_TONE = {
|
|
26
|
+
ok: "bg-(--nc-chart-seq-3)",
|
|
27
|
+
warn: "bg-(--nc-state-review)",
|
|
28
|
+
over: "bg-(--nc-state-blocked)",
|
|
7
29
|
};
|
|
8
30
|
function percent(fraction) {
|
|
9
31
|
return `${Number((fraction * 100).toFixed(3))}%`;
|
|
@@ -11,7 +33,7 @@ function percent(fraction) {
|
|
|
11
33
|
function defaultFormat(value) {
|
|
12
34
|
return value.toLocaleString("en-US");
|
|
13
35
|
}
|
|
14
|
-
function BulletBar({ value, max, thresholdFraction, label, valueFormatter = defaultFormat, valueText, className, ...props }) {
|
|
36
|
+
function BulletBar({ value, max, thresholdFraction, label, size = "panel", valueFormatter = defaultFormat, valueText, className, ...props }) {
|
|
15
37
|
const overflow = Math.max(value - max, 0);
|
|
16
38
|
const total = Math.max(value, max);
|
|
17
39
|
const fillFraction = total > 0 ? Math.min(value, max) / total : 0;
|
|
@@ -19,12 +41,43 @@ function BulletBar({ value, max, thresholdFraction, label, valueFormatter = defa
|
|
|
19
41
|
const capFraction = total > 0 ? max / total : 1;
|
|
20
42
|
const thresholdTickFraction = capFraction * thresholdFraction;
|
|
21
43
|
const tipFraction = fillFraction + overflowFraction;
|
|
22
|
-
|
|
44
|
+
// Reaching the cap IS the blocked state, not merely the last warning step:
|
|
45
|
+
// an allowance consumed to exactly 100% stops the work the same way 104%
|
|
46
|
+
// does, so both read as `over`. A zero cap with no value stays `ok` — an
|
|
47
|
+
// unconfigured meter is not an exhausted one.
|
|
48
|
+
const severity = overflow > 0 || (max > 0 && value >= max)
|
|
49
|
+
? "over"
|
|
50
|
+
: max > 0 && value >= thresholdFraction * max
|
|
51
|
+
? "warn"
|
|
52
|
+
: "ok";
|
|
23
53
|
const meterValueText = valueText ??
|
|
24
54
|
`${valueFormatter(value)} of ${valueFormatter(max)}${overflow > 0 ? ` (${valueFormatter(overflow)} over the cap)` : ""}`;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
55
|
+
// The row scale prints this instead of the tip value: at row scale the
|
|
56
|
+
// reader is asking "how close to the wall", not "how many".
|
|
57
|
+
const consumedPercent = max > 0 ? Math.round((value / max) * 100) : 0;
|
|
58
|
+
const segments = (_jsxs(_Fragment, { children: [_jsx("div", { "data-slot": "bullet-bar-track",
|
|
59
|
+
// One step darker than the surface it sits on, in both themes: at
|
|
60
|
+
// `bg-muted` an empty meter on the light canvas read as a hairline
|
|
61
|
+
// rather than as a track with nothing in it.
|
|
62
|
+
className: "absolute inset-y-0 rounded-r-sm bg-muted-foreground/20", style: { left: 0, width: percent(capFraction) } }), _jsx("div", { "data-slot": "bullet-bar-fill", className: cn("absolute inset-y-0", BULLET_BAR_FILL_TONE[severity], overflow === 0 && "rounded-r-sm"), style: { left: 0, width: percent(fillFraction) } }), overflow > 0 ? (_jsx("div", { "data-slot": "bullet-bar-overflow",
|
|
63
|
+
// A darker step of the same error family: now that the consumed
|
|
64
|
+
// length is itself red at the cap, the over-run has to stay a
|
|
65
|
+
// DISTINCT segment (DESIGN.md), which one shared tone would erase.
|
|
66
|
+
className: "absolute inset-y-0 rounded-r-sm bg-(--nc-error-deep)", style: {
|
|
67
|
+
left: percent(fillFraction),
|
|
68
|
+
width: percent(overflowFraction),
|
|
69
|
+
} })) : null] }));
|
|
70
|
+
const meterAria = {
|
|
71
|
+
role: "meter",
|
|
72
|
+
"aria-label": label,
|
|
73
|
+
"aria-valuemin": 0,
|
|
74
|
+
"aria-valuemax": max,
|
|
75
|
+
"aria-valuenow": Math.min(value, max),
|
|
76
|
+
"aria-valuetext": meterValueText,
|
|
77
|
+
};
|
|
78
|
+
if (size === "row") {
|
|
79
|
+
return (_jsxs("div", { "data-slot": "bullet-bar", "data-severity": severity, "data-size": "row", className: cn("flex items-center gap-2", className), ...props, children: [_jsxs("span", { "data-slot": "bullet-bar-percent", "aria-hidden": "true", className: cn("font-mono text-xs tabular-nums", BULLET_BAR_VALUE_TONE[severity]), children: [consumedPercent, "%"] }), _jsx("div", { ...meterAria, className: "relative h-1 min-w-0 flex-1", children: segments })] }));
|
|
80
|
+
}
|
|
81
|
+
return (_jsxs("div", { "data-slot": "bullet-bar", "data-severity": severity, "data-size": "panel", className: cn("flex flex-col gap-1", className), ...props, children: [_jsxs("div", { ...meterAria, className: "relative h-3 w-full", children: [segments, _jsx("div", { "data-slot": "bullet-bar-threshold-tick", "aria-hidden": "true", className: "absolute -inset-y-0.5 w-px bg-foreground", style: { left: percent(thresholdTickFraction) } }), _jsx("div", { "data-slot": "bullet-bar-cap-tick", "aria-hidden": "true", className: "absolute -inset-y-0.5 w-px bg-foreground", style: { left: percent(capFraction) } })] }), _jsx("div", { className: "relative h-4 w-full text-xs", "aria-hidden": "true", children: _jsx("span", { "data-slot": "bullet-bar-value", className: cn("absolute font-mono whitespace-nowrap tabular-nums", tipFraction > 0.6 && "-translate-x-full", BULLET_BAR_VALUE_TONE[severity]), style: { left: percent(tipFraction) }, children: valueFormatter(value) }) })] }));
|
|
29
82
|
}
|
|
30
83
|
export { BulletBar };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type DateRangePreset, type DateRangeValue } from "./chart-date-range";
|
|
3
|
-
declare function DateRangeControl({ value, onChange, label, presets, presetLabels, customLabel, className, ...props }: Omit<React.ComponentProps<"div">, "children" | "onChange"> & {
|
|
3
|
+
declare function DateRangeControl({ value, onChange, label, presets, presetLabels, customLabel, formatCustomValue, className, ...props }: Omit<React.ComponentProps<"div">, "children" | "onChange"> & {
|
|
4
4
|
value: DateRangeValue;
|
|
5
5
|
onChange: (value: DateRangeValue) => void;
|
|
6
6
|
/** Accessible name for the control group. */
|
|
@@ -12,6 +12,16 @@ declare function DateRangeControl({ value, onChange, label, presets, presetLabel
|
|
|
12
12
|
presets?: readonly DateRangePreset[];
|
|
13
13
|
presetLabels?: Partial<Record<DateRangePreset, string>>;
|
|
14
14
|
customLabel?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Renders the selected custom window as a finished, localized label. The
|
|
17
|
+
* package owns no locale, so without it the trigger falls back to the ISO
|
|
18
|
+
* pair the codec stores — a storage format, never a label a reader should
|
|
19
|
+
* meet. Every locale-aware consumer passes this.
|
|
20
|
+
*/
|
|
21
|
+
formatCustomValue?: (value: {
|
|
22
|
+
from: string;
|
|
23
|
+
to: string;
|
|
24
|
+
}) => string;
|
|
15
25
|
}): React.JSX.Element;
|
|
16
26
|
export { DateRangeControl };
|
|
17
27
|
//# sourceMappingURL=chart-date-range-control.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-date-range-control.d.ts","sourceRoot":"","sources":["../../src/components/chart-date-range-control.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"chart-date-range-control.d.ts","sourceRoot":"","sources":["../../src/components/chart-date-range-control.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,+BAA+B,CAAC;AAmCvC,iBAAS,gBAAgB,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,KAAoB,EACpB,OAA4B,EAC5B,YAAY,EACZ,WAAsB,EACtB,iBAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG;IAC9D,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC1C,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;CACrE,qBAoFA;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -23,13 +23,20 @@ import { DATE_RANGE_PRESETS, formatIsoDay, parseIsoDay, } from "./chart-date-ran
|
|
|
23
23
|
* (`DATE_RANGE_PRESETS`) is unchanged, so a URL arriving with an un-offered but
|
|
24
24
|
* valid preset token still decodes; the consumer decides its fallback.
|
|
25
25
|
*/
|
|
26
|
+
// Which range the chart is showing is a selection, and this row is the only
|
|
27
|
+
// thing that says it. A soft neutral fill sits about 1.1:1 against the page in
|
|
28
|
+
// both modes, which is a state no sighted reader can find, so the selected
|
|
29
|
+
// preset wears the navigation-selection role: the same colour the console
|
|
30
|
+
// marks a chosen destination with, and the only neutral-safe token that clears
|
|
31
|
+
// the 3:1 a state-bearing control owes.
|
|
32
|
+
const SELECTED_PRESET_CLASS = "bg-(--nc-navigation-selection-bg) text-(--nc-navigation-selection-fg) hover:bg-(--nc-navigation-selection-hover) hover:text-(--nc-navigation-selection-fg)";
|
|
26
33
|
const DEFAULT_PRESET_LABELS = {
|
|
27
34
|
"7d": "7d",
|
|
28
35
|
"14d": "14d",
|
|
29
36
|
"30d": "30d",
|
|
30
37
|
cycle: "This cycle",
|
|
31
38
|
};
|
|
32
|
-
function DateRangeControl({ value, onChange, label = "Date range", presets = DATE_RANGE_PRESETS, presetLabels, customLabel = "Custom", className, ...props }) {
|
|
39
|
+
function DateRangeControl({ value, onChange, label = "Date range", presets = DATE_RANGE_PRESETS, presetLabels, customLabel = "Custom", formatCustomValue, className, ...props }) {
|
|
33
40
|
const [open, setOpen] = React.useState(false);
|
|
34
41
|
const [pending, setPending] = React.useState(undefined);
|
|
35
42
|
const isCustom = value.kind === "custom";
|
|
@@ -56,7 +63,10 @@ function DateRangeControl({ value, onChange, label = "Date range", presets = DAT
|
|
|
56
63
|
}
|
|
57
64
|
return (_jsxs("div", { "data-slot": "date-range-control", role: "group", "aria-label": label, className: cn("flex flex-wrap items-center gap-1", className), ...props, children: [presets.map((preset) => {
|
|
58
65
|
const active = value.kind === "preset" && value.preset === preset;
|
|
59
|
-
return (_jsx(Button, { size: "sm", variant:
|
|
60
|
-
}), _jsxs(Popover, { open: open, onOpenChange: handleOpenChange, children: [_jsx(PopoverTrigger, { render: _jsxs(Button, { size: "sm", variant:
|
|
66
|
+
return (_jsx(Button, { size: "sm", variant: "ghost", "aria-pressed": active, className: active ? SELECTED_PRESET_CLASS : undefined, onClick: () => onChange({ kind: "preset", preset }), children: presetLabels?.[preset] ?? DEFAULT_PRESET_LABELS[preset] }, preset));
|
|
67
|
+
}), _jsxs(Popover, { open: open, onOpenChange: handleOpenChange, children: [_jsx(PopoverTrigger, { render: _jsxs(Button, { size: "sm", variant: "ghost", "aria-pressed": isCustom, className: isCustom ? SELECTED_PRESET_CLASS : undefined, children: [_jsx(CalendarIcon, { "data-icon": "inline-start" }), isCustom
|
|
68
|
+
? (formatCustomValue?.({ from: value.from, to: value.to }) ??
|
|
69
|
+
`${value.from} – ${value.to}`)
|
|
70
|
+
: customLabel] }) }), _jsx(PopoverContent, { align: "start", className: "w-auto p-0", children: _jsx(Calendar, { mode: "range", numberOfMonths: 2, defaultMonth: selected?.from, selected: selected, onSelect: handleSelect }) })] })] }));
|
|
61
71
|
}
|
|
62
72
|
export { DateRangeControl };
|
|
@@ -17,8 +17,14 @@ declare const CHART_ENTITY_COLOR_TOKENS: readonly ["var(--nc-chart-1)", "var(--n
|
|
|
17
17
|
/**
|
|
18
18
|
* The neutral register for folded "everything else" entities. A muted ink
|
|
19
19
|
* token, never an extra categorical hue.
|
|
20
|
+
*
|
|
21
|
+
* `--nc-muted` and not the `--muted-foreground` role: the role resolves to the
|
|
22
|
+
* body-text tone, which in dark is near-white (L 0.83) — as a mark it becomes
|
|
23
|
+
* the loudest thing in the chart, so the tail outshouts every named entity.
|
|
24
|
+
* `--nc-muted` is authored as a mid grey in both modes (L 0.53 light / 0.65
|
|
25
|
+
* dark), which is what a folded tail should read as either way.
|
|
20
26
|
*/
|
|
21
|
-
declare const CHART_ENTITY_OTHER_COLOR = "var(--muted
|
|
27
|
+
declare const CHART_ENTITY_OTHER_COLOR = "var(--nc-muted)";
|
|
22
28
|
type EntityColorMap = Readonly<Record<string, string>>;
|
|
23
29
|
/**
|
|
24
30
|
* Assigns `var(--nc-chart-1..6)` in fixed order by FIRST APPEARANCE of each
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-entity-colors.d.ts","sourceRoot":"","sources":["../../src/components/chart-entity-colors.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,QAAA,MAAM,yBAAyB,yIAOrB,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"chart-entity-colors.d.ts","sourceRoot":"","sources":["../../src/components/chart-entity-colors.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,QAAA,MAAM,yBAAyB,yIAOrB,CAAC;AAEX;;;;;;;;;GASG;AACH,QAAA,MAAM,wBAAwB,oBAAoB,CAAC;AAEnD,KAAK,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD;;;;GAIG;AACH,iBAAS,oBAAoB,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CA2B1E;AAED;;;;GAIG;AACH,iBAAS,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMlE;AAED,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;AAClG,YAAY,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -24,8 +24,14 @@ const CHART_ENTITY_COLOR_TOKENS = [
|
|
|
24
24
|
/**
|
|
25
25
|
* The neutral register for folded "everything else" entities. A muted ink
|
|
26
26
|
* token, never an extra categorical hue.
|
|
27
|
+
*
|
|
28
|
+
* `--nc-muted` and not the `--muted-foreground` role: the role resolves to the
|
|
29
|
+
* body-text tone, which in dark is near-white (L 0.83) — as a mark it becomes
|
|
30
|
+
* the loudest thing in the chart, so the tail outshouts every named entity.
|
|
31
|
+
* `--nc-muted` is authored as a mid grey in both modes (L 0.53 light / 0.65
|
|
32
|
+
* dark), which is what a folded tail should read as either way.
|
|
27
33
|
*/
|
|
28
|
-
const CHART_ENTITY_OTHER_COLOR = "var(--muted
|
|
34
|
+
const CHART_ENTITY_OTHER_COLOR = "var(--nc-muted)";
|
|
29
35
|
/**
|
|
30
36
|
* Assigns `var(--nc-chart-1..6)` in fixed order by FIRST APPEARANCE of each
|
|
31
37
|
* stable entity id. Duplicate ids keep their first assignment. Entities past
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-kpi-stat.d.ts","sourceRoot":"","sources":["../../src/components/chart-kpi-stat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAS,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;;;;;;;GAWG;AAEH,KAAK,YAAY,GAAG;IAClB,yCAAyC;IACzC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,iBAAS,OAAO,CAAC,EACf,KAAK,EACL,KAAK,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IACjD,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,uEAAuE;IACvE,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B,
|
|
1
|
+
{"version":3,"file":"chart-kpi-stat.d.ts","sourceRoot":"","sources":["../../src/components/chart-kpi-stat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAS,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;;;;;;;GAWG;AAEH,KAAK,YAAY,GAAG;IAClB,yCAAyC;IACzC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,iBAAS,OAAO,CAAC,EACf,KAAK,EACL,KAAK,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IACjD,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,uEAAuE;IACvE,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B,qBAkCA;AAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
3
|
import { Delta } from "./chart-delta.js";
|
|
4
4
|
function KpiStat({ label, value, delta, sparkline, className, ...props }) {
|
|
5
|
-
return (_jsxs("div", { "data-slot": "kpi-stat", className: cn("flex flex-col gap-1.5", className), ...props, children: [_jsx("div", { "data-slot": "kpi-stat-label", className: "
|
|
5
|
+
return (_jsxs("div", { "data-slot": "kpi-stat", className: cn("flex flex-col gap-1.5", className), ...props, children: [_jsx("div", { "data-slot": "kpi-stat-label", className: "text-xs font-medium text-muted-foreground", children: label }), _jsxs("div", { className: "flex items-end justify-between gap-3", children: [_jsx("div", { "data-slot": "kpi-stat-value", className: "text-3xl leading-none font-semibold text-foreground", children: value }), sparkline ? (_jsx("div", { "data-slot": "kpi-stat-sparkline", "aria-hidden": "true", children: sparkline })) : null] }), delta ? (_jsx(Delta, { value: delta.value, direction: delta.direction, upIsGood: delta.upIsGood, vsLabel: delta.vsLabel })) : null] }));
|
|
6
6
|
}
|
|
7
7
|
export { KpiStat };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-time-series.d.ts","sourceRoot":"","sources":["../../src/components/chart-time-series.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"chart-time-series.d.ts","sourceRoot":"","sources":["../../src/components/chart-time-series.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kCAAkC,CAAC;AA+G1C,KAAK,gBAAgB,GAAG;IACtB,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvD,KAAK,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,GAAG;IACxE,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACpC,2DAA2D;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAsJF,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,qBAyDjB;AAED,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,qBA6EjB;AAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -43,6 +43,59 @@ import { CHART_ENTITY_OTHER_COLOR, entityColor, } from "./chart-entity-colors.js
|
|
|
43
43
|
const CHART_SURFACE_FOCUS_CLASS = "[&_.recharts-surface:focus-visible]:outline-2 " +
|
|
44
44
|
"[&_.recharts-surface:focus-visible]:outline-ring " +
|
|
45
45
|
"[&_.recharts-surface:focus-visible]:outline-offset-2";
|
|
46
|
+
/**
|
|
47
|
+
* The x ticks land at ONE constant stride across the range, and the stride is
|
|
48
|
+
* the smallest one whose labels still clear each other at the width the chart
|
|
49
|
+
* actually has. Recharts' default `preserveEnd` fitting is greedy on label
|
|
50
|
+
* width, so a 30-day axis draws the narrow early labels daily and then switches
|
|
51
|
+
* to every other day once "Jul 10" is wider than "Jul 1" — the rhythm breaks
|
|
52
|
+
* mid-chart, differently per locale. `equidistantPreserveStart` evaluates one
|
|
53
|
+
* stride against every label and raises it until the whole run fits, so the
|
|
54
|
+
* axis is even by construction AND survives a narrow viewport: a count fixed at
|
|
55
|
+
* the wide case superimposed eight labels into an unreadable smear on a phone,
|
|
56
|
+
* and worse in locales whose date labels run longer.
|
|
57
|
+
*/
|
|
58
|
+
const X_AXIS_MIN_TICK_GAP = 48;
|
|
59
|
+
/**
|
|
60
|
+
* How many ticks the y axis draws, ends included. Recharts divides the data's
|
|
61
|
+
* own maximum by this count when it is left to itself, which produces steps of
|
|
62
|
+
* whatever the data happens to reach: one console chart read $0/$5/$10 while the
|
|
63
|
+
* chart beside it read EUR0/9/18/27/36, and the two stopped sharing a numeric
|
|
64
|
+
* register. The domain is rounded up to a step a person counts in instead.
|
|
65
|
+
*/
|
|
66
|
+
const Y_AXIS_TICK_COUNT = 5;
|
|
67
|
+
/** The steps a reader counts in, per order of magnitude. */
|
|
68
|
+
const NICE_STEP_MULTIPLES = [1, 2, 2.5, 5, 10];
|
|
69
|
+
function niceStep(rawStep) {
|
|
70
|
+
if (!Number.isFinite(rawStep) || rawStep <= 0)
|
|
71
|
+
return 1;
|
|
72
|
+
const magnitude = 10 ** Math.floor(Math.log10(rawStep));
|
|
73
|
+
const normalized = rawStep / magnitude;
|
|
74
|
+
const multiple = NICE_STEP_MULTIPLES.find((candidate) => normalized <= candidate) ?? 10;
|
|
75
|
+
return multiple * magnitude;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The stacked maximum across the data, rounded up to a whole number of nice
|
|
79
|
+
* steps. Returns `undefined` when there is nothing to bound, so the axis falls
|
|
80
|
+
* back to recharts' own domain rather than pinning itself to zero.
|
|
81
|
+
*/
|
|
82
|
+
function niceYDomainMax(data, series) {
|
|
83
|
+
let max = 0;
|
|
84
|
+
for (const datum of data) {
|
|
85
|
+
let total = 0;
|
|
86
|
+
for (const entry of series) {
|
|
87
|
+
const value = datum[entry.id];
|
|
88
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
89
|
+
total += value;
|
|
90
|
+
}
|
|
91
|
+
if (total > max)
|
|
92
|
+
max = total;
|
|
93
|
+
}
|
|
94
|
+
if (max <= 0)
|
|
95
|
+
return undefined;
|
|
96
|
+
const step = niceStep(max / (Y_AXIS_TICK_COUNT - 1));
|
|
97
|
+
return step * (Y_AXIS_TICK_COUNT - 1);
|
|
98
|
+
}
|
|
46
99
|
/**
|
|
47
100
|
* Synthetic id/key for the single aggregated neutral series. Entities past the
|
|
48
101
|
* sixth resolve to the neutral register, and rendering each as its own
|
|
@@ -63,7 +116,7 @@ function defaultFormat(value) {
|
|
|
63
116
|
*/
|
|
64
117
|
function tooltipRowFormatter(series, valueFormatter) {
|
|
65
118
|
const labelById = new Map(series.map((entry) => [entry.id, entry.label]));
|
|
66
|
-
return (value, name, item) => (_jsxs(_Fragment, { children: [_jsx("span", { "data-slot": "time-series-tooltip-swatch", className: "size-2.5 shrink-0 rounded-
|
|
119
|
+
return (value, name, item) => (_jsxs(_Fragment, { children: [_jsx("span", { "data-slot": "time-series-tooltip-swatch", className: "size-2.5 shrink-0 rounded-xs", style: { backgroundColor: item.color ?? item.payload?.fill } }), _jsxs("span", { className: "flex flex-1 items-center justify-between gap-2 leading-none", children: [_jsx("span", { className: "text-muted-foreground", children: labelById.get(String(name)) ?? name }), _jsx("span", { className: "font-mono font-medium text-foreground tabular-nums", children: typeof value === "number" ? valueFormatter(value) : String(value) })] })] }));
|
|
67
120
|
}
|
|
68
121
|
function seriesChartConfig(series, entityColorMap) {
|
|
69
122
|
return Object.fromEntries(series.map((entry) => [
|
|
@@ -114,14 +167,19 @@ function TimeSeriesFrame({ label, className, children, ...props }) {
|
|
|
114
167
|
function TimeSeriesBars({ data, xKey, series, entityColorMap, label, xLabel = "Period", valueFormatter = defaultFormat, yAxisWidth, otherLabel = "Other", className, ...props }) {
|
|
115
168
|
const folded = foldNeutralSeries(series, entityColorMap, data, otherLabel);
|
|
116
169
|
const config = seriesChartConfig(folded.series, entityColorMap);
|
|
117
|
-
|
|
170
|
+
const yDomainMax = niceYDomainMax(folded.data, folded.series);
|
|
171
|
+
return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-bars", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(BarChart, { accessibilityLayer: true, title: label, data: folded.data, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8, interval: "equidistantPreserveStart", minTickGap: X_AXIS_MIN_TICK_GAP }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickCount: Y_AXIS_TICK_COUNT, ...(yDomainMax === undefined ? {} : { domain: [0, yDomainMax] }), tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, _jsx(BarStack, { stackId: "stacked", radius: [4, 4, 0, 0], children: folded.series.map((entry) => (_jsx(Bar, { dataKey: entry.id, isAnimationActive: false, maxBarSize: 24, fill: entityColor(entityColorMap, entry.id), stroke: "var(--background)", strokeWidth: 2 }, entry.id))) })] }) }), _jsx(TimeSeriesTableAlternative, { data: folded.data, xKey: xKey, xLabel: xLabel, series: folded.series, label: label, valueFormatter: valueFormatter })] }));
|
|
118
172
|
}
|
|
119
173
|
function TimeSeriesArea({ data, xKey, series, entityColorMap, label, xLabel = "Period", valueFormatter = defaultFormat, yAxisWidth, otherLabel = "Other", className, ...props }) {
|
|
120
174
|
const folded = foldNeutralSeries(series, entityColorMap, data, otherLabel);
|
|
121
175
|
const config = seriesChartConfig(folded.series, entityColorMap);
|
|
122
|
-
|
|
176
|
+
const yDomainMax = niceYDomainMax(folded.data, folded.series);
|
|
177
|
+
return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-area", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(AreaChart, { accessibilityLayer: true, title: label, data: folded.data, margin: { top: 5, right: 20, bottom: 5, left: 20 }, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8, interval: "equidistantPreserveStart", minTickGap: X_AXIS_MIN_TICK_GAP }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickCount: Y_AXIS_TICK_COUNT, ...(yDomainMax === undefined ? {} : { domain: [0, yDomainMax] }), tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, folded.series.map((entry) => {
|
|
123
178
|
const color = entityColor(entityColorMap, entry.id);
|
|
124
|
-
return (_jsx(Area, { type: "monotone", dataKey: entry.id, isAnimationActive: false, stackId: "stacked", stroke: color, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", fill: color,
|
|
179
|
+
return (_jsx(Area, { type: "monotone", dataKey: entry.id, isAnimationActive: false, stackId: "stacked", stroke: color, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", fill: color,
|
|
180
|
+
// DESIGN.md mark specs: an area fill reads as a light wash
|
|
181
|
+
// (roughly 10% opacity) under a full-strength line.
|
|
182
|
+
fillOpacity: 0.1,
|
|
125
183
|
// Recharts' default activeDot ring is stroke #fff, which the
|
|
126
184
|
// chart foundation remaps to transparent — an explicit surface
|
|
127
185
|
// ring keeps the DESIGN.md 2px marker-ring spec on hover/focus.
|
package/dist/components/chart.js
CHANGED
|
@@ -89,7 +89,7 @@ function ChartTooltipContent({ active, payload, className, indicator = "dot", hi
|
|
|
89
89
|
const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`;
|
|
90
90
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
91
91
|
const indicatorColor = color ?? item.payload?.fill ?? item.color;
|
|
92
|
-
return (_jsx("div", { className: cn("flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center"), children: formatter && item?.value !== undefined && item.name ? (formatter(item.value, item.name, item, index, item.payload)) : (_jsxs(_Fragment, { children: [itemConfig?.icon ? (_jsx(itemConfig.icon, {})) : (!hideIndicator && (_jsx("div", { className: cn("shrink-0 rounded-
|
|
92
|
+
return (_jsx("div", { className: cn("flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center"), children: formatter && item?.value !== undefined && item.name ? (formatter(item.value, item.name, item, index, item.payload)) : (_jsxs(_Fragment, { children: [itemConfig?.icon ? (_jsx(itemConfig.icon, {})) : (!hideIndicator && (_jsx("div", { className: cn("shrink-0 rounded-xs border-(--color-border) bg-(--color-bg)", {
|
|
93
93
|
"h-2.5 w-2.5": indicator === "dot",
|
|
94
94
|
"w-1": indicator === "line",
|
|
95
95
|
"w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
|
|
@@ -113,7 +113,7 @@ function ChartLegendContent({ className, hideIcon = false, payload, verticalAlig
|
|
|
113
113
|
.map((item, index) => {
|
|
114
114
|
const key = `${nameKey ?? item.dataKey ?? "value"}`;
|
|
115
115
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
116
|
-
return (_jsxs("div", { className: cn("flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"), children: [itemConfig?.icon && !hideIcon ? (_jsx(itemConfig.icon, {})) : (_jsx("div", { className: "h-2 w-2 shrink-0 rounded-
|
|
116
|
+
return (_jsxs("div", { className: cn("flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"), children: [itemConfig?.icon && !hideIcon ? (_jsx(itemConfig.icon, {})) : (_jsx("div", { className: "h-2 w-2 shrink-0 rounded-xs", style: {
|
|
117
117
|
backgroundColor: item.color,
|
|
118
118
|
} })), itemConfig?.label] }, index));
|
|
119
119
|
}) }));
|
|
@@ -24,7 +24,7 @@ import { cn } from "../lib/utils.js";
|
|
|
24
24
|
* dots -> bg-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)]
|
|
25
25
|
*/
|
|
26
26
|
function CodeEditorMockup({ className, ...props }) {
|
|
27
|
-
return (_jsx("div", { "data-slot": "code-editor-mockup", className: cn("grid content-start overflow-hidden rounded-
|
|
27
|
+
return (_jsx("div", { "data-slot": "code-editor-mockup", className: cn("grid content-start overflow-hidden rounded-md bg-primary text-primary-foreground", className), ...props }));
|
|
28
28
|
}
|
|
29
29
|
function CodeEditorMockupChrome({ className, children, ...props }) {
|
|
30
30
|
return (_jsxs("div", { "data-slot": "code-editor-mockup-chrome", className: cn("flex items-center gap-2 border-b border-b-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)] px-6 py-3", className), ...props, children: [_jsxs("span", { "data-slot": "code-editor-mockup-dots", "aria-hidden": "true", className: "flex flex-none gap-2", children: [_jsx("span", { className: "size-[11px] rounded-full bg-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)]" }), _jsx("span", { className: "size-[11px] rounded-full bg-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)]" }), _jsx("span", { className: "size-[11px] rounded-full bg-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)]" })] }), children] }));
|
|
@@ -28,7 +28,7 @@ function NavBarLogo({ className, ...props }) {
|
|
|
28
28
|
function NavBarLinks({ className, ...props }) {
|
|
29
29
|
return (_jsx("div", { "data-slot": "nav-bar-links", className: cn("hidden items-center justify-center gap-1 text-sm text-muted-foreground lg:inline-flex",
|
|
30
30
|
// each link reads as a flat pill with hover/focus affordance against the glass.
|
|
31
|
-
"[&_a]:rounded-
|
|
31
|
+
"[&_a]:rounded-sm [&_a]:px-3 [&_a]:py-2 [&_a]:text-inherit [&_a]:no-underline [&_a]:transition-colors", "[&_a:hover]:bg-accent [&_a:hover]:text-foreground", "[&_a[data-active]]:text-foreground", "[&_a:focus-visible]:outline [&_a:focus-visible]:outline-1 [&_a:focus-visible]:[outline-color:var(--ring)] [&_a:focus-visible]:outline-offset-2", className), ...props }));
|
|
32
32
|
}
|
|
33
33
|
function NavBarCta({ className, ...props }) {
|
|
34
34
|
return (_jsx("div", { "data-slot": "nav-bar-cta", className: cn("inline-flex items-center gap-3 justify-self-end", className), ...props }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Radio as RadioPrimitive } from "@base-ui/react/radio";
|
|
2
2
|
import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
|
|
3
3
|
declare function RadioGroup({ className, ...props }: RadioGroupPrimitive.Props): import("react").JSX.Element;
|
|
4
|
-
declare function RadioGroupItem({ className, ...props }: RadioPrimitive.Root.Props): import("react").JSX.Element;
|
|
4
|
+
declare function RadioGroupItem({ children, className, ...props }: RadioPrimitive.Root.Props): import("react").JSX.Element;
|
|
5
5
|
export { RadioGroup, RadioGroupItem };
|
|
6
6
|
//# sourceMappingURL=radio-group.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../src/components/radio-group.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAI/E,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,CAAC,KAAK,+BAQrE;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,+
|
|
1
|
+
{"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../src/components/radio-group.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAI/E,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,CAAC,KAAK,+BAQrE;AAED,iBAAS,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,+BAoBnF;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -5,7 +5,7 @@ import { cn } from "../lib/utils.js";
|
|
|
5
5
|
function RadioGroup({ className, ...props }) {
|
|
6
6
|
return (_jsx(RadioGroupPrimitive, { "data-slot": "radio-group", className: cn("grid w-full gap-2", className), ...props }));
|
|
7
7
|
}
|
|
8
|
-
function RadioGroupItem({ className, ...props }) {
|
|
9
|
-
return (_jsx(RadioPrimitive.Root, { "data-slot": "radio-group-item", className: cn("group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none after:absolute after:top-1/2 after:left-1/2 after:size-touch-target after:-translate-x-1/2 after:-translate-y-1/2 focus-visible:border-ring focus-visible:ring-[length:var(--ring-width-focus)] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[length:var(--ring-width-focus)] aria-invalid:ring-destructive aria-invalid:aria-checked:border-primary data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground [@media(hover:hover)_and_(pointer:fine)]:after:hidden", className), ...props, children: _jsx(RadioPrimitive.Indicator, { "data-slot": "radio-group-indicator", className: "flex size-4 items-center justify-center", children: _jsx("span", { className: "absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary-foreground" }) }) }));
|
|
8
|
+
function RadioGroupItem({ children, className, ...props }) {
|
|
9
|
+
return (_jsx(RadioPrimitive.Root, { "data-slot": "radio-group-item", className: cn("group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none after:absolute after:top-1/2 after:left-1/2 after:size-touch-target after:-translate-x-1/2 after:-translate-y-1/2 focus-visible:border-ring focus-visible:ring-[length:var(--ring-width-focus)] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[length:var(--ring-width-focus)] aria-invalid:ring-destructive aria-invalid:aria-checked:border-primary data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground [@media(hover:hover)_and_(pointer:fine)]:after:hidden", className), ...props, children: children ?? (_jsx(RadioPrimitive.Indicator, { "data-slot": "radio-group-indicator", className: "flex size-4 items-center justify-center", children: _jsx("span", { className: "absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary-foreground" }) })) }));
|
|
10
10
|
}
|
|
11
11
|
export { RadioGroup, RadioGroupItem };
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { RadioGroup } from "./radio-group";
|
|
3
3
|
import { isThemeMode, themeModes, type ThemeMode } from "../lib/theme-mode";
|
|
4
4
|
export { isThemeMode, themeModes };
|
|
5
5
|
export type { ThemeMode };
|
|
6
6
|
export type ThemeModeOptionLabels = Record<ThemeMode, string>;
|
|
7
|
-
export type
|
|
7
|
+
export type ThemeModeOption = {
|
|
8
|
+
Icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
|
|
9
|
+
label: string;
|
|
10
|
+
mode: ThemeMode;
|
|
11
|
+
selected: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type ThemeModeSwitcherProps = Omit<React.ComponentProps<typeof RadioGroup>, "children" | "defaultValue" | "onValueChange" | "value"> & {
|
|
8
14
|
"aria-label": string;
|
|
9
15
|
compact?: boolean;
|
|
10
16
|
itemClassName?: string;
|
|
11
17
|
labels: ThemeModeOptionLabels;
|
|
12
18
|
onValueChange: (value: ThemeMode) => void;
|
|
19
|
+
renderItem?: (option: ThemeModeOption) => React.ReactNode;
|
|
13
20
|
value: ThemeMode;
|
|
14
21
|
};
|
|
15
|
-
declare function ThemeModeSwitcher({ "aria-label": ariaLabel, className, compact, disabled, itemClassName, labels, onValueChange, value, ...props }: ThemeModeSwitcherProps): React.JSX.Element;
|
|
22
|
+
declare function ThemeModeSwitcher({ "aria-label": ariaLabel, className, compact, disabled, itemClassName, labels, onValueChange, renderItem, value, ...props }: ThemeModeSwitcherProps): React.JSX.Element;
|
|
16
23
|
export { ThemeModeSwitcher };
|
|
17
24
|
//# sourceMappingURL=theme-mode-switcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-mode-switcher.d.ts","sourceRoot":"","sources":["../../src/components/theme-mode-switcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"theme-mode-switcher.d.ts","sourceRoot":"","sources":["../../src/components/theme-mode-switcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,UAAU,EAAkB,MAAM,0BAA0B,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAE9D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,KAAK,CAAC,cAAc,CAAC,OAAO,UAAU,CAAC,EACvC,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,OAAO,CACxD,GAAG;IACF,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1D,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAQF,iBAAS,iBAAiB,CAAC,EACzB,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,OAAe,EACf,QAAQ,EACR,aAAa,EACb,MAAM,EACN,aAAa,EACb,UAAU,EACV,KAAK,EACL,GAAG,KAAK,EACT,EAAE,sBAAsB,qBAkDxB;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
|
|
4
|
-
import {
|
|
4
|
+
import { RadioGroup, RadioGroupItem } from "./radio-group.js";
|
|
5
|
+
import { toggleVariants } from "./toggle.js";
|
|
5
6
|
import { isThemeMode, themeModes } from "../lib/theme-mode.js";
|
|
6
7
|
import { cn } from "../lib/utils.js";
|
|
7
8
|
export { isThemeMode, themeModes };
|
|
@@ -10,16 +11,22 @@ const themeModeIcons = {
|
|
|
10
11
|
dark: MoonIcon,
|
|
11
12
|
system: MonitorIcon,
|
|
12
13
|
};
|
|
13
|
-
function ThemeModeSwitcher({ "aria-label": ariaLabel, className, compact = false, disabled, itemClassName, labels, onValueChange, value, ...props }) {
|
|
14
|
-
return (_jsx(
|
|
15
|
-
const nextMode = nextValue[0];
|
|
14
|
+
function ThemeModeSwitcher({ "aria-label": ariaLabel, className, compact = false, disabled, itemClassName, labels, onValueChange, renderItem, value, ...props }) {
|
|
15
|
+
return (_jsx(RadioGroup, { "aria-label": ariaLabel, className: cn("max-w-full", className), disabled: disabled, onValueChange: (nextMode) => {
|
|
16
16
|
if (isThemeMode(nextMode)) {
|
|
17
17
|
onValueChange(nextMode);
|
|
18
18
|
}
|
|
19
|
-
}, value:
|
|
19
|
+
}, value: value, ...props, children: themeModes.map((mode) => {
|
|
20
20
|
const Icon = themeModeIcons[mode];
|
|
21
21
|
const label = labels[mode];
|
|
22
|
-
|
|
22
|
+
const selected = value === mode;
|
|
23
|
+
return (_jsx(RadioGroupItem, { "aria-label": label, className: cn(toggleVariants({ variant: "outline" }),
|
|
24
|
+
// The selected tile takes the muted interaction surface the
|
|
25
|
+
// toggle uses for its own on-state, so it takes that surface's
|
|
26
|
+
// foreground with it. Left on the radio primitive's on-primary
|
|
27
|
+
// foreground, the selected label reads white on near-white in
|
|
28
|
+
// light and black on black in dark.
|
|
29
|
+
"aspect-auto w-auto min-w-0 gap-1.5 px-2.5 data-checked:bg-muted data-checked:text-foreground", compact ? "h-8 text-xs" : "h-9", itemClassName), disabled: disabled, value: mode, children: renderItem ? (renderItem({ Icon, label, mode, selected })) : (_jsxs(_Fragment, { children: [_jsx(Icon, { "aria-hidden": "true", "data-icon": true }), _jsx("span", { className: "min-w-0 truncate", children: label })] })) }, mode));
|
|
23
30
|
}) }));
|
|
24
31
|
}
|
|
25
32
|
export { ThemeModeSwitcher };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
declare function UseCaseBento({ kicker, title, body, proof, proofLabel, media, mediaClassName, demo, demoLabels, className, ...props }: React.ComponentProps<"article"> & {
|
|
2
|
+
declare function UseCaseBento({ kicker, title, body, proof, proofLabel, media, mediaClassName, demo, className, ...props }: React.ComponentProps<"article"> & {
|
|
4
3
|
kicker: string;
|
|
5
4
|
title: string;
|
|
6
5
|
body: string;
|
|
@@ -8,8 +7,7 @@ declare function UseCaseBento({ kicker, title, body, proof, proofLabel, media, m
|
|
|
8
7
|
proofLabel?: string;
|
|
9
8
|
media: React.ReactNode;
|
|
10
9
|
mediaClassName?: string;
|
|
11
|
-
demo:
|
|
12
|
-
demoLabels?: Partial<DemoSurfaceLabels>;
|
|
10
|
+
demo: React.ReactNode;
|
|
13
11
|
}): React.JSX.Element;
|
|
14
12
|
export { UseCaseBento };
|
|
15
13
|
//# sourceMappingURL=use-case-bento.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-case-bento.d.ts","sourceRoot":"","sources":["../../src/components/use-case-bento.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"use-case-bento.d.ts","sourceRoot":"","sources":["../../src/components/use-case-bento.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,iBAAS,YAAY,CAAC,EACpB,MAAM,EACN,KAAK,EACL,IAAI,EACJ,KAAK,EACL,UAAmC,EACnC,KAAK,EACL,cAAc,EACd,IAAI,EACJ,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;CACvB,qBAmCA;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
3
|
import { Bento, BentoCopy, BentoDemo, BentoItem, BentoMedia } from "./bento.js";
|
|
4
|
-
import { DemoSurface } from "./demo-surface.js";
|
|
5
4
|
import { MediaMount } from "./media-mount.js";
|
|
6
|
-
function UseCaseBento({ kicker, title, body, proof, proofLabel = "What the agent shows", media, mediaClassName, demo,
|
|
7
|
-
return (_jsx("article", { "data-slot": "use-case-bento", className: className, ...props, children: _jsxs(Bento, { height: "primary", children: [_jsxs(BentoItem, { span: 3, children: [_jsx("div", { className: "nc-artifact-surface pointer-events-none absolute inset-0 border-0 p-0 opacity-60", "aria-hidden": "true" }), _jsxs(BentoCopy, { children: [_jsx("p", { className: "nc-type-caption-mono text-muted-foreground uppercase", children: kicker }), _jsx("h3", { className: "nc-type-title-md text-foreground", children: title }), _jsx("p", { className: "nc-type-body-sm text-[var(--nc-body)]", children: body }), _jsxs("div", { className: "grid gap-2 border-t border-border pt-4", children: [_jsx("p", { className: "nc-type-caption-mono text-muted-foreground uppercase", children: proofLabel }), _jsx("p", { className: "nc-type-body-sm text-foreground", children: proof })] })] })] }), _jsx(BentoItem, { span: 5, flush: true, stretch: true, className: "min-h-[var(--nc-h-bento-primary)]", children: _jsx(BentoMedia, { children: _jsx(MediaMount, { ratio: "auto", className: cn("!h-full min-h-[var(--nc-h-bento-primary)]", mediaClassName), children: media }) }) }), _jsx(BentoItem, { span: 4, surface: "soft", stretch: true, className: "min-h-0 p-[var(--nc-sm)]", children: _jsx(BentoDemo, { children:
|
|
5
|
+
function UseCaseBento({ kicker, title, body, proof, proofLabel = "What the agent shows", media, mediaClassName, demo, className, ...props }) {
|
|
6
|
+
return (_jsx("article", { "data-slot": "use-case-bento", className: className, ...props, children: _jsxs(Bento, { height: "primary", children: [_jsxs(BentoItem, { span: 3, children: [_jsx("div", { className: "nc-artifact-surface pointer-events-none absolute inset-0 border-0 p-0 opacity-60", "aria-hidden": "true" }), _jsxs(BentoCopy, { children: [_jsx("p", { className: "nc-type-caption-mono text-muted-foreground uppercase", children: kicker }), _jsx("h3", { className: "nc-type-title-md text-foreground", children: title }), _jsx("p", { className: "nc-type-body-sm text-[var(--nc-body)]", children: body }), _jsxs("div", { className: "grid gap-2 border-t border-border pt-4", children: [_jsx("p", { className: "nc-type-caption-mono text-muted-foreground uppercase", children: proofLabel }), _jsx("p", { className: "nc-type-body-sm text-foreground", children: proof })] })] })] }), _jsx(BentoItem, { span: 5, flush: true, stretch: true, className: "min-h-[var(--nc-h-bento-primary)]", children: _jsx(BentoMedia, { children: _jsx(MediaMount, { ratio: "auto", className: cn("!h-full min-h-[var(--nc-h-bento-primary)]", mediaClassName), children: media }) }) }), _jsx(BentoItem, { span: 4, surface: "soft", stretch: true, className: "min-h-0 p-[var(--nc-sm)]", children: _jsx(BentoDemo, { children: demo }) })] }) }));
|
|
8
7
|
}
|
|
9
8
|
export { UseCaseBento };
|