@basiclines/rampa 1.6.0 → 1.7.1

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.
Files changed (3) hide show
  1. package/README.md +17 -0
  2. package/dist/index.js +83 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -183,6 +183,9 @@ The `colorspace` subcommand lets you define and query multi-dimensional color sp
183
183
  # Linear: 2-color interpolated ramp
184
184
  rampa colorspace --linear '#ffffff' '#000000' --size 24 --at 12
185
185
 
186
+ # Plane: 2D saturation×lightness for a single hue
187
+ rampa colorspace --plane '#1e1e2e' '#cdd6f4' '#f38ba8' --size 6 --xy 3,5
188
+
186
189
  # Cube: 8-corner color cube with named aliases
187
190
  rampa colorspace --cube k=#1e1e2e r=#f38ba8 g=#a6e3a1 b=#89b4fa \
188
191
  y=#f9e2af m=#cba6f7 c=#94e2d5 w=#cdd6f4 \
@@ -211,15 +214,29 @@ Config file format:
211
214
  }
212
215
  ```
213
216
 
217
+ Plane config:
218
+ ```json
219
+ {
220
+ "type": "plane",
221
+ "dark": "#1e1e2e",
222
+ "light": "#cdd6f4",
223
+ "hue": "#f38ba8",
224
+ "size": 6,
225
+ "interpolation": "oklch"
226
+ }
227
+ ```
228
+
214
229
  #### Colorspace Flags
215
230
 
216
231
  | Flag | Description | Default |
217
232
  |------|-------------|---------|
218
233
  | `--linear` | Define a linear color space (2+ colors) | - |
234
+ | `--plane` | Define a plane color space (dark light hue) | - |
219
235
  | `--cube` | Define a cube color space (8 key=color pairs) | - |
220
236
  | `--config` | Load color space from a JSON config file | - |
221
237
  | `--size` | Resolution per axis | 6 |
222
238
  | `--at` | Query a specific 1-based index (linear) | - |
239
+ | `--xy` | Query plane with saturation,lightness (e.g., `3,5`) | - |
223
240
  | `--tint` | Query cube with alias:intensity pairs (e.g., `r:4,b:2`) | - |
224
241
  | `--interpolation` | Interpolation mode: oklch, lab, rgb, false | oklch |
225
242
  | `--format` | Output format: hex, hsl, rgb, oklch | hex |
package/dist/index.js CHANGED
@@ -8950,6 +8950,21 @@ function generateCubeSpace(corners, stepsPerAxis, mode = "oklch") {
8950
8950
  }
8951
8951
  return colors2;
8952
8952
  }
8953
+ function generatePlaneSpace(dark, light, hue3, stepsPerAxis, mode = "oklch") {
8954
+ const mix = (a2, b2, t2) => mixWithMode(a2, b2, t2, mode);
8955
+ const max11 = stepsPerAxis - 1;
8956
+ const colors2 = [];
8957
+ for (let xi = 0;xi < stepsPerAxis; xi++) {
8958
+ const tx = max11 === 0 ? 0 : xi / max11;
8959
+ const bottom = dark;
8960
+ const top = mix(light, hue3, tx);
8961
+ for (let yi = 0;yi < stepsPerAxis; yi++) {
8962
+ const ty = max11 === 0 ? 0 : yi / max11;
8963
+ colors2.push(mix(bottom, top, ty));
8964
+ }
8965
+ }
8966
+ return colors2;
8967
+ }
8953
8968
  var init_ColorSpaceEngine = __esm(() => {
8954
8969
  init_OklchEngine();
8955
8970
  init_chroma_js2();
@@ -8973,6 +8988,7 @@ Query colors from a color space defined by anchor colors
8973
8988
  USAGE
8974
8989
  ${cyan}rampa colorspace --cube key=color ... [options]${reset}
8975
8990
  ${cyan}rampa colorspace --linear color ... [options]${reset}
8991
+ ${cyan}rampa colorspace --plane dark light hue [options]${reset}
8976
8992
  ${cyan}rampa colorspace --config file.json [options]${reset}
8977
8993
 
8978
8994
  COLOR SPACE DEFINITION
@@ -8982,6 +8998,9 @@ COLOR SPACE DEFINITION
8982
8998
  ${cyan}--linear color ...${reset} ${dim}Define a LinearColorSpace from 2+ colors${reset}
8983
8999
  ${dim}Interpolates between first and last color${reset}
8984
9000
 
9001
+ ${cyan}--plane dark light hue${reset} ${dim}Define a PlaneColorSpace (2D saturation×lightness)${reset}
9002
+ ${dim}dark=origin, light=achromatic anchor, hue=chromatic corner${reset}
9003
+
8985
9004
  ${cyan}--config file.json${reset} ${dim}Load color space from a JSON config file${reset}
8986
9005
 
8987
9006
  OPTIONS
@@ -8997,6 +9016,9 @@ QUERIES ${dim}(omit to output full palette)${reset}
8997
9016
  ${cyan}--at N${reset} ${dim}Query LinearColorSpace by 1-based index${reset}
8998
9017
  ${dim}Example: --at 12${reset}
8999
9018
 
9019
+ ${cyan}--xy sat,light${reset} ${dim}Query PlaneColorSpace by saturation,lightness${reset}
9020
+ ${dim}Example: --xy 3,5${reset}
9021
+
9000
9022
  OUTPUT
9001
9023
  ${cyan}--format type${reset} ${dim}Color format: hex (default), hsl, rgb, oklch${reset}
9002
9024
  ${cyan}--output type${reset} ${dim}Full palette format: text (default), json${reset}
@@ -9019,6 +9041,9 @@ EXAMPLES
9019
9041
  rampa colorspace --linear '#f00' '#0f0' '#00f' '#ff0' \\
9020
9042
  --interpolation false --at 2
9021
9043
 
9044
+ ${dim}# Plane: 2D saturation×lightness for a single hue${reset}
9045
+ rampa colorspace --plane '#1e1e2e' '#cdd6f4' '#f38ba8' --size 6 --xy 3,5
9046
+
9022
9047
  ${dim}# Query from config file${reset}
9023
9048
  rampa colorspace --config catppuccin.json --tint r:4,b:2
9024
9049
  `;
@@ -9080,6 +9105,30 @@ function parseColorspaceArgs(argv2) {
9080
9105
  }
9081
9106
  continue;
9082
9107
  }
9108
+ if (arg === "--plane") {
9109
+ args.mode = "plane";
9110
+ i2++;
9111
+ const planeColors = [];
9112
+ while (i2 < argv2.length && !argv2[i2].startsWith("--")) {
9113
+ const color = argv2[i2];
9114
+ try {
9115
+ chroma_js_default(color);
9116
+ } catch {
9117
+ console.error(`Invalid color: ${color}`);
9118
+ process.exit(1);
9119
+ }
9120
+ planeColors.push(color);
9121
+ i2++;
9122
+ }
9123
+ if (planeColors.length !== 3) {
9124
+ console.error("PlaneColorSpace requires exactly 3 colors: dark light hue");
9125
+ process.exit(1);
9126
+ }
9127
+ args.dark = planeColors[0];
9128
+ args.light = planeColors[1];
9129
+ args.hue = planeColors[2];
9130
+ continue;
9131
+ }
9083
9132
  if (arg === "--config") {
9084
9133
  args.mode = "config";
9085
9134
  args.configPath = argv2[++i2];
@@ -9112,6 +9161,12 @@ function parseColorspaceArgs(argv2) {
9112
9161
  i2++;
9113
9162
  continue;
9114
9163
  }
9164
+ if (arg === "--xy") {
9165
+ const parts = argv2[++i2].split(",");
9166
+ args.xy = [parseInt(parts[0]), parseInt(parts[1])];
9167
+ i2++;
9168
+ continue;
9169
+ }
9115
9170
  if (arg === "--format") {
9116
9171
  args.format = argv2[++i2];
9117
9172
  i2++;
@@ -9140,6 +9195,11 @@ function loadConfig(path) {
9140
9195
  if (config.type === "linear" || config.colors) {
9141
9196
  args.mode = "linear";
9142
9197
  args.colors = config.colors;
9198
+ } else if (config.type === "plane") {
9199
+ args.mode = "plane";
9200
+ args.dark = config.dark;
9201
+ args.light = config.light;
9202
+ args.hue = config.hue;
9143
9203
  } else {
9144
9204
  args.mode = "cube";
9145
9205
  args.corners = config.corners;
@@ -9178,11 +9238,14 @@ function runColorspace(argv2) {
9178
9238
  ...Object.fromEntries(Object.entries(args).filter(([, v2]) => v2 !== undefined && v2 !== 0)),
9179
9239
  mode: config.mode,
9180
9240
  corners: config.corners,
9181
- colors: config.colors
9241
+ colors: config.colors,
9242
+ dark: config.dark,
9243
+ light: config.light,
9244
+ hue: config.hue
9182
9245
  };
9183
9246
  }
9184
9247
  if (args.size === 0) {
9185
- args.size = args.mode === "cube" ? 6 : 24;
9248
+ args.size = args.mode === "linear" ? 24 : 6;
9186
9249
  }
9187
9250
  let palette;
9188
9251
  let aliases;
@@ -9202,6 +9265,12 @@ function runColorspace(argv2) {
9202
9265
  } else {
9203
9266
  palette = generateCubeSpace(cornerColors, args.size, args.interpolation);
9204
9267
  }
9268
+ } else if (args.mode === "plane") {
9269
+ if (!args.dark || !args.light || !args.hue) {
9270
+ console.error("PlaneColorSpace requires 3 colors: dark light hue");
9271
+ process.exit(1);
9272
+ }
9273
+ palette = generatePlaneSpace(args.dark, args.light, args.hue, args.size, args.interpolation === false ? "oklch" : args.interpolation);
9205
9274
  } else {
9206
9275
  if (!args.colors || args.colors.length < 2) {
9207
9276
  console.error("LinearColorSpace requires at least 2 colors");
@@ -9238,6 +9307,18 @@ function runColorspace(argv2) {
9238
9307
  console.log(formatColor2(palette[i2], args.format));
9239
9308
  return;
9240
9309
  }
9310
+ if (args.xy !== undefined) {
9311
+ if (args.mode !== "plane") {
9312
+ console.error("--xy query is only supported with --plane mode");
9313
+ process.exit(1);
9314
+ }
9315
+ const [sat, light] = args.xy;
9316
+ const sx = Math.max(0, Math.min(args.size - 1, sat));
9317
+ const ly = Math.max(0, Math.min(args.size - 1, light));
9318
+ const index = sx * args.size + ly;
9319
+ console.log(formatColor2(palette[index], args.format));
9320
+ return;
9321
+ }
9241
9322
  if (args.output === "json") {
9242
9323
  const formatted = palette.map((hex6) => formatColor2(hex6, args.format));
9243
9324
  console.log(JSON.stringify({ palette: formatted, size: palette.length }, null, 2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basiclines/rampa",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "Generate mathematically accurate color palettes from a base color",
5
5
  "type": "module",
6
6
  "bin": {