@blotch/dolan 22.2.3 → 22.2.5
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/dist/commands/add.js +9 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/add.test.js +38 -3
- package/dist/commands/add.test.js.map +1 -1
- package/dist/commands/doctor.js +258 -21
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +425 -11
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.js +38 -18
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +105 -2
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/theme.js +1 -1
- package/dist/commands/theme.js.map +1 -1
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.js +194 -50
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/update.test.js +570 -3
- package/dist/commands/update.test.js.map +1 -1
- package/dist/lockfile.d.ts +17 -0
- package/dist/lockfile.js +56 -1
- package/dist/lockfile.js.map +1 -1
- package/dist/lockfile.test.d.ts +1 -0
- package/dist/lockfile.test.js +65 -0
- package/dist/lockfile.test.js.map +1 -0
- package/dist/registry.d.ts +6 -0
- package/dist/registry.js +119 -11
- package/dist/registry.js.map +1 -1
- package/dist/registry.test.js +61 -6
- package/dist/registry.test.js.map +1 -1
- package/dist/test-utils.d.ts +27 -0
- package/dist/test-utils.js +45 -1
- package/dist/test-utils.js.map +1 -1
- package/dist/testing/fire-lynx-event.d.ts +14 -0
- package/dist/testing/fire-lynx-event.js +19 -0
- package/dist/testing/fire-lynx-event.js.map +1 -0
- package/dist/testing/fire-lynx-event.test.d.ts +1 -0
- package/dist/testing/fire-lynx-event.test.js +44 -0
- package/dist/testing/fire-lynx-event.test.js.map +1 -0
- package/dist/testing/lynx-main-thread.d.ts +22 -0
- package/dist/testing/lynx-main-thread.js +11 -0
- package/dist/testing/lynx-main-thread.js.map +1 -0
- package/dist/testing/lynx-main-thread.test.d.ts +1 -0
- package/dist/testing/lynx-main-thread.test.js +24 -0
- package/dist/testing/lynx-main-thread.test.js.map +1 -0
- package/dist/testing/set-input-signal.d.ts +5 -4
- package/dist/testing/set-input-signal.js +5 -4
- package/dist/testing/set-input-signal.js.map +1 -1
- package/dist/ui/boolean-inputs.test.ts +76 -0
- package/dist/ui/components/accordion/accordion.test.ts +158 -144
- package/dist/ui/components/accordion/accordion.ts +19 -14
- package/dist/ui/components/action-sheet/action-sheet.test.ts +637 -183
- package/dist/ui/components/action-sheet/action-sheet.ts +339 -55
- package/dist/ui/components/action-sheet/index.ts +1 -0
- package/dist/ui/components/alert/alert.test.ts +67 -19
- package/dist/ui/components/alert/alert.ts +14 -16
- package/dist/ui/components/alert-dialog/alert-dialog.test.ts +740 -129
- package/dist/ui/components/alert-dialog/alert-dialog.ts +672 -58
- package/dist/ui/components/alert-dialog/index.ts +5 -0
- package/dist/ui/components/area-chart/area-chart.test.ts +81 -1
- package/dist/ui/components/area-chart/area-chart.ts +3 -2
- package/dist/ui/components/avatar/avatar.test.ts +89 -45
- package/dist/ui/components/badge/badge.test.ts +57 -23
- package/dist/ui/components/badge/badge.ts +14 -15
- package/dist/ui/components/bar-chart/bar-chart.test.ts +82 -1
- package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +1314 -273
- package/dist/ui/components/bottom-sheet/bottom-sheet.ts +1046 -119
- package/dist/ui/components/bottom-sheet/index.ts +7 -1
- package/dist/ui/components/button/button.test.ts +646 -2
- package/dist/ui/components/button/button.ts +443 -64
- package/dist/ui/components/button/index.ts +2 -0
- package/dist/ui/components/button-group/button-group.test.ts +528 -2
- package/dist/ui/components/button-group/button-group.ts +428 -70
- package/dist/ui/components/button-group/index.ts +3 -0
- package/dist/ui/components/candlestick-chart/candlestick-chart.test.ts +82 -1
- package/dist/ui/components/card/card.test.ts +97 -61
- package/dist/ui/components/card/card.ts +2 -1
- package/dist/ui/components/chart/chart-presets.test.ts +197 -1
- package/dist/ui/components/chart/chart-presets.ts +14 -7
- package/dist/ui/components/chart/chart-theme.ts +12 -0
- package/dist/ui/components/chart/chart.test.ts +1031 -0
- package/dist/ui/components/chart/chart.ts +66 -46
- package/dist/ui/components/checkbox/checkbox.test.ts +124 -42
- package/dist/ui/components/checkbox/checkbox.ts +25 -24
- package/dist/ui/components/collapsible/collapsible.test.ts +158 -81
- package/dist/ui/components/collapsible/collapsible.ts +21 -15
- package/dist/ui/components/context-menu/context-menu.test.ts +224 -0
- package/dist/ui/components/context-menu/context-menu.ts +110 -0
- package/dist/ui/components/context-menu/index.ts +1 -0
- package/dist/ui/components/dialog/dialog.test.ts +210 -152
- package/dist/ui/components/dialog/dialog.ts +35 -29
- package/dist/ui/components/dock/dock-scroll.test.ts +130 -0
- package/dist/ui/components/dock/dock-scroll.ts +142 -0
- package/dist/ui/components/dock/dock-search.test.ts +594 -0
- package/dist/ui/components/dock/dock.test.ts +752 -0
- package/dist/ui/components/dock/dock.ts +1438 -0
- package/dist/ui/components/dock/index.ts +2 -0
- package/dist/ui/components/dynamic-color/dynamic-color.test.ts +144 -0
- package/dist/ui/components/dynamic-color/dynamic-color.ts +146 -0
- package/dist/ui/components/dynamic-color/index.ts +5 -0
- package/dist/ui/components/empty-state/empty-state.test.ts +28 -39
- package/dist/ui/components/glass/concentric-radius.test.ts +13 -0
- package/dist/ui/components/glass/concentric-radius.ts +17 -0
- package/dist/ui/components/glass/glass-design.test.ts +78 -0
- package/dist/ui/components/glass/glass-design.ts +119 -0
- package/dist/ui/components/glass/glass.test.ts +376 -0
- package/dist/ui/components/glass/glass.ts +430 -0
- package/dist/ui/components/glass/index.ts +19 -0
- package/dist/ui/components/icon/icon-theme.test.ts +64 -0
- package/dist/ui/components/icon/icon-theme.ts +70 -16
- package/dist/ui/components/icon/icon.test.ts +52 -41
- package/dist/ui/components/input/input.test.ts +178 -101
- package/dist/ui/components/input/input.ts +17 -13
- package/dist/ui/components/label/label.test.ts +11 -24
- package/dist/ui/components/label/label.ts +8 -2
- package/dist/ui/components/line-chart/line-chart.test.ts +76 -1
- package/dist/ui/components/line-chart/line-chart.ts +3 -2
- package/dist/ui/components/list/list.test.ts +80 -49
- package/dist/ui/components/list/list.ts +5 -4
- package/dist/ui/components/menu/index.ts +25 -0
- package/dist/ui/components/menu/menu-placement.test.ts +153 -0
- package/dist/ui/components/menu/menu-placement.ts +159 -0
- package/dist/ui/components/menu/menu-popup.test.ts +636 -0
- package/dist/ui/components/menu/menu-popup.ts +565 -0
- package/dist/ui/components/menu/menu.test.ts +523 -0
- package/dist/ui/components/menu/menu.ts +455 -0
- package/dist/ui/components/nav-drawer/nav-drawer.test.ts +425 -260
- package/dist/ui/components/nav-drawer/nav-drawer.ts +75 -58
- package/dist/ui/components/navigation-bar/index.ts +1 -0
- package/dist/ui/components/navigation-bar/navigation-bar.test.ts +425 -0
- package/dist/ui/components/navigation-bar/navigation-bar.ts +411 -0
- package/dist/ui/components/pagination/pagination.test.ts +136 -86
- package/dist/ui/components/popover/index.ts +9 -0
- package/dist/ui/components/popover/popover-panel.test.ts +735 -0
- package/dist/ui/components/popover/popover-panel.ts +603 -0
- package/dist/ui/components/popover/popover.test.ts +286 -0
- package/dist/ui/components/popover/popover.ts +207 -0
- package/dist/ui/components/progress/progress.test.ts +102 -46
- package/dist/ui/components/progress/progress.ts +54 -55
- package/dist/ui/components/radio-group/radio-group.test.ts +128 -83
- package/dist/ui/components/radio-group/radio-group.ts +26 -25
- package/dist/ui/components/scatter-chart/scatter-chart.test.ts +74 -1
- package/dist/ui/components/scroll-area/scroll-area.test.ts +72 -36
- package/dist/ui/components/scroll-area/scroll-area.ts +4 -3
- package/dist/ui/components/search-field/index.ts +15 -0
- package/dist/ui/components/search-field/keyboard.test.ts +147 -0
- package/dist/ui/components/search-field/keyboard.ts +123 -0
- package/dist/ui/components/search-field/search-field.test.ts +549 -0
- package/dist/ui/components/search-field/search-field.ts +628 -0
- package/dist/ui/components/segmented-control/index.ts +8 -0
- package/dist/ui/components/segmented-control/segmented-control.test.ts +861 -0
- package/dist/ui/components/segmented-control/segmented-control.ts +884 -0
- package/dist/ui/components/select/select.test.ts +138 -78
- package/dist/ui/components/select/select.ts +19 -12
- package/dist/ui/components/separator/separator.test.ts +18 -17
- package/dist/ui/components/sheet/sheet.test.ts +151 -11
- package/dist/ui/components/sheet/sheet.ts +68 -5
- package/dist/ui/components/skeleton/skeleton.test.ts +24 -7
- package/dist/ui/components/skeleton/skeleton.ts +10 -16
- package/dist/ui/components/slider/index.ts +1 -0
- package/dist/ui/components/slider/slider.test.ts +695 -0
- package/dist/ui/components/slider/slider.ts +901 -0
- package/dist/ui/components/spinner/spinner.test.ts +64 -46
- package/dist/ui/components/spinner/spinner.ts +16 -19
- package/dist/ui/components/switch/index.ts +1 -1
- package/dist/ui/components/switch/switch.test.ts +534 -48
- package/dist/ui/components/switch/switch.ts +613 -48
- package/dist/ui/components/tab-bar/index.ts +1 -0
- package/dist/ui/components/tab-bar/tab-bar.test.ts +280 -0
- package/dist/ui/components/tab-bar/tab-bar.ts +230 -0
- package/dist/ui/components/tabs/index.ts +7 -1
- package/dist/ui/components/tabs/tabs.test.ts +484 -150
- package/dist/ui/components/tabs/tabs.ts +344 -149
- package/dist/ui/components/textarea/textarea.test.ts +206 -100
- package/dist/ui/components/textarea/textarea.ts +16 -13
- package/dist/ui/components/toast/toast.test.ts +434 -350
- package/dist/ui/components/toast/toast.ts +42 -51
- package/dist/ui/components/toggle/index.ts +1 -0
- package/dist/ui/components/toggle/toggle.test.ts +559 -146
- package/dist/ui/components/toggle/toggle.ts +241 -26
- package/dist/ui/components/toolbar/bar-scroll.test.ts +310 -0
- package/dist/ui/components/toolbar/bar-scroll.ts +372 -0
- package/dist/ui/components/toolbar/index.ts +12 -0
- package/dist/ui/components/toolbar/toolbar.test.ts +438 -0
- package/dist/ui/components/toolbar/toolbar.ts +535 -0
- package/dist/ui/theme/chart-colors.test.ts +8 -3
- package/dist/ui/theme/dark.css +38 -2
- package/dist/ui/theme/default.css +55 -7
- package/dist/ui/theme/icon-colors.test.ts +8 -3
- package/dist/ui/theme/rgb-channels.test.ts +84 -0
- package/dist/ui/theme/tailwind-build.test.ts +114 -0
- package/dist/ui/theme/tailwind-css.test.ts +83 -0
- package/dist/ui/theme/tailwind-plugin.test.ts +42 -2
- package/dist/ui/theme/tailwind-plugin.ts +93 -29
- package/dist/ui/theme/tailwind.css +113 -0
- package/dist/ui/utils/animate.test.ts +13 -1
- package/dist/utils/analyze.d.ts +19 -0
- package/dist/utils/analyze.js +16 -0
- package/dist/utils/analyze.js.map +1 -1
- package/dist/utils/analyze.test.js +14 -1
- package/dist/utils/analyze.test.js.map +1 -1
- package/dist/utils/installed.d.ts +25 -1
- package/dist/utils/installed.js +33 -0
- package/dist/utils/installed.js.map +1 -1
- package/dist/utils/installed.test.js +55 -1
- package/dist/utils/installed.test.js.map +1 -1
- package/dist/utils/resolve-paths.d.ts +4 -4
- package/dist/utils/resolve-paths.js +5 -7
- package/dist/utils/resolve-paths.js.map +1 -1
- package/dist/utils/resolve-paths.test.js +9 -5
- package/dist/utils/resolve-paths.test.js.map +1 -1
- package/dist/utils/tailwind.d.ts +45 -0
- package/dist/utils/tailwind.js +90 -0
- package/dist/utils/tailwind.js.map +1 -0
- package/dist/utils/tailwind.test.d.ts +1 -0
- package/dist/utils/tailwind.test.js +134 -0
- package/dist/utils/tailwind.test.js.map +1 -0
- package/package.json +9 -1
- package/dist/ui/components/area-chart/area-chart-render.test.ts +0 -63
- package/dist/ui/components/bar-chart/bar-chart-render.test.ts +0 -58
- package/dist/ui/components/button/button-render.test.ts +0 -132
- package/dist/ui/components/button-group/button-group-render.test.ts +0 -146
- package/dist/ui/components/candlestick-chart/candlestick-chart-render.test.ts +0 -59
- package/dist/ui/components/chart/chart-render.test.ts +0 -730
- package/dist/ui/components/line-chart/line-chart-render.test.ts +0 -83
- package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +0 -64
|
@@ -13,52 +13,100 @@
|
|
|
13
13
|
* rgba() values and referencing them directly sidesteps color-function parsing
|
|
14
14
|
* entirely and renders correctly on Lynx.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* Each opaque color also has its channels in a `-rgb` twin
|
|
17
|
+
* (`--primary-rgb: 24, 24, 27`) for Tailwind's opacity modifiers:
|
|
18
|
+
* `bg-primary/50` becomes `rgba(var(--primary-rgb), 0.5)`. Lynx substitutes
|
|
19
|
+
* var() as text before it parses the color, so the comma-separated list fills
|
|
20
|
+
* three arguments. Keep each pair the same color when you edit one: plain
|
|
21
|
+
* classes read `--x` and modifiers read `--x-rgb`.
|
|
20
22
|
*
|
|
21
23
|
* Apply to `page` (Lynx root element) or import globally.
|
|
22
24
|
*/
|
|
23
25
|
|
|
24
26
|
page {
|
|
25
27
|
--background: rgba(255, 255, 255, 1);
|
|
28
|
+
--background-rgb: 255, 255, 255;
|
|
26
29
|
--foreground: rgba(9, 9, 11, 1);
|
|
30
|
+
--foreground-rgb: 9, 9, 11;
|
|
27
31
|
|
|
28
32
|
--card: rgba(255, 255, 255, 1);
|
|
33
|
+
--card-rgb: 255, 255, 255;
|
|
29
34
|
--card-foreground: rgba(9, 9, 11, 1);
|
|
35
|
+
--card-foreground-rgb: 9, 9, 11;
|
|
30
36
|
|
|
31
37
|
--primary: rgba(24, 24, 27, 1);
|
|
38
|
+
--primary-rgb: 24, 24, 27;
|
|
32
39
|
--primary-foreground: rgba(250, 250, 250, 1);
|
|
40
|
+
--primary-foreground-rgb: 250, 250, 250;
|
|
33
41
|
|
|
34
42
|
--secondary: rgba(244, 244, 245, 1);
|
|
43
|
+
--secondary-rgb: 244, 244, 245;
|
|
35
44
|
--secondary-foreground: rgba(24, 24, 27, 1);
|
|
45
|
+
--secondary-foreground-rgb: 24, 24, 27;
|
|
36
46
|
|
|
37
47
|
--muted: rgba(244, 244, 245, 1);
|
|
48
|
+
--muted-rgb: 244, 244, 245;
|
|
38
49
|
--muted-foreground: rgba(113, 113, 122, 1);
|
|
50
|
+
--muted-foreground-rgb: 113, 113, 122;
|
|
39
51
|
|
|
40
52
|
--accent: rgba(244, 244, 245, 1);
|
|
53
|
+
--accent-rgb: 244, 244, 245;
|
|
41
54
|
--accent-foreground: rgba(24, 24, 27, 1);
|
|
55
|
+
--accent-foreground-rgb: 24, 24, 27;
|
|
42
56
|
|
|
43
57
|
--destructive: rgba(239, 68, 68, 1);
|
|
58
|
+
--destructive-rgb: 239, 68, 68;
|
|
44
59
|
--destructive-foreground: rgba(250, 250, 250, 1);
|
|
60
|
+
--destructive-foreground-rgb: 250, 250, 250;
|
|
45
61
|
--destructive-subtle: rgba(239, 68, 68, 0.1);
|
|
46
62
|
|
|
47
63
|
--border: rgba(228, 228, 231, 1);
|
|
64
|
+
--border-rgb: 228, 228, 231;
|
|
48
65
|
--input: rgba(228, 228, 231, 1);
|
|
66
|
+
--input-rgb: 228, 228, 231;
|
|
49
67
|
--ring: rgba(24, 24, 27, 1);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
68
|
+
--ring-rgb: 24, 24, 27;
|
|
69
|
+
/* Translucent variant of --ring for the soft outer focus ring. Input and
|
|
70
|
+
textarea set it in an inline box-shadow, where no Tailwind modifier
|
|
71
|
+
reaches, so it stays a complete color. */
|
|
53
72
|
--ring-subtle: rgba(24, 24, 27, 0.4);
|
|
54
73
|
|
|
55
74
|
/* Series palette for charts (bg-chart-1, and chart-theme.ts in the chart
|
|
56
75
|
component, which mirrors these values for SVG). */
|
|
57
76
|
--chart-1: rgba(231, 110, 80, 1);
|
|
77
|
+
--chart-1-rgb: 231, 110, 80;
|
|
58
78
|
--chart-2: rgba(42, 157, 144, 1);
|
|
79
|
+
--chart-2-rgb: 42, 157, 144;
|
|
59
80
|
--chart-3: rgba(39, 71, 84, 1);
|
|
81
|
+
--chart-3-rgb: 39, 71, 84;
|
|
60
82
|
--chart-4: rgba(232, 196, 104, 1);
|
|
83
|
+
--chart-4-rgb: 232, 196, 104;
|
|
61
84
|
--chart-5: rgba(244, 164, 98, 1);
|
|
85
|
+
--chart-5-rgb: 244, 164, 98;
|
|
86
|
+
|
|
87
|
+
/* Liquid Glass (the glass component). Glass draws its own material, so
|
|
88
|
+
these color what sits on it, and tint it:
|
|
89
|
+
- glass-tint: the color tinted glass takes, such as a prominent glass
|
|
90
|
+
button's, and glass-tint-foreground what sits on it.
|
|
91
|
+
- glass-foreground and glass-muted-foreground: text and icons on regular
|
|
92
|
+
glass. Darker than muted-foreground, since what shows through the
|
|
93
|
+
glass varies.
|
|
94
|
+
- glass-clear-foreground: on clear glass, which sits over photos and
|
|
95
|
+
video, so it's white in both themes.
|
|
96
|
+
- glass-dim: the dimming layer under clear glass over bright content,
|
|
97
|
+
black at about a third, as Apple suggests. Already translucent, so it
|
|
98
|
+
has no channels. */
|
|
99
|
+
--glass-tint: rgba(24, 24, 27, 1);
|
|
100
|
+
--glass-tint-rgb: 24, 24, 27;
|
|
101
|
+
--glass-tint-foreground: rgba(250, 250, 250, 1);
|
|
102
|
+
--glass-tint-foreground-rgb: 250, 250, 250;
|
|
103
|
+
--glass-foreground: rgba(9, 9, 11, 1);
|
|
104
|
+
--glass-foreground-rgb: 9, 9, 11;
|
|
105
|
+
--glass-muted-foreground: rgba(63, 63, 70, 1);
|
|
106
|
+
--glass-muted-foreground-rgb: 63, 63, 70;
|
|
107
|
+
--glass-clear-foreground: rgba(255, 255, 255, 1);
|
|
108
|
+
--glass-clear-foreground-rgb: 255, 255, 255;
|
|
109
|
+
--glass-dim: rgba(0, 0, 0, 0.35);
|
|
62
110
|
|
|
63
111
|
--radius: 8px;
|
|
64
112
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
// Not copied into apps (it checks the theme against a component), so it can
|
|
3
|
+
// read the theme files with Node.
|
|
1
4
|
import { readFileSync } from 'node:fs';
|
|
2
5
|
import { describe, expect, it } from 'vitest';
|
|
3
6
|
import {
|
|
@@ -11,7 +14,9 @@ import {
|
|
|
11
14
|
* theme's colors. This keeps the copy in step with default.css and dark.css.
|
|
12
15
|
*/
|
|
13
16
|
const tokens = (file: string): Record<string, string> => {
|
|
14
|
-
|
|
17
|
+
// Relative to the package, where `ng test` runs: the test runs from a build
|
|
18
|
+
// of it elsewhere, so `import.meta.url` doesn't point next to the CSS.
|
|
19
|
+
const css = readFileSync(`src/lib/theme/${file}`, 'utf8');
|
|
15
20
|
const values: Record<string, string> = {};
|
|
16
21
|
for (const match of css.matchAll(/--([\w-]+):\s*(rgba\([^)]*\))/g)) {
|
|
17
22
|
values[match[1]!] = match[2]!;
|
|
@@ -21,10 +26,10 @@ const tokens = (file: string): Record<string, string> => {
|
|
|
21
26
|
|
|
22
27
|
describe('icon color tables', () => {
|
|
23
28
|
it('match default.css', () => {
|
|
24
|
-
expect(ICON_LIGHT_COLORS).toEqual(tokens('
|
|
29
|
+
expect(ICON_LIGHT_COLORS).toEqual(tokens('default.css'));
|
|
25
30
|
});
|
|
26
31
|
|
|
27
32
|
it('match dark.css', () => {
|
|
28
|
-
expect(ICON_DARK_COLORS).toEqual(tokens('
|
|
33
|
+
expect(ICON_DARK_COLORS).toEqual(tokens('dark.css'));
|
|
29
34
|
});
|
|
30
35
|
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
// Not copied into apps (it reads the theme's CSS with Node), like the other
|
|
3
|
+
// theme checks next to it.
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { blotchPlugin } from './tailwind-plugin';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Each opaque theme color is written twice: complete (`--primary:
|
|
11
|
+
* rgba(24, 24, 27, 1)`) for plain classes, and as channels (`--primary-rgb:
|
|
12
|
+
* 24, 24, 27`) for opacity modifiers. Nothing at runtime ties the two
|
|
13
|
+
* together, so a typo would make `bg-primary/50` a different color from
|
|
14
|
+
* `bg-primary`. These tests keep the pairs in step.
|
|
15
|
+
*/
|
|
16
|
+
const variables = (file: string): Map<string, string> => {
|
|
17
|
+
// Comments mention variables too, so they go first.
|
|
18
|
+
// Relative to the package, where `ng test` runs: the test runs from a build
|
|
19
|
+
// of it elsewhere, so `import.meta.url` doesn't point next to the CSS.
|
|
20
|
+
const css = readFileSync(`src/lib/theme/${file}`, 'utf8').replace(
|
|
21
|
+
/\/\*[\s\S]*?\*\//g,
|
|
22
|
+
'',
|
|
23
|
+
);
|
|
24
|
+
return new Map(
|
|
25
|
+
[...css.matchAll(/(--[\w-]+):\s*([^;{}]+);/g)].map((match) => [
|
|
26
|
+
match[1]!,
|
|
27
|
+
match[2]!.trim(),
|
|
28
|
+
]),
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The `--x-rgb` variables the plugin's opacity modifiers read.
|
|
34
|
+
*/
|
|
35
|
+
const channelVariables = (): string[] => {
|
|
36
|
+
const factory = blotchPlugin as unknown as {
|
|
37
|
+
config: { theme: { extend: { colors: Record<string, unknown> } } };
|
|
38
|
+
};
|
|
39
|
+
const names: string[] = [];
|
|
40
|
+
const walk = (value: unknown) => {
|
|
41
|
+
if (typeof value === 'function') {
|
|
42
|
+
const css = (value as (options: object) => string)({
|
|
43
|
+
opacityValue: '0.5',
|
|
44
|
+
});
|
|
45
|
+
names.push(
|
|
46
|
+
...[...css.matchAll(/var\((--[\w-]+-rgb)\)/g)].map((m) => m[1]!),
|
|
47
|
+
);
|
|
48
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
49
|
+
Object.values(value).forEach(walk);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
walk(factory.config.theme.extend.colors);
|
|
53
|
+
return names;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
describe.each(['./default.css', './dark.css'])('%s', (file) => {
|
|
57
|
+
const vars = variables(file);
|
|
58
|
+
|
|
59
|
+
it('has the channels of every color the plugin takes a modifier on', () => {
|
|
60
|
+
const names = channelVariables();
|
|
61
|
+
expect(names.length).toBeGreaterThan(0);
|
|
62
|
+
for (const name of names) {
|
|
63
|
+
expect(vars.get(name), name).toMatch(/^\d+, \d+, \d+$/);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("gives each color's channels the same values as the color", () => {
|
|
68
|
+
for (const [name, value] of vars) {
|
|
69
|
+
if (!name.endsWith('-rgb')) continue;
|
|
70
|
+
const color = vars.get(name.slice(0, -'-rgb'.length));
|
|
71
|
+
expect(color, `${name} has no color`).toBe(`rgba(${value}, 1)`);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('has channels for every opaque color', () => {
|
|
76
|
+
// A new token added without its channels would draw nothing with a
|
|
77
|
+
// modifier.
|
|
78
|
+
for (const [name, value] of vars) {
|
|
79
|
+
const channels = /^rgba\((\d+, \d+, \d+), 1\)$/.exec(value);
|
|
80
|
+
if (!channels) continue;
|
|
81
|
+
expect(vars.get(`${name}-rgb`), `${name}-rgb`).toBe(channels[1]);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
// Not copied into apps, unlike tailwind-plugin.test.ts, which covers the
|
|
3
|
+
// plugin there: this runs Tailwind's own build, through Node and postcss, which
|
|
4
|
+
// an app's `ng test` can't count on. It checks the classes the plugin's colors
|
|
5
|
+
// make, with the Lynx preset, as an app's build does.
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
7
|
+
import preset from '@lynx-js/tailwind-preset';
|
|
8
|
+
import tailwindcss from 'tailwindcss';
|
|
9
|
+
import { describe, expect, it } from 'vitest';
|
|
10
|
+
|
|
11
|
+
import { blotchPlugin } from './tailwind-plugin';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The part of postcss these tests use.
|
|
15
|
+
*/
|
|
16
|
+
type PostCss = (plugins: unknown[]) => {
|
|
17
|
+
process: (
|
|
18
|
+
css: string,
|
|
19
|
+
options: { from: undefined },
|
|
20
|
+
) => Promise<{ css: string }>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// postcss runs Tailwind. It's Tailwind's own dependency, so it's loaded from
|
|
24
|
+
// there rather than added to this package.
|
|
25
|
+
const postcss = createRequire(
|
|
26
|
+
createRequire(import.meta.url).resolve('tailwindcss'),
|
|
27
|
+
)('postcss') as PostCss;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Compiles `classes` with Tailwind, the Lynx preset and the plugin, as an
|
|
31
|
+
* app's build does, and returns the CSS.
|
|
32
|
+
*/
|
|
33
|
+
const compile = async (classes: string): Promise<string> => {
|
|
34
|
+
const result = await postcss([
|
|
35
|
+
tailwindcss({
|
|
36
|
+
content: [{ raw: classes, extension: 'html' }],
|
|
37
|
+
presets: [preset],
|
|
38
|
+
plugins: [blotchPlugin],
|
|
39
|
+
}),
|
|
40
|
+
]).process('@tailwind utilities;', { from: undefined });
|
|
41
|
+
return result.css;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
describe('blotchPlugin colors in a Tailwind build', () => {
|
|
45
|
+
it('keeps plain color classes on the complete color', async () => {
|
|
46
|
+
const css = await compile('bg-primary text-foreground border-border');
|
|
47
|
+
|
|
48
|
+
expect(css).toContain('background-color: var(--primary)');
|
|
49
|
+
expect(css).toContain('color: var(--foreground)');
|
|
50
|
+
expect(css).toContain('border-color: var(--border)');
|
|
51
|
+
// No class reads the channels, so a theme without them still draws.
|
|
52
|
+
expect(css).not.toContain('-rgb');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('turns opacity modifiers into rgba() over the channels', async () => {
|
|
56
|
+
const css = await compile(
|
|
57
|
+
'bg-primary/50 text-foreground/70 border-border/60 bg-destructive/10 bg-chart-1/[.35]',
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
expect(css).toContain('background-color: rgba(var(--primary-rgb), 0.5)');
|
|
61
|
+
expect(css).toContain('color: rgba(var(--foreground-rgb), 0.7)');
|
|
62
|
+
expect(css).toContain('border-color: rgba(var(--border-rgb), 0.6)');
|
|
63
|
+
expect(css).toContain(
|
|
64
|
+
'background-color: rgba(var(--destructive-rgb), 0.1)',
|
|
65
|
+
);
|
|
66
|
+
expect(css).toContain('background-color: rgba(var(--chart-1-rgb), .35)');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('gives every mapped color a modifier, except the translucent destructive-subtle and glass-dim', async () => {
|
|
70
|
+
const names = [
|
|
71
|
+
'background',
|
|
72
|
+
'foreground',
|
|
73
|
+
'card',
|
|
74
|
+
'card-foreground',
|
|
75
|
+
'primary',
|
|
76
|
+
'primary-foreground',
|
|
77
|
+
'secondary',
|
|
78
|
+
'secondary-foreground',
|
|
79
|
+
'muted',
|
|
80
|
+
'muted-foreground',
|
|
81
|
+
'accent',
|
|
82
|
+
'accent-foreground',
|
|
83
|
+
'destructive',
|
|
84
|
+
'destructive-foreground',
|
|
85
|
+
'border',
|
|
86
|
+
'input',
|
|
87
|
+
'ring',
|
|
88
|
+
'chart-1',
|
|
89
|
+
'chart-2',
|
|
90
|
+
'chart-3',
|
|
91
|
+
'chart-4',
|
|
92
|
+
'chart-5',
|
|
93
|
+
'glass-tint',
|
|
94
|
+
'glass-tint-foreground',
|
|
95
|
+
'glass-foreground',
|
|
96
|
+
'glass-muted-foreground',
|
|
97
|
+
'glass-clear-foreground',
|
|
98
|
+
];
|
|
99
|
+
const css = await compile(
|
|
100
|
+
[
|
|
101
|
+
...names.map((name) => `bg-${name}/50`),
|
|
102
|
+
'bg-destructive-subtle/50',
|
|
103
|
+
'bg-glass-dim/50',
|
|
104
|
+
].join(' '),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
for (const name of names) {
|
|
108
|
+
expect(css).toContain(`rgba(var(--${name}-rgb), 0.5)`);
|
|
109
|
+
}
|
|
110
|
+
// Tailwind can't add alpha to a complete color, so it makes no class.
|
|
111
|
+
expect(css).not.toContain('destructive-subtle');
|
|
112
|
+
expect(css).not.toContain('glass-dim');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
// Not copied into apps (it reads the theme's CSS with Node), like the other
|
|
3
|
+
// theme checks next to it.
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { blotchPlugin } from './tailwind-plugin';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* tailwind.css is tailwind-plugin.ts for Tailwind 4. Nothing ties the two
|
|
11
|
+
* together, so these tests keep them mapping the same colors and radii, and
|
|
12
|
+
* keep every color it maps backed by the theme files.
|
|
13
|
+
*/
|
|
14
|
+
const read = (file: string): string =>
|
|
15
|
+
// Relative to the package, where `ng test` runs: the test runs from a build
|
|
16
|
+
// of it elsewhere, so `import.meta.url` doesn't point next to the CSS.
|
|
17
|
+
readFileSync(`src/lib/theme/${file}`, 'utf8');
|
|
18
|
+
|
|
19
|
+
const tailwindCss = (): string =>
|
|
20
|
+
read('./tailwind.css').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* `--color-x` → the theme variable it reads, from the `@theme` block.
|
|
24
|
+
*/
|
|
25
|
+
const mappedColors = (): Map<string, string> =>
|
|
26
|
+
new Map(
|
|
27
|
+
[...tailwindCss().matchAll(/--color-([\w-]+):\s*var\((--[\w-]+)\);/g)].map(
|
|
28
|
+
(match) => [match[1]!, match[2]!],
|
|
29
|
+
),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The plugin's color classes, flattened as Tailwind names them.
|
|
34
|
+
*/
|
|
35
|
+
const pluginColors = (): Map<string, string> => {
|
|
36
|
+
const factory = blotchPlugin as unknown as {
|
|
37
|
+
config: { theme: { extend: { colors: Record<string, unknown> } } };
|
|
38
|
+
};
|
|
39
|
+
const colors = new Map<string, string>();
|
|
40
|
+
const walk = (value: unknown, path: string[]) => {
|
|
41
|
+
if (typeof value === 'object' && value !== null) {
|
|
42
|
+
for (const [key, child] of Object.entries(value)) {
|
|
43
|
+
walk(child, key === 'DEFAULT' ? path : [...path, key]);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const css =
|
|
48
|
+
typeof value === 'function'
|
|
49
|
+
? (value as (options: object) => string)({})
|
|
50
|
+
: String(value);
|
|
51
|
+
colors.set(path.join('-'), /var\((--[\w-]+)\)/.exec(css)![1]!);
|
|
52
|
+
};
|
|
53
|
+
walk(factory.config.theme.extend.colors, []);
|
|
54
|
+
return colors;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
describe('tailwind.css', () => {
|
|
58
|
+
it('maps the same colors to the same variables as the plugin', () => {
|
|
59
|
+
expect(mappedColors()).toEqual(pluginColors());
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('maps the radii as the plugin does', () => {
|
|
63
|
+
const css = tailwindCss();
|
|
64
|
+
expect(css).toContain('--radius-lg: var(--radius);');
|
|
65
|
+
expect(css).toContain('--radius-md: calc(var(--radius) - 2px);');
|
|
66
|
+
expect(css).toContain('--radius-sm: calc(var(--radius) - 4px);');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it.each(['./default.css', './dark.css'])(
|
|
70
|
+
'reads only variables %s sets, each opaque one with its channels',
|
|
71
|
+
(file) => {
|
|
72
|
+
const css = read(file);
|
|
73
|
+
for (const variable of mappedColors().values()) {
|
|
74
|
+
const value = new RegExp(`${variable}:\\s*([^;]+);`).exec(css)?.[1];
|
|
75
|
+
expect(value, variable).toBeDefined();
|
|
76
|
+
if (value!.endsWith(', 1)')) {
|
|
77
|
+
// The build writes bg-primary/50 as rgba(var(--primary-rgb), 0.5).
|
|
78
|
+
expect(css, `${variable}-rgb`).toContain(`${variable}-rgb:`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
});
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addSafeAreaUtilities,
|
|
5
|
+
blotchPlugin,
|
|
6
|
+
themeColor,
|
|
7
|
+
} from './tailwind-plugin';
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* These tests exercise the utility generator in isolation with mock Tailwind
|
|
@@ -119,6 +123,42 @@ describe('blotchPlugin', () => {
|
|
|
119
123
|
};
|
|
120
124
|
const colors = factory.config?.theme?.extend?.colors;
|
|
121
125
|
expect(colors).toBeDefined();
|
|
122
|
-
|
|
126
|
+
const background = colors!['background'] as (options?: object) => string;
|
|
127
|
+
expect(background()).toBe('var(--background)');
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('themeColor', () => {
|
|
132
|
+
const primary = themeColor('primary');
|
|
133
|
+
|
|
134
|
+
it('reads the complete color when no alpha is asked for', () => {
|
|
135
|
+
// caret-primary, shadow-primary: Tailwind passes no options.
|
|
136
|
+
expect(primary()).toBe('var(--primary)');
|
|
137
|
+
expect(primary({})).toBe('var(--primary)');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("reads the complete color for a plain class with Tailwind's opacity variable", () => {
|
|
141
|
+
// bg-primary: the opacity variable is always 1 unless a deprecated
|
|
142
|
+
// bg-opacity-* utility changes it, and that never worked on these colors.
|
|
143
|
+
expect(
|
|
144
|
+
primary({
|
|
145
|
+
opacityVariable: '--tw-bg-opacity',
|
|
146
|
+
opacityValue: 'var(--tw-bg-opacity, 1)',
|
|
147
|
+
}),
|
|
148
|
+
).toBe('var(--primary)');
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('reads the complete color for an alpha of 1', () => {
|
|
152
|
+
// bg-primary/100 passes '1'; theme('colors.primary') passes the number 1.
|
|
153
|
+
expect(primary({ opacityValue: '1' })).toBe('var(--primary)');
|
|
154
|
+
expect(primary({ opacityValue: 1 })).toBe('var(--primary)');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('reads the channels for an opacity modifier', () => {
|
|
158
|
+
expect(primary({ opacityValue: '0.5' })).toBe(
|
|
159
|
+
'rgba(var(--primary-rgb), 0.5)',
|
|
160
|
+
);
|
|
161
|
+
// A gradient's transparent end stop asks for 0.
|
|
162
|
+
expect(primary({ opacityValue: 0 })).toBe('rgba(var(--primary-rgb), 0)');
|
|
123
163
|
});
|
|
124
164
|
});
|
|
@@ -69,6 +69,51 @@ export const addSafeAreaUtilities = ({
|
|
|
69
69
|
}
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* What Tailwind passes a color it was given as a function:
|
|
74
|
+
* - an opacity modifier sets only `opacityValue` (`bg-primary/50` → `0.5`);
|
|
75
|
+
* - a plain class whose utility has an opacity variable sets
|
|
76
|
+
* `opacityVariable` too, and `opacityValue` is `var(--tw-bg-opacity, 1)`
|
|
77
|
+
* (`bg-primary`);
|
|
78
|
+
* - other plain classes pass neither (`caret-primary`);
|
|
79
|
+
* - `theme('colors.primary')` in a stylesheet passes an `opacityValue` of 1.
|
|
80
|
+
*/
|
|
81
|
+
type ColorOptions = {
|
|
82
|
+
opacityValue?: string | number;
|
|
83
|
+
opacityVariable?: string;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* A theme color that takes Tailwind's opacity modifiers on Lynx.
|
|
88
|
+
*
|
|
89
|
+
* A plain class reads the complete color, as it always has:
|
|
90
|
+
* `bg-primary` → `background-color: var(--primary)`. A modifier reads the
|
|
91
|
+
* color's channels from its `-rgb` twin:
|
|
92
|
+
* `bg-primary/50` → `background-color: rgba(var(--primary-rgb), 0.5)`.
|
|
93
|
+
*
|
|
94
|
+
* Lynx substitutes `var()` as text before it parses the value, so with
|
|
95
|
+
* `--primary-rgb: 24, 24, 27` its color parser sees `rgba(24, 24, 27, 0.5)`
|
|
96
|
+
* (`CSSValue::Substitution` in lynx-family/lynx). The channels are
|
|
97
|
+
* comma-separated because every Lynx color parser takes `rgba()` in that
|
|
98
|
+
* form. Lynx takes `hsl()` only with commas, which is why the shadcn/ui form,
|
|
99
|
+
* `hsl(var(--x) / 0.5)`, draws nothing.
|
|
100
|
+
*
|
|
101
|
+
* Plain classes stay on `var(--x)` so they don't need the channels: with a
|
|
102
|
+
* theme copied before the `-rgb` variables existed, every plain class still
|
|
103
|
+
* draws, and only modifiers don't. Tailwind's `<alpha-value>` placeholder
|
|
104
|
+
* can't do that, as it puts the channels in plain classes too. An alpha of 1
|
|
105
|
+
* is the plain color, so `bg-primary/100` and `theme('colors.primary')` read
|
|
106
|
+
* `var(--primary)` as well.
|
|
107
|
+
*/
|
|
108
|
+
export const themeColor =
|
|
109
|
+
(name: string) =>
|
|
110
|
+
({ opacityValue, opacityVariable }: ColorOptions = {}): string =>
|
|
111
|
+
opacityValue === undefined ||
|
|
112
|
+
opacityVariable !== undefined ||
|
|
113
|
+
String(opacityValue) === '1'
|
|
114
|
+
? `var(--${name})`
|
|
115
|
+
: `rgba(var(--${name}-rgb), ${opacityValue})`;
|
|
116
|
+
|
|
72
117
|
/**
|
|
73
118
|
* Tailwind plugin that maps @blotch/ui CSS variables to semantic color utilities
|
|
74
119
|
* and registers safe-area-aware padding utilities.
|
|
@@ -86,10 +131,9 @@ export const addSafeAreaUtilities = ({
|
|
|
86
131
|
* referencing them directly avoids color-function parsing entirely. This matches
|
|
87
132
|
* the official React Lynx Tailwind example.
|
|
88
133
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* `--destructive-subtle` → `destructive.subtle`) or use `opacity-*` on the element.
|
|
134
|
+
* Opacity modifiers (`bg-primary/50`, `text-foreground/70`,
|
|
135
|
+
* `border-border/60`) read each color's `--x-rgb` channels instead; see
|
|
136
|
+
* `themeColor`.
|
|
93
137
|
*
|
|
94
138
|
* Safe area: see `addSafeAreaUtilities` for the `*-safe` / `*-safe-<n>` padding
|
|
95
139
|
* utilities that keep content clear of notches and home indicators.
|
|
@@ -106,49 +150,69 @@ export const blotchPlugin = plugin(
|
|
|
106
150
|
{
|
|
107
151
|
theme: {
|
|
108
152
|
extend: {
|
|
153
|
+
// Tailwind's types only allow strings here, but it also takes a
|
|
154
|
+
// function, which it calls with the modifier's alpha: that's how it
|
|
155
|
+
// applies `<alpha-value>` itself. Every color but destructive.subtle
|
|
156
|
+
// and glass.dim, which are translucent already, has an `--x-rgb` twin
|
|
157
|
+
// in the theme, so takes opacity modifiers.
|
|
109
158
|
colors: {
|
|
110
|
-
background: '
|
|
111
|
-
foreground: '
|
|
159
|
+
background: themeColor('background'),
|
|
160
|
+
foreground: themeColor('foreground'),
|
|
112
161
|
primary: {
|
|
113
|
-
DEFAULT: '
|
|
114
|
-
foreground: '
|
|
162
|
+
DEFAULT: themeColor('primary'),
|
|
163
|
+
foreground: themeColor('primary-foreground'),
|
|
115
164
|
},
|
|
116
165
|
secondary: {
|
|
117
|
-
DEFAULT: '
|
|
118
|
-
foreground: '
|
|
166
|
+
DEFAULT: themeColor('secondary'),
|
|
167
|
+
foreground: themeColor('secondary-foreground'),
|
|
119
168
|
},
|
|
120
169
|
muted: {
|
|
121
|
-
DEFAULT: '
|
|
122
|
-
foreground: '
|
|
170
|
+
DEFAULT: themeColor('muted'),
|
|
171
|
+
foreground: themeColor('muted-foreground'),
|
|
123
172
|
},
|
|
124
173
|
accent: {
|
|
125
|
-
DEFAULT: '
|
|
126
|
-
foreground: '
|
|
174
|
+
DEFAULT: themeColor('accent'),
|
|
175
|
+
foreground: themeColor('accent-foreground'),
|
|
127
176
|
},
|
|
128
177
|
destructive: {
|
|
129
|
-
DEFAULT: '
|
|
130
|
-
foreground: '
|
|
131
|
-
//
|
|
132
|
-
//
|
|
178
|
+
DEFAULT: themeColor('destructive'),
|
|
179
|
+
foreground: themeColor('destructive-foreground'),
|
|
180
|
+
// Red at 10%, the destructive alert's background. It's
|
|
181
|
+
// translucent already, so it has no channels and takes no
|
|
182
|
+
// modifier. It predates modifiers and stays for the apps that
|
|
183
|
+
// use it: bg-destructive/10 draws the same color, but only in a
|
|
184
|
+
// theme that has --destructive-rgb.
|
|
133
185
|
subtle: 'var(--destructive-subtle)',
|
|
134
186
|
},
|
|
135
|
-
border: '
|
|
136
|
-
input: '
|
|
137
|
-
ring: '
|
|
187
|
+
border: themeColor('border'),
|
|
188
|
+
input: themeColor('input'),
|
|
189
|
+
ring: themeColor('ring'),
|
|
138
190
|
card: {
|
|
139
|
-
DEFAULT: '
|
|
140
|
-
foreground: '
|
|
191
|
+
DEFAULT: themeColor('card'),
|
|
192
|
+
foreground: themeColor('card-foreground'),
|
|
141
193
|
},
|
|
142
194
|
// Chart series colors, e.g. bg-chart-1 for a legend swatch that
|
|
143
195
|
// matches the first series.
|
|
144
196
|
chart: {
|
|
145
|
-
1: '
|
|
146
|
-
2: '
|
|
147
|
-
3: '
|
|
148
|
-
4: '
|
|
149
|
-
5: '
|
|
197
|
+
1: themeColor('chart-1'),
|
|
198
|
+
2: themeColor('chart-2'),
|
|
199
|
+
3: themeColor('chart-3'),
|
|
200
|
+
4: themeColor('chart-4'),
|
|
201
|
+
5: themeColor('chart-5'),
|
|
150
202
|
},
|
|
151
|
-
|
|
203
|
+
// What sits on Liquid Glass, and its tint: text-glass-foreground,
|
|
204
|
+
// bg-glass-tint, bg-glass-dim (see the glass component).
|
|
205
|
+
glass: {
|
|
206
|
+
tint: {
|
|
207
|
+
DEFAULT: themeColor('glass-tint'),
|
|
208
|
+
foreground: themeColor('glass-tint-foreground'),
|
|
209
|
+
},
|
|
210
|
+
foreground: themeColor('glass-foreground'),
|
|
211
|
+
'muted-foreground': themeColor('glass-muted-foreground'),
|
|
212
|
+
'clear-foreground': themeColor('glass-clear-foreground'),
|
|
213
|
+
dim: 'var(--glass-dim)',
|
|
214
|
+
},
|
|
215
|
+
} as unknown as Record<string, string>,
|
|
152
216
|
borderRadius: {
|
|
153
217
|
lg: 'var(--radius)',
|
|
154
218
|
md: 'calc(var(--radius) - 2px)',
|