@stanko/ctrls 0.3.0 → 0.3.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.
package/README.md CHANGED
@@ -423,7 +423,7 @@ Thank you for stopping by! If you end up using Ctrls, please let me know, I woul
423
423
  * [x] On input event / handler
424
424
  * [x] Revisit naming `controls` vs `options` vs `values`
425
425
  * [x] Remove lucide as a dependency, swap with local SVGs
426
- * [x] Add Aleas PRNG instead of seedrandom
426
+ * [x] Add Alea PRNG instead of seedrandom
427
427
  * [x] Storage options - none
428
428
  * [x] Fix get random value float point error in dual range (modulo with floats)
429
429
  * [x] Easing - fix handles jumping to previous positions after selecting preset (no storage)
@@ -7,11 +7,11 @@ export declare class BooleanCtrl implements Ctrl<boolean> {
7
7
  label: string;
8
8
  value: boolean;
9
9
  isRandomizationDisabled: boolean;
10
- onChange: CtrlChangeHandler<boolean>;
11
- onInput: CtrlChangeHandler<boolean>;
10
+ onChange: CtrlChangeHandler;
11
+ onInput: CtrlChangeHandler;
12
12
  element: HTMLElement;
13
13
  input: HTMLInputElement;
14
- constructor(config: CtrlConfig<boolean>, onChange: CtrlChangeHandler<boolean>, onInput: CtrlChangeHandler<boolean>);
14
+ constructor(config: CtrlConfig<boolean>, onChange: CtrlChangeHandler, onInput: CtrlChangeHandler);
15
15
  parse: (string: string) => string is "true";
16
16
  getRandomValue: () => boolean;
17
17
  getDefaultValue: () => boolean;
@@ -25,11 +25,11 @@ export class BooleanCtrl {
25
25
  input.checked = this.value;
26
26
  input.addEventListener("change", () => {
27
27
  this.value = input.checked;
28
- this.onChange(this.name, this.value);
28
+ this.onChange(this);
29
29
  });
30
30
  input.addEventListener("input", () => {
31
31
  this.value = input.checked;
32
- this.onInput(this.name, this.value);
32
+ this.onInput(this);
33
33
  });
34
34
  const checkmark = document.createElement("span");
35
35
  checkmark.classList.add("ctrls__boolean-checkmark");
@@ -17,8 +17,8 @@ export declare class DualRangeCtrl implements Ctrl<DualRangeValue> {
17
17
  label: string;
18
18
  value: DualRangeValue;
19
19
  isRandomizationDisabled: boolean;
20
- onChange: CtrlChangeHandler<DualRangeValue>;
21
- onInput: CtrlChangeHandler<DualRangeValue>;
20
+ onChange: CtrlChangeHandler;
21
+ onInput: CtrlChangeHandler;
22
22
  min: number;
23
23
  max: number;
24
24
  step: number;
@@ -27,7 +27,7 @@ export declare class DualRangeCtrl implements Ctrl<DualRangeValue> {
27
27
  maxInput: HTMLInputElement;
28
28
  dualRange: DualRangeInput;
29
29
  valueSpan: HTMLSpanElement;
30
- constructor(config: ConfigFor<"dual-range">, onChange: CtrlChangeHandler<DualRangeValue>, onInput: CtrlChangeHandler<DualRangeValue>);
30
+ constructor(config: ConfigFor<"dual-range">, onChange: CtrlChangeHandler, onInput: CtrlChangeHandler);
31
31
  parse: (string: string) => {
32
32
  min: number;
33
33
  max: number;
@@ -36,7 +36,7 @@ export class DualRangeCtrl {
36
36
  max: parseFloat(maxInput.value),
37
37
  };
38
38
  this.update(this.value);
39
- this.onChange(this.name, this.value);
39
+ this.onChange(this);
40
40
  };
41
41
  const inputHandler = () => {
42
42
  this.value = {
@@ -44,7 +44,7 @@ export class DualRangeCtrl {
44
44
  max: parseFloat(maxInput.value),
45
45
  };
46
46
  this.update(this.value);
47
- this.onInput(this.name, this.value);
47
+ this.onInput(this);
48
48
  };
49
49
  const minInput = document.createElement("input");
50
50
  minInput.setAttribute("type", "range");
@@ -8,8 +8,8 @@ export declare class EasingCtrl implements Ctrl<Easing> {
8
8
  label: string;
9
9
  value: Easing;
10
10
  isRandomizationDisabled: boolean;
11
- onChange: CtrlChangeHandler<Easing>;
12
- onInput: CtrlChangeHandler<Easing>;
11
+ onChange: CtrlChangeHandler;
12
+ onInput: CtrlChangeHandler;
13
13
  element: HTMLElement;
14
14
  ticks: SVGLineElement[];
15
15
  control: HTMLDivElement;
@@ -17,7 +17,7 @@ export declare class EasingCtrl implements Ctrl<Easing> {
17
17
  lines: SVGLineElement[];
18
18
  path: SVGPathElement;
19
19
  presets: Record<string, Easing>;
20
- constructor(config: ConfigFor<"easing">, onChange: CtrlChangeHandler<Easing>, onInput: CtrlChangeHandler<Easing>);
20
+ constructor(config: ConfigFor<"easing">, onChange: CtrlChangeHandler, onInput: CtrlChangeHandler);
21
21
  parse: (string: string) => Easing;
22
22
  getRandomValue: () => Easing;
23
23
  getDefaultValue: () => Easing;
@@ -117,14 +117,14 @@ export class EasingCtrl {
117
117
  dragging = false;
118
118
  const newValue = getNewValue(e.clientX, e.clientY);
119
119
  this.value = newValue;
120
- this.onChange(this.name, this.value);
120
+ this.onChange(this);
121
121
  this.update();
122
122
  }
123
123
  });
124
124
  document.addEventListener("mousemove", (e) => {
125
125
  if (dragging) {
126
126
  const newValue = getNewValue(e.clientX, e.clientY);
127
- this.onInput(this.name, this.value);
127
+ this.onInput(this);
128
128
  this.updateUI(newValue);
129
129
  }
130
130
  });
@@ -145,7 +145,7 @@ export class EasingCtrl {
145
145
  if (dragging) {
146
146
  e.preventDefault();
147
147
  const newValue = getNewValue(e.touches[0].clientX, e.touches[0].clientY);
148
- this.onInput(this.name, this.value);
148
+ this.onInput(this);
149
149
  this.updateUI(newValue);
150
150
  }
151
151
  });
@@ -155,7 +155,7 @@ export class EasingCtrl {
155
155
  dragging = false;
156
156
  const newValue = getNewValue(e.changedTouches[0].clientX, e.changedTouches[0].clientY);
157
157
  this.value = newValue;
158
- this.onChange(this.name, this.value);
158
+ this.onChange(this);
159
159
  this.update();
160
160
  }
161
161
  });
@@ -175,7 +175,7 @@ export class EasingCtrl {
175
175
  // Cap x values
176
176
  newValue[index] = Math.max(Math.min(newValue[index], 1), 0);
177
177
  this.value = newValue;
178
- this.onChange(this.name, this.value);
178
+ this.onChange(this);
179
179
  this.update();
180
180
  }
181
181
  });
@@ -192,7 +192,7 @@ export class EasingCtrl {
192
192
  button.textContent = key.toLowerCase().replace("ease_", "");
193
193
  button.addEventListener("click", () => {
194
194
  this.value = this.presets[key];
195
- this.onChange(this.name, this.value);
195
+ this.onChange(this);
196
196
  this.update();
197
197
  });
198
198
  presetButtons.appendChild(button);
@@ -15,12 +15,12 @@ export declare class RadioCtrl implements Ctrl<string> {
15
15
  label: string;
16
16
  value: string;
17
17
  isRandomizationDisabled: boolean;
18
- onChange: CtrlChangeHandler<string>;
19
- onInput: CtrlChangeHandler<string>;
18
+ onChange: CtrlChangeHandler;
19
+ onInput: CtrlChangeHandler;
20
20
  items: Option[];
21
21
  element: HTMLElement;
22
22
  columns: 1 | 2 | 3 | 4 | 5;
23
- constructor(config: ConfigFor<"radio">, onChange: CtrlChangeHandler<string>, onInput: CtrlChangeHandler<string>);
23
+ constructor(config: ConfigFor<"radio">, onChange: CtrlChangeHandler, onInput: CtrlChangeHandler);
24
24
  parse: (string: string) => string;
25
25
  getRandomValue: () => string;
26
26
  getDefaultValue: () => string;
@@ -29,11 +29,11 @@ export class RadioCtrl {
29
29
  input.checked = item.value === value;
30
30
  input.addEventListener("change", () => {
31
31
  this.value = this.parse(input.value);
32
- this.onChange(this.name, this.value);
32
+ this.onChange(this);
33
33
  });
34
34
  input.addEventListener("input", () => {
35
35
  this.value = this.parse(input.value);
36
- this.onInput(this.name, this.value);
36
+ this.onInput(this);
37
37
  });
38
38
  const label = document.createElement("span");
39
39
  label.textContent = item.label;
@@ -7,15 +7,15 @@ export declare class RangeCtrl implements Ctrl<number> {
7
7
  label: string;
8
8
  value: number;
9
9
  isRandomizationDisabled: boolean;
10
- onChange: CtrlChangeHandler<number>;
11
- onInput: CtrlChangeHandler<number>;
10
+ onChange: CtrlChangeHandler;
11
+ onInput: CtrlChangeHandler;
12
12
  min: number;
13
13
  max: number;
14
14
  step: number;
15
15
  element: HTMLElement;
16
16
  input: HTMLInputElement;
17
17
  valueSpan: HTMLSpanElement;
18
- constructor(config: ConfigFor<"range">, onChange: CtrlChangeHandler<number>, onInput: CtrlChangeHandler<number>);
18
+ constructor(config: ConfigFor<"range">, onChange: CtrlChangeHandler, onInput: CtrlChangeHandler);
19
19
  parse: (string: string) => number;
20
20
  getRandomValue: () => number;
21
21
  getDefaultValue: () => number;
@@ -33,12 +33,12 @@ export class RangeCtrl {
33
33
  input.addEventListener("input", () => {
34
34
  this.value = this.parse(input.value);
35
35
  this.update(this.value);
36
- this.onInput(this.name, this.value);
36
+ this.onInput(this);
37
37
  });
38
38
  input.addEventListener("change", () => {
39
39
  this.value = this.parse(input.value);
40
40
  this.update(this.value);
41
- this.onChange(this.name, this.value);
41
+ this.onChange(this);
42
42
  });
43
43
  input.addEventListener("input", () => {
44
44
  const value = this.parse(input.value);
@@ -7,11 +7,11 @@ export declare class SeedCtrl implements Ctrl<string> {
7
7
  label: string;
8
8
  value: string;
9
9
  isRandomizationDisabled: boolean;
10
- onChange: CtrlChangeHandler<string>;
11
- onInput: CtrlChangeHandler<string>;
10
+ onChange: CtrlChangeHandler;
11
+ onInput: CtrlChangeHandler;
12
12
  element: HTMLElement;
13
13
  input: HTMLInputElement;
14
- constructor(config: CtrlConfig<string>, onChange: CtrlChangeHandler<string>, onInput: CtrlChangeHandler<string>);
14
+ constructor(config: CtrlConfig<string>, onChange: CtrlChangeHandler, onInput: CtrlChangeHandler);
15
15
  parse: (string: string) => string;
16
16
  getRandomValue: () => string;
17
17
  getDefaultValue: () => string;
@@ -30,11 +30,11 @@ export class SeedCtrl {
30
30
  input.setAttribute("name", id);
31
31
  input.addEventListener("change", () => {
32
32
  this.value = this.parse(input.value);
33
- this.onChange(this.name, this.value);
33
+ this.onChange(this);
34
34
  });
35
35
  input.addEventListener("input", () => {
36
36
  this.value = this.parse(input.value);
37
- this.onInput(this.name, this.value);
37
+ this.onInput(this);
38
38
  });
39
39
  const reload = document.createElement("button");
40
40
  reload.innerHTML = refreshIcon;
@@ -42,7 +42,7 @@ export class SeedCtrl {
42
42
  reload.addEventListener("click", () => {
43
43
  this.value = this.getRandomValue();
44
44
  this.update();
45
- this.onChange(this.name, this.getRandomValue());
45
+ this.onChange(this);
46
46
  });
47
47
  const right = document.createElement("div");
48
48
  right.classList.add("ctrls__control-right");
@@ -9,7 +9,7 @@ export interface PRNG {
9
9
  (): number;
10
10
  }
11
11
  export type CtrlType = "boolean" | "range" | "radio" | "seed" | "easing" | "dual-range" | "group";
12
- export type CtrlChangeHandler<T> = (name: string, value: T) => void;
12
+ export type CtrlChangeHandler = (control: CtrlComponent) => void;
13
13
  export type CtrlConfig<T = unknown> = {
14
14
  type: CtrlType;
15
15
  id?: string;
@@ -26,7 +26,7 @@ export interface Ctrl<T> {
26
26
  label: string;
27
27
  type: CtrlType;
28
28
  isRandomizationDisabled: boolean;
29
- onChange: CtrlChangeHandler<T>;
29
+ onChange: CtrlChangeHandler;
30
30
  parse: (value: string) => T;
31
31
  getRandomValue: () => T;
32
32
  getDefaultValue: () => T;
@@ -130,14 +130,14 @@ export declare class Ctrls<Configs extends readonly ConfigItem[]> {
130
130
  onChange?: (updatedValues: Partial<ReturnType<typeof this.getValues>>) => void;
131
131
  onInput?: (updatedValues: Partial<ReturnType<typeof this.getValues>>) => void;
132
132
  constructor(configs: Configs, options?: ControlsOptions);
133
- registerControl: (config: TypedControlConfig, onChangeControlHandler: (name: string, value: unknown) => void, onInputControlHandler: (name: string, value: unknown) => void, group?: string) => void;
133
+ registerControl: (config: TypedControlConfig, onChangeControlHandler: (control: CtrlComponent) => void, onInputControlHandler: (control: CtrlComponent) => void, group?: string) => void;
134
134
  buildUI: () => HTMLDivElement;
135
135
  toggleVisibility: () => void;
136
136
  addHashListeners: () => void;
137
137
  getHash: () => string;
138
138
  setHash: () => void;
139
139
  updateFromHash: () => void;
140
- updateValuesObject(options: any, control: CtrlComponent): void;
140
+ updateValuesObject(values: any, control: CtrlComponent): void;
141
141
  getValues(): OptionsMap<Configs>;
142
142
  randomize: () => void;
143
143
  }
@@ -40,11 +40,11 @@ export class Ctrls {
40
40
  // because it is nicer that URL be all lowercase
41
41
  config.name = toCamelCase(config.name);
42
42
  if (group) {
43
+ config.group = group;
43
44
  config.id = toCamelCase(`${group}-${config.name}`);
44
45
  }
45
46
  const ControlComponent = controlMap[config.type];
46
47
  const control = new ControlComponent(config, onChangeControlHandler, onInputControlHandler);
47
- control.group = group;
48
48
  this.controlsMap[control.id] = control;
49
49
  this.controls.push(control);
50
50
  };
@@ -122,22 +122,22 @@ export class Ctrls {
122
122
  const items = [];
123
123
  pairs.forEach((pair) => {
124
124
  const [kebabCaseName, value] = pair.split(":");
125
- const name = toCamelCase(kebabCaseName);
126
- const control = this.controlsMap[name];
125
+ const id = toCamelCase(kebabCaseName);
126
+ const control = this.controlsMap[id];
127
127
  if (control) {
128
128
  const parsed = control.parse(value);
129
129
  items.push({
130
- name,
130
+ id,
131
131
  value: parsed,
132
132
  });
133
133
  }
134
134
  });
135
135
  const updatedValues = {};
136
136
  items.forEach((item) => {
137
- const { name, value } = item;
138
- const control = this.controlsMap[name];
137
+ const { id, value } = item;
138
+ const control = this.controlsMap[id];
139
139
  if (control && JSON.stringify(value) !== JSON.stringify(control.value)) {
140
- updatedValues[name] = value;
140
+ this.updateValuesObject(updatedValues, control);
141
141
  control.update(value);
142
142
  }
143
143
  });
@@ -154,7 +154,7 @@ export class Ctrls {
154
154
  }
155
155
  control.value = control.getRandomValue();
156
156
  control.update(control.value);
157
- updatedValues[control.name] = control.value;
157
+ this.updateValuesObject(updatedValues, control);
158
158
  });
159
159
  if (Object.keys(updatedValues).length > 0) {
160
160
  this.onChange?.(updatedValues);
@@ -170,14 +170,18 @@ export class Ctrls {
170
170
  theme: "system",
171
171
  ...options,
172
172
  };
173
- const onChangeControlHandler = (name, value) => {
174
- this.onChange?.({ [name]: value });
173
+ const onChangeControlHandler = (control) => {
174
+ const updatedValues = {};
175
+ this.updateValuesObject(updatedValues, control);
176
+ this.onChange?.(updatedValues);
175
177
  if (this.options.storage === "hash") {
176
178
  this.setHash();
177
179
  }
178
180
  };
179
- const onInputControlHandler = (name, value) => {
180
- this.onInput?.({ [name]: value });
181
+ const onInputControlHandler = (control) => {
182
+ const updatedValues = {};
183
+ this.updateValuesObject(updatedValues, control);
184
+ this.onInput?.(updatedValues);
181
185
  };
182
186
  configs.map((config) => {
183
187
  if (config.type === "group") {
@@ -197,28 +201,27 @@ export class Ctrls {
197
201
  this.options.parent.appendChild(this.element);
198
202
  }
199
203
  }
200
- updateValuesObject(options, control) {
201
- options[control.name] = control.value;
204
+ updateValuesObject(values, control) {
205
+ let objectToUpdate = values;
206
+ if (control.group) {
207
+ if (!values[control.group]) {
208
+ values[control.group] = {};
209
+ }
210
+ objectToUpdate = values[control.group];
211
+ }
212
+ objectToUpdate[control.name] = control.value;
202
213
  if (control.type === "easing") {
203
- options[control.name + "Easing"] = BezierEasing(...control.value);
214
+ objectToUpdate[control.name + "Easing"] = BezierEasing(...control.value);
204
215
  }
205
216
  else if (control.type === "seed") {
206
- options[control.name + "Rng"] = Alea(...control.value.split("-"));
217
+ objectToUpdate[control.name + "Rng"] = Alea(...control.value.split("-"));
207
218
  }
208
219
  }
209
220
  getValues() {
210
- const options = {};
221
+ const values = {};
211
222
  this.controls.forEach((control) => {
212
- if (control.group) {
213
- if (!options[control.group]) {
214
- options[control.group] = {};
215
- }
216
- this.updateValuesObject(options[control.group], control);
217
- }
218
- else {
219
- this.updateValuesObject(options, control);
220
- }
223
+ this.updateValuesObject(values, control);
221
224
  });
222
- return options;
225
+ return values;
223
226
  }
224
227
  }
package/dist/ctrls.css CHANGED
@@ -320,22 +320,15 @@
320
320
  background: var(--ctrls-btn-hover-bg);
321
321
  }
322
322
 
323
- .ctrls__title {
324
- border-block-end: 1px solid var(--ctrls-border);
325
- }
326
-
327
323
  .ctrls__controls {
328
324
  display: grid;
329
- padding-top: 0.5rem;
325
+ padding-block: 0.5rem;
326
+ gap: 0.5rem;
330
327
  overflow: auto;
331
328
  scrollbar-width: thin;
332
329
  scrollbar-color: var(--ctrls-scrollbar-thumb-bg) transparent;
333
330
  }
334
331
 
335
- .ctrls__controls > * {
336
- margin-bottom: 0.5rem;
337
- }
338
-
339
332
  .ctrls--hidden .ctrls__controls {
340
333
  display: none;
341
334
  }
@@ -392,14 +385,15 @@
392
385
 
393
386
  /* ----- Groups ----- */
394
387
  .ctrls__group {
388
+ margin: 0 0.5rem;
395
389
  display: grid;
396
390
  gap: 0.5rem;
397
391
  padding-block-end: 0.5rem;
398
- border-block: 1px solid var(--ctrls-border);
392
+ border: 1px solid var(--ctrls-border);
393
+ border-radius: var(--ctrls-radius);
399
394
  }
400
395
 
401
396
  .ctrls__group .ctrls__control {
402
- padding-inline-start: 1rem;
403
397
  grid-template-columns: calc(var(--ctrls-label-width) - 0.5rem) minmax(0, 1fr);
404
398
  }
405
399
 
@@ -1 +1 @@
1
- {"version":3,"sourceRoot":"","sources":["../node_modules/@stanko/dual-range-input/dist/index.css","../src/scss/_ctrls.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;;AC3IF;EACE;AAAA;AAAA;EAGA;EACA;EACA;EACA;EACA;EAGA;EACA;EAEA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EAGA;EACA;EACA;EAGA;EACA;EAGA;EAGA;EAEA;EACA;EAEA;EACA;EAGA;EAGA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EAGA;EACA;EAEA;EAEA;EACA;EAEA;EAGA;EAEA;EACA;;;AA+CF;EACE;IA3CA;IAEA;IACA;IAGA;IACA;IACA;IACA;IACA;IACA;IAGA;IAGA;IACA;IACA;IAGA;IACA;IAGA;IAGA;IAEA;IAGA;IAGA;AAAA;AAAA;;;AAWF;EAhDE;EAEA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EAGA;EACA;EACA;EAGA;EACA;EAGA;EAGA;EAEA;EAGA;EAGA;AAAA;AAAA;;;AAiBF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;EAGE;EACA;EACA;;AAGF;AAAA;EAEE;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;AAAA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;;AAGF;AAAA;AAAA;EAEE;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;;AAGF;EAEE;;AAGF;EACE;EACA;EACA,YACE;;AAIJ;EACE;;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;EACA;;;AAOA;EACE;;AAGF;AAAA;AAAA;EAEE;;;AAKN;AAEA;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAEA;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAKA;AAAA;EACE;EACA;EACA;;;AAIJ;AAEA;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;;AAKJ;EACE;EACA;EACA;;;AAIF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAGF;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;;AAmCJ;EA5BE;EACA;EACA;EACA;EACA;EAEA;;;AA0BF;EAhCE;EACA;EACA;EACA;EACA;EAEA;;;AA8BF;EAtBE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAkBA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAKF;EAvDE;EACA;EACA;EACA;EACA;EAEA;;;AAqDF;EA7CE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAwCA;EACA;;;AAGF;EACE;EACA;;;AAGF;AAEA;EAGE;;AAEA;EACE;;AANJ;EASE;EACA;EAEA;EACA;EACA;EAEA;EACA;EACA;EACA;EAEA;EACA;EACA;;AAEA;EACE;;;AAIJ;AAEA;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;EAEF;EACA;EACA;;AAEA;EAEE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;AAEA;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;EACA;;AAIE;EACE;;;AAKN;AAEA;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;AAAA;EAEE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;;AAGF;EAEE;EACA;;;AAIJ;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;;AAEA;EACE;EACA","file":"ctrls.css"}
1
+ {"version":3,"sourceRoot":"","sources":["../node_modules/@stanko/dual-range-input/dist/index.css","../src/scss/_ctrls.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;;AC3IF;EACE;AAAA;AAAA;EAGA;EACA;EACA;EACA;EACA;EAGA;EACA;EAEA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EAGA;EACA;EACA;EAGA;EACA;EAGA;EAGA;EAEA;EACA;EAEA;EACA;EAGA;EAGA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EAGA;EACA;EAEA;EAEA;EACA;EAEA;EAGA;EAEA;EACA;;;AA+CF;EACE;IA3CA;IAEA;IACA;IAGA;IACA;IACA;IACA;IACA;IACA;IAGA;IAGA;IACA;IACA;IAGA;IACA;IAGA;IAGA;IAEA;IAGA;IAGA;AAAA;AAAA;;;AAWF;EAhDE;EAEA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EAGA;EACA;EACA;EAGA;EACA;EAGA;EAGA;EAEA;EAGA;EAGA;AAAA;AAAA;;;AAiBF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;EAGE;EACA;EACA;;AAGF;AAAA;EAEE;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;AAAA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;;AAGF;AAAA;AAAA;EAEE;EACA;;;AAOJ;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;;AAGF;EAEE;;AAGF;EACE;EACA;EACA,YACE;;AAIJ;EACE;;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;EACA;;;AAOA;EACE;;AAGF;AAAA;AAAA;EAEE;;;AAKN;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAEA;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAKA;AAAA;EACE;EACA;EACA;;;AAIJ;AAEA;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;;AAKJ;EACE;EACA;EACA;;;AAIF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAGF;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;;AAmCJ;EA5BE;EACA;EACA;EACA;EACA;EAEA;;;AA0BF;EAhCE;EACA;EACA;EACA;EACA;EAEA;;;AA8BF;EAtBE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAkBA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAKF;EAvDE;EACA;EACA;EACA;EACA;EAEA;;;AAqDF;EA7CE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAwCA;EACA;;;AAGF;EACE;EACA;;;AAGF;AAEA;EAGE;;AAEA;EACE;;AANJ;EASE;EACA;EAEA;EACA;EACA;EAEA;EACA;EACA;EACA;EAEA;EACA;EACA;;AAEA;EACE;;;AAIJ;AAEA;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;EAEF;EACA;EACA;;AAEA;EAEE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;AAEA;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;EACA;;AAIE;EACE;;;AAKN;AAEA;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;AAAA;EAEE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;;AAGF;EAEE;EACA;;;AAIJ;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;;AAEA;EACE;EACA","file":"ctrls.css"}
@@ -1,28 +1,35 @@
1
1
  // Algorithm by Johannes Baagøe
2
2
  // Slim TypeScript version of this implementation:
3
3
  // https://github.com/coverslide/node-alea
4
- const getMash = () => {
5
- let n = 0xefc8249d;
6
- const mash = (seed) => {
7
- for (let i = 0; i < seed.length; i++) {
8
- n += seed.charCodeAt(i);
9
- let h = 0.02519603282416938 * n;
10
- n = h >>> 0;
11
- h -= n;
12
- h *= n;
13
- n = h >>> 0;
14
- h -= n;
15
- n += h * 0x100000000; // 2^32
16
- }
17
- return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
18
- };
19
- return mash;
20
- };
21
4
  const Alea = (...seeds) => {
5
+ const getMash = () => {
6
+ let n = 0xefc8249d;
7
+ const mash = (seed) => {
8
+ for (let i = 0; i < seed.length; i++) {
9
+ n += seed.charCodeAt(i);
10
+ let h = 0.02519603282416938 * n;
11
+ n = h >>> 0;
12
+ h -= n;
13
+ h *= n;
14
+ n = h >>> 0;
15
+ h -= n;
16
+ n += h * 0x100000000; // 2^32
17
+ }
18
+ return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
19
+ };
20
+ return mash;
21
+ };
22
+ const getRandomSeeds = () => {
23
+ return [
24
+ Math.random().toString(36).slice(2),
25
+ Math.random().toString(36).slice(2),
26
+ Math.random().toString(36).slice(2),
27
+ ];
28
+ };
22
29
  const mash = getMash();
23
30
  const s = [mash(" "), mash(" "), mash(" ")];
24
31
  let c = 1;
25
- seeds.forEach((seed) => {
32
+ (seeds || getRandomSeeds()).forEach((seed) => {
26
33
  s.forEach((_, i) => {
27
34
  s[i] -= mash(seed);
28
35
  if (s[i] < 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stanko/ctrls",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "vitest",
@@ -20,13 +20,13 @@
20
20
  ],
21
21
  "devDependencies": {
22
22
  "highlight.js": "^11.11.1",
23
- "marked": "^16.2.1",
24
- "marked-highlight": "^2.2.2",
25
- "sass": "^1.92.1",
23
+ "marked": "^17.0.0",
24
+ "marked-highlight": "^2.2.3",
25
+ "sass": "^1.94.0",
26
26
  "simplex-noise": "^4.0.3",
27
- "typescript": "~5.9.2",
28
- "vite": "^7.1.5",
29
- "vitest": "^4.0.9"
27
+ "typescript": "~5.9.3",
28
+ "vite": "^7.2.2",
29
+ "vitest": "^4.0.10"
30
30
  },
31
31
  "dependencies": {
32
32
  "@stanko/dual-range-input": "^1.0.1",