@adea-ai/ui 0.61.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -6
- package/dist/LICENSE +201 -0
- package/dist/NOTICE +50 -0
- package/dist/components/composites/account-menu/index.js +2 -0
- package/dist/components/composites/list-row/index.js +2 -0
- package/dist/components/composites/settings/index.js +2 -0
- package/dist/components/composites/stat/index.js +2 -0
- package/dist/components/composites/update-dialog/index.js +2 -0
- package/dist/components/composites/workspace-mark/index.js +2 -0
- package/dist/components/conversation/index.js +6 -0
- package/dist/components/layout/app-shell/index.js +2 -0
- package/dist/components/layout/page/index.js +2 -0
- package/dist/components/layout/panel/index.js +2 -0
- package/dist/components/layout/side-rail/index.js +3 -0
- package/dist/components/layout/sidebar-nav/index.js +2 -0
- package/dist/components/layout/status-bar/index.js +2 -0
- package/dist/components/layout/top-bar/index.js +2 -0
- package/dist/components/motion/index.js +2 -2
- package/dist/components/theme/index.js +5 -0
- package/dist/components/ui/accordion/index.js +2 -0
- package/dist/components/ui/alert/index.js +2 -0
- package/dist/components/ui/alert-dialog/index.js +2 -0
- package/dist/components/ui/aspect-ratio/index.js +2 -0
- package/dist/components/ui/avatar/index.js +2 -0
- package/dist/components/ui/badge/index.js +2 -0
- package/dist/components/ui/board/index.js +2 -0
- package/dist/components/ui/breadcrumb/index.js +2 -0
- package/dist/components/ui/button/index.js +2 -0
- package/dist/components/ui/button-group/index.js +2 -0
- package/dist/components/ui/calendar/index.js +2 -0
- package/dist/components/ui/card/index.js +2 -0
- package/dist/components/ui/carousel/index.js +2 -0
- package/dist/components/ui/chart/index.js +2 -0
- package/dist/components/ui/checkbox/index.js +2 -0
- package/dist/components/ui/code-block/index.js +2 -0
- package/dist/components/ui/collapsible/index.js +2 -0
- package/dist/components/ui/combobox/index.js +2 -0
- package/dist/components/ui/command/index.js +2 -0
- package/dist/components/ui/context-menu/index.js +2 -0
- package/dist/components/ui/detail-panel/index.js +2 -0
- package/dist/components/ui/dialog/index.js +2 -0
- package/dist/components/ui/diff-block/index.js +2 -0
- package/dist/components/ui/drawer/index.js +2 -0
- package/dist/components/ui/dropdown-menu/index.js +2 -0
- package/dist/components/ui/empty/index.js +2 -0
- package/dist/components/ui/entity-icon/index.js +2 -0
- package/dist/components/ui/field/index.js +2 -0
- package/dist/components/ui/hover-card/index.js +2 -0
- package/dist/components/ui/input/index.js +2 -0
- package/dist/components/ui/input-group/index.js +2 -0
- package/dist/components/ui/input-otp/index.js +2 -0
- package/dist/components/ui/item/index.js +2 -0
- package/dist/components/ui/kbd/index.js +2 -0
- package/dist/components/ui/label/index.js +2 -0
- package/dist/components/ui/menubar/index.js +2 -0
- package/dist/components/ui/modal-dialog/index.js +2 -0
- package/dist/components/ui/navigation-menu/index.js +2 -0
- package/dist/components/ui/pagination/index.js +2 -0
- package/dist/components/ui/popover/index.js +2 -0
- package/dist/components/ui/progress/index.js +2 -0
- package/dist/components/ui/radio-group/index.js +2 -0
- package/dist/components/ui/resizable/index.js +2 -0
- package/dist/components/ui/scroll-area/index.js +2 -0
- package/dist/components/ui/select/index.js +2 -0
- package/dist/components/ui/separator/index.js +2 -0
- package/dist/components/ui/sheet/index.js +2 -0
- package/dist/components/ui/skeleton/index.js +2 -0
- package/dist/components/ui/slider/index.js +2 -0
- package/dist/components/ui/spinner/index.js +2 -0
- package/dist/components/ui/status-chip/index.js +2 -0
- package/dist/components/ui/switch/index.js +2 -0
- package/dist/components/ui/table/index.js +2 -0
- package/dist/components/ui/tabs/index.js +2 -0
- package/dist/components/ui/textarea/index.js +2 -0
- package/dist/components/ui/toast/index.js +2 -0
- package/dist/components/ui/toggle/index.js +2 -0
- package/dist/components/ui/toggle-group/index.js +2 -0
- package/dist/components/ui/tooltip/index.js +2 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/r/accordion.json +3 -1
- package/dist/r/account-menu.json +2 -1
- package/dist/r/alert-dialog.json +3 -1
- package/dist/r/alert.json +3 -1
- package/dist/r/app-shell.json +3 -1
- package/dist/r/aspect-ratio.json +3 -1
- package/dist/r/avatar.json +3 -1
- package/dist/r/badge.json +3 -1
- package/dist/r/board.json +3 -1
- package/dist/r/breadcrumb.json +3 -1
- package/dist/r/button-group.json +2 -1
- package/dist/r/button.json +3 -1
- package/dist/r/calendar.json +2 -1
- package/dist/r/card.json +3 -1
- package/dist/r/carousel.json +2 -1
- package/dist/r/chart.json +3 -1
- package/dist/r/checkbox.json +3 -1
- package/dist/r/code-block.json +2 -1
- package/dist/r/collapsible.json +3 -1
- package/dist/r/combobox.json +3 -1
- package/dist/r/command.json +3 -1
- package/dist/r/context-menu.json +3 -1
- package/dist/r/conversation.json +2 -1
- package/dist/r/detail-panel.json +2 -1
- package/dist/r/dialog.json +3 -1
- package/dist/r/diff-block.json +3 -1
- package/dist/r/drawer.json +3 -1
- package/dist/r/dropdown-menu.json +3 -1
- package/dist/r/empty.json +3 -1
- package/dist/r/entity-icon.json +3 -1
- package/dist/r/field.json +3 -1
- package/dist/r/hover-card.json +3 -1
- package/dist/r/input-group.json +3 -1
- package/dist/r/input-otp.json +3 -1
- package/dist/r/input.json +3 -1
- package/dist/r/item.json +3 -1
- package/dist/r/kbd.json +3 -1
- package/dist/r/label.json +3 -1
- package/dist/r/lib.json +50 -0
- package/dist/r/list-row.json +3 -1
- package/dist/r/menubar.json +3 -1
- package/dist/r/modal-dialog.json +2 -1
- package/dist/r/motion.json +22 -0
- package/dist/r/navigation-menu.json +3 -1
- package/dist/r/page.json +3 -1
- package/dist/r/pagination.json +3 -1
- package/dist/r/panel.json +3 -1
- package/dist/r/popover.json +3 -1
- package/dist/r/progress.json +3 -1
- package/dist/r/radio-group.json +3 -1
- package/dist/r/registry.json +320 -73
- package/dist/r/resizable.json +3 -1
- package/dist/r/scroll-area.json +3 -1
- package/dist/r/select.json +3 -1
- package/dist/r/separator.json +3 -1
- package/dist/r/settings.json +3 -1
- package/dist/r/sheet.json +2 -1
- package/dist/r/side-rail.json +3 -1
- package/dist/r/sidebar-nav.json +3 -1
- package/dist/r/skeleton.json +3 -1
- package/dist/r/slider.json +3 -1
- package/dist/r/spinner.json +3 -1
- package/dist/r/src/components/composites/account-menu/account-menu.tsx +150 -0
- package/dist/r/src/components/composites/account-menu/index.ts +1 -0
- package/dist/r/src/components/composites/list-row/index.ts +1 -0
- package/dist/r/src/components/composites/list-row/list-row.tsx +116 -0
- package/dist/r/src/components/composites/settings/index.ts +1 -0
- package/dist/r/src/components/composites/settings/settings.tsx +142 -0
- package/dist/r/src/components/composites/stat/index.ts +9 -0
- package/dist/r/src/components/composites/stat/stat.tsx +155 -0
- package/dist/r/src/components/composites/update-dialog/index.ts +7 -0
- package/dist/r/src/components/composites/update-dialog/update-dialog.tsx +529 -0
- package/dist/r/src/components/composites/workspace-mark/index.ts +1 -0
- package/dist/r/src/components/composites/workspace-mark/workspace-mark.tsx +72 -0
- package/dist/r/src/components/conversation/conversation-avatar.tsx +60 -0
- package/dist/r/src/components/conversation/conversation-surface.tsx +107 -0
- package/dist/r/src/components/conversation/index.ts +25 -0
- package/dist/r/src/components/conversation/message-composer.tsx +239 -0
- package/dist/r/src/components/conversation/message-row.tsx +387 -0
- package/dist/r/src/components/conversation/thread-panel.tsx +141 -0
- package/dist/r/src/components/layout/app-shell/app-shell.tsx +92 -0
- package/dist/r/src/components/layout/app-shell/index.ts +1 -0
- package/dist/r/src/components/layout/page/index.ts +9 -0
- package/dist/r/src/components/layout/page/page.tsx +122 -0
- package/dist/r/src/components/layout/panel/index.ts +12 -0
- package/dist/r/src/components/layout/panel/panel.tsx +166 -0
- package/dist/r/src/components/layout/side-rail/index.ts +12 -0
- package/dist/r/src/components/layout/side-rail/side-rail-context.ts +42 -0
- package/dist/r/src/components/layout/side-rail/side-rail.tsx +405 -0
- package/dist/r/src/components/layout/sidebar-nav/index.ts +14 -0
- package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +244 -0
- package/dist/r/src/components/layout/status-bar/index.ts +1 -0
- package/dist/r/src/components/layout/status-bar/status-bar.tsx +73 -0
- package/dist/r/src/components/layout/top-bar/index.ts +10 -0
- package/dist/r/src/components/layout/top-bar/top-bar.tsx +166 -0
- package/dist/r/src/components/motion/index.ts +2 -0
- package/dist/r/src/components/motion/presence.tsx +32 -0
- package/dist/r/src/components/theme/appearance-panel.tsx +179 -0
- package/dist/r/src/components/theme/index.ts +22 -0
- package/dist/r/src/components/theme/theme-picker.tsx +174 -0
- package/dist/r/src/components/theme/theme-provider.tsx +309 -0
- package/dist/r/src/components/theme/theme-toggle.tsx +64 -0
- package/dist/r/src/components/ui/accordion/accordion.tsx +66 -0
- package/dist/r/src/components/ui/accordion/index.ts +1 -0
- package/dist/r/src/components/ui/alert/alert.tsx +95 -0
- package/dist/r/src/components/ui/alert/index.ts +1 -0
- package/dist/r/src/components/ui/alert-dialog/alert-dialog.tsx +176 -0
- package/dist/r/src/components/ui/alert-dialog/index.ts +13 -0
- package/dist/r/src/components/ui/aspect-ratio/aspect-ratio.tsx +38 -0
- package/dist/r/src/components/ui/aspect-ratio/index.ts +1 -0
- package/dist/r/src/components/ui/avatar/avatar.tsx +114 -0
- package/dist/r/src/components/ui/avatar/index.ts +9 -0
- package/dist/r/src/components/ui/badge/badge.tsx +59 -0
- package/dist/r/src/components/ui/badge/index.ts +1 -0
- package/dist/r/src/components/ui/board/board.tsx +254 -0
- package/dist/r/src/components/ui/board/index.ts +10 -0
- package/dist/r/src/components/ui/breadcrumb/breadcrumb.tsx +117 -0
- package/dist/r/src/components/ui/breadcrumb/index.ts +9 -0
- package/dist/r/src/components/ui/button/button.tsx +89 -0
- package/dist/r/src/components/ui/button/index.ts +1 -0
- package/dist/r/src/components/ui/button-group/button-group.tsx +92 -0
- package/dist/r/src/components/ui/button-group/index.ts +6 -0
- package/dist/r/src/components/ui/calendar/calendar.tsx +277 -0
- package/dist/r/src/components/ui/calendar/index.ts +1 -0
- package/dist/r/src/components/ui/card/card.tsx +82 -0
- package/dist/r/src/components/ui/card/index.ts +10 -0
- package/dist/r/src/components/ui/carousel/carousel.tsx +209 -0
- package/dist/r/src/components/ui/carousel/index.ts +1 -0
- package/dist/r/src/components/ui/chart/chart.tsx +413 -0
- package/dist/r/src/components/ui/chart/index.ts +17 -0
- package/dist/r/src/components/ui/checkbox/checkbox.tsx +99 -0
- package/dist/r/src/components/ui/checkbox/index.ts +1 -0
- package/dist/r/src/components/ui/code-block/code-block.tsx +238 -0
- package/dist/r/src/components/ui/code-block/index.ts +1 -0
- package/dist/r/src/components/ui/collapsible/collapsible.tsx +54 -0
- package/dist/r/src/components/ui/collapsible/index.ts +1 -0
- package/dist/r/src/components/ui/combobox/combobox.tsx +142 -0
- package/dist/r/src/components/ui/combobox/index.ts +10 -0
- package/dist/r/src/components/ui/command/command.tsx +214 -0
- package/dist/r/src/components/ui/command/index.ts +12 -0
- package/dist/r/src/components/ui/context-menu/context-menu.tsx +163 -0
- package/dist/r/src/components/ui/context-menu/index.ts +15 -0
- package/dist/r/src/components/ui/detail-panel/detail-panel.tsx +161 -0
- package/dist/r/src/components/ui/detail-panel/index.ts +9 -0
- package/dist/r/src/components/ui/dialog/dialog.tsx +138 -0
- package/dist/r/src/components/ui/dialog/index.ts +14 -0
- package/dist/r/src/components/ui/diff-block/diff-block.tsx +286 -0
- package/dist/r/src/components/ui/diff-block/index.ts +11 -0
- package/dist/r/src/components/ui/drawer/drawer.tsx +144 -0
- package/dist/r/src/components/ui/drawer/index.ts +13 -0
- package/dist/r/src/components/ui/dropdown-menu/dropdown-menu.tsx +203 -0
- package/dist/r/src/components/ui/dropdown-menu/index.ts +18 -0
- package/dist/r/src/components/ui/empty/empty.tsx +104 -0
- package/dist/r/src/components/ui/empty/index.ts +10 -0
- package/dist/r/src/components/ui/entity-icon/entity-icon.tsx +154 -0
- package/dist/r/src/components/ui/entity-icon/index.ts +1 -0
- package/dist/r/src/components/ui/field/field.tsx +131 -0
- package/dist/r/src/components/ui/field/index.ts +11 -0
- package/dist/r/src/components/ui/hover-card/hover-card.tsx +48 -0
- package/dist/r/src/components/ui/hover-card/index.ts +1 -0
- package/dist/r/src/components/ui/input/index.ts +1 -0
- package/dist/r/src/components/ui/input/input.tsx +41 -0
- package/dist/r/src/components/ui/input-group/index.ts +8 -0
- package/dist/r/src/components/ui/input-group/input-group.tsx +111 -0
- package/dist/r/src/components/ui/input-otp/index.ts +1 -0
- package/dist/r/src/components/ui/input-otp/input-otp.tsx +108 -0
- package/dist/r/src/components/ui/item/index.ts +10 -0
- package/dist/r/src/components/ui/item/item.tsx +146 -0
- package/dist/r/src/components/ui/kbd/index.ts +1 -0
- package/dist/r/src/components/ui/kbd/kbd.tsx +42 -0
- package/dist/r/src/components/ui/label/index.ts +1 -0
- package/dist/r/src/components/ui/label/label.tsx +36 -0
- package/dist/r/src/components/ui/menubar/index.ts +16 -0
- package/dist/r/src/components/ui/menubar/menubar.tsx +190 -0
- package/dist/r/src/components/ui/modal-dialog/index.ts +1 -0
- package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +95 -0
- package/dist/r/src/components/ui/navigation-menu/index.ts +13 -0
- package/dist/r/src/components/ui/navigation-menu/navigation-menu.tsx +229 -0
- package/dist/r/src/components/ui/pagination/index.ts +8 -0
- package/dist/r/src/components/ui/pagination/pagination.tsx +144 -0
- package/dist/r/src/components/ui/popover/index.ts +10 -0
- package/dist/r/src/components/ui/popover/popover.tsx +81 -0
- package/dist/r/src/components/ui/progress/index.ts +1 -0
- package/dist/r/src/components/ui/progress/progress.tsx +67 -0
- package/dist/r/src/components/ui/radio-group/index.ts +1 -0
- package/dist/r/src/components/ui/radio-group/radio-group.tsx +78 -0
- package/dist/r/src/components/ui/resizable/index.ts +6 -0
- package/dist/r/src/components/ui/resizable/resizable.tsx +74 -0
- package/dist/r/src/components/ui/scroll-area/index.ts +1 -0
- package/dist/r/src/components/ui/scroll-area/scroll-area.tsx +66 -0
- package/dist/r/src/components/ui/select/index.ts +11 -0
- package/dist/r/src/components/ui/select/select.tsx +188 -0
- package/dist/r/src/components/ui/separator/index.ts +1 -0
- package/dist/r/src/components/ui/separator/separator.tsx +40 -0
- package/dist/r/src/components/ui/sheet/index.ts +13 -0
- package/dist/r/src/components/ui/sheet/sheet.tsx +132 -0
- package/dist/r/src/components/ui/skeleton/index.ts +1 -0
- package/dist/r/src/components/ui/skeleton/skeleton.tsx +28 -0
- package/dist/r/src/components/ui/slider/index.ts +1 -0
- package/dist/r/src/components/ui/slider/slider.tsx +81 -0
- package/dist/r/src/components/ui/spinner/index.ts +1 -0
- package/dist/r/src/components/ui/spinner/spinner.tsx +58 -0
- package/dist/r/src/components/ui/status-chip/index.ts +8 -0
- package/dist/r/src/components/ui/status-chip/status-chip.tsx +142 -0
- package/dist/r/src/components/ui/switch/index.ts +1 -0
- package/dist/r/src/components/ui/switch/switch.tsx +100 -0
- package/dist/r/src/components/ui/table/index.ts +11 -0
- package/dist/r/src/components/ui/table/table.tsx +125 -0
- package/dist/r/src/components/ui/tabs/index.ts +8 -0
- package/dist/r/src/components/ui/tabs/tabs.tsx +77 -0
- package/dist/r/src/components/ui/textarea/index.ts +1 -0
- package/dist/r/src/components/ui/textarea/textarea.tsx +36 -0
- package/dist/r/src/components/ui/toast/index.ts +1 -0
- package/dist/r/src/components/ui/toast/toast.tsx +220 -0
- package/dist/r/src/components/ui/toggle/index.ts +1 -0
- package/dist/r/src/components/ui/toggle/toggle.tsx +60 -0
- package/dist/r/src/components/ui/toggle-group/index.ts +6 -0
- package/dist/r/src/components/ui/toggle-group/toggle-group.tsx +66 -0
- package/dist/r/src/components/ui/tooltip/index.ts +9 -0
- package/dist/r/src/components/ui/tooltip/tooltip.tsx +102 -0
- package/dist/r/src/lib/keyed-rows.ts +68 -0
- package/dist/r/src/lib/overlay.ts +70 -0
- package/dist/r/src/lib/themes.ts +490 -0
- package/dist/r/src/lib/tokens.ts +688 -0
- package/dist/r/src/lib/utils.ts +76 -0
- package/dist/r/src/lib/variants.ts +62 -0
- package/dist/r/src/lib/version-notes.ts +65 -0
- package/dist/r/src/styles/base.css +644 -0
- package/dist/r/src/styles/fonts.css +26 -0
- package/dist/r/src/styles/globals.css +18 -0
- package/dist/r/src/styles/theme.css +864 -0
- package/dist/r/stat.json +3 -1
- package/dist/r/status-bar.json +3 -1
- package/dist/r/status-chip.json +2 -1
- package/dist/r/switch.json +3 -1
- package/dist/r/table.json +3 -1
- package/dist/r/tabs.json +3 -1
- package/dist/r/textarea.json +3 -1
- package/dist/r/theming.json +42 -0
- package/dist/r/toast.json +3 -1
- package/dist/r/toggle-group.json +2 -1
- package/dist/r/toggle.json +3 -1
- package/dist/r/tooltip.json +3 -1
- package/dist/r/top-bar.json +3 -1
- package/dist/r/update-dialog.json +2 -1
- package/dist/r/workspace-mark.json +2 -1
- package/package.json +10 -9
- package/registry.json +320 -73
- package/src/index.ts +2 -4
- package/dist/components/ui/diff-block/diff-block.test.d.ts +0 -2
- package/dist/components/ui/diff-block/diff-block.test.d.ts.map +0 -1
- package/dist/lib/keyed-rows.test.d.ts +0 -2
- package/dist/lib/keyed-rows.test.d.ts.map +0 -1
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The theme registry, now a bridge.
|
|
3
|
+
*
|
|
4
|
+
* The catalogue itself lives in `@adea-ai/themes`. This module is what is left in
|
|
5
|
+
* the design system: the translation between the catalogue's **canonical** role
|
|
6
|
+
* names and the **shadcn** vocabulary every component here is written against, plus
|
|
7
|
+
* the handful of custom properties this system declares that are presentations of
|
|
8
|
+
* data the catalogue already holds — the `--terminal-*` ramp, the `--editor-*` ramp,
|
|
9
|
+
* and `--chrome`.
|
|
10
|
+
*
|
|
11
|
+
* ## Why it is a bridge and not a copy
|
|
12
|
+
*
|
|
13
|
+
* This file used to hold thirteen themes as hand-written hex literal tables, with its
|
|
14
|
+
* own contrast validator, its own terminal and editor palettes, and its own
|
|
15
|
+
* provenance records. That is a lot of surface to maintain for one consumer of a
|
|
16
|
+
* palette, and it meant every product that wanted the same themes — Adea, Cortana —
|
|
17
|
+
* either imported this package or wrote its own. The catalogue moved out so that
|
|
18
|
+
* there is one answer to "what is Catppuccin Mocha", and this file is the part that
|
|
19
|
+
* genuinely belongs to the design system.
|
|
20
|
+
*
|
|
21
|
+
* It is deliberately thin. If you are looking for a colour, it is not here: see
|
|
22
|
+
* `@adea-ai/themes`, whose README explains how the values are produced and whose
|
|
23
|
+
* `NOTICE` records where every palette came from.
|
|
24
|
+
*
|
|
25
|
+
* ## The mapping, and the entry that is not a rename
|
|
26
|
+
*
|
|
27
|
+
* {@link ROLE_FOR} maps canonical roles onto this system's variable vocabulary. One
|
|
28
|
+
* entry will trip a reader: the catalogue's `accent` becomes this system's
|
|
29
|
+
* `primary`, because in the shadcn vocabulary `--primary` is the action colour — the
|
|
30
|
+
* fill of a primary button, the thing a focus ring is drawn in — while `--accent` is
|
|
31
|
+
* a low-contrast hover wash. The catalogue's `accent` is the former, so it goes to
|
|
32
|
+
* `--primary`, and `--accent` is filled from `surfaceHover`, which is what shadcn
|
|
33
|
+
* components actually use it for.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import {
|
|
37
|
+
ACCENTS,
|
|
38
|
+
accentRoles,
|
|
39
|
+
chartSeries,
|
|
40
|
+
getAccent,
|
|
41
|
+
hasTheme,
|
|
42
|
+
statusForeground,
|
|
43
|
+
primaryHover,
|
|
44
|
+
primarySubtleCss,
|
|
45
|
+
syntaxRoles,
|
|
46
|
+
themes as catalogue,
|
|
47
|
+
themesByAppearance,
|
|
48
|
+
validateCatalogue,
|
|
49
|
+
type AdeaThemeRecord,
|
|
50
|
+
type ContrastFinding,
|
|
51
|
+
} from '@adea-ai/themes'
|
|
52
|
+
|
|
53
|
+
export type ThemeAppearance = 'light' | 'dark'
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The surface and text roles, in shadcn's vocabulary.
|
|
57
|
+
*
|
|
58
|
+
* Named to match the components below, which is why they differ from the
|
|
59
|
+
* catalogue's: these are this system's variable names, and renaming them would mean
|
|
60
|
+
* touching every component in the library for no gain.
|
|
61
|
+
*/
|
|
62
|
+
export type ThemeColors = {
|
|
63
|
+
background: string
|
|
64
|
+
foreground: string
|
|
65
|
+
card: string
|
|
66
|
+
cardForeground: string
|
|
67
|
+
popover: string
|
|
68
|
+
popoverForeground: string
|
|
69
|
+
primary: string
|
|
70
|
+
primaryForeground: string
|
|
71
|
+
secondary: string
|
|
72
|
+
secondaryForeground: string
|
|
73
|
+
muted: string
|
|
74
|
+
mutedForeground: string
|
|
75
|
+
accent: string
|
|
76
|
+
accentForeground: string
|
|
77
|
+
destructive: string
|
|
78
|
+
destructiveForeground: string
|
|
79
|
+
success: string
|
|
80
|
+
warning: string
|
|
81
|
+
info: string
|
|
82
|
+
border: string
|
|
83
|
+
input: string
|
|
84
|
+
ring: string
|
|
85
|
+
sidebar: string
|
|
86
|
+
sidebarForeground: string
|
|
87
|
+
sidebarAccent: string
|
|
88
|
+
sidebarBorder: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** The sixteen ANSI colours a terminal needs, plus its cursor and selection. */
|
|
92
|
+
export type ThemeTerminalPalette = {
|
|
93
|
+
background: string
|
|
94
|
+
foreground: string
|
|
95
|
+
cursor: string
|
|
96
|
+
selection: string
|
|
97
|
+
black: string
|
|
98
|
+
red: string
|
|
99
|
+
green: string
|
|
100
|
+
yellow: string
|
|
101
|
+
blue: string
|
|
102
|
+
magenta: string
|
|
103
|
+
cyan: string
|
|
104
|
+
white: string
|
|
105
|
+
brightBlack: string
|
|
106
|
+
brightRed: string
|
|
107
|
+
brightGreen: string
|
|
108
|
+
brightYellow: string
|
|
109
|
+
brightBlue: string
|
|
110
|
+
brightMagenta: string
|
|
111
|
+
brightCyan: string
|
|
112
|
+
brightWhite: string
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** The syntax roles a code view needs. */
|
|
116
|
+
export type ThemeEditorPalette = {
|
|
117
|
+
keyword: string
|
|
118
|
+
string: string
|
|
119
|
+
number: string
|
|
120
|
+
comment: string
|
|
121
|
+
function: string
|
|
122
|
+
variable: string
|
|
123
|
+
type: string
|
|
124
|
+
tag: string
|
|
125
|
+
attribute: string
|
|
126
|
+
operator: string
|
|
127
|
+
heading: string
|
|
128
|
+
link: string
|
|
129
|
+
diffAdd: string
|
|
130
|
+
diffDelete: string
|
|
131
|
+
diffHunk: string
|
|
132
|
+
searchMatch: string
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Where a palette came from, and the terms it is used under. */
|
|
136
|
+
export type ThemeProvenance = {
|
|
137
|
+
/** The project or person the palette belongs to. */
|
|
138
|
+
source: string
|
|
139
|
+
url: string
|
|
140
|
+
/** An SPDX identifier. Every palette in this catalogue is permissive. */
|
|
141
|
+
license: string
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export type ThemeVariant = {
|
|
145
|
+
/** The `data-theme` value and the id a preference stores. */
|
|
146
|
+
id: string
|
|
147
|
+
/** Groups the variants that came from one project. */
|
|
148
|
+
family: string
|
|
149
|
+
familyLabel: string
|
|
150
|
+
label: string
|
|
151
|
+
appearance: ThemeAppearance
|
|
152
|
+
/** One line, shown in a picker. */
|
|
153
|
+
description: string
|
|
154
|
+
colors: ThemeColors
|
|
155
|
+
terminal: ThemeTerminalPalette
|
|
156
|
+
editor: ThemeEditorPalette
|
|
157
|
+
/** The categorical series, in order. */
|
|
158
|
+
chart: readonly string[]
|
|
159
|
+
provenance: ThemeProvenance
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Canonical role → this system's `ThemeColors` key.
|
|
164
|
+
*
|
|
165
|
+
* Read by {@link toVariant}. Every key of `ThemeColors` must appear, so a role added
|
|
166
|
+
* to this system fails the type check rather than silently resolving to `undefined`.
|
|
167
|
+
*/
|
|
168
|
+
const ROLE_FOR: Readonly<Record<keyof ThemeColors, keyof AdeaThemeRecord['colors']>> = {
|
|
169
|
+
background: 'background',
|
|
170
|
+
foreground: 'text',
|
|
171
|
+
card: 'surface',
|
|
172
|
+
cardForeground: 'text',
|
|
173
|
+
popover: 'surfaceElevated',
|
|
174
|
+
popoverForeground: 'text',
|
|
175
|
+
// Not a rename — see this module's header.
|
|
176
|
+
primary: 'accent',
|
|
177
|
+
primaryForeground: 'accentForeground',
|
|
178
|
+
// shadcn's `secondary` and `muted` are both the first surface rung used as a fill.
|
|
179
|
+
secondary: 'surface',
|
|
180
|
+
secondaryForeground: 'text',
|
|
181
|
+
muted: 'surface',
|
|
182
|
+
mutedForeground: 'textMuted',
|
|
183
|
+
// shadcn's `accent` is a hover wash, which is exactly `surfaceHover`.
|
|
184
|
+
accent: 'surfaceHover',
|
|
185
|
+
accentForeground: 'text',
|
|
186
|
+
destructive: 'error',
|
|
187
|
+
// Overwritten below from the measured pairing; nominal here so the table is total.
|
|
188
|
+
destructiveForeground: 'error',
|
|
189
|
+
success: 'success',
|
|
190
|
+
warning: 'warning',
|
|
191
|
+
info: 'info',
|
|
192
|
+
border: 'border',
|
|
193
|
+
input: 'border',
|
|
194
|
+
ring: 'accent',
|
|
195
|
+
sidebar: 'surface',
|
|
196
|
+
sidebarForeground: 'text',
|
|
197
|
+
sidebarAccent: 'surfaceHover',
|
|
198
|
+
sidebarBorder: 'border',
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Builds the design system's view of one catalogue entry. */
|
|
202
|
+
function toVariant(theme: AdeaThemeRecord): ThemeVariant {
|
|
203
|
+
const colors = {} as ThemeColors
|
|
204
|
+
for (const key of Object.keys(ROLE_FOR) as (keyof ThemeColors)[]) {
|
|
205
|
+
colors[key] = theme.colors[ROLE_FOR[key]]
|
|
206
|
+
}
|
|
207
|
+
// The label on a solid destructive fill is measured rather than mapped: on a bright
|
|
208
|
+
// red it is black and on a deep red it is white, and using the body text would put
|
|
209
|
+
// white on a mid-tone red at about 3:1.
|
|
210
|
+
colors.destructiveForeground = statusForeground(theme, 'error')
|
|
211
|
+
|
|
212
|
+
const syntax = syntaxRoles(theme)
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
id: theme.id,
|
|
216
|
+
family: theme.family,
|
|
217
|
+
familyLabel: theme.familyLabel,
|
|
218
|
+
label: theme.label,
|
|
219
|
+
appearance: theme.appearance,
|
|
220
|
+
description: theme.description,
|
|
221
|
+
colors,
|
|
222
|
+
terminal: {
|
|
223
|
+
// The embedded terminal uses the theme's own canvas rather than a palette of its
|
|
224
|
+
// own. The ANSI colours came from the palette that produced the canvas, so they
|
|
225
|
+
// were chosen against it; a terminal on a different background would be the one
|
|
226
|
+
// surface in the application not lit by the active theme.
|
|
227
|
+
background: theme.colors.background,
|
|
228
|
+
foreground: theme.colors.foreground,
|
|
229
|
+
cursor: theme.cursor,
|
|
230
|
+
selection: theme.selection,
|
|
231
|
+
...theme.ansi,
|
|
232
|
+
},
|
|
233
|
+
editor: {
|
|
234
|
+
keyword: syntax.keyword,
|
|
235
|
+
string: syntax.string,
|
|
236
|
+
number: syntax.number,
|
|
237
|
+
comment: syntax.comment,
|
|
238
|
+
function: syntax.function,
|
|
239
|
+
variable: syntax.variable,
|
|
240
|
+
type: syntax.type,
|
|
241
|
+
tag: syntax.tag,
|
|
242
|
+
attribute: syntax.attribute,
|
|
243
|
+
operator: syntax.operator,
|
|
244
|
+
heading: syntax.heading,
|
|
245
|
+
link: syntax.link,
|
|
246
|
+
diffAdd: syntax.diffAdd,
|
|
247
|
+
diffDelete: syntax.diffDelete,
|
|
248
|
+
diffHunk: syntax.diffHunk,
|
|
249
|
+
searchMatch: syntax.searchMatch,
|
|
250
|
+
},
|
|
251
|
+
chart: chartSeries(theme),
|
|
252
|
+
provenance: {
|
|
253
|
+
source: theme.provenance.project,
|
|
254
|
+
url: theme.provenance.url,
|
|
255
|
+
license: theme.provenance.license,
|
|
256
|
+
},
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** The catalogue, in catalogue order. */
|
|
261
|
+
export const builtinThemes: readonly ThemeVariant[] = Object.freeze(catalogue.map(toVariant))
|
|
262
|
+
|
|
263
|
+
export function themeById(id: string): ThemeVariant | undefined {
|
|
264
|
+
if (!hasTheme(id)) return undefined
|
|
265
|
+
return builtinThemes.find((theme) => theme.id === id)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** The variants of one appearance, which is what a picker for that mode shows. */
|
|
269
|
+
export function themesForAppearance(appearance: ThemeAppearance): readonly ThemeVariant[] {
|
|
270
|
+
const ids = new Set(themesByAppearance(appearance).map((theme) => theme.id))
|
|
271
|
+
return builtinThemes.filter((theme) => ids.has(theme.id))
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** The families in the catalogue, in catalogue order. */
|
|
275
|
+
export function themeFamilies(): { family: string; label: string; themes: ThemeVariant[] }[] {
|
|
276
|
+
const families = new Map<string, { family: string; label: string; themes: ThemeVariant[] }>()
|
|
277
|
+
for (const theme of builtinThemes) {
|
|
278
|
+
const entry = families.get(theme.family) ?? {
|
|
279
|
+
family: theme.family,
|
|
280
|
+
label: theme.familyLabel,
|
|
281
|
+
themes: [],
|
|
282
|
+
}
|
|
283
|
+
entry.themes.push(theme)
|
|
284
|
+
families.set(theme.family, entry)
|
|
285
|
+
}
|
|
286
|
+
return [...families.values()]
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** The accent presets, in the order a picker should show them. */
|
|
290
|
+
export const accents = ACCENTS
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* The properties an accent selection overrides, as CSS custom properties.
|
|
294
|
+
*
|
|
295
|
+
* ## Why this exists rather than relying on the `[data-accent]` blocks
|
|
296
|
+
*
|
|
297
|
+
* `theme.css` carries a `[data-accent='…']` block per preset, and those blocks are
|
|
298
|
+
* correct — but they are unreachable at runtime. `ThemeProvider` writes a theme's
|
|
299
|
+
* whole role set onto `<html>` as *inline* custom properties, and an inline
|
|
300
|
+
* declaration outranks any stylesheet selector regardless of specificity. The
|
|
301
|
+
* attribute was set, the rules existed, the values were right, and every one of the
|
|
302
|
+
* seven accents rendered as the same blue.
|
|
303
|
+
*
|
|
304
|
+
* The blocks are kept, because they are what styles the window between the document
|
|
305
|
+
* arriving and the provider mounting — which is the whole reason `themeScript`
|
|
306
|
+
* exists. But the authoritative value has to be applied by the same code that
|
|
307
|
+
* applies the theme, from the same source, or the two can drift again. So both the
|
|
308
|
+
* provider and the CSS generator call `accentRoles` out of `@adea-ai/themes`, and
|
|
309
|
+
* `tests/appearance-axes.test.ts` asserts the two agree value for value.
|
|
310
|
+
*
|
|
311
|
+
* Returns `undefined` for `theme` — the variant's own primary — and for an id the
|
|
312
|
+
* catalogue does not have, so a stale stored preference falls back to the theme
|
|
313
|
+
* rather than blanking the primary.
|
|
314
|
+
*/
|
|
315
|
+
export function accentVariables(
|
|
316
|
+
accentId: string,
|
|
317
|
+
appearance: ThemeAppearance
|
|
318
|
+
): Record<string, string> | undefined {
|
|
319
|
+
if (accentId === 'theme') return undefined
|
|
320
|
+
const preset = getAccent(accentId)
|
|
321
|
+
if (!preset) return undefined
|
|
322
|
+
|
|
323
|
+
const roles = accentRoles(preset, appearance)
|
|
324
|
+
return {
|
|
325
|
+
'--primary': roles.primary,
|
|
326
|
+
'--primary-foreground': roles.primaryForeground,
|
|
327
|
+
'--primary-hover': roles.primaryHover,
|
|
328
|
+
'--primary-subtle': roles.primarySubtle,
|
|
329
|
+
'--ring': roles.ring,
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* The roles a variant sets, as CSS custom properties.
|
|
335
|
+
*
|
|
336
|
+
* The one place that knows the mapping from a theme's roles to this system's variable
|
|
337
|
+
* names. A provider applies this; nothing else repeats it. The `--terminal-*` and
|
|
338
|
+
* `--editor-*` ramps are presentations of the catalogue's ANSI and syntax data rather
|
|
339
|
+
* than separate roles, which is why they are built here and not in the catalogue.
|
|
340
|
+
*/
|
|
341
|
+
export function themeCssVariables(theme: ThemeVariant): Record<string, string> {
|
|
342
|
+
const c = theme.colors
|
|
343
|
+
const t = theme.terminal
|
|
344
|
+
const e = theme.editor
|
|
345
|
+
return {
|
|
346
|
+
'--background': c.background,
|
|
347
|
+
'--foreground': c.foreground,
|
|
348
|
+
'--card': c.card,
|
|
349
|
+
'--card-foreground': c.cardForeground,
|
|
350
|
+
'--popover': c.popover,
|
|
351
|
+
'--popover-foreground': c.popoverForeground,
|
|
352
|
+
'--primary': c.primary,
|
|
353
|
+
'--primary-foreground': c.primaryForeground,
|
|
354
|
+
/*
|
|
355
|
+
* The two tokens derived from the primary, and they are here rather than left to
|
|
356
|
+
* `theme.css` because they must follow `--primary` — which this function writes
|
|
357
|
+
* for *any* theme in the catalogue, not just the two defaults `theme.css` carries.
|
|
358
|
+
*
|
|
359
|
+
* `--primary-hover` is a resolved colour, not a `color-mix()`: a uniform hover
|
|
360
|
+
* step cannot be expressed as a mix (see `primaryHover`). Left out, a theme switch
|
|
361
|
+
* would keep the previous theme's hover on the new theme's primary.
|
|
362
|
+
*
|
|
363
|
+
* `--primary-subtle` is a mix over `--primary`, so it would follow on its own —
|
|
364
|
+
* it is written anyway so the pair is applied together and neither is left to
|
|
365
|
+
* depend on which stylesheet happened to load.
|
|
366
|
+
*/
|
|
367
|
+
'--primary-hover': primaryHover(c.primary, theme.appearance),
|
|
368
|
+
'--primary-subtle': primarySubtleCss(theme.appearance),
|
|
369
|
+
'--secondary': c.secondary,
|
|
370
|
+
'--secondary-foreground': c.secondaryForeground,
|
|
371
|
+
'--muted': c.muted,
|
|
372
|
+
'--muted-foreground': c.mutedForeground,
|
|
373
|
+
'--accent': c.accent,
|
|
374
|
+
'--accent-foreground': c.accentForeground,
|
|
375
|
+
'--destructive': c.destructive,
|
|
376
|
+
'--destructive-foreground': c.destructiveForeground,
|
|
377
|
+
'--success': c.success,
|
|
378
|
+
'--warning': c.warning,
|
|
379
|
+
'--info': c.info,
|
|
380
|
+
'--border': c.border,
|
|
381
|
+
'--input': c.input,
|
|
382
|
+
'--ring': c.ring,
|
|
383
|
+
'--sidebar': c.sidebar,
|
|
384
|
+
'--sidebar-foreground': c.sidebarForeground,
|
|
385
|
+
'--sidebar-accent': c.sidebarAccent,
|
|
386
|
+
'--sidebar-border': c.sidebarBorder,
|
|
387
|
+
'--sidebar-primary': c.primary,
|
|
388
|
+
'--sidebar-primary-foreground': c.primaryForeground,
|
|
389
|
+
'--sidebar-ring': c.ring,
|
|
390
|
+
'--sidebar-muted-foreground': c.mutedForeground,
|
|
391
|
+
'--surface-sunken': c.muted,
|
|
392
|
+
'--surface-hover': c.accent,
|
|
393
|
+
'--surface-active': c.border,
|
|
394
|
+
'--chrome': c.background,
|
|
395
|
+
'--terminal-background': t.background,
|
|
396
|
+
'--terminal-foreground': t.foreground,
|
|
397
|
+
'--terminal-cursor': t.cursor,
|
|
398
|
+
'--terminal-selection': t.selection,
|
|
399
|
+
'--terminal-ansi-black': t.black,
|
|
400
|
+
'--terminal-ansi-red': t.red,
|
|
401
|
+
'--terminal-ansi-green': t.green,
|
|
402
|
+
'--terminal-ansi-yellow': t.yellow,
|
|
403
|
+
'--terminal-ansi-blue': t.blue,
|
|
404
|
+
'--terminal-ansi-magenta': t.magenta,
|
|
405
|
+
'--terminal-ansi-cyan': t.cyan,
|
|
406
|
+
'--terminal-ansi-white': t.white,
|
|
407
|
+
'--terminal-ansi-bright-black': t.brightBlack,
|
|
408
|
+
'--terminal-ansi-bright-red': t.brightRed,
|
|
409
|
+
'--terminal-ansi-bright-green': t.brightGreen,
|
|
410
|
+
'--terminal-ansi-bright-yellow': t.brightYellow,
|
|
411
|
+
'--terminal-ansi-bright-blue': t.brightBlue,
|
|
412
|
+
'--terminal-ansi-bright-magenta': t.brightMagenta,
|
|
413
|
+
'--terminal-ansi-bright-cyan': t.brightCyan,
|
|
414
|
+
'--terminal-ansi-bright-white': t.brightWhite,
|
|
415
|
+
'--editor-keyword': e.keyword,
|
|
416
|
+
'--editor-string': e.string,
|
|
417
|
+
'--editor-number': e.number,
|
|
418
|
+
'--editor-comment': e.comment,
|
|
419
|
+
'--editor-function': e.function,
|
|
420
|
+
'--editor-variable': e.variable,
|
|
421
|
+
'--editor-type': e.type,
|
|
422
|
+
'--editor-tag': e.tag,
|
|
423
|
+
'--editor-attribute': e.attribute,
|
|
424
|
+
'--editor-operator': e.operator,
|
|
425
|
+
'--editor-heading': e.heading,
|
|
426
|
+
'--editor-link': e.link,
|
|
427
|
+
'--editor-diff-add': e.diffAdd,
|
|
428
|
+
'--editor-diff-delete': e.diffDelete,
|
|
429
|
+
'--editor-diff-hunk': e.diffHunk,
|
|
430
|
+
'--editor-search-match': e.searchMatch,
|
|
431
|
+
'--chart-1': theme.chart[0] ?? c.primary,
|
|
432
|
+
'--chart-2': theme.chart[1] ?? c.info,
|
|
433
|
+
'--chart-3': theme.chart[2] ?? c.success,
|
|
434
|
+
'--chart-4': theme.chart[3] ?? c.warning,
|
|
435
|
+
'--chart-5': theme.chart[4] ?? c.destructive,
|
|
436
|
+
'--chart-6': theme.chart[5] ?? c.mutedForeground,
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* ---------------------------------------------------------------------------
|
|
441
|
+
* Validation
|
|
442
|
+
*
|
|
443
|
+
* Delegated. The floors are the catalogue's, because they are what makes the
|
|
444
|
+
* catalogue able to hold other people's palettes at all, and a second set of floors
|
|
445
|
+
* here would be a second answer to the same question — and the one that drifts.
|
|
446
|
+
* ------------------------------------------------------------------------- */
|
|
447
|
+
|
|
448
|
+
export type ThemeFinding = {
|
|
449
|
+
themeId: string
|
|
450
|
+
role: string
|
|
451
|
+
message: string
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function toFinding(finding: ContrastFinding): ThemeFinding {
|
|
455
|
+
return { themeId: finding.themeId, role: finding.role, message: finding.message }
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/** Validates one variant. The floors, and the reasoning behind them, live in the catalogue. */
|
|
459
|
+
export function validateTheme(theme: ThemeVariant): ThemeFinding[] {
|
|
460
|
+
const record = catalogue.find((entry) => entry.id === theme.id)
|
|
461
|
+
if (!record) {
|
|
462
|
+
return [{ themeId: theme.id, role: 'id', message: `${theme.id} is not in the catalogue` }]
|
|
463
|
+
}
|
|
464
|
+
return validateCatalogue([record]).map(toFinding)
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/** Validates the whole registry, including the catalogue-level invariants. */
|
|
468
|
+
export function validateThemeRegistry(
|
|
469
|
+
themes: readonly ThemeVariant[] = builtinThemes
|
|
470
|
+
): ThemeFinding[] {
|
|
471
|
+
const records = themes
|
|
472
|
+
.map((theme) => catalogue.find((entry) => entry.id === theme.id))
|
|
473
|
+
.filter((record): record is AdeaThemeRecord => !!record)
|
|
474
|
+
|
|
475
|
+
const orphaned = themes
|
|
476
|
+
.filter((theme) => !hasTheme(theme.id))
|
|
477
|
+
.map((theme) => ({
|
|
478
|
+
themeId: theme.id,
|
|
479
|
+
role: 'id',
|
|
480
|
+
message: `${theme.id} is in the registry but not in the catalogue`,
|
|
481
|
+
}))
|
|
482
|
+
|
|
483
|
+
return [...orphaned, ...validateCatalogue(records).map(toFinding)]
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
export const defaultLightThemeId = 'adea-light'
|
|
487
|
+
export const defaultDarkThemeId = 'adea-dark'
|
|
488
|
+
|
|
489
|
+
/** Re-exported so a consumer measuring a colour does not need a second import. */
|
|
490
|
+
export { contrastRatio } from '@adea-ai/themes'
|