@patternmode/swatch 0.1.1 → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel Howells
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # @patternmode/swatch
2
+
3
+ Color, gradient, image, and palette swatch primitives for React.
4
+
5
+ ```tsx
6
+ import { DistributionBar, Swatch } from "@patternmode/swatch";
7
+ import "@patternmode/swatch/styles.css";
8
+
9
+ export function Example() {
10
+ return (
11
+ <>
12
+ <Swatch
13
+ aria-label="Palette"
14
+ colors={[
15
+ { color: "#315c4b", ratio: 60 },
16
+ { color: "#e1ebe5", ratio: 40 },
17
+ ]}
18
+ shape="pill"
19
+ size="2xl"
20
+ />
21
+ <DistributionBar
22
+ aria-label="Finish distribution"
23
+ segments={[
24
+ { id: "evergreen", color: "#315c4b", label: "Evergreen", value: 48 },
25
+ { id: "saffron", color: "#d9a441", label: "Saffron", value: 30 },
26
+ { id: "oxblood", color: "#9b3d32", label: "Oxblood", value: 22 },
27
+ ]}
28
+ />
29
+ </>
30
+ );
31
+ }
32
+ ```
33
+
34
+ Use `color` for a solid fill, `background` for a CSS background value, or `colors` for weighted palette stops. `Swatch` remains representation-only: compose selection around it, or pass `onRemove` when the swatch should expose its built-in remove request affordance.
35
+
36
+ Use `DistributionBar` as a sibling primitive when a weighted visual distribution should be edited with draggable boundary handles.
37
+
38
+ Distribution segment values are weights, not persisted percentages. The bar renders segment widths proportionally and its legend displays derived percentages.
39
+
40
+ For external segment controls, keep `segments` controlled and pass the next value to `onChange`. The package also exports `moveDistributionBoundary`, `updateDistributionSegment`, and `removeDistributionSegment` so custom controls can move handles, change segment metadata, or remove a segment without duplicating the bar math. `updateDistributionSegment` does not change distribution values.
41
+
42
+ Import `@patternmode/swatch/styles.css` once in your app.
@@ -0,0 +1,15 @@
1
+ export interface DistributionBarSegment {
2
+ color: string;
3
+ id: string;
4
+ label?: string;
5
+ value: number;
6
+ }
7
+ export type DistributionBarSegmentUpdate = Partial<Omit<DistributionBarSegment, "value">> & {
8
+ value?: never;
9
+ };
10
+ export declare function getDistributionTotal(segments: DistributionBarSegment[]): number;
11
+ export declare function getDistributionBoundaryPercent(segments: DistributionBarSegment[], boundaryIndex: number): number;
12
+ export declare function moveDistributionBoundary(segments: DistributionBarSegment[], boundaryIndex: number, deltaValue: number, minValue: number): DistributionBarSegment[];
13
+ export declare function removeDistributionSegment(segments: DistributionBarSegment[], segmentId: string): DistributionBarSegment[];
14
+ export declare function updateDistributionSegment(segments: DistributionBarSegment[], segmentId: string, update: DistributionBarSegmentUpdate): DistributionBarSegment[];
15
+ //# sourceMappingURL=DistributionBarMath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DistributionBarMath.d.ts","sourceRoot":"","sources":["../../src/DistributionBar/DistributionBarMath.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,4BAA4B,GAAG,OAAO,CACjD,IAAI,CAAC,sBAAsB,EAAE,OAAO,CAAC,CACrC,GAAG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,sBAAsB,EAAE,GAChC,MAAM,CAKR;AAED,wBAAgB,8BAA8B,CAC7C,QAAQ,EAAE,sBAAsB,EAAE,EAClC,aAAa,EAAE,MAAM,GACnB,MAAM,CAUR;AAED,wBAAgB,wBAAwB,CACvC,QAAQ,EAAE,sBAAsB,EAAE,EAClC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACd,sBAAsB,EAAE,CAyB1B;AAED,wBAAgB,yBAAyB,CACxC,QAAQ,EAAE,sBAAsB,EAAE,EAClC,SAAS,EAAE,MAAM,GACf,sBAAsB,EAAE,CAmC1B;AAED,wBAAgB,yBAAyB,CACxC,QAAQ,EAAE,sBAAsB,EAAE,EAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,4BAA4B,GAClC,sBAAsB,EAAE,CAI1B"}
@@ -0,0 +1,10 @@
1
+ import type { HTMLAttributes } from "react";
2
+ import { type DistributionBarSegment } from "./DistributionBarMath";
3
+ export interface DistributionBarProps extends Omit<HTMLAttributes<HTMLFieldSetElement>, "onChange"> {
4
+ minValue?: number;
5
+ onChange?: (segments: DistributionBarSegment[]) => void;
6
+ segments: DistributionBarSegment[];
7
+ step?: number;
8
+ }
9
+ export declare function DistributionBar({ "aria-label": ariaLabel, className, minValue, onChange, segments, step, ...props }: DistributionBarProps): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=DistributionBarRoot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DistributionBarRoot.d.ts","sourceRoot":"","sources":["../../src/DistributionBar/DistributionBarRoot.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,cAAc,EAAiB,MAAM,OAAO,CAAC;AAG1E,OAAO,EACN,KAAK,sBAAsB,EAI3B,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,oBAChB,SAAQ,IAAI,CAAC,cAAc,CAAC,mBAAmB,CAAC,EAAE,UAAU,CAAC;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,sBAAsB,EAAE,KAAK,IAAI,CAAC;IACxD,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,eAAe,CAAC,EAC/B,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,QAAY,EACZ,QAAQ,EACR,QAAQ,EACR,IAAQ,EACR,GAAG,KAAK,EACR,EAAE,oBAAoB,2CA+FtB"}
@@ -0,0 +1,3 @@
1
+ export { type DistributionBarSegment, type DistributionBarSegmentUpdate, getDistributionBoundaryPercent, getDistributionTotal, moveDistributionBoundary, removeDistributionSegment, updateDistributionSegment, } from "./DistributionBarMath";
2
+ export { DistributionBar, type DistributionBarProps, } from "./DistributionBarRoot";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/DistributionBar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,8BAA8B,EAC9B,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,eAAe,EACf,KAAK,oBAAoB,GACzB,MAAM,uBAAuB,CAAC"}
@@ -1,3 +1,3 @@
1
- import type { SwatchProps } from "./SwatchTypes";
2
- export declare function Swatch({ "aria-label": ariaLabel, background, children, className, color, colors, icon: Icon, isLight, objectFit, objectPosition, onRemove, raised, role: _role, selected, shape, showRing, size, style, unavailable, ...props }: SwatchProps): import("react/jsx-runtime").JSX.Element;
1
+ import { type SwatchProps } from "./SwatchTypes";
2
+ export declare function Swatch({ "aria-label": ariaLabel, background, children, className, color, colors, icon: Icon, isLight, objectFit, objectPosition, onRemove, raised, removeLabel, role: _role, selected, shape, showRing, size, style, unavailable, ...props }: SwatchProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=SwatchRoot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SwatchRoot.d.ts","sourceRoot":"","sources":["../../src/Swatch/SwatchRoot.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,wBAAgB,MAAM,CAAC,EACtB,YAAY,EAAE,SAAS,EACvB,UAAU,EACV,QAAQ,EACR,SAAS,EACT,KAAK,EACL,MAAM,EACN,IAAI,EAAE,IAAI,EACV,OAAO,EACP,SAAS,EACT,cAAc,EACd,QAAQ,EACR,MAAc,EACd,IAAI,EAAE,KAAK,EACX,QAAgB,EAChB,KAAgB,EAChB,QAAe,EACf,IAAa,EACb,KAAK,EACL,WAAmB,EACnB,GAAG,KAAK,EACR,EAAE,WAAW,2CAqEb"}
1
+ {"version":3,"file":"SwatchRoot.d.ts","sourceRoot":"","sources":["../../src/Swatch/SwatchRoot.tsx"],"names":[],"mappings":"AAIA,OAAO,EAA8B,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7E,wBAAgB,MAAM,CAAC,EACtB,YAAY,EAAE,SAAS,EACvB,UAAU,EACV,QAAQ,EACR,SAAS,EACT,KAAK,EACL,MAAM,EACN,IAAI,EAAE,IAAI,EACV,OAAO,EACP,SAAS,EACT,cAAc,EACd,QAAQ,EACR,MAAc,EACd,WAAW,EACX,IAAI,EAAE,KAAK,EACX,QAAgB,EAChB,KAAgB,EAChB,QAAe,EACf,IAAa,EACb,KAAK,EACL,WAAmB,EACnB,GAAG,KAAK,EACR,EAAE,WAAW,2CAgGb"}
@@ -1,15 +1,30 @@
1
- import { type ObjectFit, type PatternmodeSize } from "@patternmode/system";
1
+ import { type ObjectFit } from "@patternmode/system";
2
2
  import type { ComponentType, HTMLAttributes, SVGProps } from "react";
3
- export declare const SWATCH_SIZES: readonly ["2xs", "xs", "sm", "base", "lg", "xl", "2xl", "3xl"];
3
+ export declare const SWATCH_SIZES: readonly ["2xs", "xs", "sm", "base", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "6xl", "7xl"];
4
+ export declare const SWATCH_SIZE_VALUES: {
5
+ readonly "4xl": "4.5rem";
6
+ readonly "5xl": "5rem";
7
+ readonly "6xl": "5.5rem";
8
+ readonly "7xl": "6rem";
9
+ readonly "2xs": "1rem";
10
+ readonly xs: "1.25rem";
11
+ readonly sm: "1.5rem";
12
+ readonly base: "2rem";
13
+ readonly lg: "2.5rem";
14
+ readonly xl: "3rem";
15
+ readonly "2xl": "3.5rem";
16
+ readonly "3xl": "4rem";
17
+ };
4
18
  export declare const SWATCH_SHAPES: readonly ["circle", "pill", "square"];
5
- export type SwatchSize = PatternmodeSize;
19
+ export type SwatchSize = (typeof SWATCH_SIZES)[number];
6
20
  export type SwatchShape = (typeof SWATCH_SHAPES)[number];
7
21
  export type SwatchColorStop = string | {
8
22
  color: string;
9
23
  ratio?: number;
10
24
  };
11
25
  type SwatchIcon = ComponentType<SVGProps<SVGSVGElement>>;
12
- export interface SwatchProps extends HTMLAttributes<HTMLSpanElement> {
26
+ export declare function getSwatchSizeVariableStyle(size: SwatchSize, variableName?: string): Record<string, string>;
27
+ export interface SwatchProps extends HTMLAttributes<HTMLElement> {
13
28
  background?: string;
14
29
  color?: string;
15
30
  colors?: SwatchColorStop[];
@@ -19,6 +34,7 @@ export interface SwatchProps extends HTMLAttributes<HTMLSpanElement> {
19
34
  objectPosition?: string;
20
35
  onRemove?: () => void;
21
36
  raised?: boolean;
37
+ removeLabel?: string;
22
38
  selected?: boolean;
23
39
  shape?: SwatchShape;
24
40
  showRing?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"SwatchTypes.d.ts","sourceRoot":"","sources":["../../src/Swatch/SwatchTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EAEd,KAAK,eAAe,EACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAErE,eAAO,MAAM,YAAY,gEAAoB,CAAC;AAE9C,eAAO,MAAM,aAAa,uCAAwC,CAAC;AAEnE,MAAM,MAAM,UAAU,GAAG,eAAe,CAAC;AACzC,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AACzD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACzE,KAAK,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;AAEzD,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,eAAe,CAAC;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB"}
1
+ {"version":3,"file":"SwatchTypes.d.ts","sourceRoot":"","sources":["../../src/Swatch/SwatchTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EAGd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAErE,eAAO,MAAM,YAAY,4FAMf,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;CAMgB,CAAC;AAEhD,eAAO,MAAM,aAAa,uCAAwC,CAAC;AAEnE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AACzD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACzE,KAAK,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;AAEzD,wBAAgB,0BAA0B,CACzC,IAAI,EAAE,UAAU,EAChB,YAAY,SAA8B,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIxB;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,WAAW,CAAC;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB"}
@@ -1,4 +1,5 @@
1
+ export { DistributionBar, type DistributionBarProps, type DistributionBarSegment, type DistributionBarSegmentUpdate, getDistributionBoundaryPercent, getDistributionTotal, moveDistributionBoundary, removeDistributionSegment, updateDistributionSegment, } from "../DistributionBar";
1
2
  export { getSwatchColorsBackground } from "./SwatchColors";
2
3
  export { Swatch } from "./SwatchRoot";
3
- export { SWATCH_SHAPES, SWATCH_SIZES, type SwatchColorStop, type SwatchProps, type SwatchShape, type SwatchSize, } from "./SwatchTypes";
4
+ export { getSwatchSizeVariableStyle, SWATCH_SHAPES, SWATCH_SIZE_VALUES, SWATCH_SIZES, type SwatchColorStop, type SwatchProps, type SwatchShape, type SwatchSize, } from "./SwatchTypes";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Swatch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EACN,aAAa,EACb,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,GACf,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Swatch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,8BAA8B,EAC9B,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EACN,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,GACf,MAAM,eAAe,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { getSwatchColorsBackground, SWATCH_SHAPES, SWATCH_SIZES, Swatch, type SwatchColorStop, type SwatchProps, type SwatchShape, type SwatchSize, } from "./swatch";
1
+ export { DistributionBar, type DistributionBarProps, type DistributionBarSegment, type DistributionBarSegmentUpdate, getDistributionBoundaryPercent, getDistributionTotal, getSwatchColorsBackground, getSwatchSizeVariableStyle, moveDistributionBoundary, removeDistributionSegment, SWATCH_SHAPES, SWATCH_SIZE_VALUES, SWATCH_SIZES, Swatch, type SwatchColorStop, type SwatchProps, type SwatchShape, type SwatchSize, updateDistributionSegment, } from "./swatch";
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,yBAAyB,EACzB,aAAa,EACb,YAAY,EACZ,MAAM,EACN,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,GACf,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,8BAA8B,EAC9B,oBAAoB,EACpB,yBAAyB,EACzB,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,MAAM,EACN,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,yBAAyB,GACzB,MAAM,UAAU,CAAC"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,166 @@
1
- import { PATTERNMODE_SIZES, getObjectSizingStyle, getSizeVariableStyle, joinClassNames } from "@patternmode/system";
2
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { PATTERNMODE_SIZES, PATTERNMODE_SIZE_VALUES, getObjectSizingStyle, joinClassNames } from "@patternmode/system";
2
+ import { motion } from "motion/react";
3
+ import { useRef } from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/DistributionBar/DistributionBarMath.ts
6
+ function getDistributionTotal(segments) {
7
+ return segments.reduce((sum, segment) => sum + sanitizeValue(segment.value), 0);
8
+ }
9
+ function getDistributionBoundaryPercent(segments, boundaryIndex) {
10
+ const total = getDistributionTotal(segments);
11
+ if (total <= 0) return 0;
12
+ return roundValue(segments.slice(0, boundaryIndex + 1).reduce((sum, segment) => sum + sanitizeValue(segment.value), 0) / total * 100);
13
+ }
14
+ function moveDistributionBoundary(segments, boundaryIndex, deltaValue, minValue) {
15
+ const left = segments[boundaryIndex];
16
+ const right = segments[boundaryIndex + 1];
17
+ if (!(left && right)) return segments;
18
+ const pairTotal = sanitizeValue(left.value) + sanitizeValue(right.value);
19
+ const clampedMin = Math.max(0, Math.min(minValue, pairTotal / 2));
20
+ const nextLeft = clamp(sanitizeValue(left.value) + deltaValue, clampedMin, pairTotal - clampedMin);
21
+ const nextRight = pairTotal - nextLeft;
22
+ return segments.map((segment, index) => {
23
+ if (index === boundaryIndex) return {
24
+ ...segment,
25
+ value: roundValue(nextLeft)
26
+ };
27
+ if (index === boundaryIndex + 1) return {
28
+ ...segment,
29
+ value: roundValue(nextRight)
30
+ };
31
+ return segment;
32
+ });
33
+ }
34
+ function removeDistributionSegment(segments, segmentId) {
35
+ if (segments.length <= 1) return segments;
36
+ const removed = segments.find((segment) => segment.id === segmentId);
37
+ if (!removed) return segments;
38
+ const remaining = segments.filter((segment) => segment.id !== segmentId);
39
+ const removedValue = sanitizeValue(removed.value);
40
+ const remainingTotal = getDistributionTotal(remaining);
41
+ if (remainingTotal <= 0) {
42
+ const equalValue = removedValue / remaining.length;
43
+ return remaining.map((segment) => ({
44
+ ...segment,
45
+ value: roundValue(equalValue)
46
+ }));
47
+ }
48
+ let assignedValue = 0;
49
+ const originalTotal = getDistributionTotal(segments);
50
+ return remaining.map((segment, index) => {
51
+ if (index === remaining.length - 1) return {
52
+ ...segment,
53
+ value: roundValue(originalTotal - assignedValue)
54
+ };
55
+ const nextValue = roundValue(sanitizeValue(segment.value) + removedValue * sanitizeValue(segment.value) / remainingTotal);
56
+ assignedValue += nextValue;
57
+ return {
58
+ ...segment,
59
+ value: nextValue
60
+ };
61
+ });
62
+ }
63
+ function updateDistributionSegment(segments, segmentId, update) {
64
+ return segments.map((segment) => segment.id === segmentId ? {
65
+ ...segment,
66
+ ...update
67
+ } : segment);
68
+ }
69
+ function sanitizeValue(value) {
70
+ return Number.isFinite(value) ? Math.max(0, value) : 0;
71
+ }
72
+ function clamp(value, min, max) {
73
+ return Math.min(Math.max(value, min), max);
74
+ }
75
+ function roundValue(value) {
76
+ return Number(value.toFixed(1));
77
+ }
78
+ //#endregion
79
+ //#region src/DistributionBar/DistributionBarRoot.tsx
80
+ function DistributionBar({ "aria-label": ariaLabel, className, minValue = 4, onChange, segments, step = 1, ...props }) {
81
+ const trackRef = useRef(null);
82
+ const total = getDistributionTotal(segments);
83
+ function moveBoundary(boundaryIndex, deltaValue) {
84
+ onChange?.(moveDistributionBoundary(segments, boundaryIndex, deltaValue, minValue));
85
+ }
86
+ function handleDragEnd(boundaryIndex, info) {
87
+ const trackWidth = trackRef.current?.getBoundingClientRect().width ?? 0;
88
+ if (!(trackWidth > 0 && total > 0)) return;
89
+ moveBoundary(boundaryIndex, info.offset.x / trackWidth * total);
90
+ }
91
+ function handleKeyDown(event, boundaryIndex) {
92
+ if (event.key === "ArrowLeft") {
93
+ event.preventDefault();
94
+ moveBoundary(boundaryIndex, -step);
95
+ }
96
+ if (event.key === "ArrowRight") {
97
+ event.preventDefault();
98
+ moveBoundary(boundaryIndex, step);
99
+ }
100
+ }
101
+ return /* @__PURE__ */ jsxs("fieldset", {
102
+ ...props,
103
+ "aria-label": ariaLabel,
104
+ className: joinClassNames("patternmode-distribution-bar", className),
105
+ "data-slot": "distribution-bar",
106
+ children: [/* @__PURE__ */ jsxs("div", {
107
+ className: "patternmode-distribution-bar__track",
108
+ ref: trackRef,
109
+ children: [/* @__PURE__ */ jsx("div", {
110
+ className: "patternmode-distribution-bar__segments",
111
+ children: segments.map((segment) => /* @__PURE__ */ jsx("div", {
112
+ "aria-hidden": "true",
113
+ className: "patternmode-distribution-bar__segment",
114
+ style: {
115
+ "--patternmode-distribution-segment-color": segment.color,
116
+ width: total > 0 ? `${segment.value / total * 100}%` : "0%"
117
+ }
118
+ }, segment.id))
119
+ }), segments.slice(0, -1).map((segment, boundaryIndex) => {
120
+ const nextSegment = segments[boundaryIndex + 1];
121
+ const boundaryPercent = getDistributionBoundaryPercent(segments, boundaryIndex);
122
+ return /* @__PURE__ */ jsx(DistributionBarHandle, {
123
+ "aria-label": `Adjust ${segment.label ?? segment.id} and ${nextSegment?.label ?? nextSegment?.id} distribution`,
124
+ boundaryPercent,
125
+ onDragEnd: (info) => handleDragEnd(boundaryIndex, info),
126
+ onKeyDown: (event) => handleKeyDown(event, boundaryIndex)
127
+ }, `${segment.id}-${nextSegment?.id ?? "end"}`);
128
+ })]
129
+ }), /* @__PURE__ */ jsx("div", {
130
+ className: "patternmode-distribution-bar__legend",
131
+ children: segments.map((segment) => /* @__PURE__ */ jsxs("span", { children: [
132
+ /* @__PURE__ */ jsx("span", {
133
+ "aria-hidden": "true",
134
+ className: "patternmode-distribution-bar__swatch",
135
+ style: { "--patternmode-distribution-segment-color": segment.color }
136
+ }),
137
+ segment.label ?? segment.id,
138
+ " ",
139
+ getDerivedDistributionPercentage(segment.value, total),
140
+ "%"
141
+ ] }, segment.id))
142
+ })]
143
+ });
144
+ }
145
+ function getDerivedDistributionPercentage(value, total) {
146
+ if (!(total > 0 && Number.isFinite(value))) return 0;
147
+ return Math.round(Math.max(0, value) / total * 100);
148
+ }
149
+ function DistributionBarHandle({ "aria-label": ariaLabel, boundaryPercent, onDragEnd, onKeyDown }) {
150
+ return /* @__PURE__ */ jsx(motion.button, {
151
+ "aria-label": ariaLabel,
152
+ className: "patternmode-distribution-bar__handle",
153
+ drag: "x",
154
+ dragElastic: 0,
155
+ dragMomentum: false,
156
+ dragSnapToOrigin: true,
157
+ onDragEnd: (_event, info) => onDragEnd(info),
158
+ onKeyDown,
159
+ style: { left: `calc(${boundaryPercent}% - 1.375rem)` },
160
+ type: "button"
161
+ });
162
+ }
163
+ //#endregion
3
164
  //#region src/Swatch/SwatchColors.ts
4
165
  function isLightColor(color) {
5
166
  const normalized = normalizeHex(color);
@@ -43,13 +204,38 @@ function formatPercent(value) {
43
204
  return `${Number.isInteger(value) ? value : Number(value.toFixed(2))}%`;
44
205
  }
45
206
  //#endregion
207
+ //#region src/Swatch/SwatchTypes.ts
208
+ const SWATCH_SIZES = [
209
+ ...PATTERNMODE_SIZES,
210
+ "4xl",
211
+ "5xl",
212
+ "6xl",
213
+ "7xl"
214
+ ];
215
+ const SWATCH_SIZE_VALUES = {
216
+ ...PATTERNMODE_SIZE_VALUES,
217
+ "4xl": "4.5rem",
218
+ "5xl": "5rem",
219
+ "6xl": "5.5rem",
220
+ "7xl": "6rem"
221
+ };
222
+ const SWATCH_SHAPES = [
223
+ "circle",
224
+ "pill",
225
+ "square"
226
+ ];
227
+ function getSwatchSizeVariableStyle(size, variableName = "--patternmode-swatch-size") {
228
+ return { [variableName]: SWATCH_SIZE_VALUES[size] };
229
+ }
230
+ //#endregion
46
231
  //#region src/Swatch/SwatchRoot.tsx
47
- function Swatch({ "aria-label": ariaLabel, background, children, className, color, colors, icon: Icon, isLight, objectFit, objectPosition, onRemove, raised = false, role: _role, selected = false, shape = "circle", showRing = true, size = "base", style, unavailable = false, ...props }) {
232
+ function Swatch({ "aria-label": ariaLabel, background, children, className, color, colors, icon: Icon, isLight, objectFit, objectPosition, onRemove, raised = false, removeLabel, role: _role, selected = false, shape = "circle", showRing = true, size = "base", style, unavailable = false, ...props }) {
48
233
  const colorsBackground = getSwatchColorsBackground(colors);
49
234
  const fill = background ?? colorsBackground ?? color;
50
235
  const light = isLight ?? (color && !background && !colorsBackground ? isLightColor(color) : false);
236
+ const resolvedRemoveLabel = removeLabel ?? (ariaLabel ? `Remove ${ariaLabel}` : "Remove");
51
237
  const rootStyle = {
52
- ...getSizeVariableStyle(size, "--patternmode-swatch-size"),
238
+ ...getSwatchSizeVariableStyle(size),
53
239
  "--patternmode-swatch-fill": fill,
54
240
  ...style
55
241
  };
@@ -61,7 +247,33 @@ function Swatch({ "aria-label": ariaLabel, background, children, className, colo
61
247
  event.stopPropagation();
62
248
  onRemove?.();
63
249
  }
64
- return /* @__PURE__ */ jsxs("span", {
250
+ const swatchContent = /* @__PURE__ */ jsxs(Fragment, { children: [
251
+ /* @__PURE__ */ jsx("span", {
252
+ "aria-hidden": "true",
253
+ className: "patternmode-swatch__fill"
254
+ }),
255
+ children ? /* @__PURE__ */ jsx("span", {
256
+ className: "patternmode-swatch__media",
257
+ style: mediaStyle,
258
+ children
259
+ }) : null,
260
+ /* @__PURE__ */ jsx("span", {
261
+ "aria-hidden": "true",
262
+ className: "patternmode-swatch__scrim"
263
+ }),
264
+ selected && Icon ? /* @__PURE__ */ jsx("span", {
265
+ className: "patternmode-swatch__icon",
266
+ children: /* @__PURE__ */ jsx(Icon, {
267
+ "aria-hidden": "true",
268
+ focusable: "false"
269
+ })
270
+ }) : null,
271
+ unavailable ? /* @__PURE__ */ jsx("span", {
272
+ "aria-hidden": "true",
273
+ className: "patternmode-swatch__slash"
274
+ }) : null
275
+ ] });
276
+ if (onRemove) return /* @__PURE__ */ jsxs("fieldset", {
65
277
  ...props,
66
278
  "aria-label": ariaLabel,
67
279
  className: joinClassNames("patternmode-swatch", className),
@@ -73,57 +285,38 @@ function Swatch({ "aria-label": ariaLabel, background, children, className, colo
73
285
  "data-slot": "swatch",
74
286
  "data-tone": light ? "light" : "dark",
75
287
  "data-unavailable": unavailable ? "true" : void 0,
76
- role: "img",
77
288
  style: rootStyle,
78
- children: [
79
- /* @__PURE__ */ jsx("span", {
80
- "aria-hidden": "true",
81
- className: "patternmode-swatch__fill"
82
- }),
83
- children ? /* @__PURE__ */ jsx("span", {
84
- className: "patternmode-swatch__media",
85
- style: mediaStyle,
86
- children
87
- }) : null,
88
- /* @__PURE__ */ jsx("span", {
89
- "aria-hidden": "true",
90
- className: "patternmode-swatch__scrim"
91
- }),
92
- selected && Icon ? /* @__PURE__ */ jsx("span", {
93
- className: "patternmode-swatch__icon",
94
- children: /* @__PURE__ */ jsx(Icon, {
95
- "aria-hidden": "true",
96
- focusable: "false"
97
- })
98
- }) : null,
99
- unavailable ? /* @__PURE__ */ jsx("span", {
289
+ children: [swatchContent, /* @__PURE__ */ jsx("button", {
290
+ "aria-label": resolvedRemoveLabel,
291
+ className: "patternmode-swatch__remove",
292
+ onClick: handleRemove,
293
+ type: "button",
294
+ children: /* @__PURE__ */ jsx("svg", {
100
295
  "aria-hidden": "true",
101
- className: "patternmode-swatch__slash"
102
- }) : null,
103
- onRemove ? /* @__PURE__ */ jsx("button", {
104
- "aria-label": "Remove",
105
- className: "patternmode-swatch__remove",
106
- onClick: handleRemove,
107
- type: "button",
108
- children: /* @__PURE__ */ jsx("svg", {
109
- "aria-hidden": "true",
110
- fill: "none",
111
- viewBox: "0 0 20 20",
112
- children: /* @__PURE__ */ jsx("path", { d: "M5.5 5.5l9 9M14.5 5.5l-9 9" })
113
- })
114
- }) : null
115
- ]
296
+ fill: "none",
297
+ viewBox: "0 0 20 20",
298
+ children: /* @__PURE__ */ jsx("path", { d: "M5.5 5.5l9 9M14.5 5.5l-9 9" })
299
+ })
300
+ })]
301
+ });
302
+ return /* @__PURE__ */ jsx("span", {
303
+ ...props,
304
+ "aria-label": ariaLabel,
305
+ className: joinClassNames("patternmode-swatch", className),
306
+ "data-raised": raised ? "true" : void 0,
307
+ "data-selected": selected ? "true" : void 0,
308
+ "data-shape": shape,
309
+ "data-show-ring": showRing ? "true" : "false",
310
+ "data-size": size,
311
+ "data-slot": "swatch",
312
+ "data-tone": light ? "light" : "dark",
313
+ "data-unavailable": unavailable ? "true" : void 0,
314
+ role: "img",
315
+ style: rootStyle,
316
+ children: swatchContent
116
317
  });
117
318
  }
118
319
  //#endregion
119
- //#region src/Swatch/SwatchTypes.ts
120
- const SWATCH_SIZES = PATTERNMODE_SIZES;
121
- const SWATCH_SHAPES = [
122
- "circle",
123
- "pill",
124
- "square"
125
- ];
126
- //#endregion
127
- export { SWATCH_SHAPES, SWATCH_SIZES, Swatch, getSwatchColorsBackground };
320
+ export { DistributionBar, SWATCH_SHAPES, SWATCH_SIZES, SWATCH_SIZE_VALUES, Swatch, getDistributionBoundaryPercent, getDistributionTotal, getSwatchColorsBackground, getSwatchSizeVariableStyle, moveDistributionBoundary, removeDistributionSegment, updateDistributionSegment };
128
321
 
129
322
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/Swatch/SwatchColors.ts","../src/Swatch/SwatchRoot.tsx","../src/Swatch/SwatchTypes.ts"],"sourcesContent":["import type { SwatchColorStop } from \"./SwatchTypes\";\n\nexport function isLightColor(color: string): boolean {\n\tconst normalized = normalizeHex(color);\n\tif (!normalized) {\n\t\treturn false;\n\t}\n\n\tconst red = Number.parseInt(normalized.slice(0, 2), 16);\n\tconst green = Number.parseInt(normalized.slice(2, 4), 16);\n\tconst blue = Number.parseInt(normalized.slice(4, 6), 16);\n\tconst luminance = (0.299 * red + 0.587 * green + 0.114 * blue) / 255;\n\treturn luminance > 0.62;\n}\n\nexport function getSwatchColorsBackground(\n\tcolors: SwatchColorStop[] | undefined,\n): string | undefined {\n\tif (!colors || colors.length === 0) {\n\t\treturn undefined;\n\t}\n\n\tif (colors.length === 1) {\n\t\treturn toColorStop(colors[0] as SwatchColorStop).color;\n\t}\n\n\tconst stops = colors.map(toColorStop);\n\tconst weights = stops.map((stop) => getRatioWeight(stop.ratio));\n\tconst rawTotal = weights.reduce((sum, ratio) => sum + ratio, 0);\n\tconst useEqualWeights = rawTotal <= 0;\n\tconst total = useEqualWeights ? stops.length : rawTotal;\n\tlet cursor = 0;\n\tconst parts = stops.map((stop, index) => {\n\t\tconst ratio = useEqualWeights ? 1 : (weights[index] ?? 0);\n\t\tconst start = cursor;\n\t\tconst end =\n\t\t\tindex === stops.length - 1 ? 100 : cursor + (ratio / total) * 100;\n\t\tcursor = end;\n\t\treturn `${stop.color} ${formatPercent(start)} ${formatPercent(end)}`;\n\t});\n\n\treturn `linear-gradient(90deg, ${parts.join(\", \")})`;\n}\n\nfunction normalizeHex(hex: string): string | null {\n\tconst value = hex.trim().replace(/^#/, \"\");\n\tif (/^[\\da-f]{3}$/i.test(value)) {\n\t\treturn value\n\t\t\t.split(\"\")\n\t\t\t.map((part) => part + part)\n\t\t\t.join(\"\");\n\t}\n\tif (/^[\\da-f]{6}$/i.test(value)) {\n\t\treturn value;\n\t}\n\treturn null;\n}\n\nfunction toColorStop(stop: SwatchColorStop): { color: string; ratio?: number } {\n\treturn typeof stop === \"string\" ? { color: stop } : stop;\n}\n\nfunction getRatioWeight(ratio: number | undefined): number {\n\tif (ratio === undefined) {\n\t\treturn 1;\n\t}\n\n\treturn Number.isFinite(ratio) ? Math.max(0, ratio) : 0;\n}\n\nfunction formatPercent(value: number): string {\n\treturn `${Number.isInteger(value) ? value : Number(value.toFixed(2))}%`;\n}\n","import {\n\tgetObjectSizingStyle,\n\tgetSizeVariableStyle,\n\tjoinClassNames,\n} from \"@patternmode/system\";\nimport type { CSSProperties, MouseEvent } from \"react\";\n\nimport { getSwatchColorsBackground, isLightColor } from \"./SwatchColors\";\nimport type { SwatchProps } from \"./SwatchTypes\";\n\nexport function Swatch({\n\t\"aria-label\": ariaLabel,\n\tbackground,\n\tchildren,\n\tclassName,\n\tcolor,\n\tcolors,\n\ticon: Icon,\n\tisLight,\n\tobjectFit,\n\tobjectPosition,\n\tonRemove,\n\traised = false,\n\trole: _role,\n\tselected = false,\n\tshape = \"circle\",\n\tshowRing = true,\n\tsize = \"base\",\n\tstyle,\n\tunavailable = false,\n\t...props\n}: SwatchProps) {\n\tconst colorsBackground = getSwatchColorsBackground(colors);\n\tconst fill = background ?? colorsBackground ?? color;\n\tconst light =\n\t\tisLight ??\n\t\t(color && !background && !colorsBackground\n\t\t\t? isLightColor(color as string)\n\t\t\t: false);\n\n\tconst rootStyle = {\n\t\t...getSizeVariableStyle(size, \"--patternmode-swatch-size\"),\n\t\t\"--patternmode-swatch-fill\": fill,\n\t\t...style,\n\t} as CSSProperties;\n\tconst mediaStyle = getObjectSizingStyle({\n\t\tfit: objectFit,\n\t\tposition: objectPosition,\n\t}) as CSSProperties;\n\n\tfunction handleRemove(event: MouseEvent<HTMLButtonElement>) {\n\t\tevent.stopPropagation();\n\t\tonRemove?.();\n\t}\n\n\treturn (\n\t\t<span\n\t\t\t{...props}\n\t\t\taria-label={ariaLabel}\n\t\t\tclassName={joinClassNames(\"patternmode-swatch\", className)}\n\t\t\tdata-raised={raised ? \"true\" : undefined}\n\t\t\tdata-selected={selected ? \"true\" : undefined}\n\t\t\tdata-shape={shape}\n\t\t\tdata-show-ring={showRing ? \"true\" : \"false\"}\n\t\t\tdata-size={size}\n\t\t\tdata-slot=\"swatch\"\n\t\t\tdata-tone={light ? \"light\" : \"dark\"}\n\t\t\tdata-unavailable={unavailable ? \"true\" : undefined}\n\t\t\trole=\"img\"\n\t\t\tstyle={rootStyle}\n\t\t>\n\t\t\t<span aria-hidden=\"true\" className=\"patternmode-swatch__fill\" />\n\t\t\t{children ? (\n\t\t\t\t<span className=\"patternmode-swatch__media\" style={mediaStyle}>\n\t\t\t\t\t{children}\n\t\t\t\t</span>\n\t\t\t) : null}\n\t\t\t<span aria-hidden=\"true\" className=\"patternmode-swatch__scrim\" />\n\t\t\t{selected && Icon ? (\n\t\t\t\t<span className=\"patternmode-swatch__icon\">\n\t\t\t\t\t<Icon aria-hidden=\"true\" focusable=\"false\" />\n\t\t\t\t</span>\n\t\t\t) : null}\n\t\t\t{unavailable ? (\n\t\t\t\t<span aria-hidden=\"true\" className=\"patternmode-swatch__slash\" />\n\t\t\t) : null}\n\t\t\t{onRemove ? (\n\t\t\t\t<button\n\t\t\t\t\taria-label=\"Remove\"\n\t\t\t\t\tclassName=\"patternmode-swatch__remove\"\n\t\t\t\t\tonClick={handleRemove}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t<svg aria-hidden=\"true\" fill=\"none\" viewBox=\"0 0 20 20\">\n\t\t\t\t\t\t<path d=\"M5.5 5.5l9 9M14.5 5.5l-9 9\" />\n\t\t\t\t\t</svg>\n\t\t\t\t</button>\n\t\t\t) : null}\n\t\t</span>\n\t);\n}\n","import {\n\ttype ObjectFit,\n\tPATTERNMODE_SIZES,\n\ttype PatternmodeSize,\n} from \"@patternmode/system\";\nimport type { ComponentType, HTMLAttributes, SVGProps } from \"react\";\n\nexport const SWATCH_SIZES = PATTERNMODE_SIZES;\n\nexport const SWATCH_SHAPES = [\"circle\", \"pill\", \"square\"] as const;\n\nexport type SwatchSize = PatternmodeSize;\nexport type SwatchShape = (typeof SWATCH_SHAPES)[number];\nexport type SwatchColorStop = string | { color: string; ratio?: number };\ntype SwatchIcon = ComponentType<SVGProps<SVGSVGElement>>;\n\nexport interface SwatchProps extends HTMLAttributes<HTMLSpanElement> {\n\tbackground?: string;\n\tcolor?: string;\n\tcolors?: SwatchColorStop[];\n\ticon?: SwatchIcon;\n\tisLight?: boolean;\n\tobjectFit?: ObjectFit;\n\tobjectPosition?: string;\n\tonRemove?: () => void;\n\traised?: boolean;\n\tselected?: boolean;\n\tshape?: SwatchShape;\n\tshowRing?: boolean;\n\tsize?: SwatchSize;\n\tunavailable?: boolean;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/DistributionBar/DistributionBarMath.ts","../src/DistributionBar/DistributionBarRoot.tsx","../src/Swatch/SwatchColors.ts","../src/Swatch/SwatchTypes.ts","../src/Swatch/SwatchRoot.tsx"],"sourcesContent":["export interface DistributionBarSegment {\n\tcolor: string;\n\tid: string;\n\tlabel?: string;\n\tvalue: number;\n}\n\nexport type DistributionBarSegmentUpdate = Partial<\n\tOmit<DistributionBarSegment, \"value\">\n> & {\n\tvalue?: never;\n};\n\nexport function getDistributionTotal(\n\tsegments: DistributionBarSegment[],\n): number {\n\treturn segments.reduce(\n\t\t(sum, segment) => sum + sanitizeValue(segment.value),\n\t\t0,\n\t);\n}\n\nexport function getDistributionBoundaryPercent(\n\tsegments: DistributionBarSegment[],\n\tboundaryIndex: number,\n): number {\n\tconst total = getDistributionTotal(segments);\n\tif (total <= 0) {\n\t\treturn 0;\n\t}\n\n\tconst boundaryValue = segments\n\t\t.slice(0, boundaryIndex + 1)\n\t\t.reduce((sum, segment) => sum + sanitizeValue(segment.value), 0);\n\treturn roundValue((boundaryValue / total) * 100);\n}\n\nexport function moveDistributionBoundary(\n\tsegments: DistributionBarSegment[],\n\tboundaryIndex: number,\n\tdeltaValue: number,\n\tminValue: number,\n): DistributionBarSegment[] {\n\tconst left = segments[boundaryIndex];\n\tconst right = segments[boundaryIndex + 1];\n\tif (!(left && right)) {\n\t\treturn segments;\n\t}\n\n\tconst pairTotal = sanitizeValue(left.value) + sanitizeValue(right.value);\n\tconst clampedMin = Math.max(0, Math.min(minValue, pairTotal / 2));\n\tconst nextLeft = clamp(\n\t\tsanitizeValue(left.value) + deltaValue,\n\t\tclampedMin,\n\t\tpairTotal - clampedMin,\n\t);\n\tconst nextRight = pairTotal - nextLeft;\n\n\treturn segments.map((segment, index) => {\n\t\tif (index === boundaryIndex) {\n\t\t\treturn { ...segment, value: roundValue(nextLeft) };\n\t\t}\n\t\tif (index === boundaryIndex + 1) {\n\t\t\treturn { ...segment, value: roundValue(nextRight) };\n\t\t}\n\t\treturn segment;\n\t});\n}\n\nexport function removeDistributionSegment(\n\tsegments: DistributionBarSegment[],\n\tsegmentId: string,\n): DistributionBarSegment[] {\n\tif (segments.length <= 1) {\n\t\treturn segments;\n\t}\n\n\tconst removed = segments.find((segment) => segment.id === segmentId);\n\tif (!removed) {\n\t\treturn segments;\n\t}\n\n\tconst remaining = segments.filter((segment) => segment.id !== segmentId);\n\tconst removedValue = sanitizeValue(removed.value);\n\tconst remainingTotal = getDistributionTotal(remaining);\n\tif (remainingTotal <= 0) {\n\t\tconst equalValue = removedValue / remaining.length;\n\t\treturn remaining.map((segment) => ({\n\t\t\t...segment,\n\t\t\tvalue: roundValue(equalValue),\n\t\t}));\n\t}\n\n\tlet assignedValue = 0;\n\tconst originalTotal = getDistributionTotal(segments);\n\treturn remaining.map((segment, index) => {\n\t\tif (index === remaining.length - 1) {\n\t\t\treturn { ...segment, value: roundValue(originalTotal - assignedValue) };\n\t\t}\n\n\t\tconst nextValue = roundValue(\n\t\t\tsanitizeValue(segment.value) +\n\t\t\t\t(removedValue * sanitizeValue(segment.value)) / remainingTotal,\n\t\t);\n\t\tassignedValue += nextValue;\n\t\treturn { ...segment, value: nextValue };\n\t});\n}\n\nexport function updateDistributionSegment(\n\tsegments: DistributionBarSegment[],\n\tsegmentId: string,\n\tupdate: DistributionBarSegmentUpdate,\n): DistributionBarSegment[] {\n\treturn segments.map((segment) =>\n\t\tsegment.id === segmentId ? { ...segment, ...update } : segment,\n\t);\n}\n\nfunction sanitizeValue(value: number): number {\n\treturn Number.isFinite(value) ? Math.max(0, value) : 0;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n\treturn Math.min(Math.max(value, min), max);\n}\n\nfunction roundValue(value: number): number {\n\treturn Number(value.toFixed(1));\n}\n","import { joinClassNames } from \"@patternmode/system\";\nimport { motion, type PanInfo } from \"motion/react\";\nimport type { CSSProperties, HTMLAttributes, KeyboardEvent } from \"react\";\nimport { useRef } from \"react\";\n\nimport {\n\ttype DistributionBarSegment,\n\tgetDistributionBoundaryPercent,\n\tgetDistributionTotal,\n\tmoveDistributionBoundary,\n} from \"./DistributionBarMath\";\n\nexport interface DistributionBarProps\n\textends Omit<HTMLAttributes<HTMLFieldSetElement>, \"onChange\"> {\n\tminValue?: number;\n\tonChange?: (segments: DistributionBarSegment[]) => void;\n\tsegments: DistributionBarSegment[];\n\tstep?: number;\n}\n\nexport function DistributionBar({\n\t\"aria-label\": ariaLabel,\n\tclassName,\n\tminValue = 4,\n\tonChange,\n\tsegments,\n\tstep = 1,\n\t...props\n}: DistributionBarProps) {\n\tconst trackRef = useRef<HTMLDivElement>(null);\n\tconst total = getDistributionTotal(segments);\n\n\tfunction moveBoundary(boundaryIndex: number, deltaValue: number) {\n\t\tonChange?.(\n\t\t\tmoveDistributionBoundary(segments, boundaryIndex, deltaValue, minValue),\n\t\t);\n\t}\n\n\tfunction handleDragEnd(boundaryIndex: number, info: PanInfo) {\n\t\tconst trackWidth = trackRef.current?.getBoundingClientRect().width ?? 0;\n\t\tif (!(trackWidth > 0 && total > 0)) {\n\t\t\treturn;\n\t\t}\n\n\t\tmoveBoundary(boundaryIndex, (info.offset.x / trackWidth) * total);\n\t}\n\n\tfunction handleKeyDown(\n\t\tevent: KeyboardEvent<HTMLButtonElement>,\n\t\tboundaryIndex: number,\n\t) {\n\t\tif (event.key === \"ArrowLeft\") {\n\t\t\tevent.preventDefault();\n\t\t\tmoveBoundary(boundaryIndex, -step);\n\t\t}\n\t\tif (event.key === \"ArrowRight\") {\n\t\t\tevent.preventDefault();\n\t\t\tmoveBoundary(boundaryIndex, step);\n\t\t}\n\t}\n\n\treturn (\n\t\t<fieldset\n\t\t\t{...props}\n\t\t\taria-label={ariaLabel}\n\t\t\tclassName={joinClassNames(\"patternmode-distribution-bar\", className)}\n\t\t\tdata-slot=\"distribution-bar\"\n\t\t>\n\t\t\t<div className=\"patternmode-distribution-bar__track\" ref={trackRef}>\n\t\t\t\t<div className=\"patternmode-distribution-bar__segments\">\n\t\t\t\t\t{segments.map((segment) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\tclassName=\"patternmode-distribution-bar__segment\"\n\t\t\t\t\t\t\tkey={segment.id}\n\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"--patternmode-distribution-segment-color\": segment.color,\n\t\t\t\t\t\t\t\t\twidth: total > 0 ? `${(segment.value / total) * 100}%` : \"0%\",\n\t\t\t\t\t\t\t\t} as CSSProperties\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{segments.slice(0, -1).map((segment, boundaryIndex) => {\n\t\t\t\t\tconst nextSegment = segments[boundaryIndex + 1];\n\t\t\t\t\tconst boundaryPercent = getDistributionBoundaryPercent(\n\t\t\t\t\t\tsegments,\n\t\t\t\t\t\tboundaryIndex,\n\t\t\t\t\t);\n\t\t\t\t\tconst label = `Adjust ${segment.label ?? segment.id} and ${\n\t\t\t\t\t\tnextSegment?.label ?? nextSegment?.id\n\t\t\t\t\t} distribution`;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<DistributionBarHandle\n\t\t\t\t\t\t\taria-label={label}\n\t\t\t\t\t\t\tboundaryPercent={boundaryPercent}\n\t\t\t\t\t\t\tkey={`${segment.id}-${nextSegment?.id ?? \"end\"}`}\n\t\t\t\t\t\t\tonDragEnd={(info) => handleDragEnd(boundaryIndex, info)}\n\t\t\t\t\t\t\tonKeyDown={(event) => handleKeyDown(event, boundaryIndex)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t<div className=\"patternmode-distribution-bar__legend\">\n\t\t\t\t{segments.map((segment) => (\n\t\t\t\t\t<span key={segment.id}>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\tclassName=\"patternmode-distribution-bar__swatch\"\n\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"--patternmode-distribution-segment-color\": segment.color,\n\t\t\t\t\t\t\t\t} as CSSProperties\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{segment.label ?? segment.id}{\" \"}\n\t\t\t\t\t\t{getDerivedDistributionPercentage(segment.value, total)}%\n\t\t\t\t\t</span>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t</fieldset>\n\t);\n}\n\nfunction getDerivedDistributionPercentage(\n\tvalue: number,\n\ttotal: number,\n): number {\n\tif (!(total > 0 && Number.isFinite(value))) {\n\t\treturn 0;\n\t}\n\n\treturn Math.round((Math.max(0, value) / total) * 100);\n}\n\ninterface DistributionBarHandleProps {\n\t\"aria-label\": string;\n\tboundaryPercent: number;\n\tonDragEnd: (info: PanInfo) => void;\n\tonKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void;\n}\n\nfunction DistributionBarHandle({\n\t\"aria-label\": ariaLabel,\n\tboundaryPercent,\n\tonDragEnd,\n\tonKeyDown,\n}: DistributionBarHandleProps) {\n\treturn (\n\t\t<motion.button\n\t\t\taria-label={ariaLabel}\n\t\t\tclassName=\"patternmode-distribution-bar__handle\"\n\t\t\tdrag=\"x\"\n\t\t\tdragElastic={0}\n\t\t\tdragMomentum={false}\n\t\t\tdragSnapToOrigin\n\t\t\tonDragEnd={(_event, info) => onDragEnd(info)}\n\t\t\tonKeyDown={onKeyDown}\n\t\t\tstyle={{ left: `calc(${boundaryPercent}% - 1.375rem)` }}\n\t\t\ttype=\"button\"\n\t\t/>\n\t);\n}\n","import type { SwatchColorStop } from \"./SwatchTypes\";\n\nexport function isLightColor(color: string): boolean {\n\tconst normalized = normalizeHex(color);\n\tif (!normalized) {\n\t\treturn false;\n\t}\n\n\tconst red = Number.parseInt(normalized.slice(0, 2), 16);\n\tconst green = Number.parseInt(normalized.slice(2, 4), 16);\n\tconst blue = Number.parseInt(normalized.slice(4, 6), 16);\n\tconst luminance = (0.299 * red + 0.587 * green + 0.114 * blue) / 255;\n\treturn luminance > 0.62;\n}\n\nexport function getSwatchColorsBackground(\n\tcolors: SwatchColorStop[] | undefined,\n): string | undefined {\n\tif (!colors || colors.length === 0) {\n\t\treturn undefined;\n\t}\n\n\tif (colors.length === 1) {\n\t\treturn toColorStop(colors[0] as SwatchColorStop).color;\n\t}\n\n\tconst stops = colors.map(toColorStop);\n\tconst weights = stops.map((stop) => getRatioWeight(stop.ratio));\n\tconst rawTotal = weights.reduce((sum, ratio) => sum + ratio, 0);\n\tconst useEqualWeights = rawTotal <= 0;\n\tconst total = useEqualWeights ? stops.length : rawTotal;\n\tlet cursor = 0;\n\tconst parts = stops.map((stop, index) => {\n\t\tconst ratio = useEqualWeights ? 1 : (weights[index] ?? 0);\n\t\tconst start = cursor;\n\t\tconst end =\n\t\t\tindex === stops.length - 1 ? 100 : cursor + (ratio / total) * 100;\n\t\tcursor = end;\n\t\treturn `${stop.color} ${formatPercent(start)} ${formatPercent(end)}`;\n\t});\n\n\treturn `linear-gradient(90deg, ${parts.join(\", \")})`;\n}\n\nfunction normalizeHex(hex: string): string | null {\n\tconst value = hex.trim().replace(/^#/, \"\");\n\tif (/^[\\da-f]{3}$/i.test(value)) {\n\t\treturn value\n\t\t\t.split(\"\")\n\t\t\t.map((part) => part + part)\n\t\t\t.join(\"\");\n\t}\n\tif (/^[\\da-f]{6}$/i.test(value)) {\n\t\treturn value;\n\t}\n\treturn null;\n}\n\nfunction toColorStop(stop: SwatchColorStop): { color: string; ratio?: number } {\n\treturn typeof stop === \"string\" ? { color: stop } : stop;\n}\n\nfunction getRatioWeight(ratio: number | undefined): number {\n\tif (ratio === undefined) {\n\t\treturn 1;\n\t}\n\n\treturn Number.isFinite(ratio) ? Math.max(0, ratio) : 0;\n}\n\nfunction formatPercent(value: number): string {\n\treturn `${Number.isInteger(value) ? value : Number(value.toFixed(2))}%`;\n}\n","import {\n\ttype ObjectFit,\n\tPATTERNMODE_SIZE_VALUES,\n\tPATTERNMODE_SIZES,\n} from \"@patternmode/system\";\nimport type { ComponentType, HTMLAttributes, SVGProps } from \"react\";\n\nexport const SWATCH_SIZES = [\n\t...PATTERNMODE_SIZES,\n\t\"4xl\",\n\t\"5xl\",\n\t\"6xl\",\n\t\"7xl\",\n] as const;\n\nexport const SWATCH_SIZE_VALUES = {\n\t...PATTERNMODE_SIZE_VALUES,\n\t\"4xl\": \"4.5rem\",\n\t\"5xl\": \"5rem\",\n\t\"6xl\": \"5.5rem\",\n\t\"7xl\": \"6rem\",\n} as const satisfies Record<SwatchSize, string>;\n\nexport const SWATCH_SHAPES = [\"circle\", \"pill\", \"square\"] as const;\n\nexport type SwatchSize = (typeof SWATCH_SIZES)[number];\nexport type SwatchShape = (typeof SWATCH_SHAPES)[number];\nexport type SwatchColorStop = string | { color: string; ratio?: number };\ntype SwatchIcon = ComponentType<SVGProps<SVGSVGElement>>;\n\nexport function getSwatchSizeVariableStyle(\n\tsize: SwatchSize,\n\tvariableName = \"--patternmode-swatch-size\",\n): Record<string, string> {\n\treturn {\n\t\t[variableName]: SWATCH_SIZE_VALUES[size],\n\t};\n}\n\nexport interface SwatchProps extends HTMLAttributes<HTMLElement> {\n\tbackground?: string;\n\tcolor?: string;\n\tcolors?: SwatchColorStop[];\n\ticon?: SwatchIcon;\n\tisLight?: boolean;\n\tobjectFit?: ObjectFit;\n\tobjectPosition?: string;\n\tonRemove?: () => void;\n\traised?: boolean;\n\tremoveLabel?: string;\n\tselected?: boolean;\n\tshape?: SwatchShape;\n\tshowRing?: boolean;\n\tsize?: SwatchSize;\n\tunavailable?: boolean;\n}\n","import { getObjectSizingStyle, joinClassNames } from \"@patternmode/system\";\nimport type { CSSProperties, MouseEvent } from \"react\";\n\nimport { getSwatchColorsBackground, isLightColor } from \"./SwatchColors\";\nimport { getSwatchSizeVariableStyle, type SwatchProps } from \"./SwatchTypes\";\n\nexport function Swatch({\n\t\"aria-label\": ariaLabel,\n\tbackground,\n\tchildren,\n\tclassName,\n\tcolor,\n\tcolors,\n\ticon: Icon,\n\tisLight,\n\tobjectFit,\n\tobjectPosition,\n\tonRemove,\n\traised = false,\n\tremoveLabel,\n\trole: _role,\n\tselected = false,\n\tshape = \"circle\",\n\tshowRing = true,\n\tsize = \"base\",\n\tstyle,\n\tunavailable = false,\n\t...props\n}: SwatchProps) {\n\tconst colorsBackground = getSwatchColorsBackground(colors);\n\tconst fill = background ?? colorsBackground ?? color;\n\tconst light =\n\t\tisLight ??\n\t\t(color && !background && !colorsBackground\n\t\t\t? isLightColor(color as string)\n\t\t\t: false);\n\tconst resolvedRemoveLabel =\n\t\tremoveLabel ?? (ariaLabel ? `Remove ${ariaLabel}` : \"Remove\");\n\n\tconst rootStyle = {\n\t\t...getSwatchSizeVariableStyle(size),\n\t\t\"--patternmode-swatch-fill\": fill,\n\t\t...style,\n\t} as CSSProperties;\n\tconst mediaStyle = getObjectSizingStyle({\n\t\tfit: objectFit,\n\t\tposition: objectPosition,\n\t}) as CSSProperties;\n\n\tfunction handleRemove(event: MouseEvent<HTMLButtonElement>) {\n\t\tevent.stopPropagation();\n\t\tonRemove?.();\n\t}\n\n\tconst swatchContent = (\n\t\t<>\n\t\t\t<span aria-hidden=\"true\" className=\"patternmode-swatch__fill\" />\n\t\t\t{children ? (\n\t\t\t\t<span className=\"patternmode-swatch__media\" style={mediaStyle}>\n\t\t\t\t\t{children}\n\t\t\t\t</span>\n\t\t\t) : null}\n\t\t\t<span aria-hidden=\"true\" className=\"patternmode-swatch__scrim\" />\n\t\t\t{selected && Icon ? (\n\t\t\t\t<span className=\"patternmode-swatch__icon\">\n\t\t\t\t\t<Icon aria-hidden=\"true\" focusable=\"false\" />\n\t\t\t\t</span>\n\t\t\t) : null}\n\t\t\t{unavailable ? (\n\t\t\t\t<span aria-hidden=\"true\" className=\"patternmode-swatch__slash\" />\n\t\t\t) : null}\n\t\t</>\n\t);\n\n\tif (onRemove) {\n\t\treturn (\n\t\t\t<fieldset\n\t\t\t\t{...props}\n\t\t\t\taria-label={ariaLabel}\n\t\t\t\tclassName={joinClassNames(\"patternmode-swatch\", className)}\n\t\t\t\tdata-raised={raised ? \"true\" : undefined}\n\t\t\t\tdata-selected={selected ? \"true\" : undefined}\n\t\t\t\tdata-shape={shape}\n\t\t\t\tdata-show-ring={showRing ? \"true\" : \"false\"}\n\t\t\t\tdata-size={size}\n\t\t\t\tdata-slot=\"swatch\"\n\t\t\t\tdata-tone={light ? \"light\" : \"dark\"}\n\t\t\t\tdata-unavailable={unavailable ? \"true\" : undefined}\n\t\t\t\tstyle={rootStyle}\n\t\t\t>\n\t\t\t\t{swatchContent}\n\t\t\t\t<button\n\t\t\t\t\taria-label={resolvedRemoveLabel}\n\t\t\t\t\tclassName=\"patternmode-swatch__remove\"\n\t\t\t\t\tonClick={handleRemove}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t<svg aria-hidden=\"true\" fill=\"none\" viewBox=\"0 0 20 20\">\n\t\t\t\t\t\t<path d=\"M5.5 5.5l9 9M14.5 5.5l-9 9\" />\n\t\t\t\t\t</svg>\n\t\t\t\t</button>\n\t\t\t</fieldset>\n\t\t);\n\t}\n\n\treturn (\n\t\t<span\n\t\t\t{...props}\n\t\t\taria-label={ariaLabel}\n\t\t\tclassName={joinClassNames(\"patternmode-swatch\", className)}\n\t\t\tdata-raised={raised ? \"true\" : undefined}\n\t\t\tdata-selected={selected ? \"true\" : undefined}\n\t\t\tdata-shape={shape}\n\t\t\tdata-show-ring={showRing ? \"true\" : \"false\"}\n\t\t\tdata-size={size}\n\t\t\tdata-slot=\"swatch\"\n\t\t\tdata-tone={light ? \"light\" : \"dark\"}\n\t\t\tdata-unavailable={unavailable ? \"true\" : undefined}\n\t\t\trole=\"img\"\n\t\t\tstyle={rootStyle}\n\t\t>\n\t\t\t{swatchContent}\n\t\t</span>\n\t);\n}\n"],"mappings":"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"}
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- @layer components{.patternmode-swatch{--patternmode-swatch-size:2rem;--patternmode-swatch-fill:#e3e1dc;--patternmode-swatch-radius:999px;aspect-ratio:1;border-radius:var(--patternmode-swatch-radius);color:#fff;height:var(--patternmode-swatch-size);vertical-align:middle;width:var(--patternmode-swatch-size);justify-content:center;align-items:center;transition:box-shadow .14s,opacity .14s,transform .14s;display:inline-flex;position:relative;box-shadow:0 1px 2px #1118271a}.patternmode-swatch[data-tone=light]{color:#1d1d1b}.patternmode-swatch[data-shape=pill]{--patternmode-swatch-radius:999px;aspect-ratio:auto;width:calc(var(--patternmode-swatch-size) * 3)}.patternmode-swatch[data-shape=square]{--patternmode-swatch-radius:7px}.patternmode-swatch[data-raised=true]{box-shadow:0 1px 2px #1118271a, 0 0 0 2px var(--surface,#fff)}.patternmode-swatch[data-selected=true][data-show-ring=true]{box-shadow:0 1px 2px #1118271a, 0 0 0 2px var(--surface,#fff), 0 0 0 4px var(--accent,#315c4b)}.patternmode-swatch[data-unavailable=true]{opacity:.5}.patternmode-swatch__fill,.patternmode-swatch__media,.patternmode-swatch__scrim{border-radius:inherit;position:absolute;inset:0;overflow:hidden}.patternmode-swatch__fill{background:var(--patternmode-swatch-fill)}.patternmode-swatch__media>*{object-fit:inherit;object-position:inherit;width:100%;height:100%;display:block}.patternmode-swatch__scrim{pointer-events:none;background:linear-gradient(#0000 0%,#0003 100%)}.patternmode-swatch__icon{justify-content:center;align-items:center;display:inline-flex;position:absolute;inset:0}.patternmode-swatch__icon svg{stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.4px;width:48%;height:48%;display:block}.patternmode-swatch__slash{background:currentColor;border-radius:999px;width:112%;height:2px;position:absolute;transform:rotate(-45deg)}.patternmode-swatch__remove{background:var(--ink,#1d1d1b);color:var(--surface,#fff);cursor:pointer;opacity:0;border:0;border-radius:999px;justify-content:center;align-items:center;width:1.25rem;height:1.25rem;padding:0;transition:background .14s,opacity .14s;display:inline-flex;position:absolute;top:-.35rem;right:-.35rem}.patternmode-swatch:hover .patternmode-swatch__remove,.patternmode-swatch__remove:focus-visible{opacity:1}.patternmode-swatch__remove:hover{background:var(--accent,#315c4b)}.patternmode-swatch__remove:focus-visible{outline:2px solid var(--accent,#315c4b);outline-offset:2px}.patternmode-swatch__remove svg{stroke:currentColor;stroke-linecap:round;stroke-width:2px;width:.8rem;height:.8rem}}
1
+ @layer components{.patternmode-swatch{--patternmode-swatch-size:2rem;--patternmode-swatch-fill:#e3e1dc;--patternmode-swatch-radius:999px;aspect-ratio:1;border-radius:var(--patternmode-swatch-radius);color:#fff;height:var(--patternmode-swatch-size);vertical-align:middle;min-inline-size:0;width:var(--patternmode-swatch-size);border:0;justify-content:center;align-items:center;margin:0;padding:0;transition:box-shadow .14s,opacity .14s,transform .14s;display:inline-flex;position:relative;box-shadow:0 1px 2px #1118271a}.patternmode-swatch[data-tone=light]{color:#1d1d1b}.patternmode-swatch[data-shape=pill]{--patternmode-swatch-radius:999px;aspect-ratio:auto;width:calc(var(--patternmode-swatch-size) * 3)}.patternmode-swatch[data-shape=square]{--patternmode-swatch-radius:7px}.patternmode-swatch[data-raised=true]{box-shadow:0 1px 2px #1118271a, 0 0 0 2px var(--surface,#fff)}.patternmode-swatch[data-selected=true][data-show-ring=true]{box-shadow:0 1px 2px #1118271a, 0 0 0 2px var(--surface,#fff), 0 0 0 4px var(--accent,#315c4b)}.patternmode-swatch[data-unavailable=true]{opacity:.5}.patternmode-swatch__fill,.patternmode-swatch__media,.patternmode-swatch__scrim{border-radius:inherit;position:absolute;inset:0;overflow:hidden}.patternmode-swatch__fill{background:var(--patternmode-swatch-fill)}.patternmode-swatch__media>*{object-fit:inherit;object-position:inherit;width:100%;height:100%;display:block}.patternmode-swatch__scrim{pointer-events:none;background:linear-gradient(#0000 0%,#0003 100%)}.patternmode-swatch__icon{justify-content:center;align-items:center;display:inline-flex;position:absolute;inset:0}.patternmode-swatch__icon svg{stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.4px;width:48%;height:48%;display:block}.patternmode-swatch__slash{background:currentColor;border-radius:999px;width:112%;height:2px;position:absolute;transform:rotate(-45deg)}.patternmode-swatch__remove{color:var(--surface,#fff);cursor:pointer;opacity:0;background:0 0;border:0;border-radius:999px;justify-content:center;align-items:center;width:2.75rem;height:2.75rem;padding:0;transition:opacity .14s;display:inline-flex;position:absolute;top:-1.1rem;right:-1.1rem}.patternmode-swatch__remove:before{background:var(--ink,#1d1d1b);border-radius:inherit;content:"";width:1.25rem;height:1.25rem;transition:background .14s;position:absolute}.patternmode-swatch__remove:focus-visible{opacity:1}@media (hover:hover){.patternmode-swatch:hover .patternmode-swatch__remove{opacity:1}.patternmode-swatch__remove:hover:before{background:var(--accent,#315c4b)}}.patternmode-swatch__remove:focus-visible{outline:2px solid var(--accent,#315c4b);outline-offset:2px}.patternmode-swatch__remove svg{stroke:currentColor;stroke-linecap:round;stroke-width:2px;z-index:1;width:.8rem;height:.8rem}@media (prefers-reduced-motion:reduce){.patternmode-swatch,.patternmode-swatch__remove,.patternmode-swatch__remove:before{transition:none}}.patternmode-distribution-bar{min-inline-size:0;border:0;gap:10px;width:100%;margin:0;padding:0;display:grid}.patternmode-distribution-bar__track{touch-action:none;width:100%;height:40px;position:relative}.patternmode-distribution-bar__segments{border:1px solid var(--border-soft,#1118271f);border-radius:999px;width:100%;height:100%;display:flex;overflow:hidden}.patternmode-distribution-bar__segment{background:var(--patternmode-distribution-segment-color);min-width:0;height:100%}.patternmode-distribution-bar__segment+.patternmode-distribution-bar__segment{box-shadow:inset 1px 0 #fff9}.patternmode-distribution-bar__handle{cursor:ew-resize;z-index:1;background:0 0;border:0;border-radius:999px;justify-content:center;align-items:center;width:2.75rem;height:2.75rem;padding:0;display:inline-flex;position:absolute;top:calc(50% - 1.375rem)}.patternmode-distribution-bar__handle:before{background:var(--surface,#fff);content:"";border-radius:999px;width:.62rem;height:.62rem;transition:box-shadow .12s,transform .12s;box-shadow:0 1px 4px #1118272e,0 0 0 1px #11182733}.patternmode-distribution-bar__handle:focus-visible{outline:2px solid var(--accent,#315c4b);outline-offset:-4px}@media (hover:hover){.patternmode-distribution-bar__handle:hover:before{transform:scale(1.15);box-shadow:0 5px 14px #1118274d,0 0 0 1px #11182738}}.patternmode-distribution-bar__legend{flex-wrap:wrap;gap:8px 14px;display:flex}.patternmode-distribution-bar__legend>span{color:var(--muted,#595853);align-items:center;gap:6px;font-size:.68rem;font-weight:500;display:inline-flex}.patternmode-distribution-bar__swatch{background:var(--patternmode-distribution-segment-color);border-radius:999px;width:.55rem;height:.55rem;display:inline-flex}@media (prefers-reduced-motion:reduce){.patternmode-distribution-bar__handle:before{transition:none}}}
package/dist/swatch.d.ts CHANGED
@@ -1,4 +1,5 @@
1
+ export { DistributionBar, type DistributionBarProps, type DistributionBarSegment, type DistributionBarSegmentUpdate, getDistributionBoundaryPercent, getDistributionTotal, moveDistributionBoundary, removeDistributionSegment, updateDistributionSegment, } from "./DistributionBar";
1
2
  export { getSwatchColorsBackground } from "./Swatch/SwatchColors";
2
3
  export { Swatch } from "./Swatch/SwatchRoot";
3
- export { SWATCH_SHAPES, SWATCH_SIZES, type SwatchColorStop, type SwatchProps, type SwatchShape, type SwatchSize, } from "./Swatch/SwatchTypes";
4
+ export { getSwatchSizeVariableStyle, SWATCH_SHAPES, SWATCH_SIZE_VALUES, SWATCH_SIZES, type SwatchColorStop, type SwatchProps, type SwatchShape, type SwatchSize, } from "./Swatch/SwatchTypes";
4
5
  //# sourceMappingURL=swatch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"swatch.d.ts","sourceRoot":"","sources":["../src/swatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EACN,aAAa,EACb,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,GACf,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"swatch.d.ts","sourceRoot":"","sources":["../src/swatch.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,8BAA8B,EAC9B,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EACN,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,GACf,MAAM,sBAAsB,CAAC"}
package/package.json CHANGED
@@ -1,81 +1,83 @@
1
1
  {
2
- "name": "@patternmode/swatch",
3
- "version": "0.1.1",
4
- "private": false,
5
- "description": "Color, gradient, image, and palette swatch primitives for Patternmode interfaces.",
6
- "type": "module",
7
- "sideEffects": [
8
- "**/*.css"
9
- ],
10
- "license": "MIT",
11
- "author": "Daniel Howells",
12
- "repository": {
13
- "type": "git",
14
- "url": "git+ssh://git@github.com/howells/patternmode.git",
15
- "directory": "packages/swatch"
16
- },
17
- "bugs": {
18
- "url": "https://github.com/howells/patternmode/issues"
19
- },
20
- "homepage": "https://github.com/howells/patternmode/tree/main/packages/swatch#readme",
21
- "files": [
22
- "dist"
23
- ],
24
- "exports": {
25
- ".": {
26
- "types": "./dist/index.d.ts",
27
- "default": "./dist/index.mjs"
28
- },
29
- "./styles.css": "./dist/styles.css",
30
- "./package.json": "./package.json"
31
- },
32
- "publishConfig": {
33
- "access": "public"
34
- },
35
- "engines": {
36
- "node": ">=20"
37
- },
38
- "keywords": [
39
- "swatch",
40
- "palette",
41
- "color",
42
- "react",
43
- "component",
44
- "patternmode"
45
- ],
46
- "dependencies": {
47
- "@patternmode/system": "0.2.0"
48
- },
49
- "peerDependencies": {
50
- "react": "^18.0.0 || ^19.0.0",
51
- "react-dom": "^18.0.0 || ^19.0.0"
52
- },
53
- "devDependencies": {
54
- "@howells/lint": "^0.1.7",
55
- "@howells/typescript-config": "^0.1.2",
56
- "@tailwindcss/cli": "^4.3.0",
57
- "@testing-library/jest-dom": "^6.9.1",
58
- "@testing-library/react": "^16.3.2",
59
- "@testing-library/user-event": "^14.6.1",
60
- "@types/react": "^19.2.14",
61
- "@types/react-dom": "^19.2.3",
62
- "concurrently": "^9.2.1",
63
- "jsdom": "^29.1.1",
64
- "tailwindcss": "^4.3.0",
65
- "tsdown": "^0.22.0",
66
- "typescript": "^6.0.3",
67
- "vitest": "^4.1.6"
68
- },
69
- "scripts": {
70
- "build": "tsdown && tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false && pnpm build:styles",
71
- "build:styles": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
72
- "clean": "rm -rf dist .turbo",
73
- "dev": "concurrently \"pnpm dev:js\" \"pnpm dev:types\" \"pnpm dev:styles\"",
74
- "dev:js": "tsdown --watch",
75
- "dev:styles": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --watch",
76
- "dev:types": "tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false --watch --preserveWatchOutput",
77
- "lint:check": "find src -type f \\( -name '*.ts' -o -name '*.tsx' \\) -print0 | xargs -0 howells-biome check",
78
- "test": "vitest run",
79
- "typecheck": "tsc --noEmit"
80
- }
81
- }
2
+ "name": "@patternmode/swatch",
3
+ "version": "0.2.0",
4
+ "private": false,
5
+ "description": "Color, gradient, image, and palette swatch primitives for Patternmode interfaces.",
6
+ "type": "module",
7
+ "sideEffects": [
8
+ "**/*.css"
9
+ ],
10
+ "license": "MIT",
11
+ "author": "Daniel Howells",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+ssh://git@github.com/howells/patternmode.git",
15
+ "directory": "packages/swatch"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/howells/patternmode/issues"
19
+ },
20
+ "homepage": "https://github.com/howells/patternmode/tree/main/packages/swatch#readme",
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "default": "./dist/index.mjs"
28
+ },
29
+ "./styles.css": "./dist/styles.css",
30
+ "./package.json": "./package.json"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "engines": {
36
+ "node": ">=20"
37
+ },
38
+ "scripts": {
39
+ "build": "tsdown && tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false && pnpm build:styles",
40
+ "build:styles": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
41
+ "clean": "rm -rf dist .turbo",
42
+ "dev": "concurrently \"pnpm dev:js\" \"pnpm dev:types\" \"pnpm dev:styles\"",
43
+ "dev:js": "tsdown --watch",
44
+ "dev:styles": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --watch",
45
+ "dev:types": "tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false --watch --preserveWatchOutput",
46
+ "lint:check": "find src -type f \\( -name '*.ts' -o -name '*.tsx' \\) -print0 | xargs -0 howells-biome check",
47
+ "prepack": "pnpm build",
48
+ "test": "vitest run",
49
+ "typecheck": "tsc --noEmit"
50
+ },
51
+ "keywords": [
52
+ "swatch",
53
+ "palette",
54
+ "color",
55
+ "react",
56
+ "component",
57
+ "patternmode"
58
+ ],
59
+ "dependencies": {
60
+ "@patternmode/system": "workspace:*",
61
+ "motion": "^12.38.0"
62
+ },
63
+ "peerDependencies": {
64
+ "react": "^18.0.0 || ^19.0.0",
65
+ "react-dom": "^18.0.0 || ^19.0.0"
66
+ },
67
+ "devDependencies": {
68
+ "@howells/lint": "^0.1.7",
69
+ "@howells/typescript-config": "^0.1.2",
70
+ "@tailwindcss/cli": "^4.3.0",
71
+ "@testing-library/jest-dom": "^6.9.1",
72
+ "@testing-library/react": "^16.3.2",
73
+ "@testing-library/user-event": "^14.6.1",
74
+ "@types/react": "^19.2.14",
75
+ "@types/react-dom": "^19.2.3",
76
+ "concurrently": "^9.2.1",
77
+ "jsdom": "^29.1.1",
78
+ "tailwindcss": "^4.3.0",
79
+ "tsdown": "^0.22.0",
80
+ "typescript": "^6.0.3",
81
+ "vitest": "^4.1.6"
82
+ }
83
+ }