@blotch/dolan 22.2.3 → 22.2.4
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 +36 -3
- package/dist/commands/add.test.js.map +1 -1
- package/dist/commands/doctor.js +187 -7
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +280 -7
- 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 +107 -1
- 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 +5 -0
- package/dist/commands/update.js +126 -45
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/update.test.js +314 -2
- package/dist/commands/update.test.js.map +1 -1
- package/dist/lockfile.d.ts +7 -0
- package/dist/lockfile.js +36 -0
- package/dist/lockfile.js.map +1 -1
- package/dist/lockfile.test.d.ts +1 -0
- package/dist/lockfile.test.js +25 -0
- package/dist/lockfile.test.js.map +1 -0
- package/dist/registry.d.ts +6 -0
- package/dist/registry.js +48 -2
- package/dist/registry.js.map +1 -1
- package/dist/registry.test.js +45 -3
- package/dist/registry.test.js.map +1 -1
- package/dist/test-utils.d.ts +5 -0
- package/dist/test-utils.js +6 -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/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 +272 -187
- package/dist/ui/components/action-sheet/action-sheet.ts +40 -34
- 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 +206 -139
- package/dist/ui/components/alert-dialog/alert-dialog.ts +32 -26
- package/dist/ui/components/area-chart/area-chart.test.ts +81 -1
- 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 +12 -14
- package/dist/ui/components/bar-chart/bar-chart.test.ts +82 -1
- package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +373 -297
- package/dist/ui/components/bottom-sheet/bottom-sheet.ts +34 -33
- package/dist/ui/components/button/button.test.ts +611 -2
- package/dist/ui/components/button/button.ts +431 -62
- package/dist/ui/components/button/index.ts +2 -0
- package/dist/ui/components/button-group/button-group.test.ts +484 -2
- package/dist/ui/components/button-group/button-group.ts +380 -68
- 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 +82 -62
- package/dist/ui/components/chart/chart-presets.test.ts +197 -1
- package/dist/ui/components/chart/chart-presets.ts +8 -1
- package/dist/ui/components/chart/chart-theme.ts +12 -0
- package/dist/ui/components/chart/chart.test.ts +1017 -0
- package/dist/ui/components/chart/chart.ts +56 -43
- package/dist/ui/components/checkbox/checkbox.test.ts +124 -42
- package/dist/ui/components/checkbox/checkbox.ts +23 -23
- package/dist/ui/components/collapsible/collapsible.test.ts +158 -81
- package/dist/ui/components/collapsible/collapsible.ts +19 -14
- 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 +29 -23
- package/dist/ui/components/dock/dock-scroll.test.ts +130 -0
- package/dist/ui/components/dock/dock-scroll.ts +133 -0
- package/dist/ui/components/dock/dock.test.ts +749 -0
- package/dist/ui/components/dock/dock.ts +960 -0
- package/dist/ui/components/dock/index.ts +2 -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 +338 -0
- package/dist/ui/components/glass/glass.ts +360 -0
- package/dist/ui/components/glass/index.ts +18 -0
- package/dist/ui/components/icon/icon-theme.test.ts +36 -0
- package/dist/ui/components/icon/icon-theme.ts +36 -13
- 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 +15 -12
- package/dist/ui/components/label/label.test.ts +11 -24
- package/dist/ui/components/line-chart/line-chart.test.ts +76 -1
- package/dist/ui/components/list/list.test.ts +80 -49
- 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 +632 -0
- package/dist/ui/components/menu/menu-popup.ts +544 -0
- package/dist/ui/components/menu/menu.test.ts +429 -0
- package/dist/ui/components/menu/menu.ts +415 -0
- package/dist/ui/components/nav-drawer/nav-drawer.test.ts +425 -260
- package/dist/ui/components/nav-drawer/nav-drawer.ts +72 -56
- package/dist/ui/components/pagination/pagination.test.ts +136 -86
- package/dist/ui/components/progress/progress.test.ts +102 -46
- package/dist/ui/components/progress/progress.ts +52 -54
- package/dist/ui/components/radio-group/radio-group.test.ts +128 -83
- package/dist/ui/components/radio-group/radio-group.ts +24 -24
- 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/select/select.test.ts +138 -78
- package/dist/ui/components/select/select.ts +17 -11
- package/dist/ui/components/separator/separator.test.ts +18 -17
- package/dist/ui/components/sheet/sheet.test.ts +64 -11
- package/dist/ui/components/sheet/sheet.ts +9 -1
- package/dist/ui/components/skeleton/skeleton.test.ts +24 -7
- package/dist/ui/components/skeleton/skeleton.ts +10 -16
- package/dist/ui/components/spinner/spinner.test.ts +64 -46
- package/dist/ui/components/spinner/spinner.ts +16 -19
- package/dist/ui/components/switch/switch.test.ts +116 -46
- package/dist/ui/components/switch/switch.ts +8 -13
- 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/tabs.test.ts +215 -157
- package/dist/ui/components/tabs/tabs.ts +110 -118
- package/dist/ui/components/textarea/textarea.test.ts +206 -100
- package/dist/ui/components/textarea/textarea.ts +14 -12
- package/dist/ui/components/toast/toast.test.ts +434 -350
- package/dist/ui/components/toast/toast.ts +42 -51
- package/dist/ui/components/toggle/toggle.test.ts +247 -140
- 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 +14 -0
- package/dist/utils/analyze.js +15 -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 +12 -0
- package/dist/utils/installed.js +16 -0
- package/dist/utils/installed.js.map +1 -1
- package/dist/utils/installed.test.js +17 -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 +25 -0
- package/dist/utils/tailwind.js +51 -0
- package/dist/utils/tailwind.js.map +1 -0
- package/dist/utils/tailwind.test.d.ts +1 -0
- package/dist/utils/tailwind.test.js +71 -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
package/dist/ui/theme/dark.css
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* @blotch/ui dark theme
|
|
3
3
|
*
|
|
4
|
-
* Complete rgba() color values referenced directly via var(--x)
|
|
5
|
-
*
|
|
4
|
+
* Complete rgba() color values referenced directly via var(--x), each with
|
|
5
|
+
* its `-rgb` channels for opacity modifiers — see default.css for why both,
|
|
6
|
+
* and why not HSL, on Lynx.
|
|
6
7
|
*
|
|
7
8
|
* Apply via a `.dark` class on the page element, or import as an
|
|
8
9
|
* alternative to default.css.
|
|
@@ -10,40 +11,75 @@
|
|
|
10
11
|
|
|
11
12
|
page.dark {
|
|
12
13
|
--background: rgba(9, 9, 11, 1);
|
|
14
|
+
--background-rgb: 9, 9, 11;
|
|
13
15
|
--foreground: rgba(250, 250, 250, 1);
|
|
16
|
+
--foreground-rgb: 250, 250, 250;
|
|
14
17
|
|
|
15
18
|
--card: rgba(9, 9, 11, 1);
|
|
19
|
+
--card-rgb: 9, 9, 11;
|
|
16
20
|
--card-foreground: rgba(250, 250, 250, 1);
|
|
21
|
+
--card-foreground-rgb: 250, 250, 250;
|
|
17
22
|
|
|
18
23
|
--primary: rgba(250, 250, 250, 1);
|
|
24
|
+
--primary-rgb: 250, 250, 250;
|
|
19
25
|
--primary-foreground: rgba(24, 24, 27, 1);
|
|
26
|
+
--primary-foreground-rgb: 24, 24, 27;
|
|
20
27
|
|
|
21
28
|
--secondary: rgba(39, 39, 42, 1);
|
|
29
|
+
--secondary-rgb: 39, 39, 42;
|
|
22
30
|
--secondary-foreground: rgba(250, 250, 250, 1);
|
|
31
|
+
--secondary-foreground-rgb: 250, 250, 250;
|
|
23
32
|
|
|
24
33
|
--muted: rgba(39, 39, 42, 1);
|
|
34
|
+
--muted-rgb: 39, 39, 42;
|
|
25
35
|
--muted-foreground: rgba(161, 161, 170, 1);
|
|
36
|
+
--muted-foreground-rgb: 161, 161, 170;
|
|
26
37
|
|
|
27
38
|
--accent: rgba(39, 39, 42, 1);
|
|
39
|
+
--accent-rgb: 39, 39, 42;
|
|
28
40
|
--accent-foreground: rgba(250, 250, 250, 1);
|
|
41
|
+
--accent-foreground-rgb: 250, 250, 250;
|
|
29
42
|
|
|
30
43
|
--destructive: rgba(127, 29, 29, 1);
|
|
44
|
+
--destructive-rgb: 127, 29, 29;
|
|
31
45
|
--destructive-foreground: rgba(250, 250, 250, 1);
|
|
46
|
+
--destructive-foreground-rgb: 250, 250, 250;
|
|
32
47
|
--destructive-subtle: rgba(127, 29, 29, 0.1);
|
|
33
48
|
|
|
34
49
|
--border: rgba(39, 39, 42, 1);
|
|
50
|
+
--border-rgb: 39, 39, 42;
|
|
35
51
|
--input: rgba(39, 39, 42, 1);
|
|
52
|
+
--input-rgb: 39, 39, 42;
|
|
36
53
|
--ring: rgba(212, 212, 216, 1);
|
|
54
|
+
--ring-rgb: 212, 212, 216;
|
|
37
55
|
/* Translucent variant of --ring for a softer focus outline (see default.css). */
|
|
38
56
|
--ring-subtle: rgba(212, 212, 216, 0.4);
|
|
39
57
|
|
|
40
58
|
/* Series palette for charts (bg-chart-1, and chart-theme.ts in the chart
|
|
41
59
|
component, which mirrors these values for SVG). */
|
|
42
60
|
--chart-1: rgba(38, 98, 217, 1);
|
|
61
|
+
--chart-1-rgb: 38, 98, 217;
|
|
43
62
|
--chart-2: rgba(46, 184, 138, 1);
|
|
63
|
+
--chart-2-rgb: 46, 184, 138;
|
|
44
64
|
--chart-3: rgba(232, 140, 48, 1);
|
|
65
|
+
--chart-3-rgb: 232, 140, 48;
|
|
45
66
|
--chart-4: rgba(175, 87, 219, 1);
|
|
67
|
+
--chart-4-rgb: 175, 87, 219;
|
|
46
68
|
--chart-5: rgba(226, 54, 112, 1);
|
|
69
|
+
--chart-5-rgb: 226, 54, 112;
|
|
70
|
+
|
|
71
|
+
/* Liquid Glass (the glass component): see default.css. */
|
|
72
|
+
--glass-tint: rgba(250, 250, 250, 1);
|
|
73
|
+
--glass-tint-rgb: 250, 250, 250;
|
|
74
|
+
--glass-tint-foreground: rgba(24, 24, 27, 1);
|
|
75
|
+
--glass-tint-foreground-rgb: 24, 24, 27;
|
|
76
|
+
--glass-foreground: rgba(250, 250, 250, 1);
|
|
77
|
+
--glass-foreground-rgb: 250, 250, 250;
|
|
78
|
+
--glass-muted-foreground: rgba(212, 212, 216, 1);
|
|
79
|
+
--glass-muted-foreground-rgb: 212, 212, 216;
|
|
80
|
+
--glass-clear-foreground: rgba(255, 255, 255, 1);
|
|
81
|
+
--glass-clear-foreground-rgb: 255, 255, 255;
|
|
82
|
+
--glass-dim: rgba(0, 0, 0, 0.35);
|
|
47
83
|
|
|
48
84
|
--radius: 8px;
|
|
49
85
|
}
|
|
@@ -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
|
});
|