@wtasnorg/candi 0.0.22

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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright © 2025 wtasg
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,292 @@
1
+ # Candi Design System
2
+
3
+ A multi-platform design system based on Nordic/Scandinavian design principles: Hygge (warmth) and Lagom (balance).
4
+
5
+ Candi provides a single source of truth for colors using the OKLCH color space, synchronized across Web, Flutter, VS Code, Vim, KDE, GNOME, and Obsidian.
6
+
7
+ **[View Documentation Website](https://wtasg.github.io/candi/)** - Interactive color explorer, component playground, and comprehensive guides.
8
+
9
+ ---
10
+
11
+ ## Multi-Platform Support
12
+
13
+ | Platform | Support | Integration |
14
+ | :--- | :--- | :--- |
15
+ | **Web** | Full | Tailwind CSS Plugin & CSS Variables |
16
+ | **Flutter** | Full | Type-safe `CandiColors` with OKLCH metadata |
17
+ | **VS Code** | Full | Light & Dark themes with unified syntax highlighting |
18
+ | **Vim** | Full | Standalone `.vim` colorschemes (GUI & Terminal) |
19
+ | **KDE Plasma** | Full | Color schemes for KDE 4, 5 & 6 |
20
+ | **GNOME** | Full | GTK3 & GTK4 themes for X11 and Wayland |
21
+ | **Obsidian** | Full | Light & Dark themes with 60+ CSS variables |
22
+
23
+ ---
24
+
25
+ ## Architecture
26
+
27
+ ### Single Source of Truth
28
+
29
+ All colors are defined in `src/data/colors.js`. This file is the canonical source for the entire design system.
30
+
31
+ ```text
32
+ src/data/colors.js (Source of Truth)
33
+
34
+
35
+ scripts/sync-colors.js (Generator)
36
+
37
+ ├── src/css/base.css (CSS Variables)
38
+ ├── src/v4/theme.css (Tailwind v4 @theme)
39
+ └── dist/colors.json (Data export)
40
+
41
+ Platform Builds (all consume colors.js directly):
42
+ ├── build-flutter.js → flutter/lib/candi_colors.dart
43
+ ├── build-vscode.js → vscode/themes/*.json
44
+ ├── build-vim.js → vim/colors/*.vim
45
+ ├── build-kde.js → kde/v4,v5/*.colors
46
+ ├── build-gnome.js → gnome/gtk-*/*.css
47
+ └── build-obsidian.js → obsidian/theme.css
48
+ ```
49
+
50
+ ### OKLCH Color Space
51
+
52
+ Candi uses OKLCH as its primary color space instead of Hex codes:
53
+
54
+ - **Perceptual Uniformity**: Consistent contrast and brightness across the palette
55
+ - **Synchronized Themes**: Updates to `src/data/colors.js` propagate to all platforms via `npm run build:all`
56
+ - **Shared Logic**: Centralized conversion in `scripts/color-conv.js` ensures color accuracy
57
+ - **Automated Accessibility**: Integrated WCAG 2.1 contrast ratio validation
58
+
59
+ **[Learn more about OKLCH color conversion](docs/color-conversion.md)**
60
+
61
+ ---
62
+
63
+ ## Project Structure
64
+
65
+ ```text
66
+ candi/
67
+ ├── src/ # Source files for npm package
68
+ │ ├── css/ # CSS files (base, components, utilities)
69
+ │ ├── data/ # Source of truth (colors.js)
70
+ │ ├── v4/ # Tailwind v4 theme
71
+ │ ├── index.js # Main entry point
72
+ │ ├── plugin.js # Tailwind v3 plugin
73
+ │ └── theme.js # Tailwind v3 theme extension
74
+ ├── scripts/ # Build and test scripts
75
+ │ ├── build.js # Main npm package build
76
+ │ ├── build-*.js # Platform-specific builds
77
+ │ ├── test-*.js # Platform-specific tests
78
+ │ ├── sync-colors.js # Color synchronization
79
+ │ └── color-conv.js # OKLCH/RGB conversion utilities
80
+ ├── dist/ # Built output (git-ignored)
81
+ ├── docs/ # Documentation guides
82
+ ├── website/ # Documentation site (Vite + React)
83
+ ├── flutter/ # Flutter package
84
+ ├── vscode/ # VS Code extension
85
+ ├── vim/ # Vim colorschemes
86
+ ├── kde/ # KDE Plasma color schemes
87
+ ├── gnome/ # GTK3/GTK4 themes
88
+ └── obsidian/ # Obsidian theme
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Commands
94
+
95
+ ### Build
96
+
97
+ | Command | Description |
98
+ | :--- | :--- |
99
+ | `npm run build` | Build npm package (CSS, JS, TypeScript declarations) |
100
+ | `npm run build:all` | Build all platforms (Web, Flutter, VS Code, Vim, KDE, GNOME, Obsidian) |
101
+ | `npm run build:flutter` | Build Flutter package only |
102
+ | `npm run build:vscode` | Build VS Code extension only |
103
+ | `npm run build:vim` | Build Vim colorschemes only |
104
+ | `npm run build:kde` | Build KDE color schemes only |
105
+ | `npm run build:gnome` | Build GNOME/GTK themes only |
106
+ | `npm run build:obsidian` | Build Obsidian theme only |
107
+
108
+ ### Test
109
+
110
+ | Command | Description |
111
+ | :--- | :--- |
112
+ | `npm test` | Run all tests |
113
+ | `npm run test:color` | Test color definitions |
114
+ | `npm run test:colors` | Test color conversions |
115
+ | `npm run test:flutter` | Test Flutter package |
116
+ | `npm run test:vscode` | Test VS Code extension |
117
+ | `npm run test:vim` | Test Vim colorschemes |
118
+ | `npm run test:kde` | Test KDE color schemes |
119
+ | `npm run test:gnome` | Test GNOME themes |
120
+ | `npm run test:obsidian` | Test Obsidian theme |
121
+
122
+ ### Package & Publish
123
+
124
+ | Command | Description |
125
+ | :--- | :--- |
126
+ | `npm run artifact` | Package all platforms into zip archives |
127
+ | `npm run vscode:package` | Generate `.vsix` VS Code extension |
128
+ | `./scripts/package-bump.sh <version>` | Bump version across all packages |
129
+
130
+ ---
131
+
132
+ ## Installation & Usage
133
+
134
+ ### Using Prebuilt Releases
135
+
136
+ Download ready-to-use artifacts from GitHub releases (recommended for most users).
137
+
138
+ **[Using Prebuilt Releases Guide](docs/using-release-artifacts.md)**
139
+
140
+ ### GitHub Packages Authentication (Required)
141
+
142
+ > [!IMPORTANT]
143
+ > This package is published to **GitHub Packages**, not npmjs.com. You must authenticate with GitHub before installing.
144
+
145
+ To install the package, you need to authenticate with GitHub:
146
+
147
+ 1. **Create a Personal Access Token (PAT)**:
148
+ - Go to GitHub Settings → [Developer settings → Personal access tokens → Tokens (classic)](https://github.com/settings/tokens)
149
+ - Click "Generate new token (classic)"
150
+ - Give it a descriptive name (e.g., "npm packages")
151
+ - Select the `read:packages` scope
152
+ - Click "Generate token" and copy the token
153
+
154
+ 2. **Configure npm authentication**:
155
+
156
+ ```bash
157
+ npm login --scope=@wtasg --auth-type=legacy --registry=https://npm.pkg.github.com
158
+ ```
159
+
160
+ - Username: Your GitHub username
161
+ - Password: The PAT you just created
162
+ - Email: Your GitHub email
163
+
164
+ Or create/update your `~/.npmrc` file:
165
+
166
+ ```text
167
+ //npm.pkg.github.com/:_authToken=YOUR_GITHUB_PAT
168
+ @wtasg:registry=https://npm.pkg.github.com
169
+ ```
170
+
171
+ ### Web (Tailwind CSS)
172
+
173
+ ```bash
174
+ npm install @wtasnorg/candi
175
+ ```
176
+
177
+ **Tailwind v4** (Recommended):
178
+
179
+ ```css
180
+ /* In your CSS */
181
+ @import "tailwindcss";
182
+ @import "@wtasnorg/candi/v4";
183
+ ```
184
+
185
+ **Tailwind v3**:
186
+
187
+ ```js
188
+ // tailwind.config.js
189
+ const { theme, plugin } = require('@wtasnorg/candi');
190
+ module.exports = {
191
+ theme: { extend: theme },
192
+ plugins: [plugin],
193
+ };
194
+ ```
195
+
196
+ **[Full Web Setup Guide](docs/use-with-tailwindcss.md)** | **[Use Without Tailwind](docs/use-without-tailwindcss.md)**
197
+
198
+ ### Platform Guides
199
+
200
+ | Platform | Guide |
201
+ | :--- | :--- |
202
+ | Flutter | [Flutter Integration Guide](docs/flutter-integration.md) |
203
+ | VS Code | [VS Code Theme Guide](docs/vscode-theme.md) |
204
+ | Vim | [Vim Theme Guide](docs/vim-theme.md) |
205
+ | KDE Plasma | [KDE Theme Guide](docs/kde-theme.md) |
206
+ | GNOME | [GNOME Theme Guide](docs/gnome-theme.md) |
207
+ | Obsidian | [Obsidian Theme Guide](docs/obsidian-theme.md) |
208
+
209
+ ---
210
+
211
+ ## Color Tokens
212
+
213
+ | Token | Light | Dark | Usage |
214
+ | :--- | :--- | :--- | :--- |
215
+ | `bg` | Warm white | Warm dark | Page background |
216
+ | `surface` | Soft cream | Card surface | Cards, sections |
217
+ | `elevated` | Pure white | Elevated dark | Modals, popups |
218
+ | `text` | Warm charcoal | Off-white | Primary text |
219
+ | `text-subtle` | Medium gray | Light gray | Secondary text |
220
+ | `text-muted` | Light gray | Muted gray | Tertiary text |
221
+ | `accent` | Steel blue | Lighter steel | Primary actions |
222
+ | `secondary` | Terracotta | Lighter terracotta | Secondary actions |
223
+ | `success` | Forest green | Lighter green | Success states |
224
+ | `warning` | Amber | Lighter amber | Warning states |
225
+ | `error` | Coral red | Lighter coral | Error states |
226
+
227
+ **[Customize Colors](docs/customizing-colors.md)**
228
+
229
+ ---
230
+
231
+ ## Design & Accessibility
232
+
233
+ Candi is built with accessibility as a core requirement:
234
+
235
+ - **WCAG Standards**: Color extraction pipeline automatically validates contrast ratios
236
+ - **Primary Text**: Aimed at **4.5:1** contrast (WCAG AA) for standard text
237
+ - **UI Elements**: Accents and status indicators tuned for **3.0:1** contrast (WCAG Graphical Objects)
238
+
239
+ ---
240
+
241
+ ## Development
242
+
243
+ ### Prerequisites
244
+
245
+ - Node.js 24+
246
+ - npm
247
+ - Flutter SDK (for Flutter package development)
248
+
249
+ ### Setup
250
+
251
+ ```bash
252
+ # Clone the repository
253
+ git clone https://github.com/wtasg/candi.git
254
+ cd candi
255
+
256
+ # Install dependencies
257
+ npm install
258
+
259
+ # Build all platforms
260
+ npm run build:all
261
+ ```
262
+
263
+ ### Working on the Documentation Website
264
+
265
+ The docs website lives in `website/` and uses the built theme from `dist/`:
266
+
267
+ ```bash
268
+ cd website
269
+ npm install
270
+ npm run dev # Starts dev server at http://localhost:3000
271
+ ```
272
+
273
+ The `predev` and `prebuild` scripts automatically rebuild the parent package, so changes to `src/data/colors.js` are reflected immediately.
274
+
275
+ ### Making Color Changes
276
+
277
+ 1. Edit `src/data/colors.js` (the single source of truth)
278
+ 2. Run `npm run build:all` to regenerate all platform themes
279
+ 3. Run `npm test` to validate color accuracy and contrast ratios
280
+
281
+ ---
282
+
283
+ ## Related Documentation
284
+
285
+ - [Knowledge Base](Knowledge.md) - Lessons learned and development gotchas
286
+ - [Color Conversion](docs/color-conversion.md) - OKLCH to RGB conversion pipeline
287
+
288
+ ---
289
+
290
+ ## License
291
+
292
+ MIT
package/dist/base.css ADDED
@@ -0,0 +1,164 @@
1
+ /*
2
+ * Scandinavian Theme - Base CSS
3
+ *
4
+ * AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
5
+ * This file is generated by: npm run build (scripts/sync-colors.js)
6
+ * Source of truth: src/data/colors.js
7
+ * Manual changes will be overwritten on next build.
8
+ *
9
+ * OKLCH color tokens for light and dark modes.
10
+ * Import this file to get CSS custom properties without Tailwind.
11
+ */
12
+
13
+ :root {
14
+ /* @tokens-start-light */
15
+ --candi-bg: oklch(98% 0.008 85);
16
+ --candi-surface: oklch(95.5% 0.012 85);
17
+ --candi-elevated: oklch(100% 0 0);
18
+ --candi-text: oklch(28% 0.015 250);
19
+ --candi-text-subtle: oklch(50% 0.01 250);
20
+ --candi-text-muted: oklch(62% 0.008 250);
21
+ --candi-border: oklch(90% 0.008 85);
22
+ --candi-border-strong: oklch(82% 0.01 85);
23
+ --candi-divider: oklch(88% 0.006 85);
24
+ --candi-accent: oklch(52% 0.06 230);
25
+ --candi-accent-subtle: oklch(85% 0.03 230);
26
+ --candi-on-accent: oklch(100% 0 0);
27
+ --candi-secondary: oklch(58% 0.12 55);
28
+ --candi-secondary-subtle: oklch(88% 0.04 55);
29
+ --candi-on-secondary: oklch(100% 0 0);
30
+ --candi-success: oklch(52% 0.08 145);
31
+ --candi-on-success: oklch(100% 0 0);
32
+ --candi-warning: oklch(68% 0.13 70);
33
+ --candi-on-warning: oklch(20% 0.02 70);
34
+ --candi-error: oklch(58% 0.12 25);
35
+ --candi-on-error: oklch(100% 0 0);
36
+ --candi-info: oklch(55% 0.1 240);
37
+ --candi-on-info: oklch(100% 0 0);
38
+ --candi-link: oklch(50% 0.08 230);
39
+ --candi-disabled: oklch(75% 0.005 250);
40
+ --candi-overlay: oklch(0% 0 0 / 0.5);
41
+ --candi-scrim: oklch(0% 0 0 / 0.32);
42
+ --candi-inverse-surface: oklch(25% 0.015 250);
43
+ --candi-inverse-text: oklch(92% 0.01 85);
44
+ --candi-shadow: 0 2px 8px rgba(45, 50, 57, 0.06);
45
+ --candi-shadow-md: 0 4px 20px rgba(45, 50, 57, 0.1);
46
+ --candi-shadow-lg: 0 8px 40px rgba(45, 50, 57, 0.15);
47
+ --candi-shadow-color: oklch(25% 0.01 250 / 0.15);
48
+ --candi-focus-ring: oklch(52% 0.06 230 / 0.4);
49
+ --candi-syntax-keyword: oklch(60% 0.15 0);
50
+ --candi-syntax-type: oklch(65% 0.12 280);
51
+ --candi-syntax-var: oklch(65% 0.1 200);
52
+ --candi-syntax-const: oklch(70% 0.14 50);
53
+ --candi-syntax-func: oklch(55% 0.12 240);
54
+ --candi-syntax-string: oklch(60% 0.12 140);
55
+ --candi-hover: oklch(0% 0 0 / 0.05);
56
+ --candi-active: oklch(0% 0 0 / 0.1);
57
+ --candi-terminal-black: oklch(25% 0.01 250);
58
+ --candi-terminal-red: oklch(58% 0.12 25);
59
+ --candi-terminal-green: oklch(52% 0.08 145);
60
+ --candi-terminal-yellow: oklch(68% 0.13 70);
61
+ --candi-terminal-blue: oklch(52% 0.06 230);
62
+ --candi-terminal-magenta: oklch(60% 0.15 0);
63
+ --candi-terminal-cyan: oklch(65% 0.1 200);
64
+ --candi-terminal-white: oklch(92% 0.01 85);
65
+
66
+ /* Terminal Palette */
67
+ --candi-terminal-black: oklch(25% 0.01 250);
68
+ --candi-terminal-red: var(--candi-error);
69
+ --candi-terminal-green: var(--candi-success);
70
+ --candi-terminal-yellow: var(--candi-warning);
71
+ --candi-terminal-blue: var(--candi-accent);
72
+ --candi-terminal-magenta: var(--candi-syntax-keyword);
73
+ --candi-terminal-cyan: var(--candi-syntax-var);
74
+ --candi-terminal-white: var(--candi-text);
75
+ /* @tokens-end-light */
76
+ }
77
+
78
+ .dark {
79
+ /* @tokens-start-dark */
80
+ --candi-bg: oklch(18% 0.015 250);
81
+ --candi-surface: oklch(22% 0.012 250);
82
+ --candi-elevated: oklch(25% 0.015 250);
83
+ --candi-text: oklch(92% 0.01 85);
84
+ --candi-text-subtle: oklch(72% 0.008 85);
85
+ --candi-text-muted: oklch(58% 0.006 85);
86
+ --candi-border: oklch(30% 0.01 250);
87
+ --candi-border-strong: oklch(40% 0.012 250);
88
+ --candi-divider: oklch(28% 0.008 250);
89
+ --candi-accent: oklch(62% 0.08 230);
90
+ --candi-accent-subtle: oklch(35% 0.04 230);
91
+ --candi-on-accent: oklch(15% 0.01 230);
92
+ --candi-secondary: oklch(65% 0.12 55);
93
+ --candi-secondary-subtle: oklch(30% 0.05 55);
94
+ --candi-on-secondary: oklch(15% 0.02 55);
95
+ --candi-success: oklch(60% 0.1 145);
96
+ --candi-on-success: oklch(15% 0.02 145);
97
+ --candi-warning: oklch(72% 0.13 70);
98
+ --candi-on-warning: oklch(15% 0.02 70);
99
+ --candi-error: oklch(65% 0.12 25);
100
+ --candi-on-error: oklch(15% 0.02 25);
101
+ --candi-info: oklch(65% 0.1 240);
102
+ --candi-on-info: oklch(15% 0.02 240);
103
+ --candi-link: oklch(60% 0.08 230);
104
+ --candi-disabled: oklch(45% 0.005 250);
105
+ --candi-overlay: oklch(0% 0 0 / 0.7);
106
+ --candi-scrim: oklch(0% 0 0 / 0.6);
107
+ --candi-inverse-surface: oklch(92% 0.008 85);
108
+ --candi-inverse-text: oklch(25% 0.015 250);
109
+ --candi-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
110
+ --candi-shadow-md: 0 4px 20px rgba(0, 0, 0, 0.35);
111
+ --candi-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.45);
112
+ --candi-shadow-color: oklch(0% 0 0 / 0.4);
113
+ --candi-focus-ring: oklch(62% 0.08 230 / 0.5);
114
+ --candi-syntax-keyword: oklch(70% 0.15 0);
115
+ --candi-syntax-type: oklch(75% 0.12 280);
116
+ --candi-syntax-var: oklch(75% 0.1 200);
117
+ --candi-syntax-const: oklch(80% 0.14 50);
118
+ --candi-syntax-func: oklch(65% 0.12 240);
119
+ --candi-syntax-string: oklch(70% 0.12 140);
120
+ --candi-hover: oklch(100% 0 0 / 0.1);
121
+ --candi-active: oklch(100% 0 0 / 0.2);
122
+ --candi-terminal-black: oklch(15% 0.01 250);
123
+ --candi-terminal-red: oklch(65% 0.12 25);
124
+ --candi-terminal-green: oklch(60% 0.1 145);
125
+ --candi-terminal-yellow: oklch(72% 0.13 70);
126
+ --candi-terminal-blue: oklch(62% 0.08 230);
127
+ --candi-terminal-magenta: oklch(70% 0.15 0);
128
+ --candi-terminal-cyan: oklch(75% 0.1 200);
129
+ --candi-terminal-white: oklch(92% 0.01 85);
130
+
131
+ /* Terminal Palette */
132
+ --candi-terminal-black: oklch(15% 0.01 250);
133
+ --candi-terminal-red: var(--candi-error);
134
+ --candi-terminal-green: var(--candi-success);
135
+ --candi-terminal-yellow: var(--candi-warning);
136
+ --candi-terminal-blue: var(--candi-accent);
137
+ --candi-terminal-magenta: var(--candi-syntax-keyword);
138
+ --candi-terminal-cyan: var(--candi-syntax-var);
139
+ --candi-terminal-white: var(--candi-text);
140
+ /* @tokens-end-dark */
141
+ }
142
+
143
+ /* Base styles */
144
+ html {
145
+ font-family: Helvetica, sans-serif;
146
+ line-height: 1.7;
147
+ letter-spacing: 0.01em;
148
+ }
149
+
150
+ body {
151
+ background-color: var(--candi-bg);
152
+ color: var(--candi-text);
153
+ transition: background-color 0.3s ease, color 0.3s ease;
154
+ }
155
+
156
+ ::selection {
157
+ background-color: var(--candi-accent-subtle);
158
+ color: var(--candi-text);
159
+ }
160
+
161
+ :focus-visible {
162
+ outline: 2px solid var(--candi-accent);
163
+ outline-offset: 2px;
164
+ }