@zag-js/color-picker 0.24.0 → 0.25.0

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/index.d.mts CHANGED
@@ -8,7 +8,7 @@ import { InteractOutsideHandlers } from '@zag-js/dismissable';
8
8
  import { PositioningOptions } from '@zag-js/popper';
9
9
  import { MaybeFunction } from '@zag-js/utils';
10
10
 
11
- declare const anatomy: _zag_js_anatomy.Anatomy<"root" | "label" | "control" | "trigger" | "positioner" | "content" | "area" | "areaThumb" | "areaBackground" | "channelSlider" | "channelSliderTrack" | "channelSliderThumb" | "channelInput" | "transparancyGrid" | "swatchGroup" | "swatchTrigger" | "swatch" | "eyeDropperTrigger">;
11
+ declare const anatomy: _zag_js_anatomy.Anatomy<"root" | "label" | "control" | "trigger" | "positioner" | "content" | "area" | "areaThumb" | "areaBackground" | "channelSlider" | "channelSliderTrack" | "channelSliderThumb" | "channelInput" | "transparencyGrid" | "swatchGroup" | "swatchTrigger" | "swatch" | "eyeDropperTrigger">;
12
12
 
13
13
  interface ValueChangeDetails {
14
14
  value: Color;
@@ -69,16 +69,6 @@ interface PublicContext extends CommonProperties, InteractOutsideHandlers {
69
69
  * The name for the form input
70
70
  */
71
71
  name?: string;
72
- /**
73
- * The color format to use (rgb, hsl, hsb)
74
- * @default "hsl"
75
- */
76
- format?: ColorFormat;
77
- /**
78
- * The alpha format to use (decimal, percent)
79
- * @default "decimal"
80
- */
81
- alphaFormat?: "decimal" | "percent";
82
72
  /**
83
73
  * The positioning options for the color picker
84
74
  */
@@ -157,8 +147,8 @@ interface SwatchProps {
157
147
  */
158
148
  respectAlpha?: boolean;
159
149
  }
160
- interface TransparancyGridProps {
161
- size: string;
150
+ interface TransparencyGridProps {
151
+ size?: string;
162
152
  }
163
153
  interface MachineApi<T extends PropTypes = PropTypes> {
164
154
  /**
@@ -193,6 +183,10 @@ interface MachineApi<T extends PropTypes = PropTypes> {
193
183
  * Function to set the color value of a specific channel
194
184
  */
195
185
  setChannelValue(channel: ColorChannel, value: number): void;
186
+ /**
187
+ * The current color format
188
+ */
189
+ format: ColorFormat;
196
190
  /**
197
191
  * Function to set the color format
198
192
  */
@@ -200,7 +194,7 @@ interface MachineApi<T extends PropTypes = PropTypes> {
200
194
  /**
201
195
  * The alpha value of the color
202
196
  */
203
- getAlpha(): number;
197
+ alpha: number;
204
198
  /**
205
199
  * Function to set the color alpha
206
200
  */
@@ -219,7 +213,7 @@ interface MachineApi<T extends PropTypes = PropTypes> {
219
213
  getChannelSliderTrackProps(props: ChannelProps): T["element"];
220
214
  getChannelSliderThumbProps(props: ChannelProps): T["element"];
221
215
  getChannelInputProps(props: ChannelInputProps): T["input"];
222
- getTransparencyGridProps(props: TransparancyGridProps): T["element"];
216
+ getTransparencyGridProps(props?: TransparencyGridProps): T["element"];
223
217
  eyeDropperTriggerProps: T["button"];
224
218
  swatchGroupProps: T["element"];
225
219
  getSwatchTriggerProps(props: SwatchTriggerProps): T["button"];
@@ -232,4 +226,4 @@ declare function machine(userContext: UserDefinedContext): _zag_js_core.Machine<
232
226
 
233
227
  declare const parse: (color: string) => Color;
234
228
 
235
- export { MachineApi as Api, AreaProps, ChannelInputProps, ChannelProps, UserDefinedContext as Context, SwatchProps, anatomy, connect, machine, parse };
229
+ export { MachineApi as Api, AreaProps, ChannelInputProps, ChannelProps, UserDefinedContext as Context, SwatchProps, SwatchTriggerProps, TransparencyGridProps, anatomy, connect, machine, parse };
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import { InteractOutsideHandlers } from '@zag-js/dismissable';
8
8
  import { PositioningOptions } from '@zag-js/popper';
9
9
  import { MaybeFunction } from '@zag-js/utils';
10
10
 
11
- declare const anatomy: _zag_js_anatomy.Anatomy<"root" | "label" | "control" | "trigger" | "positioner" | "content" | "area" | "areaThumb" | "areaBackground" | "channelSlider" | "channelSliderTrack" | "channelSliderThumb" | "channelInput" | "transparancyGrid" | "swatchGroup" | "swatchTrigger" | "swatch" | "eyeDropperTrigger">;
11
+ declare const anatomy: _zag_js_anatomy.Anatomy<"root" | "label" | "control" | "trigger" | "positioner" | "content" | "area" | "areaThumb" | "areaBackground" | "channelSlider" | "channelSliderTrack" | "channelSliderThumb" | "channelInput" | "transparencyGrid" | "swatchGroup" | "swatchTrigger" | "swatch" | "eyeDropperTrigger">;
12
12
 
13
13
  interface ValueChangeDetails {
14
14
  value: Color;
@@ -69,16 +69,6 @@ interface PublicContext extends CommonProperties, InteractOutsideHandlers {
69
69
  * The name for the form input
70
70
  */
71
71
  name?: string;
72
- /**
73
- * The color format to use (rgb, hsl, hsb)
74
- * @default "hsl"
75
- */
76
- format?: ColorFormat;
77
- /**
78
- * The alpha format to use (decimal, percent)
79
- * @default "decimal"
80
- */
81
- alphaFormat?: "decimal" | "percent";
82
72
  /**
83
73
  * The positioning options for the color picker
84
74
  */
@@ -157,8 +147,8 @@ interface SwatchProps {
157
147
  */
158
148
  respectAlpha?: boolean;
159
149
  }
160
- interface TransparancyGridProps {
161
- size: string;
150
+ interface TransparencyGridProps {
151
+ size?: string;
162
152
  }
163
153
  interface MachineApi<T extends PropTypes = PropTypes> {
164
154
  /**
@@ -193,6 +183,10 @@ interface MachineApi<T extends PropTypes = PropTypes> {
193
183
  * Function to set the color value of a specific channel
194
184
  */
195
185
  setChannelValue(channel: ColorChannel, value: number): void;
186
+ /**
187
+ * The current color format
188
+ */
189
+ format: ColorFormat;
196
190
  /**
197
191
  * Function to set the color format
198
192
  */
@@ -200,7 +194,7 @@ interface MachineApi<T extends PropTypes = PropTypes> {
200
194
  /**
201
195
  * The alpha value of the color
202
196
  */
203
- getAlpha(): number;
197
+ alpha: number;
204
198
  /**
205
199
  * Function to set the color alpha
206
200
  */
@@ -219,7 +213,7 @@ interface MachineApi<T extends PropTypes = PropTypes> {
219
213
  getChannelSliderTrackProps(props: ChannelProps): T["element"];
220
214
  getChannelSliderThumbProps(props: ChannelProps): T["element"];
221
215
  getChannelInputProps(props: ChannelInputProps): T["input"];
222
- getTransparencyGridProps(props: TransparancyGridProps): T["element"];
216
+ getTransparencyGridProps(props?: TransparencyGridProps): T["element"];
223
217
  eyeDropperTriggerProps: T["button"];
224
218
  swatchGroupProps: T["element"];
225
219
  getSwatchTriggerProps(props: SwatchTriggerProps): T["button"];
@@ -232,4 +226,4 @@ declare function machine(userContext: UserDefinedContext): _zag_js_core.Machine<
232
226
 
233
227
  declare const parse: (color: string) => Color;
234
228
 
235
- export { MachineApi as Api, AreaProps, ChannelInputProps, ChannelProps, UserDefinedContext as Context, SwatchProps, anatomy, connect, machine, parse };
229
+ export { MachineApi as Api, AreaProps, ChannelInputProps, ChannelProps, UserDefinedContext as Context, SwatchProps, SwatchTriggerProps, TransparencyGridProps, anatomy, connect, machine, parse };
package/dist/index.js CHANGED
@@ -43,7 +43,7 @@ var anatomy = (0, import_anatomy.createAnatomy)("color-picker", [
43
43
  "channelSliderTrack",
44
44
  "channelSliderThumb",
45
45
  "channelInput",
46
- "transparancyGrid",
46
+ "transparencyGrid",
47
47
  "swatchGroup",
48
48
  "swatchTrigger",
49
49
  "swatch",
@@ -104,7 +104,10 @@ var dom = (0, import_dom_query.createScope)({
104
104
  return percent;
105
105
  },
106
106
  getChannelInputEls: (ctx) => {
107
- return (0, import_dom_query.queryAll)(dom.getContentEl(ctx), "input[data-channel]");
107
+ return [
108
+ ...(0, import_dom_query.queryAll)(dom.getContentEl(ctx), "input[data-channel]"),
109
+ ...(0, import_dom_query.queryAll)(dom.getControlEl(ctx), "input[data-channel]")
110
+ ];
108
111
  },
109
112
  getFirstFocusableEl: (ctx) => (0, import_tabbable.getFirstFocusable)(dom.getContentEl(ctx), "if-empty"),
110
113
  getInitialFocusEl: (ctx) => {
@@ -208,19 +211,18 @@ function getSliderBackgroundDirection(orientation, dir) {
208
211
  return "left";
209
212
  }
210
213
  }
211
- var getSliderBackground = (ctx, props) => {
212
- const { channel } = props;
213
- const dir = getSliderBackgroundDirection(props.orientation, ctx.dir);
214
- const value = ctx.value;
214
+ var getSliderBackground = (props) => {
215
+ const { channel, value, dir } = props;
216
+ const bgDirection = getSliderBackgroundDirection(props.orientation, dir);
215
217
  const { minValue, maxValue } = value.getChannelRange(channel);
216
218
  switch (channel) {
217
219
  case "hue":
218
- return `linear-gradient(to ${dir}, rgb(255, 0, 0) 0%, rgb(255, 255, 0) 17%, rgb(0, 255, 0) 33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 67%, rgb(255, 0, 255) 83%, rgb(255, 0, 0) 100%)`;
220
+ return `linear-gradient(to ${bgDirection}, rgb(255, 0, 0) 0%, rgb(255, 255, 0) 17%, rgb(0, 255, 0) 33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 67%, rgb(255, 0, 255) 83%, rgb(255, 0, 0) 100%)`;
219
221
  case "lightness": {
220
222
  let start = value.withChannelValue(channel, minValue).toString("css");
221
223
  let middle = value.withChannelValue(channel, (maxValue - minValue) / 2).toString("css");
222
224
  let end = value.withChannelValue(channel, maxValue).toString("css");
223
- return `linear-gradient(to ${dir}, ${start}, ${middle}, ${end})`;
225
+ return `linear-gradient(to ${bgDirection}, ${start}, ${middle}, ${end})`;
224
226
  }
225
227
  case "saturation":
226
228
  case "brightness":
@@ -230,7 +232,7 @@ var getSliderBackground = (ctx, props) => {
230
232
  case "alpha": {
231
233
  let start = value.withChannelValue(channel, minValue).toString("css");
232
234
  let end = value.withChannelValue(channel, maxValue).toString("css");
233
- return `linear-gradient(to ${dir}, ${start}, ${end})`;
235
+ return `linear-gradient(to ${bgDirection}, ${start}, ${end})`;
234
236
  }
235
237
  default:
236
238
  throw new Error("Unknown color channel: " + channel);
@@ -246,11 +248,13 @@ function connect(state, send, normalize) {
246
248
  const isDragging = state.hasTag("dragging");
247
249
  const isOpen = state.hasTag("open");
248
250
  const channels = value.getChannels();
249
- const getAreaChannels = (props) => ({
250
- value: value.toFormat("hsl"),
251
- xChannel: props.xChannel ?? "saturation",
252
- yChannel: props.yChannel ?? "lightness"
253
- });
251
+ const getAreaChannels = (props) => {
252
+ const channels2 = value.getChannels();
253
+ return {
254
+ xChannel: props.xChannel ?? channels2[1],
255
+ yChannel: props.yChannel ?? channels2[2]
256
+ };
257
+ };
254
258
  const currentPlacement = state.context.currentPlacement;
255
259
  const popperStyles = (0, import_popper.getPlacementStyles)({
256
260
  ...state.context.positioning,
@@ -272,13 +276,12 @@ function connect(state, send, normalize) {
272
276
  const color = value.withChannelValue(channel, channelValue);
273
277
  send({ type: "VALUE.SET", value: color, src: "set-channel" });
274
278
  },
279
+ format: value.outputFormat ?? value.getFormat(),
275
280
  setFormat(format) {
276
281
  const formatValue = value.toFormat(format);
277
282
  send({ type: "VALUE.SET", value: formatValue, src: "set-format" });
278
283
  },
279
- getAlpha() {
280
- return value.getChannelValue("alpha");
281
- },
284
+ alpha: value.getChannelValue("alpha"),
282
285
  setAlpha(alphaValue) {
283
286
  const color = value.withChannelValue("alpha", alphaValue);
284
287
  send({ type: "VALUE.SET", value: color, src: "set-alpha" });
@@ -391,10 +394,10 @@ function connect(state, send, normalize) {
391
394
  });
392
395
  },
393
396
  getAreaThumbProps(props = {}) {
394
- const { xChannel, yChannel, value: valueAsHSL } = getAreaChannels(props);
397
+ const { xChannel, yChannel } = getAreaChannels(props);
395
398
  const channel = { xChannel, yChannel };
396
- const x = valueAsHSL.getChannelValuePercent(xChannel);
397
- const y = 1 - valueAsHSL.getChannelValuePercent(yChannel);
399
+ const x = value.getChannelValuePercent(xChannel);
400
+ const y = 1 - value.getChannelValuePercent(yChannel);
398
401
  return normalize.element({
399
402
  ...parts.areaThumb.attrs,
400
403
  id: dom.getAreaThumbId(state.context),
@@ -449,10 +452,10 @@ function connect(state, send, normalize) {
449
452
  }
450
453
  });
451
454
  },
452
- getTransparencyGridProps(props) {
453
- const { size } = props;
455
+ getTransparencyGridProps(props = {}) {
456
+ const { size = "12px" } = props;
454
457
  return normalize.element({
455
- ...parts.transparancyGrid.attrs,
458
+ ...parts.transparencyGrid.attrs,
456
459
  style: {
457
460
  "--size": size,
458
461
  width: "100%",
@@ -501,7 +504,12 @@ function connect(state, send, normalize) {
501
504
  style: {
502
505
  position: "relative",
503
506
  forcedColorAdjust: "none",
504
- backgroundImage: getSliderBackground(state.context, { orientation, channel })
507
+ backgroundImage: getSliderBackground({
508
+ orientation,
509
+ channel,
510
+ dir: state.context.dir,
511
+ value
512
+ })
505
513
  }
506
514
  });
507
515
  },
@@ -697,7 +705,14 @@ var import_utils2 = require("@zag-js/utils");
697
705
  // src/color-picker.parse.ts
698
706
  var import_color_utils4 = require("@zag-js/color-utils");
699
707
  var import_core = require("@zag-js/core");
700
- var parse = (color) => (0, import_core.ref)((0, import_color_utils4.parseColor)(color));
708
+ var parse = (color) => {
709
+ const value = (0, import_color_utils4.parseColor)(color);
710
+ const colorFormat = value.getFormat();
711
+ const lockedFormat = colorFormat.startsWith("hsl") ? "hsla" : "hsba";
712
+ const result = value.toFormat(lockedFormat);
713
+ result.outputFormat = colorFormat;
714
+ return (0, import_core.ref)(result);
715
+ };
701
716
 
702
717
  // src/color-picker.machine.ts
703
718
  var { stateIn } = import_core2.guards;
@@ -726,7 +741,10 @@ function machine(userContext) {
726
741
  isRtl: (ctx2) => ctx2.dir === "rtl",
727
742
  isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled,
728
743
  isInteractive: (ctx2) => !(ctx2.isDisabled || ctx2.readOnly),
729
- valueAsString: (ctx2) => ctx2.value.toString("css")
744
+ valueAsString: (ctx2) => {
745
+ const color = ctx2.value.outputFormat ? ctx2.value.toFormat(ctx2.value.outputFormat) : ctx2.value;
746
+ return color.toString("css");
747
+ }
730
748
  },
731
749
  activities: ["trackFormControl"],
732
750
  watch: {
@@ -1040,10 +1058,9 @@ function machine(userContext) {
1040
1058
  return;
1041
1059
  }
1042
1060
  if (isTextField) {
1043
- const format = "hsl";
1044
1061
  const currentAlpha = ctx2.value.getChannelValue("alpha");
1045
1062
  const color2 = (0, import_utils2.tryCatch)(
1046
- () => (0, import_color_utils5.parseColor)(value).toFormat(format).withChannelValue("alpha", currentAlpha),
1063
+ () => parse(value).withChannelValue("alpha", currentAlpha),
1047
1064
  () => ctx2.value
1048
1065
  );
1049
1066
  const inputEl = dom.getChannelInputEl(ctx2, channel);
@@ -1051,7 +1068,7 @@ function machine(userContext) {
1051
1068
  set.value(ctx2, color2);
1052
1069
  return;
1053
1070
  }
1054
- const color = ctx2.value.withChannelValue(channel, value);
1071
+ const color = ctx2.value.toFormat(ctx2.value.outputFormat).withChannelValue(channel, value);
1055
1072
  set.value(ctx2, color);
1056
1073
  },
1057
1074
  incrementChannel(ctx2, evt) {
@@ -1121,6 +1138,9 @@ function machine(userContext) {
1121
1138
  toggleVisibility(ctx2, _evt, { send }) {
1122
1139
  send({ type: ctx2.open ? "OPEN" : "CLOSE", src: "controlled" });
1123
1140
  }
1141
+ },
1142
+ compareFns: {
1143
+ value: (a, b) => a.isEqual(b)
1124
1144
  }
1125
1145
  }
1126
1146
  );
@@ -1154,7 +1174,13 @@ var set = {
1154
1174
  sync.inputs(ctx);
1155
1175
  if (!color || ctx.value.isEqual(color))
1156
1176
  return;
1157
- ctx.value = (0, import_core2.ref)(color);
1177
+ const currentFormat = ctx.value.getFormat();
1178
+ const outputColor = color.toFormat(currentFormat);
1179
+ try {
1180
+ outputColor.outputFormat = ctx.value.outputFormat;
1181
+ } catch {
1182
+ }
1183
+ ctx.value = (0, import_core2.ref)(outputColor);
1158
1184
  invoke.change(ctx);
1159
1185
  }
1160
1186
  };